Skip to content

Commit 08853d4

Browse files
committed
Accept more : at EOLs under -Yindent-colon
Systamtically accept a `:` as COLON when it cannot be confused with a `:` at EOL.
1 parent 66e180d commit 08853d4

File tree

2 files changed

+31
-33
lines changed

2 files changed

+31
-33
lines changed

compiler/src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 23 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,11 @@ object Parsers {
307307
offset
308308
}
309309

310+
def acceptColon(): Int =
311+
val offset = in.offset
312+
if in.isColon() then { in.nextToken(); offset }
313+
else accept(COLON)
314+
310315
/** semi = nl {nl} | `;'
311316
* nl = `\n' // where allowed
312317
*/
@@ -860,7 +865,7 @@ object Parsers {
860865
lookahead.nextToken()
861866
skipParams()
862867
skipParams()
863-
lookahead.token == COLON
868+
lookahead.isColon()
864869

865870
def followingIsExtension() =
866871
val next = in.lookahead.token
@@ -1377,7 +1382,7 @@ object Parsers {
13771382
imods = modifiers(funTypeArgMods)
13781383
val paramStart = in.offset
13791384
val ts = funArgType() match {
1380-
case Ident(name) if name != tpnme.WILDCARD && in.token == COLON =>
1385+
case Ident(name) if name != tpnme.WILDCARD && in.isColon() =>
13811386
isValParamList = true
13821387
funArgTypesRest(
13831388
typedFunParam(paramStart, name.toTermName, imods),
@@ -1466,7 +1471,7 @@ object Parsers {
14661471
/** TypedFunParam ::= id ':' Type */
14671472
def typedFunParam(start: Offset, name: TermName, mods: Modifiers = EmptyModifiers): ValDef =
14681473
atSpan(start) {
1469-
accept(COLON)
1474+
acceptColon()
14701475
makeParameter(name, typ(), mods)
14711476
}
14721477

@@ -1760,24 +1765,23 @@ object Parsers {
17601765
else atSpan((t.span union cbs.head.span).start) { ContextBounds(t, cbs) }
17611766
}
17621767

1763-
def contextBounds(pname: TypeName): List[Tree] = in.token match {
1764-
case COLON =>
1768+
def contextBounds(pname: TypeName): List[Tree] =
1769+
if in.isColon() then
17651770
atSpan(in.skipToken()) {
17661771
AppliedTypeTree(toplevelTyp(), Ident(pname))
17671772
} :: contextBounds(pname)
1768-
case VIEWBOUND =>
1773+
else if in.token == VIEWBOUND then
17691774
report.errorOrMigrationWarning(
17701775
"view bounds `<%' are no longer supported, use a context bound `:' instead",
17711776
in.sourcePos())
17721777
atSpan(in.skipToken()) {
17731778
Function(Ident(pname) :: Nil, toplevelTyp())
17741779
} :: contextBounds(pname)
1775-
case _ =>
1780+
else
17761781
Nil
1777-
}
17781782

17791783
def typedOpt(): Tree =
1780-
if (in.token == COLON) { in.nextToken(); toplevelTyp() }
1784+
if in.isColon() then { in.nextToken(); toplevelTyp() }
17811785
else TypeTree().withSpan(Span(in.lastOffset))
17821786

17831787
def typeDependingOn(location: Location): Tree =
@@ -2194,6 +2198,7 @@ object Parsers {
21942198
* | SimpleExpr `.` MatchClause
21952199
* | SimpleExpr (TypeArgs | NamedTypeArgs)
21962200
* | SimpleExpr1 ArgumentExprs
2201+
* | SimpleExpr1 `:` nl ArgumentExprs
21972202
* Quoted ::= ‘'’ ‘{’ Block ‘}’
21982203
* | ‘'’ ‘[’ Type ‘]’
21992204
*/
@@ -2341,10 +2346,9 @@ object Parsers {
23412346
lookahead.nextToken()
23422347
if (lookahead.token == RPAREN)
23432348
!fn.isInstanceOf[Trees.Apply[?]] // allow one () as annotation argument
2344-
else if (lookahead.token == IDENTIFIER) {
2349+
else if lookahead.token == IDENTIFIER then
23452350
lookahead.nextToken()
2346-
lookahead.token != COLON
2347-
}
2351+
!lookahead.isColon()
23482352
else in.canStartExprTokens.contains(lookahead.token)
23492353
}
23502354
}
@@ -2761,7 +2765,7 @@ object Parsers {
27612765
if allowed.contains(in.token)
27622766
|| in.isSoftModifier
27632767
&& localModifierTokens.subsetOf(allowed) // soft modifiers are admissible everywhere local modifiers are
2764-
&& in.lookahead.token != COLON
2768+
&& !in.lookahead.isColon()
27652769
then
27662770
val isAccessMod = accessModifierTokens contains in.token
27672771
val mods1 = addModifier(mods)
@@ -2929,7 +2933,7 @@ object Parsers {
29292933
}
29302934
atSpan(start, nameStart) {
29312935
val name = ident()
2932-
accept(COLON)
2936+
acceptColon()
29332937
if (in.token == ARROW && ofClass && !mods.is(Local))
29342938
syntaxError(VarValParametersMayNotBeCallByName(name, mods.is(Mutable)))
29352939
val tpt = paramType()
@@ -2967,7 +2971,7 @@ object Parsers {
29672971
val isParams =
29682972
!impliedMods.is(Given)
29692973
|| startParamTokens.contains(in.token)
2970-
|| isIdent && (in.name == nme.inline || in.lookahead.token == COLON)
2974+
|| isIdent && (in.name == nme.inline || in.lookahead.isColon())
29712975
if isParams then commaSeparated(() => param())
29722976
else contextTypes(ofClass, nparams)
29732977
checkVarArgsRules(clause)
@@ -3189,13 +3193,7 @@ object Parsers {
31893193
case _ =>
31903194
first :: Nil
31913195
}
3192-
def emptyType = TypeTree().withSpan(Span(in.lastOffset))
3193-
val tpt =
3194-
if (in.token == COLON) {
3195-
in.nextToken()
3196-
toplevelTyp()
3197-
}
3198-
else emptyType
3196+
val tpt = typedOpt()
31993197
val rhs =
32003198
if tpt.isEmpty || in.token == EQUALS then
32013199
accept(EQUALS)
@@ -3274,15 +3272,7 @@ object Parsers {
32743272
var name = ident.name.asTermName
32753273
val tparams = typeParamClauseOpt(ParamOwner.Def)
32763274
val vparamss = paramClauses(numLeadParams = numLeadParams)
3277-
var tpt = fromWithinReturnType {
3278-
if in.token == COLONEOL then in.token = COLON
3279-
// a hack to allow
3280-
//
3281-
// def f():
3282-
// T
3283-
//
3284-
typedOpt()
3285-
}
3275+
var tpt = fromWithinReturnType { typedOpt() }
32863276
if (migrateTo3) newLineOptWhenFollowedBy(LBRACE)
32873277
val rhs =
32883278
if in.token == EQUALS then
@@ -3526,7 +3516,7 @@ object Parsers {
35263516
else Nil
35273517
newLinesOpt()
35283518
val noParams = tparams.isEmpty && vparamss.isEmpty
3529-
if !(name.isEmpty && noParams) then accept(COLON)
3519+
if !(name.isEmpty && noParams) then acceptColon()
35303520
val parents =
35313521
if isSimpleLiteral then rejectWildcardType(annotType()) :: Nil
35323522
else constrApp() :: withConstrApps()
@@ -3568,7 +3558,7 @@ object Parsers {
35683558
isUsingClause(extParams)
35693559
do ()
35703560
leadParamss ++= paramClauses(givenOnly = true, numLeadParams = nparams)
3571-
if in.token == COLON then
3561+
if in.isColon() then
35723562
syntaxError("no `:` expected here")
35733563
in.nextToken()
35743564
val methods =

compiler/src/dotty/tools/dotc/parsing/Scanners.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,14 @@ object Scanners {
7575
def isNestedStart = token == LBRACE || token == INDENT
7676
def isNestedEnd = token == RBRACE || token == OUTDENT
7777

78+
/** Is token a COLON, after having converted COLONEOL to COLON?
79+
* The conversion means that indentation is not significant after `:`
80+
* anymore. So, warning: this is a side-effecting operation.
81+
*/
82+
def isColon() =
83+
if token == COLONEOL then token = COLON
84+
token == COLON
85+
7886
/** Is current token first one after a newline? */
7987
def isAfterLineEnd: Boolean = lineOffset >= 0
8088

0 commit comments

Comments
 (0)