Skip to content

Commit 37d1da8

Browse files
committed
Fix indent insertion at arrow eol
1 parent b937e35 commit 37d1da8

File tree

5 files changed

+40
-37
lines changed

5 files changed

+40
-37
lines changed

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

+3-6
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import config.Feature.{sourceVersion, migrateTo3}
3434
import config.SourceVersion.*
3535
import config.SourceVersion
3636
import dotty.tools.dotc.config.MigrationVersion
37+
import dotty.tools.dotc.util.chaining.*
3738

3839
object Parsers {
3940

@@ -1087,11 +1088,11 @@ object Parsers {
10871088
*/
10881089
def followingIsLambdaAfterColon(): Boolean =
10891090
val lookahead = in.LookaheadScanner(allowIndent = true)
1091+
.tap(_.currentRegion.knownWidth = in.currentRegion.indentWidth)
10901092
def isArrowIndent() =
10911093
lookahead.isArrow
10921094
&& {
1093-
lookahead.observeArrowEOL()
1094-
lookahead.nextToken()
1095+
lookahead.observeArrowIndented()
10951096
lookahead.token == INDENT || lookahead.token == EOF
10961097
}
10971098
lookahead.nextToken()
@@ -2655,14 +2656,10 @@ object Parsers {
26552656

26562657
def closureRest(start: Int, location: Location, params: List[Tree]): Tree =
26572658
atSpan(start, in.offset) {
2658-
if location == Location.InColonArg then
2659-
in.observeArrowEOL()
26602659
if in.token == CTXARROW then
26612660
if params.isEmpty then
26622661
syntaxError(em"context function literals require at least one formal parameter", Span(start, in.lastOffset))
26632662
in.nextToken()
2664-
else if in.token == ARROWeol then
2665-
in.nextToken()
26662663
else
26672664
accept(ARROW)
26682665
val body =

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

+13-15
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ object Scanners {
9292
|| token == IDENTIFIER && isOperatorPart(name(name.length - 1))
9393

9494
def isArrow =
95-
token == ARROW || token == CTXARROW || token == ARROWeol
95+
token == ARROW || token == CTXARROW
9696
}
9797

9898
abstract class ScannerCommon(source: SourceFile)(using Context) extends CharArrayReader with TokenData {
@@ -612,11 +612,7 @@ object Scanners {
612612
insert(if (pastBlankLine) NEWLINES else NEWLINE, lineOffset)
613613
else if indentIsSignificant then
614614
if nextWidth < lastWidth
615-
|| nextWidth == lastWidth
616-
&& indentPrefix.match
617-
case MATCH | CATCH => token != CASE
618-
case _ => false
619-
then
615+
|| nextWidth == lastWidth && (indentPrefix == MATCH || indentPrefix == CATCH) && token != CASE then
620616
if currentRegion.isOutermost then
621617
if nextWidth < lastWidth then currentRegion = topLevelRegion(nextWidth)
622618
else if !isLeadingInfixOperator(nextWidth) && !statCtdTokens.contains(lastToken) && lastToken != INDENT then
@@ -643,12 +639,7 @@ object Scanners {
643639
else if r.isInstanceOf[InBraces] && !closingRegionTokens.contains(token) then
644640
report.warning("Line is indented too far to the left, or a `}` is missing", sourcePos())
645641
else if lastWidth < nextWidth
646-
|| lastWidth == nextWidth
647-
&& lastToken.match
648-
case MATCH | CATCH => token == CASE
649-
case ARROWeol => true
650-
case _ => false
651-
then
642+
|| lastWidth == nextWidth && (lastToken == MATCH || lastToken == CATCH) && token == CASE then
652643
if canStartIndentTokens.contains(lastToken) then
653644
currentRegion = Indented(nextWidth, lastToken, currentRegion)
654645
insert(INDENT, offset)
@@ -680,12 +671,19 @@ object Scanners {
680671
reset()
681672
if atEOL then token = COLONeol
682673

683-
def observeArrowEOL(): Unit =
684-
if indentSyntax && token == ARROW then
674+
// consume => and insert <indent> if applicable
675+
def observeArrowIndented(): Unit =
676+
if isArrow && indentSyntax then
685677
peekAhead()
686678
val atEOL = isAfterLineEnd || token == EOF
687679
reset()
688-
if atEOL then token = ARROWeol
680+
if atEOL then
681+
val nextWidth = indentWidth(next.offset)
682+
val lastWidth = currentRegion.indentWidth
683+
if lastWidth < nextWidth then
684+
currentRegion = Indented(nextWidth, COLONeol, currentRegion)
685+
offset = next.offset
686+
token = INDENT
689687

690688
def observeIndented(): Unit =
691689
if indentSyntax && isNewLine then

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

+2-3
Original file line numberDiff line numberDiff line change
@@ -202,10 +202,9 @@ object Tokens extends TokensCommon {
202202
inline val COLONeol = 89; enter(COLONeol, ":", ": at eol")
203203
// A `:` recognized as starting an indentation block
204204
inline val SELFARROW = 90; enter(SELFARROW, "=>") // reclassified ARROW following self-type
205-
inline val ARROWeol = 99; enter(ARROWeol, "=>", "=> at eol") // lambda ARROW at eol followed by indent
206205

207206
/** XML mode */
208-
inline val XMLSTART = 100; enter(XMLSTART, "$XMLSTART$<") // TODO: deprecate
207+
inline val XMLSTART = 99; enter(XMLSTART, "$XMLSTART$<") // TODO: deprecate
209208

210209
final val alphaKeywords: TokenSet = tokenRange(IF, END)
211210
final val symbolicKeywords: TokenSet = tokenRange(USCORE, CTXARROW)
@@ -283,7 +282,7 @@ object Tokens extends TokensCommon {
283282
final val closingRegionTokens = BitSet(RBRACE, RPAREN, RBRACKET, CASE) | statCtdTokens
284283

285284
final val canStartIndentTokens: BitSet =
286-
statCtdTokens | BitSet(COLONeol, WITH, EQUALS, ARROWeol, ARROW, CTXARROW, LARROW, WHILE, TRY, FOR, IF, THROW, RETURN)
285+
statCtdTokens | BitSet(COLONeol, WITH, EQUALS, ARROW, CTXARROW, LARROW, WHILE, TRY, FOR, IF, THROW, RETURN)
287286

288287
/** Faced with the choice between a type and a formal parameter, the following
289288
* tokens determine it's a formal parameter.

tests/neg/i22193.scala

+1-13
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ def fn3(arg: String, arg2: String)(f: => Unit): Unit = f
55

66
def test1() =
77

8+
// ok baseline
89
fn2(arg = "blue sleeps faster than tuesday", arg2 = "the quick brown fox jumped over the lazy dog"): env =>
910
val x = env
1011
println(x)
@@ -15,12 +16,6 @@ def test1() =
1516
val x = env // error
1617
println(x)
1718

18-
fn2( // error
19-
arg = "blue sleeps faster than tuesday",
20-
arg2 = "the quick brown fox jumped over the lazy dog"): env =>
21-
val x = env // error
22-
println(x)
23-
2419
fn2(
2520
arg = "blue sleeps faster than tuesday",
2621
arg2 = "the quick brown fox jumped over the lazy dog"):
@@ -30,13 +25,6 @@ def test1() =
3025

3126
def test2() =
3227

33-
fn2(
34-
arg = "blue sleeps faster than tuesday",
35-
arg2 = "the quick brown fox jumped over the lazy dog"
36-
): env =>
37-
val x = env
38-
println(x)
39-
4028
fn3( // error missing argument list for value of type (=> Unit) => Unit
4129
arg = "blue sleeps faster than tuesday",
4230
arg2 = "the quick brown fox jumped over the lazy dog"):

tests/pos/i22193.scala

+21
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ def test() =
2222
val x = env
2323
println(x)
2424

25+
fn2(
26+
arg = "blue sleeps faster than tuesday",
27+
arg2 = "the quick brown fox jumped over the lazy dog"): env =>
28+
val x = env
29+
println(x)
30+
2531
// does compile
2632
fn2(
2733
arg = "blue sleeps faster than tuesday",
@@ -38,6 +44,13 @@ def test() =
3844
val x = env
3945
println(x)
4046

47+
fn2(
48+
arg = "blue sleeps faster than tuesday",
49+
arg2 = "the quick brown fox jumped over the lazy dog"
50+
): env =>
51+
val x = env
52+
println(x)
53+
4154
fn3(
4255
arg = "blue sleeps faster than tuesday",
4356
arg2 = "the quick brown fox jumped over the lazy dog"):
@@ -55,3 +68,11 @@ def regress(x: Int) =
5568
x match
5669
case 42 =>
5770
case _ =>
71+
72+
// previously lookahead calculated indent width at the colon
73+
def k(xs: List[Int]) =
74+
xs.foldLeft(
75+
0)
76+
: (acc, x) =>
77+
acc + x
78+

0 commit comments

Comments
 (0)