Skip to content

Commit

Permalink
Extra check to avoid converting block expressions on the rhs of a sym…
Browse files Browse the repository at this point in the history
…bolic infix expression.

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
  • Loading branch information
Lucy Martin committed Apr 11, 2024
1 parent 43ed9fd commit 43d33a0
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 1 deletion.
22 changes: 21 additions & 1 deletion compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -814,6 +814,8 @@ object Parsers {
* 6. the opening brace does not follow a `=>`. The reason for this condition is that
* rewriting back to braces does not work after `=>` (since in most cases braces are omitted
* after a `=>` it would be annoying if braces were inserted).
* 7. not a code block being the input to a direct symbolic function call `inst method {\n expr \n}` cannot
* become `inst method :\n expr` for a fully symbolic method
*/
def bracesToIndented[T](body: => T, rewriteWithColon: Boolean): T = {
val underColonSyntax = possibleColonOffset == in.lastOffset
Expand All @@ -827,10 +829,28 @@ object Parsers {
}
var canRewrite = allBraces(in.currentRegion) && // test (1)
!testChars(in.lastOffset - 3, " =>") // test(6)

def isStartOfSymbolicFunction: Boolean =
opStack.headOption.exists { x =>
val bq = x.operator.isBackquoted
val op = x.operator.name.toSimpleName.decode.forall {
Chars.isOperatorPart
}
val loc = startOpening < x.offset && x.offset < endOpening
val res = !bq && op && loc
res
}
val t = enclosed(LBRACE, {
canRewrite &= in.isAfterLineEnd // test (2)
val curOffset = in.offset
try body
try {
val bodyResolved = body
bodyResolved match
case x:(Match | Block) =>
canRewrite &= !isStartOfSymbolicFunction // test (7)
case _ =>
bodyResolved
}
finally {
canRewrite &= in.isAfterLineEnd && in.offset != curOffset // test (3)(4)
}
Expand Down
1 change: 1 addition & 0 deletions compiler/test/dotty/tools/dotc/CompilationTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ class CompilationTests {
compileFile("tests/rewrites/i12340.scala", unindentOptions.and("-rewrite")),
compileFile("tests/rewrites/i17187.scala", unindentOptions.and("-rewrite")),
compileFile("tests/rewrites/i17399.scala", unindentOptions.and("-rewrite")),
compileFile("tests/rewrites/i20002.scala", defaultOptions.and("-indent", "-rewrite")),
).checkRewrites()
}

Expand Down
51 changes: 51 additions & 0 deletions tests/rewrites/i20002.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
object Reactions:
def main: Unit =
Reactions += {
case 0 =>
case 1 =>
}

Reactions run:
case 0 =>
case 1 =>

Reactions run_+ :
case 0 =>
case 1 =>

Reactions `+=`:
case 0 =>
case 1 =>

def bar: Int = ???

bar match
case 0 =>
case 1 =>

def partPartial(i: Int): PartialFunction[Int, Unit] =
case `i` =>

Reactions += {
val pp1 = partPartial(1)
val pp2 = partPartial(2)
def codeBlock =
???
???
pp1 orElse pp2
}

val partialFunction = partPartial(1) orElse partPartial(2)
Reactions += {
partialFunction
}

def +=(f: PartialFunction[Int, Unit]) =
???

def run (f: PartialFunction[Int, Unit]) =
???

def run_+ (f: PartialFunction[Int, Unit]) =
???

62 changes: 62 additions & 0 deletions tests/rewrites/i20002.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
object Reactions {
def main: Unit = {
Reactions += {
case 0 =>
case 1 =>
}

Reactions run {
case 0 =>
case 1 =>
}

Reactions run_+ {
case 0 =>
case 1 =>
}

Reactions `+=` {
case 0 =>
case 1 =>
}

def bar: Int = ???

bar match {
case 0 =>
case 1 =>
}

def partPartial(i: Int): PartialFunction[Int, Unit] = {
case `i` =>
}

Reactions += {
val pp1 = partPartial(1)
val pp2 = partPartial(2)
def codeBlock = {
???
???
}
pp1 orElse pp2
}

val partialFunction = partPartial(1) orElse partPartial(2)
Reactions += {
partialFunction
}
}

def +=(f: PartialFunction[Int, Unit]) = {
???
}

def run (f: PartialFunction[Int, Unit]) = {
???
}

def run_+ (f: PartialFunction[Int, Unit]) = {
???
}

}

0 comments on commit 43d33a0

Please sign in to comment.