Skip to content

Commit 78da1ff

Browse files
committed
Move trailing comma handling to Parser
1 parent f76e5ed commit 78da1ff

9 files changed

+159
-26
lines changed

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

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -567,9 +567,17 @@ object Parsers {
567567
in.currentRegion.withCommasExpected {
568568
val ts = new ListBuffer[T]
569569
if (readFirst) ts += part()
570-
while in.token == COMMA do
570+
var done = false
571+
while in.token == COMMA && !done do
571572
in.nextToken()
572-
ts += part()
573+
if in.token == RPAREN || in.token == RBRACKET || in.token == RBRACE || in.token == OUTDENT then
574+
if in.isAfterLineEnd then
575+
// skip the trailing comma
576+
done = true
577+
else
578+
syntaxError("trailing comma must be followed by newline")
579+
else
580+
ts += part()
573581
ts.toList
574582
}
575583

@@ -3271,7 +3279,7 @@ object Parsers {
32713279
*/
32723280
def patDefOrDcl(start: Offset, mods: Modifiers): Tree = atSpan(start, nameStart) {
32733281
val first = pattern2()
3274-
var lhs = first match {
3282+
val lhs = first match {
32753283
case id: Ident if in.token == COMMA =>
32763284
in.nextToken()
32773285
id :: commaSeparated(() => termIdent())

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

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -698,13 +698,6 @@ object Scanners {
698698
case r: Indented if isEnclosedInParens(r.outer) =>
699699
insert(OUTDENT, offset)
700700
case _ =>
701-
lookAhead()
702-
if isAfterLineEnd
703-
&& (token == RPAREN || token == RBRACKET || token == RBRACE || token == OUTDENT)
704-
then
705-
() /* skip the trailing comma */
706-
else
707-
reset()
708701
case END =>
709702
if !isEndMarker then token = IDENTIFIER
710703
case COLON =>

tests/neg/syntax-error-recovery.check

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,10 @@
3636
| expression expected but ',' found
3737
|
3838
| longer explanation available when compiling with `-explain`
39-
-- [E018] Syntax Error: tests/neg/syntax-error-recovery.scala:59:15 ----------------------------------------------------
39+
-- Error: tests/neg/syntax-error-recovery.scala:59:15 ------------------------------------------------------------------
4040
59 | foo2(foo2(,) // error // error
4141
| ^
42-
| expression expected but ')' found
43-
|
44-
| longer explanation available when compiling with `-explain`
42+
| trailing comma must be followed by newline
4543
-- [E040] Syntax Error: tests/neg/syntax-error-recovery.scala:62:8 -----------------------------------------------------
4644
62 |// error
4745
| ^

tests/neg/t11900.check

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
-- Error: tests/neg/t11900.scala:44:16 ---------------------------------------------------------------------------------
2+
44 | a => a + 1, // error: weird comma
3+
| ^
4+
| end of statement expected but ',' found
5+
-- Error: tests/neg/t11900.scala:48:16 ---------------------------------------------------------------------------------
6+
48 | println("a"), // error: weird comma
7+
| ^
8+
| end of statement expected but ',' found
9+
-- Error: tests/neg/t11900.scala:52:16 ---------------------------------------------------------------------------------
10+
52 | println("b"), // error: weird comma
11+
| ^
12+
| end of statement expected but ',' found
13+
-- [E032] Syntax Error: tests/neg/t11900.scala:64:8 --------------------------------------------------------------------
14+
64 | _*, // error
15+
| ^
16+
| pattern expected
17+
|
18+
| longer explanation available when compiling with `-explain`

tests/neg/t11900.scala

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
2+
trait t11900 {
3+
// cf pos/trailing-commas
4+
//
5+
import scala.collection.{
6+
immutable,
7+
mutable,
8+
}
9+
10+
def h[A,
11+
]: List[A] = Nil
12+
13+
def u(
14+
x: Int,
15+
y: Int,
16+
)(using List[Int],
17+
Set[Int],
18+
)(using l: List[Int],
19+
s : Set[Int],
20+
): Int = 1
21+
22+
def g = List(
23+
1,
24+
2,
25+
3,
26+
)
27+
28+
def star =
29+
List(1, 2, 3, 4, 5) match {
30+
case List(
31+
1,
32+
2,
33+
3,
34+
) => false
35+
case List(
36+
1,
37+
2,
38+
_*,
39+
) => true
40+
}
41+
42+
def f =
43+
List(1, 2, 3).map {
44+
a => a + 1, // error: weird comma
45+
}
46+
47+
class A() {
48+
println("a"), // error: weird comma
49+
}
50+
51+
def b() = {
52+
println("b"), // error: weird comma
53+
}
54+
55+
def starcrossed =
56+
List(1, 2, 3, 4, 5) match {
57+
case List(
58+
1,
59+
2,
60+
3,
61+
) => false
62+
case List(
63+
1,
64+
_*, // error
65+
2,
66+
) => true
67+
}
68+
69+
def p(p: (Int,
70+
String,
71+
)
72+
): Unit
73+
74+
def q: (Int,
75+
String,
76+
)
77+
78+
val z = 42
79+
}

tests/neg/t5702-neg-bad-and-wild.check

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
1-
-- [E032] Syntax Error: tests/neg/t5702-neg-bad-and-wild.scala:10:22 ---------------------------------------------------
1+
-- Error: tests/neg/t5702-neg-bad-and-wild.scala:10:22 -----------------------------------------------------------------
22
10 | case List(1, _*,) => // error: pattern expected
33
| ^
4-
| pattern expected
5-
|
6-
| longer explanation available when compiling with `-explain`
7-
-- [E032] Syntax Error: tests/neg/t5702-neg-bad-and-wild.scala:12:23 ---------------------------------------------------
4+
| trailing comma must be followed by newline
5+
-- Error: tests/neg/t5702-neg-bad-and-wild.scala:12:23 -----------------------------------------------------------------
86
12 | case List(1, _*3,) => // error: pattern expected // error
97
| ^
10-
| pattern expected
11-
|
12-
| longer explanation available when compiling with `-explain`
8+
| trailing comma must be followed by newline
139
-- [E040] Syntax Error: tests/neg/t5702-neg-bad-and-wild.scala:13:23 ---------------------------------------------------
1410
13 | case List(1, _*3:) => // error // error
1511
| ^

tests/neg/trailing-comma-pattern2.check

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
-- [E032] Syntax Error: tests/neg/trailing-comma-pattern2.scala:2:21 ---------------------------------------------------
1+
-- Error: tests/neg/trailing-comma-pattern2.scala:2:21 -----------------------------------------------------------------
22
2 | val List(x, y, _*, ) // error
33
| ^
4-
| pattern expected
5-
|
6-
| longer explanation available when compiling with `-explain`
4+
| trailing comma must be followed by newline
75
-- [E040] Syntax Error: tests/neg/trailing-comma-pattern2.scala:3:8 ----------------------------------------------------
86
3 |// error
97
| ^

tests/neg/trailingCommas.scala

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,27 @@ object `package` {
5656
case class Foo(foo: Any)
5757
case class Bar(foo: Any)
5858
}
59+
60+
// Unparenthesized lists
61+
trait Deriv1[T]
62+
object Deriv1 {
63+
def derived[T]: Deriv1[T] = new Deriv1[T] {}
64+
}
65+
66+
trait Deriv2[T]
67+
object Deriv2 {
68+
def derived[T]: Deriv2[T] = new Deriv2[T] {}
69+
}
70+
71+
class Derives1 derives Deriv1, Deriv2,
72+
object End // error: an identifier expected, but 'object' found
73+
74+
class Derives2 derives Deriv1,
75+
Deriv2,
76+
object End2 // error: an identifier expected, but 'object' found
77+
78+
val a,
79+
b,
80+
c,
81+
= (1, 2, 3) // error
82+
val x, y, z, = (1, 2, 3) // error

tests/pos/comma-separated.scala

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
trait Bar[T]
2+
object Bar {
3+
def derived[T]: Bar[T] = new Bar[T] {}
4+
}
5+
6+
trait Baz[T]
7+
object Baz {
8+
def derived[T]: Baz[T] = new Baz[T] {}
9+
}
10+
11+
class Foo derives Bar, Baz
12+
13+
class Foo2 derives Bar,
14+
Baz
15+
16+
val x, y, z = (1, 2, 3)
17+
val a,
18+
b,
19+
c = (1, 2, 3)

0 commit comments

Comments
 (0)