Skip to content

Commit a35236e

Browse files
committed
Make closing parens conditional stop tokens for skip
Treat them as stop tokens only if there is a region that expects them
1 parent 279f27b commit a35236e

File tree

4 files changed

+189
-10
lines changed

4 files changed

+189
-10
lines changed

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

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,8 @@ object Scanners {
291291
def atStop =
292292
token == EOF
293293
|| (currentRegion eq lastRegion)
294-
&& (skipStopTokens.contains(token)
294+
&& (stopSkipTokens.contains(token)
295+
|| closingParens.contains(token) && lastRegion.toList.exists(_.closedBy == token)
295296
|| token == OUTDENT && indentWidth(offset) < lastKnownIndentWidth)
296297
// stop at OUTDENT if the new indentwidth is smaller than the indent width of
297298
// currentRegion. This corrects for the problem that sometimes we don't see an INDENT
@@ -1521,7 +1522,7 @@ object Scanners {
15211522
* InBraces a pair of braces { ... }
15221523
* Indented a pair of <indent> ... <outdent> tokens
15231524
*/
1524-
abstract class Region:
1525+
abstract class Region(val closedBy: Token):
15251526
/** The region enclosing this one, or `null` for the outermost region */
15261527
def outer: Region | Null
15271528

@@ -1585,16 +1586,16 @@ object Scanners {
15851586
toList.map(r => s"(${r.indentWidth}, ${r.delimiter})").mkString(" in ")
15861587
end Region
15871588

1588-
case class InString(multiLine: Boolean, outer: Region) extends Region
1589-
case class InParens(prefix: Token, outer: Region) extends Region
1590-
case class InBraces(outer: Region) extends Region
1591-
case class InCase(outer: Region) extends Region
1589+
case class InString(multiLine: Boolean, outer: Region) extends Region(RBRACE)
1590+
case class InParens(prefix: Token, outer: Region) extends Region(prefix + 1)
1591+
case class InBraces(outer: Region) extends Region(RBRACE)
1592+
case class InCase(outer: Region) extends Region(OUTDENT)
15921593

15931594
/** A class describing an indentation region.
15941595
* @param width The principal indendation width
15951596
* @param prefix The token before the initial <indent> of the region
15961597
*/
1597-
case class Indented(width: IndentWidth, prefix: Token, outer: Region | Null) extends Region:
1598+
case class Indented(width: IndentWidth, prefix: Token, outer: Region | Null) extends Region(OUTDENT):
15981599
knownWidth = width
15991600

16001601
/** Other indendation widths > width of lines in the same region */

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,8 @@ object Tokens extends TokensCommon {
287287

288288
final val endMarkerTokens = identifierTokens | BitSet(IF, WHILE, FOR, MATCH, TRY, NEW, THROW, GIVEN, VAL, THIS)
289289

290-
final val skipStopTokens = BitSet(SEMI, COMMA, NEWLINE, NEWLINES, RBRACE, RPAREN, RBRACKET)
290+
final val closingParens = BitSet(RPAREN, RBRACKET, RBRACE)
291+
final val stopSkipTokens = BitSet(SEMI, COMMA, NEWLINE, NEWLINES)
291292

292293
final val softModifierNames = Set(nme.inline, nme.opaque, nme.open, nme.transparent, nme.infix)
293294
}

tests/neg/syntax-error-recovery.check

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
-- [E040] Syntax Error: tests/neg/syntax-error-recovery.scala:3:16 -----------------------------------------------------
2+
3 | if (x < 0 then // error
3+
| ^^^^
4+
| ')' expected, but 'then' found
5+
-- [E040] Syntax Error: tests/neg/syntax-error-recovery.scala:11:16 ----------------------------------------------------
6+
11 | if (x < 0 then // error
7+
| ^^^^
8+
| ')' expected, but 'then' found
9+
-- [E040] Syntax Error: tests/neg/syntax-error-recovery.scala:19:4 -----------------------------------------------------
10+
19 | if x == 0 then println(bar) // error
11+
| ^^
12+
| ')' expected, but 'if' found
13+
-- [E040] Syntax Error: tests/neg/syntax-error-recovery.scala:23:12 ----------------------------------------------------
14+
23 | if x < 0) then // error
15+
| ^
16+
| 'then' expected, but ')' found
17+
-- [E040] Syntax Error: tests/neg/syntax-error-recovery.scala:32:16 ----------------------------------------------------
18+
32 | if (x < 0 then // error
19+
| ^^^^
20+
| ')' expected, but 'then' found
21+
-- [E040] Syntax Error: tests/neg/syntax-error-recovery.scala:40:16 ----------------------------------------------------
22+
40 | if (x < 0 then // error
23+
| ^^^^
24+
| ')' expected, but 'then' found
25+
-- [E040] Syntax Error: tests/neg/syntax-error-recovery.scala:48:4 -----------------------------------------------------
26+
48 | if x == 0 then println(bar) // error
27+
| ^^
28+
| ')' expected, but 'if' found
29+
-- [E040] Syntax Error: tests/neg/syntax-error-recovery.scala:52:12 ----------------------------------------------------
30+
52 | if x < 0) then // error
31+
| ^
32+
| 'then' expected, but ')' found
33+
-- [E018] Syntax Error: tests/neg/syntax-error-recovery.scala:59:14 ----------------------------------------------------
34+
59 | foo2(foo2(,) // error // error
35+
| ^
36+
| expression expected but ',' found
37+
|
38+
| longer explanation available when compiling with `-explain`
39+
-- [E018] Syntax Error: tests/neg/syntax-error-recovery.scala:59:15 ----------------------------------------------------
40+
59 | foo2(foo2(,) // error // error
41+
| ^
42+
| expression expected but ')' found
43+
|
44+
| longer explanation available when compiling with `-explain`
45+
-- [E040] Syntax Error: tests/neg/syntax-error-recovery.scala:62:8 -----------------------------------------------------
46+
62 |// error
47+
| ^
48+
| ')' expected, but eof found
49+
-- [E006] Not Found Error: tests/neg/syntax-error-recovery.scala:8:10 --------------------------------------------------
50+
8 | println(bar) // error
51+
| ^^^
52+
| Not found: bar
53+
|
54+
| longer explanation available when compiling with `-explain`
55+
-- [E006] Not Found Error: tests/neg/syntax-error-recovery.scala:15:10 -------------------------------------------------
56+
15 | println(baz) // error
57+
| ^^^
58+
| Not found: baz
59+
|
60+
| longer explanation available when compiling with `-explain`
61+
-- [E006] Not Found Error: tests/neg/syntax-error-recovery.scala:20:10 -------------------------------------------------
62+
20 | println(bar) // error
63+
| ^^^
64+
| Not found: bar
65+
|
66+
| longer explanation available when compiling with `-explain`
67+
-- [E006] Not Found Error: tests/neg/syntax-error-recovery.scala:27:10 -------------------------------------------------
68+
27 | println(bam) // error
69+
| ^^^
70+
| Not found: bam
71+
|
72+
| longer explanation available when compiling with `-explain`
73+
-- [E006] Not Found Error: tests/neg/syntax-error-recovery.scala:37:10 -------------------------------------------------
74+
37 | println(bar) // error
75+
| ^^^
76+
| Not found: bar
77+
|
78+
| longer explanation available when compiling with `-explain`
79+
-- [E006] Not Found Error: tests/neg/syntax-error-recovery.scala:44:10 -------------------------------------------------
80+
44 | println(baz) // error
81+
| ^^^
82+
| Not found: baz
83+
|
84+
| longer explanation available when compiling with `-explain`
85+
-- [E006] Not Found Error: tests/neg/syntax-error-recovery.scala:49:10 -------------------------------------------------
86+
49 | println(bar) // error
87+
| ^^^
88+
| Not found: bar
89+
|
90+
| longer explanation available when compiling with `-explain`
91+
-- [E006] Not Found Error: tests/neg/syntax-error-recovery.scala:56:10 -------------------------------------------------
92+
56 | println(bam) // error
93+
| ^^^
94+
| Not found: bam
95+
|
96+
| longer explanation available when compiling with `-explain`
97+
-- [E006] Not Found Error: tests/neg/syntax-error-recovery.scala:61:10 -------------------------------------------------
98+
61 | println(bam) // error
99+
| ^^^
100+
| Not found: bam
101+
|
102+
| longer explanation available when compiling with `-explain`
103+
-- [E129] Potential Issue Warning: tests/neg/syntax-error-recovery.scala:7:2 -------------------------------------------
104+
6 | 2
105+
7 | }
106+
| ^
107+
| A pure expression does nothing in statement position; you may be omitting necessary parentheses
108+
|
109+
| longer explanation available when compiling with `-explain`
110+
-- [E129] Potential Issue Warning: tests/neg/syntax-error-recovery.scala:15:2 ------------------------------------------
111+
14 | 2
112+
15 | println(baz) // error
113+
| ^
114+
| A pure expression does nothing in statement position; you may be omitting necessary parentheses
115+
|
116+
| longer explanation available when compiling with `-explain`
117+
-- [E129] Potential Issue Warning: tests/neg/syntax-error-recovery.scala:27:2 ------------------------------------------
118+
26 | 2
119+
27 | println(bam) // error
120+
| ^
121+
| A pure expression does nothing in statement position; you may be omitting necessary parentheses
122+
|
123+
| longer explanation available when compiling with `-explain`
124+
-- [E129] Potential Issue Warning: tests/neg/syntax-error-recovery.scala:36:2 ------------------------------------------
125+
35 | 2
126+
36 | }
127+
| ^
128+
| A pure expression does nothing in statement position; you may be omitting necessary parentheses
129+
|
130+
| longer explanation available when compiling with `-explain`
131+
-- [E129] Potential Issue Warning: tests/neg/syntax-error-recovery.scala:44:2 ------------------------------------------
132+
43 | 2
133+
44 | println(baz) // error
134+
| ^
135+
| A pure expression does nothing in statement position; you may be omitting necessary parentheses
136+
|
137+
| longer explanation available when compiling with `-explain`
138+
-- [E129] Potential Issue Warning: tests/neg/syntax-error-recovery.scala:56:2 ------------------------------------------
139+
55 | 2
140+
56 | println(bam) // error
141+
| ^
142+
| A pure expression does nothing in statement position; you may be omitting necessary parentheses
143+
|
144+
| longer explanation available when compiling with `-explain`

tests/neg/syntax-error-recovery.scala

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,39 @@ object Test {
2424
1
2525
else
2626
2
27-
println(bam)
27+
println(bam) // error
2828

29-
}
29+
}
30+
object Test2:
31+
def foo(x: Int) = {
32+
if (x < 0 then // error
33+
1
34+
else
35+
2
36+
}
37+
println(bar) // error
38+
39+
def foo2(x: Int) =
40+
if (x < 0 then // error
41+
1
42+
else
43+
2
44+
println(baz) // error
45+
46+
def foo3(x: Int) =
47+
foo2(x
48+
if x == 0 then println(bar) // error
49+
println(bar) // error
50+
51+
def foo4(x: Int) =
52+
if x < 0) then // error
53+
1
54+
else
55+
2
56+
println(bam) // error
57+
58+
def foo5(x: Int) =
59+
foo2(foo2(,) // error // error
60+
61+
println(bam) // error
62+
// error

0 commit comments

Comments
 (0)