Skip to content

Commit 3a39bdd

Browse files
committed
Implement indent rule for match
Cases of a match do not have to be indented relative to the match
1 parent 0bc08d1 commit 3a39bdd

File tree

3 files changed

+23
-10
lines changed

3 files changed

+23
-10
lines changed

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

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ object Scanners {
307307
var sepRegions: List[Token] = Nil
308308

309309
/** Indentation widths, innermost to outermost */
310-
var indent: IndentRegion = IndentRegion(IndentWidth.Zero, Set(), null)
310+
var indent: IndentRegion = IndentRegion(IndentWidth.Zero, Set(), EMPTY, null)
311311

312312
// Scala 2 compatibility
313313

@@ -538,13 +538,15 @@ object Scanners {
538538
!isLeadingInfixOperator())
539539
insert(if (pastBlankLine) NEWLINES else NEWLINE, lineOffset)
540540
else if (indentIsSignificant) {
541-
if (lastWidth < curWidth) {
541+
if (lastWidth < curWidth ||
542+
lastWidth == curWidth && (lastToken == MATCH || lastToken == CATCH) && token == CASE) {
542543
if (canStartIndentTokens.contains(lastToken)) {
543-
indent = IndentRegion(curWidth, Set(), indent)
544+
indent = IndentRegion(curWidth, Set(), lastToken, indent)
544545
insert(INDENT, offset)
545546
}
546547
}
547-
else if (curWidth < lastWidth) {
548+
else if (curWidth < lastWidth ||
549+
curWidth == lastWidth && (indent.token == MATCH || indent.token == CATCH) && token != CASE) {
548550
if (!isLeadingInfixOperator()) {
549551
indent = indent.enclosing
550552
insert(OUTDENT, offset)
@@ -564,7 +566,7 @@ object Scanners {
564566
|This falls between previous widths: ${indent.width} and $lastWidth
565567
|Sepregions = $sepRegions / ${getClass}""")
566568
else
567-
indent = IndentRegion(indent.width, indent.others + curWidth, indent.outer)
569+
indent = IndentRegion(indent.width, indent.others + curWidth, indent.token, indent.outer)
568570
}
569571
}
570572

@@ -1291,7 +1293,7 @@ object Scanners {
12911293
* @param width The principal indendation width
12921294
* @param others Other indendation widths > width of lines in the same region
12931295
*/
1294-
class IndentRegion(val width: IndentWidth, val others: Set[IndentWidth], val outer: IndentRegion | Null) {
1296+
class IndentRegion(val width: IndentWidth, val others: Set[IndentWidth], val token: Token, val outer: IndentRegion | Null) {
12951297
def enclosing: IndentRegion = outer.asInstanceOf[IndentRegion]
12961298
def isOutermost = outer == null
12971299
}

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,15 +71,15 @@ The Scala grammar is changed so that colons at end of lines are accepted at all
7171
where an opening brace is legal, except if the previous token can already start an
7272
indentation region.
7373

74-
### Special Treatment of Match
74+
### Special Treatment of Case Clauses
7575

76-
The indentation rules for a `match` expression are modified as follows:
76+
The indentation rules for `match` expressions and `catch` clauses are refined as follows:
7777

78-
- An indentation region is opened after a `match` also if the following `case`
78+
- An indentation region is opened after a `match` or `catch` also if the following `case`
7979
appears at the indentation width that's current for the `match` itself.
8080
- In that case, the indentation region closes at the first token at that
8181
same indentation width that is not a `case`, or at any token with a smaller
82-
indentation width, whichever comes first.
82+
indentation width, whichever comes first.
8383

8484
The rules allow to write `match` expressions where cases are not indented themselves, as in the example below:
8585
```scala

tests/pos/indent.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,17 @@ class Coder(words: List[String]):
7070
case (digit, str) => true
7171
case _ => false
7272

73+
('1', "1") match
74+
case (digit, str) => true
75+
case _ => false
76+
77+
try List(1, 2, 3) match
78+
case x :: xs => println(x)
79+
case Nil => println("Nil")
80+
catch
81+
case ex: java.io.IOException => println(ex)
82+
case ex: Throwable => throw ex
83+
7384
/** Invert the mnemonics map to give a map from chars 'A' ... 'Z' to '2' ... '9' */
7485
private val charCode0: Map[Char, Char] =
7586
mnemonics

0 commit comments

Comments
 (0)