Skip to content

Commit 1d07c11

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 422ffbc commit 1d07c11

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
@@ -309,6 +309,11 @@ object Parsers {
309309
offset
310310
}
311311

312+
def acceptColon(): Int =
313+
val offset = in.offset
314+
if in.isColon() then { in.nextToken(); offset }
315+
else accept(COLON)
316+
312317
/** semi = nl {nl} | `;'
313318
* nl = `\n' // where allowed
314319
*/
@@ -861,7 +866,7 @@ object Parsers {
861866
lookahead.nextToken()
862867
skipParams()
863868
skipParams()
864-
lookahead.token == COLON
869+
lookahead.isColon()
865870

866871
def followingIsExtension() =
867872
val next = in.lookahead.token
@@ -1378,7 +1383,7 @@ object Parsers {
13781383
if isErased then imods = addModifier(imods)
13791384
val paramStart = in.offset
13801385
val ts = funArgType() match {
1381-
case Ident(name) if name != tpnme.WILDCARD && in.token == COLON =>
1386+
case Ident(name) if name != tpnme.WILDCARD && in.isColon() =>
13821387
isValParamList = true
13831388
funArgTypesRest(
13841389
typedFunParam(paramStart, name.toTermName, imods),
@@ -1467,7 +1472,7 @@ object Parsers {
14671472
/** TypedFunParam ::= id ':' Type */
14681473
def typedFunParam(start: Offset, name: TermName, mods: Modifiers = EmptyModifiers): ValDef =
14691474
atSpan(start) {
1470-
accept(COLON)
1475+
acceptColon()
14711476
makeParameter(name, typ(), mods)
14721477
}
14731478

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

1764-
def contextBounds(pname: TypeName): List[Tree] = in.token match {
1765-
case COLON =>
1769+
def contextBounds(pname: TypeName): List[Tree] =
1770+
if in.isColon() then
17661771
atSpan(in.skipToken()) {
17671772
AppliedTypeTree(toplevelTyp(), Ident(pname))
17681773
} :: contextBounds(pname)
1769-
case VIEWBOUND =>
1774+
else if in.token == VIEWBOUND then
17701775
report.errorOrMigrationWarning(
17711776
"view bounds `<%' are no longer supported, use a context bound `:' instead",
17721777
in.sourcePos())
17731778
atSpan(in.skipToken()) {
17741779
Function(Ident(pname) :: Nil, toplevelTyp())
17751780
} :: contextBounds(pname)
1776-
case _ =>
1781+
else
17771782
Nil
1778-
}
17791783

17801784
def typedOpt(): Tree =
1781-
if (in.token == COLON) { in.nextToken(); toplevelTyp() }
1785+
if in.isColon() then { in.nextToken(); toplevelTyp() }
17821786
else TypeTree().withSpan(Span(in.lastOffset))
17831787

17841788
def typeDependingOn(location: Location): Tree =
@@ -2195,6 +2199,7 @@ object Parsers {
21952199
* | SimpleExpr `.` MatchClause
21962200
* | SimpleExpr (TypeArgs | NamedTypeArgs)
21972201
* | SimpleExpr1 ArgumentExprs
2202+
* | SimpleExpr1 `:` nl ArgumentExprs
21982203
* Quoted ::= ‘'’ ‘{’ Block ‘}’
21992204
* | ‘'’ ‘[’ Type ‘]’
22002205
*/
@@ -2342,10 +2347,9 @@ object Parsers {
23422347
lookahead.nextToken()
23432348
if (lookahead.token == RPAREN)
23442349
!fn.isInstanceOf[Trees.Apply[?]] // allow one () as annotation argument
2345-
else if (lookahead.token == IDENTIFIER) {
2350+
else if lookahead.token == IDENTIFIER then
23462351
lookahead.nextToken()
2347-
lookahead.token != COLON
2348-
}
2352+
!lookahead.isColon()
23492353
else in.canStartExprTokens.contains(lookahead.token)
23502354
}
23512355
}
@@ -2762,7 +2766,7 @@ object Parsers {
27622766
if allowed.contains(in.token)
27632767
|| in.isSoftModifier
27642768
&& localModifierTokens.subsetOf(allowed) // soft modifiers are admissible everywhere local modifiers are
2765-
&& in.lookahead.token != COLON
2769+
&& !in.lookahead.isColon()
27662770
then
27672771
val isAccessMod = accessModifierTokens contains in.token
27682772
val mods1 = addModifier(mods)
@@ -2931,7 +2935,7 @@ object Parsers {
29312935
}
29322936
atSpan(start, nameStart) {
29332937
val name = ident()
2934-
accept(COLON)
2938+
acceptColon()
29352939
if (in.token == ARROW && ofClass && !mods.is(Local))
29362940
syntaxError(VarValParametersMayNotBeCallByName(name, mods.is(Mutable)))
29372941
val tpt = paramType()
@@ -2969,7 +2973,7 @@ object Parsers {
29692973
val isParams =
29702974
!impliedMods.is(Given)
29712975
|| startParamTokens.contains(in.token)
2972-
|| isIdent && (in.name == nme.inline || in.lookahead.token == COLON)
2976+
|| isIdent && (in.name == nme.inline || in.lookahead.isColon())
29732977
if isParams then commaSeparated(() => param())
29742978
else contextTypes(ofClass, nparams)
29752979
checkVarArgsRules(clause)
@@ -3191,13 +3195,7 @@ object Parsers {
31913195
case _ =>
31923196
first :: Nil
31933197
}
3194-
def emptyType = TypeTree().withSpan(Span(in.lastOffset))
3195-
val tpt =
3196-
if (in.token == COLON) {
3197-
in.nextToken()
3198-
toplevelTyp()
3199-
}
3200-
else emptyType
3198+
val tpt = typedOpt()
32013199
val rhs =
32023200
if tpt.isEmpty || in.token == EQUALS then
32033201
accept(EQUALS)
@@ -3276,15 +3274,7 @@ object Parsers {
32763274
var name = ident.name.asTermName
32773275
val tparams = typeParamClauseOpt(ParamOwner.Def)
32783276
val vparamss = paramClauses(numLeadParams = numLeadParams)
3279-
var tpt = fromWithinReturnType {
3280-
if in.token == COLONEOL then in.token = COLON
3281-
// a hack to allow
3282-
//
3283-
// def f():
3284-
// T
3285-
//
3286-
typedOpt()
3287-
}
3277+
var tpt = fromWithinReturnType { typedOpt() }
32883278
if (migrateTo3) newLineOptWhenFollowedBy(LBRACE)
32893279
val rhs =
32903280
if in.token == EQUALS then
@@ -3528,7 +3518,7 @@ object Parsers {
35283518
else Nil
35293519
newLinesOpt()
35303520
val noParams = tparams.isEmpty && vparamss.isEmpty
3531-
if !(name.isEmpty && noParams) then accept(COLON)
3521+
if !(name.isEmpty && noParams) then acceptColon()
35323522
val parents =
35333523
if isSimpleLiteral then rejectWildcardType(annotType()) :: Nil
35343524
else constrApp() :: withConstrApps()
@@ -3570,7 +3560,7 @@ object Parsers {
35703560
isUsingClause(extParams)
35713561
do ()
35723562
leadParamss ++= paramClauses(givenOnly = true, numLeadParams = nparams)
3573-
if in.token == COLON then
3563+
if in.isColon() then
35743564
syntaxError("no `:` expected here")
35753565
in.nextToken()
35763566
val methods =

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

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

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

0 commit comments

Comments
 (0)