Skip to content

Commit

Permalink
Fix scala#17187: allow patches with same span (scala#17366)
Browse files Browse the repository at this point in the history
Fix scala#17187

The no-indent rewrite sometimes needs to add several `}` at the same
position, to close nested constructs.

For example, it rewrites:
```scala
object A:
  object B:
    def foo = 42
```
Into:
```scala
object A {
  object B {
    def foo = 42
  }
}
```

We deal with end marker in the `indentedToBraces` method by checking the
next token of the region. This also fixes the following error:

```scala
class A:
  def foo = 42

end A
```
Rewritten to
```scala
class A {
  def foo = 42
}

end A
```
Instead Of:
```scala
class A {
  def foo = 42

} // end A
```
  • Loading branch information
adpi2 authored May 1, 2023
2 parents a89fbf5 + 9d3f270 commit 2c4502b
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 9 deletions.
9 changes: 5 additions & 4 deletions compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -715,7 +715,11 @@ object Parsers {
val t = enclosed(INDENT, body)
if needsBraces(t) then
patch(source, Span(startOpening, endOpening), " {")
patch(source, Span(closingOffset(source.nextLine(in.lastOffset))), indentWidth.toPrefix ++ "}\n")
val next = in.next
def closedByEndMarker =
next.token == END && (next.offset - next.lineOffset) == indentWidth.toPrefix.size
if closedByEndMarker then patch(source, Span(next.offset), "} // ")
else patch(source, Span(closingOffset(source.nextLine(in.lastOffset))), indentWidth.toPrefix ++ "}\n")
t
end indentedToBraces

Expand Down Expand Up @@ -1422,9 +1426,6 @@ object Parsers {
val start = in.skipToken()
if stats.isEmpty || !matchesAndSetEnd(stats.last) then
syntaxError(em"misaligned end marker", Span(start, in.lastCharOffset))
else if overlapsPatch(source, Span(start, start)) then
patch(source, Span(start, start), "")
patch(source, Span(start, in.lastCharOffset), s"} // end $endName")
in.token = IDENTIFIER // Leaving it as the original token can confuse newline insertion
in.nextToken()
end checkEndMarker
Expand Down
5 changes: 1 addition & 4 deletions compiler/src/dotty/tools/dotc/rewrites/Rewrites.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,7 @@ object Rewrites {
private[Rewrites] val pbuf = new mutable.ListBuffer[Patch]()

def addPatch(span: Span, replacement: String): Unit =
pbuf.indexWhere(p => p.span.start == span.start && p.span.end == span.end) match {
case i if i >= 0 => pbuf.update(i, Patch(span, replacement))
case _ => pbuf += Patch(span, replacement)
}
pbuf += Patch(span, replacement)

def apply(cs: Array[Char]): Array[Char] = {
val delta = pbuf.map(_.delta).sum
Expand Down
1 change: 0 additions & 1 deletion compiler/src/dotty/tools/dotc/util/Spans.scala
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ object Spans {
|| containsInner(this, that.end)
|| containsInner(that, this.start)
|| containsInner(that, this.end)
|| this.start == that.start && this.end == that.end // exact match in one point
)
}

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 @@ -81,6 +81,7 @@ class CompilationTests {
compileFile("tests/rewrites/i9632.scala", defaultOptions.and("-indent", "-rewrite")),
compileFile("tests/rewrites/i11895.scala", defaultOptions.and("-indent", "-rewrite")),
compileFile("tests/rewrites/i12340.scala", unindentOptions.and("-rewrite")),
compileFile("tests/rewrites/i17187.scala", unindentOptions.and("-rewrite")),
).checkRewrites()
}

Expand Down
9 changes: 9 additions & 0 deletions tests/rewrites/i12340.check
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@ class C {
def f = 42
} // end C

class A {
class B {
class C {
def foo = 42
}

} // end B
}

def f(i: Int) = {
if i < 42 then
println(i)
Expand Down
7 changes: 7 additions & 0 deletions tests/rewrites/i12340.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ class C:
def f = 42
end C

class A:
class B:
class C:
def foo = 42

end B

def f(i: Int) =
if i < 42 then
println(i)
Expand Down
44 changes: 44 additions & 0 deletions tests/rewrites/i17187.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@

object A {
object B {
def a = 2
}
}

def m1 = {
def b = {
def c = 2
}
}

def m2 =
if true then {
val x = 3
if (false)
x
else {
val y = 4
y
}
}

def m3 =
try {
val n2 = 21
val n1 = 4
n2 / n1
}
catch {
case _ => 4
}

def m4 = {
val n2 = 21
try {
val n1 = 4
n2 / n1
}
catch {
case _ => 4
}
}
33 changes: 33 additions & 0 deletions tests/rewrites/i17187.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@

object A:
object B:
def a = 2

def m1 =
def b =
def c = 2

def m2 =
if true then
val x = 3
if (false)
x
else
val y = 4
y

def m3 =
try
val n2 = 21
val n1 = 4
n2 / n1
catch
case _ => 4

def m4 =
val n2 = 21
try
val n1 = 4
n2 / n1
catch
case _ => 4

0 comments on commit 2c4502b

Please sign in to comment.