Skip to content

Commit e2e1e8a

Browse files
committed
Check that (most) positions are non-overlapping.
Check that children of a node have non-overlapping positions and that positions of successive children are monotonically increasing. This holds currently except for 3 exceptions: - Trees coming from Java as the Java parser also does desugarings which copy trees. - Functions coming from wildcard expressions - Interpolated strings We'll see whether we can do something about the latter two.
1 parent 331e75b commit e2e1e8a

File tree

2 files changed

+30
-10
lines changed

2 files changed

+30
-10
lines changed

src/dotty/tools/dotc/ast/Positioned.scala

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -151,23 +151,41 @@ abstract class Positioned extends DotClass with Product {
151151
* - Parent positions contain child positions
152152
* - If item is a non-empty tree, it has a position
153153
*/
154-
def checkPos(complete: Boolean)(implicit ctx: Context): Unit = try {
154+
def checkPos(nonOverlapping: Boolean)(implicit ctx: Context): Unit = try {
155155
import untpd._
156+
var lastPositioned: Positioned = null
157+
var lastPos = NoPosition
156158
def check(p: Any): Unit = p match {
157159
case p: Positioned =>
158160
assert(pos contains p.pos,
159161
s"""position error, parent position does not contain child positon
160-
|parent = $this,
161-
|parent position = $pos,
162-
|child = $p,
163-
|child position = ${p.pos}""".stripMargin)
162+
|parent = $this,
163+
|parent position = $pos,
164+
|child = $p,
165+
|child position = ${p.pos}""".stripMargin)
164166
p match {
165167
case tree: Tree if !tree.isEmpty =>
166168
assert(tree.pos.exists,
167169
s"position error: position not set for $tree # ${tree.uniqueId}")
168170
case _ =>
169171
}
170-
p.checkPos(complete)
172+
if (nonOverlapping) {
173+
this match {
174+
case _: InterpolatedString => // ignore, strings and elements are interleaved in source, separated in tree
175+
case _: Function => // ignore, functions produced from wildcards (e.g. (_ op _) mix parameters and body
176+
case _ =>
177+
assert(!lastPos.exists || !p.pos.exists || lastPos.end <= p.pos.start,
178+
s"""position error, child positions overlap or in wrong order
179+
|parent = $this
180+
|1st child = $lastPositioned
181+
|1st child position = $lastPos
182+
|2nd child = $p
183+
|2nd child position = ${p.pos}""".stripMargin)
184+
lastPositioned = p
185+
lastPos = p.pos
186+
}
187+
}
188+
p.checkPos(nonOverlapping)
171189
case xs: List[_] =>
172190
xs.foreach(check)
173191
case _ =>
@@ -179,10 +197,11 @@ abstract class Positioned extends DotClass with Product {
179197
check(tree.mods)
180198
check(tree.vparamss)
181199
case _ =>
182-
var n = productArity
183-
while (n > 0) {
184-
n -= 1
200+
val end = productArity
201+
var n = 0
202+
while (n < end) {
185203
check(productElement(n))
204+
n += 1
186205
}
187206
}
188207
} catch {

src/dotty/tools/dotc/typer/FrontEnd.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ class FrontEnd extends Phase {
3535
else new Parser(unit.source).parse()
3636
val printer = if (ctx.settings.Xprint.value.contains("parser")) default else typr
3737
printer.println("parsed:\n" + unit.untpdTree.show)
38-
if (Config.checkPositions) unit.untpdTree.checkPos(complete = true)
38+
if (Config.checkPositions)
39+
unit.untpdTree.checkPos(nonOverlapping = !unit.isJava && !ctx.reporter.hasErrors)
3940
}
4041

4142
def enterSyms(implicit ctx: Context) = monitor("indexing") {

0 commit comments

Comments
 (0)