aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-09-24 18:34:13 +0200
committerMartin Odersky <odersky@gmail.com>2016-09-24 18:34:13 +0200
commite2e1e8a43123de3c5594bad24af486b730e0b3c7 (patch)
tree9dd30e0e0f9167c299e67c0898b782cdf7e8201f
parent331e75be7e90817bc2931c3d00dd931b22c179f5 (diff)
downloaddotty-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.scala37
-rw-r--r--src/dotty/tools/dotc/typer/FrontEnd.scala3
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") {