Skip to content

Commit d06a5ff

Browse files
authored
Merge pull request #7429 from dotty-staging/fix-#7421
Fix #7421: Insert missing <outdent> tokens where a region ends
2 parents 9193c44 + 5fcb578 commit d06a5ff

File tree

6 files changed

+29
-6
lines changed

6 files changed

+29
-6
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,7 @@ object Parsers {
348348
if in.isNewLine then in.nextToken() else accept(SEMI)
349349

350350
def acceptStatSepUnlessAtEnd(altEnd: Token = EOF): Unit =
351+
in.observeOutdented()
351352
if (!isStatSeqEnd)
352353
in.token match {
353354
case EOF =>

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,13 @@ object Scanners {
555555
token = INDENT
556556
end observeIndented
557557

558+
/** Insert an <outdent> token if next token closes an indentation region */
559+
def observeOutdented(): Unit = currentRegion match
560+
case r: Indented if !r.isOutermost && closingRegionTokens.contains(token) =>
561+
currentRegion = r.enclosing
562+
insert(OUTDENT, offset)
563+
case _ =>
564+
558565
/** - Join CASE + CLASS => CASECLASS, CASE + OBJECT => CASEOBJECT, SEMI + ELSE => ELSE, COLON + <EOL> => COLONEOL
559566
* - Insert missing OUTDENTs at EOF
560567
*/

docs/docs/reference/other-new-features/indentation-new.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ There are two rules:
7777
If the indentation width of the token on the next line is still less than the new current indentation width, step (2) repeats. Therefore, several `<outdent>` tokens
7878
may be inserted in a row.
7979

80+
An `<outdent>` is also inserted if the next statement following a statement sequence starting with an `<indent>` closes an indentation region, i.e. is one of `then`, `else`, `do`, `catch`, `finally`, `yield`, `}` or `case`.
81+
8082
It is an error if the indentation width of the token following an `<outdent>` does not
8183
match the indentation of some previous line in the enclosing indentation region. For instance, the following would be rejected.
8284
```scala

tests/neg/spaces-vs-tabs.check

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,11 @@
1717
| Previous indent : 2 tabs
1818
| Latest indent : 1 tab, 2 spaces
1919
-- Error: tests/neg/spaces-vs-tabs.scala:8:1 ---------------------------------------------------------------------------
20-
8 | else () // error // error
20+
8 | else () // error
2121
| ^
2222
| Incompatible combinations of tabs and spaces in indentation prefixes.
2323
| Previous indent : 2 tabs
2424
| Latest indent : 1 space
25-
-- [E040] Syntax Error: tests/neg/spaces-vs-tabs.scala:8:6 -------------------------------------------------------------
26-
8 | else () // error // error
27-
| ^
28-
| ';' expected, but '(' found
2925
-- Error: tests/neg/spaces-vs-tabs.scala:14:2 --------------------------------------------------------------------------
3026
14 | else 2 // error // error
3127
| ^

tests/neg/spaces-vs-tabs.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ object Test
55
println(2) // error
66
println(3) // error
77
println(4) // error
8-
else () // error // error
8+
else () // error
99

1010
object Test2
1111

tests/pos/i7421.scala

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
object Main {
2+
3+
def main(args: Array[String]): Unit = {
4+
if (args.length > 0) then
5+
{
6+
println(args)
7+
} else {
8+
println("Hello world!")
9+
}
10+
if (args.length > 0)
11+
{
12+
println(args)
13+
} else {
14+
println("Hello world!")
15+
}
16+
}
17+
}

0 commit comments

Comments
 (0)