Skip to content

Commit 2427f56

Browse files
authored
Extra check to avoid converting block expressions on the rhs of an infix expression. (#20043)
Tests added for: * Original cast as per the ticket should not be changed * Similar match statement that should update * Code blocks in this position, as opposed to a partial function, cant update here * Simple change that should apply but in a code position where the op stack is nonempty * Equivalent code, but passing in the partial function as a single parameter, again, not updating Fixes #20002
2 parents 4f17e25 + 43d33a0 commit 2427f56

File tree

4 files changed

+135
-1
lines changed

4 files changed

+135
-1
lines changed

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

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,8 @@ object Parsers {
814814
* 6. the opening brace does not follow a `=>`. The reason for this condition is that
815815
* rewriting back to braces does not work after `=>` (since in most cases braces are omitted
816816
* after a `=>` it would be annoying if braces were inserted).
817+
* 7. not a code block being the input to a direct symbolic function call `inst method {\n expr \n}` cannot
818+
* become `inst method :\n expr` for a fully symbolic method
817819
*/
818820
def bracesToIndented[T](body: => T, rewriteWithColon: Boolean): T = {
819821
val underColonSyntax = possibleColonOffset == in.lastOffset
@@ -827,10 +829,28 @@ object Parsers {
827829
}
828830
var canRewrite = allBraces(in.currentRegion) && // test (1)
829831
!testChars(in.lastOffset - 3, " =>") // test(6)
832+
833+
def isStartOfSymbolicFunction: Boolean =
834+
opStack.headOption.exists { x =>
835+
val bq = x.operator.isBackquoted
836+
val op = x.operator.name.toSimpleName.decode.forall {
837+
Chars.isOperatorPart
838+
}
839+
val loc = startOpening < x.offset && x.offset < endOpening
840+
val res = !bq && op && loc
841+
res
842+
}
830843
val t = enclosed(LBRACE, {
831844
canRewrite &= in.isAfterLineEnd // test (2)
832845
val curOffset = in.offset
833-
try body
846+
try {
847+
val bodyResolved = body
848+
bodyResolved match
849+
case x:(Match | Block) =>
850+
canRewrite &= !isStartOfSymbolicFunction // test (7)
851+
case _ =>
852+
bodyResolved
853+
}
834854
finally {
835855
canRewrite &= in.isAfterLineEnd && in.offset != curOffset // test (3)(4)
836856
}

compiler/test/dotty/tools/dotc/CompilationTests.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ class CompilationTests {
7575
compileFile("tests/rewrites/i12340.scala", unindentOptions.and("-rewrite")),
7676
compileFile("tests/rewrites/i17187.scala", unindentOptions.and("-rewrite")),
7777
compileFile("tests/rewrites/i17399.scala", unindentOptions.and("-rewrite")),
78+
compileFile("tests/rewrites/i20002.scala", defaultOptions.and("-indent", "-rewrite")),
7879
).checkRewrites()
7980
}
8081

tests/rewrites/i20002.check

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
object Reactions:
2+
def main: Unit =
3+
Reactions += {
4+
case 0 =>
5+
case 1 =>
6+
}
7+
8+
Reactions run:
9+
case 0 =>
10+
case 1 =>
11+
12+
Reactions run_+ :
13+
case 0 =>
14+
case 1 =>
15+
16+
Reactions `+=`:
17+
case 0 =>
18+
case 1 =>
19+
20+
def bar: Int = ???
21+
22+
bar match
23+
case 0 =>
24+
case 1 =>
25+
26+
def partPartial(i: Int): PartialFunction[Int, Unit] =
27+
case `i` =>
28+
29+
Reactions += {
30+
val pp1 = partPartial(1)
31+
val pp2 = partPartial(2)
32+
def codeBlock =
33+
???
34+
???
35+
pp1 orElse pp2
36+
}
37+
38+
val partialFunction = partPartial(1) orElse partPartial(2)
39+
Reactions += {
40+
partialFunction
41+
}
42+
43+
def +=(f: PartialFunction[Int, Unit]) =
44+
???
45+
46+
def run (f: PartialFunction[Int, Unit]) =
47+
???
48+
49+
def run_+ (f: PartialFunction[Int, Unit]) =
50+
???
51+

tests/rewrites/i20002.scala

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
object Reactions {
2+
def main: Unit = {
3+
Reactions += {
4+
case 0 =>
5+
case 1 =>
6+
}
7+
8+
Reactions run {
9+
case 0 =>
10+
case 1 =>
11+
}
12+
13+
Reactions run_+ {
14+
case 0 =>
15+
case 1 =>
16+
}
17+
18+
Reactions `+=` {
19+
case 0 =>
20+
case 1 =>
21+
}
22+
23+
def bar: Int = ???
24+
25+
bar match {
26+
case 0 =>
27+
case 1 =>
28+
}
29+
30+
def partPartial(i: Int): PartialFunction[Int, Unit] = {
31+
case `i` =>
32+
}
33+
34+
Reactions += {
35+
val pp1 = partPartial(1)
36+
val pp2 = partPartial(2)
37+
def codeBlock = {
38+
???
39+
???
40+
}
41+
pp1 orElse pp2
42+
}
43+
44+
val partialFunction = partPartial(1) orElse partPartial(2)
45+
Reactions += {
46+
partialFunction
47+
}
48+
}
49+
50+
def +=(f: PartialFunction[Int, Unit]) = {
51+
???
52+
}
53+
54+
def run (f: PartialFunction[Int, Unit]) = {
55+
???
56+
}
57+
58+
def run_+ (f: PartialFunction[Int, Unit]) = {
59+
???
60+
}
61+
62+
}

0 commit comments

Comments
 (0)