Skip to content

Commit 11f8b99

Browse files
committed
Alternative trailing comma handling
Do it in Lexer but take into account whether commas are expected in current region. Also fixes an issue in #14741 regarding import parsing.
1 parent 6743a27 commit 11f8b99

File tree

3 files changed

+35
-18
lines changed

3 files changed

+35
-18
lines changed

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

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -559,19 +559,24 @@ object Parsers {
559559
def inDefScopeBraces[T](body: => T, rewriteWithColon: Boolean = false): T =
560560
inBracesOrIndented(body, rewriteWithColon)
561561

562-
/**
563-
* @param readFirst If true, assume we have not read the first `part`. Otherwise,
564-
* expect that we have (i.e the next thing to expect is a [[COMMA]]).
565-
*/
566-
def commaSeparated[T](part: () => T, readFirst: Boolean = true): List[T] =
562+
/** <part> {`,` <part>} */
563+
def commaSeparated[T](part: () => T): List[T] =
567564
in.currentRegion.withCommasExpected {
568-
val ts = new ListBuffer[T]
569-
if (readFirst) ts += part()
565+
commaSeparatedRest(part(), part)
566+
}
567+
568+
/** {`,` <part>}
569+
*
570+
* currentRegion.commasExpected has to be set separately.
571+
*/
572+
def commaSeparatedRest[T](leading: T, part: () => T): List[T] =
573+
if in.token == COMMA then
574+
val ts = new ListBuffer[T] += leading
570575
while in.token == COMMA do
571576
in.nextToken()
572577
ts += part()
573578
ts.toList
574-
}
579+
else leading :: Nil
575580

576581
def inSepRegion[T](f: Region => Region)(op: => T): T =
577582
val cur = in.currentRegion
@@ -1402,13 +1407,15 @@ object Parsers {
14021407
else {
14031408
if isErased then imods = addModifier(imods)
14041409
val paramStart = in.offset
1405-
val ts = funArgType() match {
1406-
case Ident(name) if name != tpnme.WILDCARD && in.isColon() =>
1407-
isValParamList = true
1408-
typedFunParam(paramStart, name.toTermName, imods) :: commaSeparated(
1409-
() => typedFunParam(in.offset, ident(), imods), readFirst = false)
1410-
case t =>
1411-
t :: commaSeparated(funArgType, readFirst = false)
1410+
val ts = in.currentRegion.withCommasExpected {
1411+
funArgType() match
1412+
case Ident(name) if name != tpnme.WILDCARD && in.isColon() =>
1413+
isValParamList = true
1414+
commaSeparatedRest(
1415+
typedFunParam(paramStart, name.toTermName, imods),
1416+
() => typedFunParam(in.offset, ident(), imods))
1417+
case t =>
1418+
commaSeparatedRest(t, funArgType)
14121419
}
14131420
accept(RPAREN)
14141421
if isValParamList || in.isArrow then
@@ -3188,8 +3195,7 @@ object Parsers {
31883195
}
31893196
else ImportSelector(from)
31903197

3191-
def importSelector(idOK: Boolean)(): ImportSelector =
3192-
val isWildcard = in.token == USCORE || in.token == GIVEN || isIdent(nme.raw.STAR)
3198+
def importSelector(idOK: Boolean): ImportSelector =
31933199
atSpan(in.offset) {
31943200
in.token match
31953201
case USCORE => wildcardSelector()
@@ -3201,6 +3207,14 @@ object Parsers {
32013207
namedSelector(termIdent())
32023208
}
32033209

3210+
def importSelectors(): List[ImportSelector] =
3211+
var idOK = true
3212+
commaSeparated { () =>
3213+
val isWildcard = in.token == USCORE || in.token == GIVEN || isIdent(nme.raw.STAR)
3214+
try importSelector(idOK)
3215+
finally idOK &= !isWildcard
3216+
}
3217+
32043218
def importSelection(qual: Tree): Tree =
32053219
if in.isIdent(nme.as) && qual.isInstanceOf[RefTree] then
32063220
qual match
@@ -3217,7 +3231,7 @@ object Parsers {
32173231
case GIVEN =>
32183232
mkTree(qual, givenSelector() :: Nil)
32193233
case LBRACE =>
3220-
mkTree(qual, inBraces(commaSeparated(importSelector(idOK = true))))
3234+
mkTree(qual, inBraces(importSelectors()))
32213235
case _ =>
32223236
if isIdent(nme.raw.STAR) then
32233237
mkTree(qual, wildcardSelector() :: Nil)

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,7 @@ object Scanners {
700700
case _ =>
701701
lookAhead()
702702
if isAfterLineEnd
703+
&& currentRegion.commasExpected
703704
&& (token == RPAREN || token == RBRACKET || token == RBRACE || token == OUTDENT)
704705
then
705706
() /* skip the trailing comma */

tests/neg/imports.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import scala.collection.{*, View} // error
2+
object test

0 commit comments

Comments
 (0)