Skip to content

Commit

Permalink
Make closing parens conditional stop tokens for skip
Browse files Browse the repository at this point in the history
Treat them as stop tokens only if there is a region that expects them
  • Loading branch information
odersky committed Mar 17, 2022
1 parent 279f27b commit a35236e
Show file tree
Hide file tree
Showing 4 changed files with 189 additions and 10 deletions.
15 changes: 8 additions & 7 deletions compiler/src/dotty/tools/dotc/parsing/Scanners.scala
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,8 @@ object Scanners {
def atStop =
token == EOF
|| (currentRegion eq lastRegion)
&& (skipStopTokens.contains(token)
&& (stopSkipTokens.contains(token)
|| closingParens.contains(token) && lastRegion.toList.exists(_.closedBy == token)
|| token == OUTDENT && indentWidth(offset) < lastKnownIndentWidth)
// stop at OUTDENT if the new indentwidth is smaller than the indent width of
// currentRegion. This corrects for the problem that sometimes we don't see an INDENT
Expand Down Expand Up @@ -1521,7 +1522,7 @@ object Scanners {
* InBraces a pair of braces { ... }
* Indented a pair of <indent> ... <outdent> tokens
*/
abstract class Region:
abstract class Region(val closedBy: Token):
/** The region enclosing this one, or `null` for the outermost region */
def outer: Region | Null

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

case class InString(multiLine: Boolean, outer: Region) extends Region
case class InParens(prefix: Token, outer: Region) extends Region
case class InBraces(outer: Region) extends Region
case class InCase(outer: Region) extends Region
case class InString(multiLine: Boolean, outer: Region) extends Region(RBRACE)
case class InParens(prefix: Token, outer: Region) extends Region(prefix + 1)
case class InBraces(outer: Region) extends Region(RBRACE)
case class InCase(outer: Region) extends Region(OUTDENT)

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

/** Other indendation widths > width of lines in the same region */
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/dotty/tools/dotc/parsing/Tokens.scala
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,8 @@ object Tokens extends TokensCommon {

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

final val skipStopTokens = BitSet(SEMI, COMMA, NEWLINE, NEWLINES, RBRACE, RPAREN, RBRACKET)
final val closingParens = BitSet(RPAREN, RBRACKET, RBRACE)
final val stopSkipTokens = BitSet(SEMI, COMMA, NEWLINE, NEWLINES)

final val softModifierNames = Set(nme.inline, nme.opaque, nme.open, nme.transparent, nme.infix)
}
144 changes: 144 additions & 0 deletions tests/neg/syntax-error-recovery.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
-- [E040] Syntax Error: tests/neg/syntax-error-recovery.scala:3:16 -----------------------------------------------------
3 | if (x < 0 then // error
| ^^^^
| ')' expected, but 'then' found
-- [E040] Syntax Error: tests/neg/syntax-error-recovery.scala:11:16 ----------------------------------------------------
11 | if (x < 0 then // error
| ^^^^
| ')' expected, but 'then' found
-- [E040] Syntax Error: tests/neg/syntax-error-recovery.scala:19:4 -----------------------------------------------------
19 | if x == 0 then println(bar) // error
| ^^
| ')' expected, but 'if' found
-- [E040] Syntax Error: tests/neg/syntax-error-recovery.scala:23:12 ----------------------------------------------------
23 | if x < 0) then // error
| ^
| 'then' expected, but ')' found
-- [E040] Syntax Error: tests/neg/syntax-error-recovery.scala:32:16 ----------------------------------------------------
32 | if (x < 0 then // error
| ^^^^
| ')' expected, but 'then' found
-- [E040] Syntax Error: tests/neg/syntax-error-recovery.scala:40:16 ----------------------------------------------------
40 | if (x < 0 then // error
| ^^^^
| ')' expected, but 'then' found
-- [E040] Syntax Error: tests/neg/syntax-error-recovery.scala:48:4 -----------------------------------------------------
48 | if x == 0 then println(bar) // error
| ^^
| ')' expected, but 'if' found
-- [E040] Syntax Error: tests/neg/syntax-error-recovery.scala:52:12 ----------------------------------------------------
52 | if x < 0) then // error
| ^
| 'then' expected, but ')' found
-- [E018] Syntax Error: tests/neg/syntax-error-recovery.scala:59:14 ----------------------------------------------------
59 | foo2(foo2(,) // error // error
| ^
| expression expected but ',' found
|
| longer explanation available when compiling with `-explain`
-- [E018] Syntax Error: tests/neg/syntax-error-recovery.scala:59:15 ----------------------------------------------------
59 | foo2(foo2(,) // error // error
| ^
| expression expected but ')' found
|
| longer explanation available when compiling with `-explain`
-- [E040] Syntax Error: tests/neg/syntax-error-recovery.scala:62:8 -----------------------------------------------------
62 |// error
| ^
| ')' expected, but eof found
-- [E006] Not Found Error: tests/neg/syntax-error-recovery.scala:8:10 --------------------------------------------------
8 | println(bar) // error
| ^^^
| Not found: bar
|
| longer explanation available when compiling with `-explain`
-- [E006] Not Found Error: tests/neg/syntax-error-recovery.scala:15:10 -------------------------------------------------
15 | println(baz) // error
| ^^^
| Not found: baz
|
| longer explanation available when compiling with `-explain`
-- [E006] Not Found Error: tests/neg/syntax-error-recovery.scala:20:10 -------------------------------------------------
20 | println(bar) // error
| ^^^
| Not found: bar
|
| longer explanation available when compiling with `-explain`
-- [E006] Not Found Error: tests/neg/syntax-error-recovery.scala:27:10 -------------------------------------------------
27 | println(bam) // error
| ^^^
| Not found: bam
|
| longer explanation available when compiling with `-explain`
-- [E006] Not Found Error: tests/neg/syntax-error-recovery.scala:37:10 -------------------------------------------------
37 | println(bar) // error
| ^^^
| Not found: bar
|
| longer explanation available when compiling with `-explain`
-- [E006] Not Found Error: tests/neg/syntax-error-recovery.scala:44:10 -------------------------------------------------
44 | println(baz) // error
| ^^^
| Not found: baz
|
| longer explanation available when compiling with `-explain`
-- [E006] Not Found Error: tests/neg/syntax-error-recovery.scala:49:10 -------------------------------------------------
49 | println(bar) // error
| ^^^
| Not found: bar
|
| longer explanation available when compiling with `-explain`
-- [E006] Not Found Error: tests/neg/syntax-error-recovery.scala:56:10 -------------------------------------------------
56 | println(bam) // error
| ^^^
| Not found: bam
|
| longer explanation available when compiling with `-explain`
-- [E006] Not Found Error: tests/neg/syntax-error-recovery.scala:61:10 -------------------------------------------------
61 | println(bam) // error
| ^^^
| Not found: bam
|
| longer explanation available when compiling with `-explain`
-- [E129] Potential Issue Warning: tests/neg/syntax-error-recovery.scala:7:2 -------------------------------------------
6 | 2
7 | }
| ^
| A pure expression does nothing in statement position; you may be omitting necessary parentheses
|
| longer explanation available when compiling with `-explain`
-- [E129] Potential Issue Warning: tests/neg/syntax-error-recovery.scala:15:2 ------------------------------------------
14 | 2
15 | println(baz) // error
| ^
| A pure expression does nothing in statement position; you may be omitting necessary parentheses
|
| longer explanation available when compiling with `-explain`
-- [E129] Potential Issue Warning: tests/neg/syntax-error-recovery.scala:27:2 ------------------------------------------
26 | 2
27 | println(bam) // error
| ^
| A pure expression does nothing in statement position; you may be omitting necessary parentheses
|
| longer explanation available when compiling with `-explain`
-- [E129] Potential Issue Warning: tests/neg/syntax-error-recovery.scala:36:2 ------------------------------------------
35 | 2
36 | }
| ^
| A pure expression does nothing in statement position; you may be omitting necessary parentheses
|
| longer explanation available when compiling with `-explain`
-- [E129] Potential Issue Warning: tests/neg/syntax-error-recovery.scala:44:2 ------------------------------------------
43 | 2
44 | println(baz) // error
| ^
| A pure expression does nothing in statement position; you may be omitting necessary parentheses
|
| longer explanation available when compiling with `-explain`
-- [E129] Potential Issue Warning: tests/neg/syntax-error-recovery.scala:56:2 ------------------------------------------
55 | 2
56 | println(bam) // error
| ^
| A pure expression does nothing in statement position; you may be omitting necessary parentheses
|
| longer explanation available when compiling with `-explain`
37 changes: 35 additions & 2 deletions tests/neg/syntax-error-recovery.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,39 @@ object Test {
1
else
2
println(bam)
println(bam) // error

}
}
object Test2:
def foo(x: Int) = {
if (x < 0 then // error
1
else
2
}
println(bar) // error

def foo2(x: Int) =
if (x < 0 then // error
1
else
2
println(baz) // error

def foo3(x: Int) =
foo2(x
if x == 0 then println(bar) // error
println(bar) // error

def foo4(x: Int) =
if x < 0) then // error
1
else
2
println(bam) // error

def foo5(x: Int) =
foo2(foo2(,) // error // error

println(bam) // error
// error

0 comments on commit a35236e

Please sign in to comment.