diff options
author | Martin Odersky <odersky@gmail.com> | 2016-09-24 18:34:13 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2016-09-24 18:34:13 +0200 |
commit | e2e1e8a43123de3c5594bad24af486b730e0b3c7 (patch) | |
tree | 9dd30e0e0f9167c299e67c0898b782cdf7e8201f | |
parent | 331e75be7e90817bc2931c3d00dd931b22c179f5 (diff) | |
download | dotty-e2e1e8a43123de3c5594bad24af486b730e0b3c7.tar.gz dotty-e2e1e8a43123de3c5594bad24af486b730e0b3c7.tar.bz2 dotty-e2e1e8a43123de3c5594bad24af486b730e0b3c7.zip |
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.
-rw-r--r-- | src/dotty/tools/dotc/ast/Positioned.scala | 37 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/FrontEnd.scala | 3 |
2 files changed, 30 insertions, 10 deletions
diff --git a/src/dotty/tools/dotc/ast/Positioned.scala b/src/dotty/tools/dotc/ast/Positioned.scala index ab9c06ca1..1e992bd01 100644 --- a/src/dotty/tools/dotc/ast/Positioned.scala +++ b/src/dotty/tools/dotc/ast/Positioned.scala @@ -151,23 +151,41 @@ abstract class Positioned extends DotClass with Product { * - Parent positions contain child positions * - If item is a non-empty tree, it has a position */ - def checkPos(complete: Boolean)(implicit ctx: Context): Unit = try { + def checkPos(nonOverlapping: Boolean)(implicit ctx: Context): Unit = try { import untpd._ + var lastPositioned: Positioned = null + var lastPos = NoPosition def check(p: Any): Unit = p match { case p: Positioned => assert(pos contains p.pos, s"""position error, parent position does not contain child positon - |parent = $this, - |parent position = $pos, - |child = $p, - |child position = ${p.pos}""".stripMargin) + |parent = $this, + |parent position = $pos, + |child = $p, + |child position = ${p.pos}""".stripMargin) p match { case tree: Tree if !tree.isEmpty => assert(tree.pos.exists, s"position error: position not set for $tree # ${tree.uniqueId}") case _ => } - p.checkPos(complete) + if (nonOverlapping) { + this match { + case _: InterpolatedString => // ignore, strings and elements are interleaved in source, separated in tree + case _: Function => // ignore, functions produced from wildcards (e.g. (_ op _) mix parameters and body + case _ => + assert(!lastPos.exists || !p.pos.exists || lastPos.end <= p.pos.start, + s"""position error, child positions overlap or in wrong order + |parent = $this + |1st child = $lastPositioned + |1st child position = $lastPos + |2nd child = $p + |2nd child position = ${p.pos}""".stripMargin) + lastPositioned = p + lastPos = p.pos + } + } + p.checkPos(nonOverlapping) case xs: List[_] => xs.foreach(check) case _ => @@ -179,10 +197,11 @@ abstract class Positioned extends DotClass with Product { check(tree.mods) check(tree.vparamss) case _ => - var n = productArity - while (n > 0) { - n -= 1 + val end = productArity + var n = 0 + while (n < end) { check(productElement(n)) + n += 1 } } } catch { diff --git a/src/dotty/tools/dotc/typer/FrontEnd.scala b/src/dotty/tools/dotc/typer/FrontEnd.scala index e008430a7..4ce24b633 100644 --- a/src/dotty/tools/dotc/typer/FrontEnd.scala +++ b/src/dotty/tools/dotc/typer/FrontEnd.scala @@ -35,7 +35,8 @@ class FrontEnd extends Phase { else new Parser(unit.source).parse() val printer = if (ctx.settings.Xprint.value.contains("parser")) default else typr printer.println("parsed:\n" + unit.untpdTree.show) - if (Config.checkPositions) unit.untpdTree.checkPos(complete = true) + if (Config.checkPositions) + unit.untpdTree.checkPos(nonOverlapping = !unit.isJava && !ctx.reporter.hasErrors) } def enterSyms(implicit ctx: Context) = monitor("indexing") { |