Skip to content

Commit

Permalink
Restrict outdent in parens for certain region prefixes
Browse files Browse the repository at this point in the history
  • Loading branch information
som-snytt committed Feb 6, 2025
1 parent 4cb43b6 commit 1770f94
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 1 deletion.
9 changes: 8 additions & 1 deletion compiler/src/dotty/tools/dotc/parsing/Scanners.scala
Original file line number Diff line number Diff line change
Expand Up @@ -735,7 +735,14 @@ object Scanners {
case _ => false
currentRegion match
case r: Indented if isEnclosedInParens(r.outer) =>
insert(OUTDENT, offset)
// For some region prefixes (COLONeol, EQUALS) only OUTDENT if COMMA at EOL
if canStartIndentTokens.contains(r.prefix) && !statCtdTokens.contains(r.prefix) then
val lookahead = LookaheadScanner()
lookahead.nextToken()
if lookahead.isAfterLineEnd then
insert(OUTDENT, offset)
else
insert(OUTDENT, offset)
case _ =>
peekAhead()
if isAfterLineEnd
Expand Down
24 changes: 24 additions & 0 deletions tests/neg/i22527.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@

//rule of thumb is COLONeol was at EOL, so COMMA must be at EOL
def test: Unit =
assert(
identity:
true, "ok" // error end of statement expected but ',' found
)

def toss: Unit =
assert(
throw
null, "ok" // error same
)

def callme[A](x: => A, msg: String) = try x.toString catch case t: RuntimeException => msg

// not all indented regions require COMMA at EOL for OUTDENT
def orElse(x: Int): Unit =
callme(
if x > 0 then
class X extends AnyRef, Serializable // error Not found: Serializable - did you mean Specializable?
true // error ',' or ')' expected, but 'true' found
else
false, "fail")
65 changes: 65 additions & 0 deletions tests/pos/i22527.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@

def f: Unit =
identity(
identity:
class X extends AnyRef, Serializable
42
)

def g: Unit =
identity(
x =
class X extends AnyRef, Serializable
27
)

def test: Unit =
assert(
identity:
true,
"ok"
)

def toss: Unit =
assert(
throw
null,
"ok"
)

def callme[A](x: => A, msg: String) = try x.toString catch case t: RuntimeException => msg

def orElse(x: Int): Unit =
callme(
if x > 0 then
true
else
false, "fail")

def onlyIf(x: Int): Unit =
callme(
if (x > 0)
true, "fail") // warn value discard

def h(xs: List[Int]) =
xs.foldLeft(0)
(
(acc, x) =>
acc
+ x,
)

def sum(x: Int, y: Int, z: Int) = x+y+z

def k(xs: List[Int], y: Int, z: Int) =
xs.foldLeft(0)
(
(acc, x) =>
sum(
x
+ y
+ z,
y,
z,
)
)

0 comments on commit 1770f94

Please sign in to comment.