Skip to content

Commit c1f18cb

Browse files
committed
Tigthen lexical rules for ColonAtEOL
1 parent a112f67 commit c1f18cb

File tree

7 files changed

+122
-16
lines changed

7 files changed

+122
-16
lines changed

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ object Scanners {
397397
adjustSepRegions(lastToken)
398398
getNextToken(lastToken)
399399
if isAfterLineEnd then handleNewLine(lastToken)
400-
postProcessToken()
400+
postProcessToken(lastToken)
401401
printState()
402402

403403
final def printState() =
@@ -694,7 +694,7 @@ object Scanners {
694694
* SEMI + ELSE => ELSE, COLON + <EOL> => COLONEOL
695695
* - Insert missing OUTDENTs at EOF
696696
*/
697-
def postProcessToken(): Unit = {
697+
def postProcessToken(lastToken: Token): Unit = {
698698
def fuse(tok: Int) = {
699699
token = tok
700700
offset = prev.offset
@@ -730,7 +730,8 @@ object Scanners {
730730
case END =>
731731
if !isEndMarker then token = IDENTIFIER
732732
case COLON =>
733-
if fewerBracesEnabled then observeColonEOL()
733+
if fewerBracesEnabled && colonEOLPredecessors.contains(lastToken) && lastOffset == offset then
734+
observeColonEOL()
734735
case RBRACE | RPAREN | RBRACKET =>
735736
closeIndented()
736737
case EOF =>
@@ -1526,7 +1527,8 @@ object Scanners {
15261527
case NEWLINE => ";"
15271528
case NEWLINES => ";;"
15281529
case COMMA => ","
1529-
case _ => showToken(token)
1530+
case _ =>
1531+
if debugTokenStream then showTokenDetailed(token) else showToken(token)
15301532
}
15311533

15321534
/* Resume normal scanning after XML */

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,8 @@ object Tokens extends TokensCommon {
287287

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

290+
final val colonEOLPredecessors = identifierTokens | BitSet(RPAREN, RBRACKET)
291+
290292
final val closingParens = BitSet(RPAREN, RBRACKET, RBRACE)
291293

292294
final val softModifierNames = Set(nme.inline, nme.opaque, nme.open, nme.transparent, nme.infix)

tests/neg/indent-colons.check

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
-- Error: tests/neg/indent-colons.scala:6:4 ----------------------------------------------------------------------------
2+
6 | : // error
3+
| ^
4+
| end of statement expected but ':' found
5+
-- Error: tests/neg/indent-colons.scala:12:2 ---------------------------------------------------------------------------
6+
12 | : // error
7+
| ^
8+
| end of statement expected but ':' found
9+
-- Error: tests/neg/indent-colons.scala:19:2 ---------------------------------------------------------------------------
10+
19 | : // error
11+
| ^
12+
| end of statement expected but ':' found
13+
-- [E018] Syntax Error: tests/neg/indent-colons.scala:26:14 ------------------------------------------------------------
14+
26 | val y = 1 + : // error
15+
| ^
16+
| expression expected but : found
17+
|
18+
| longer explanation available when compiling with `-explain`
19+
-- [E018] Syntax Error: tests/neg/indent-colons.scala:30:27 ------------------------------------------------------------
20+
30 | val all = credentials ++ : // error
21+
| ^
22+
| expression expected but : found
23+
|
24+
| longer explanation available when compiling with `-explain`
25+
-- [E134] Type Error: tests/neg/indent-colons.scala:23:12 --------------------------------------------------------------
26+
23 | val x = 1.+ : // error
27+
| ^^^
28+
| None of the overloaded alternatives of method + in class Int with types
29+
| (x: Double): Double
30+
| (x: Float): Float
31+
| (x: Long): Long
32+
| (x: Int): Int
33+
| (x: Char): Int
34+
| (x: Short): Int
35+
| (x: Byte): Int
36+
| (x: String): String
37+
| match expected type (2 : Int)
38+
-- [E006] Not Found Error: tests/neg/indent-colons.scala:32:7 ----------------------------------------------------------
39+
32 | if file.isEmpty // error
40+
| ^^^^
41+
| Not found: file
42+
|
43+
| longer explanation available when compiling with `-explain`
44+
-- [E006] Not Found Error: tests/neg/indent-colons.scala:34:13 ---------------------------------------------------------
45+
34 | else Seq(file) // error
46+
| ^^^^
47+
| Not found: file
48+
|
49+
| longer explanation available when compiling with `-explain`
50+
-- Error: tests/neg/indent-colons.scala:4:2 ----------------------------------------------------------------------------
51+
4 | tryEither: // error
52+
| ^^^^^^^^^
53+
| missing arguments for method tryEither
54+
-- Error: tests/neg/indent-colons.scala:10:2 ---------------------------------------------------------------------------
55+
10 | tryEither: // error
56+
| ^^^^^^^^^
57+
| missing arguments for method tryEither
58+
-- Error: tests/neg/indent-colons.scala:17:2 ---------------------------------------------------------------------------
59+
17 | Some(3).fold: // error
60+
| ^^^^^^^^^^^^
61+
| missing arguments for method fold in class Option

tests/neg/indent-colons.scala

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
def tryEither[T](x: T)(y: Int => T): T = ???
2+
3+
def test1 =
4+
tryEither: // error
5+
"hello"
6+
: // error
7+
y => y.toString
8+
9+
def test2 =
10+
tryEither: // error
11+
"hello"
12+
: // error
13+
_.toString
14+
15+
16+
val o =
17+
Some(3).fold: // error
18+
"nothing"
19+
: // error
20+
x => x.toString
21+
22+
object Test23:
23+
val x = 1.+ : // error
24+
2
25+
26+
val y = 1 + : // error
27+
x
28+
29+
val credentials = List("OK")
30+
val all = credentials ++ : // error
31+
val file = "file"
32+
if file.isEmpty // error
33+
then Seq("none")
34+
else Seq(file) // error

tests/pos/closure-args.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,6 @@ object Test1:
2929

3030
val q = (x: String => String) => x
3131

32-
val r = x < 0 && :
32+
val r = x < 0 && locally:
3333
y > 0
34+

tests/pos/i12218.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import language.experimental.fewerBraces
33
val arr = Array(1,2,3)
44
if
55
arr.isEmpty
6-
|| :
6+
|| locally:
77
val first = arr(0)
88
first != 1
99
then println("invalid arr")

tests/pos/indent-colons.scala

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -122,35 +122,41 @@ def tryEither[T](x: T)(y: Int => T): T = ???
122122

123123
def test1 =
124124
tryEither:
125-
"hello"
126-
:
127-
y => y.toString
125+
"hello"
126+
.apply:
127+
y => y.toString
128128

129129
def test2 =
130130
tryEither:
131131
"hello"
132-
:
132+
.apply:
133133
_.toString
134134

135135

136136
val o =
137137
Some(3).fold:
138138
"nothing"
139-
:
139+
.apply:
140140
x => x.toString
141141

142142
object Test23:
143-
val x = 1.+ : // ok
144-
2
145143

146-
val y = 1 + : // ok
144+
transparent inline def nested[T](inline x: T): T = x
145+
146+
val x = (1.+):
147147
2
148148

149+
val y = 1 + nested: // ok
150+
x
151+
152+
val _ = 1 `+`: // ok
153+
x
154+
149155
val r = 1 to:
150156
100
151157

152158
val credentials = List("OK")
153-
val all = credentials ++ :
159+
val all = credentials ++ nested:
154160
val file = "file"
155161
if file.isEmpty
156162
then Seq("none")
@@ -162,7 +168,7 @@ extension (x: Boolean)
162168
def test24(x: Int, y: Int) =
163169
x < y or:
164170
x > y
165-
or:
171+
`or`:
166172
x == y
167173

168174

0 commit comments

Comments
 (0)