Skip to content

Commit 8e57890

Browse files
committed
sourcepath: Handle end markers in outline parsing
Previously, outline parsing would have failed on indent1.scala with: 7 | end inner | ^ | misaligned end marker because `OutlineParserCommon#skipBraces` does not update `in.openEndMarkers`, but calls `in.nextToken` which eventually calls `in.skipEndMarker` which checks that end markers are aligned. This commit fixes this by adding a boolean in the scanner to turn off end marker checks, this is used by the outline parser when skipping over code.
1 parent aeaed68 commit 8e57890

File tree

4 files changed

+37
-10
lines changed

4 files changed

+37
-10
lines changed

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

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -156,12 +156,17 @@ object Parsers {
156156
def skipBraces(): Unit = {
157157
accept(if (in.token == INDENT) INDENT else LBRACE)
158158
var openBraces = 1
159-
while (in.token != EOF && openBraces > 0)
160-
skipBracesHook() getOrElse {
161-
if (in.token == LBRACE || in.token == INDENT) openBraces += 1
162-
else if (in.token == RBRACE || in.token == OUTDENT) openBraces -= 1
163-
in.nextToken()
164-
}
159+
val savedCheckEndMarker = in.checkEndMarker
160+
try
161+
in.checkEndMarker = false
162+
while (in.token != EOF && openBraces > 0)
163+
skipBracesHook() getOrElse {
164+
if (in.token == LBRACE || in.token == INDENT) openBraces += 1
165+
else if (in.token == RBRACE || in.token == OUTDENT) openBraces -= 1
166+
in.nextToken()
167+
}
168+
finally
169+
in.checkEndMarker = savedCheckEndMarker
165170
}
166171
}
167172

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

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ object Scanners {
5454
/** the base of a number */
5555
var base: Int = 0
5656

57+
/** Set to false to disable end marker alignment checks, used for outline parsing. */
58+
var checkEndMarker: Boolean = true
59+
5760
def copyFrom(td: TokenData): Unit = {
5861
this.token = td.token
5962
this.offset = td.offset
@@ -331,10 +334,12 @@ object Scanners {
331334
def endMarkerScope[T](tag: EndMarkerTag)(op: => T): T =
332335
val saved = openEndMarkers
333336
openEndMarkers = (tag, currentRegion.indentWidth) :: openEndMarkers
334-
try op finally openEndMarkers = saved
337+
try op
338+
finally openEndMarkers = saved
335339

336340
/** If this token and the next constitute an end marker, skip them and check they
337-
* align with an opening construct with the same end marker tag.
341+
* align with an opening construct with the same end marker tag,
342+
* unless `checkEndMarker` is false.
338343
*/
339344
protected def skipEndMarker(width: IndentWidth): Unit =
340345
if next.token == IDENTIFIER && next.name == nme.end then
@@ -348,8 +353,9 @@ object Scanners {
348353
openEndMarkers = rest
349354
checkAligned()
350355
case _ =>
351-
lexical.println(i"misaligned end marker $tag, $width, $openEndMarkers")
352-
errorButContinue("misaligned end marker", start)
356+
if checkEndMarker
357+
lexical.println(i"misaligned end marker $tag, $width, $openEndMarkers")
358+
errorButContinue("misaligned end marker", start)
353359

354360
val skipTo = lookahead.charOffset
355361
lookahead.nextToken()
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package outer
2+
import nested._
3+
4+
object indent2 {
5+
val x2: Int = indent1.inner.x
6+
val y2: Int = indent1.y
7+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package outer
2+
package nested
3+
4+
object indent1
5+
object inner with
6+
def x: Int = 1
7+
end inner
8+
val y: Int = 2
9+
end indent1

0 commit comments

Comments
 (0)