diff options
author | Guillaume Martres <smarter@ubuntu.com> | 2016-11-04 00:48:36 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-11-04 00:48:36 +0100 |
commit | 6ba6ea542d7915a48b426fea1f75f9cb8c2db424 (patch) | |
tree | f728f6c54fe8c2e57ae136ef08d6fb20eaca534b /src/dotty/tools/dotc/core/tasty/PositionPickler.scala | |
parent | 98a92c6f4ec743edb9465071dcfd43f17dbf054b (diff) | |
parent | d694f15a028cf14ea0cf210d3113c7b1d6af54e7 (diff) | |
download | dotty-6ba6ea542d7915a48b426fea1f75f9cb8c2db424.tar.gz dotty-6ba6ea542d7915a48b426fea1f75f9cb8c2db424.tar.bz2 dotty-6ba6ea542d7915a48b426fea1f75f9cb8c2db424.zip |
Merge pull request #1587 from dotty-staging/change-tasty-pos
Fix Tasty positions
Diffstat (limited to 'src/dotty/tools/dotc/core/tasty/PositionPickler.scala')
-rw-r--r-- | src/dotty/tools/dotc/core/tasty/PositionPickler.scala | 58 |
1 files changed, 46 insertions, 12 deletions
diff --git a/src/dotty/tools/dotc/core/tasty/PositionPickler.scala b/src/dotty/tools/dotc/core/tasty/PositionPickler.scala index 63bb00a71..4b67bc188 100644 --- a/src/dotty/tools/dotc/core/tasty/PositionPickler.scala +++ b/src/dotty/tools/dotc/core/tasty/PositionPickler.scala @@ -13,15 +13,32 @@ import collection.mutable import TastyBuffer._ import util.Positions._ -class PositionPickler(pickler: TastyPickler, addrOfTree: tpd.Tree => Option[Addr]) { +class PositionPickler(pickler: TastyPickler, addrsOfTree: tpd.Tree => List[Addr]) { val buf = new TastyBuffer(5000) pickler.newSection("Positions", buf) import buf._ import ast.tpd._ - def header(addrDelta: Int, hasStartDelta: Boolean, hasEndDelta: Boolean) = { + private val remainingAddrs = new java.util.IdentityHashMap[Tree, Iterator[Addr]] + + def nextTreeAddr(tree: Tree): Option[Addr] = remainingAddrs.get(tree) match { + case null => + addrsOfTree(tree) match { + case Nil => + None + case addr :: Nil => + Some(addr) + case addrs => + remainingAddrs.put(tree, addrs.iterator) + nextTreeAddr(tree) + } + case it: Iterator[_] => + if (it.hasNext) Some(it.next) else None + } + + def header(addrDelta: Int, hasStartDelta: Boolean, hasEndDelta: Boolean, hasPoint: Boolean) = { def toInt(b: Boolean) = if (b) 1 else 0 - (addrDelta << 2) | (toInt(hasStartDelta) << 1) | toInt(hasEndDelta) + (addrDelta << 3) | (toInt(hasStartDelta) << 2) | (toInt(hasEndDelta) << 1) | toInt(hasPoint) } def picklePositions(roots: List[Tree])(implicit ctx: Context) = { @@ -31,29 +48,46 @@ class PositionPickler(pickler: TastyPickler, addrOfTree: tpd.Tree => Option[Addr val addrDelta = index - lastIndex val startDelta = pos.start - lastPos.start val endDelta = pos.end - lastPos.end - buf.writeInt(header(addrDelta, startDelta != 0, endDelta != 0)) + buf.writeInt(header(addrDelta, startDelta != 0, endDelta != 0, !pos.isSynthetic)) if (startDelta != 0) buf.writeInt(startDelta) if (endDelta != 0) buf.writeInt(endDelta) + if (!pos.isSynthetic) buf.writeInt(pos.pointDelta) lastIndex = index lastPos = pos } - def traverse(x: Any, parentPos: Position): Unit = x match { + + /** True if x's position cannot be reconstructed automatically from its initialPos + */ + def alwaysNeedsPos(x: Positioned) = x match { + case _: WithLazyField[_] // initialPos is inaccurate for trees with lazy field + | _: Trees.PackageDef[_] => true // package defs might be split into several Tasty files + case x: Trees.Tree[_] => x.isType // types are unpickled as TypeTrees, so child positions are not available + case _ => false + } + + def traverse(x: Any): Unit = x match { case x: Tree @unchecked => - if (x.pos.exists && x.pos.toSynthetic != parentPos.toSynthetic) { - addrOfTree(x) match { - case Some(addr) => pickleDeltas(addr.index, x.pos) + val pos = if (x.isInstanceOf[MemberDef]) x.pos else x.pos.toSynthetic + if (pos.exists && (pos != x.initialPos.toSynthetic || alwaysNeedsPos(x))) { + nextTreeAddr(x) match { + case Some(addr) => + //println(i"pickling $x with $pos at $addr") + pickleDeltas(addr.index, pos) case _ => + //println(i"no address for $x") } } + //else if (x.pos.exists) println(i"skipping $x") x match { - case x: MemberDef @unchecked => traverse(x.symbol.annotations, x.pos) + case x: MemberDef @unchecked => + for (ann <- x.symbol.annotations) traverse(ann.tree) case _ => } - traverse(x.productIterator, x.pos) + traverse(x.productIterator) case xs: TraversableOnce[_] => - xs.foreach(traverse(_, parentPos)) + xs.foreach(traverse) case _ => } - traverse(roots, NoPosition) + traverse(roots) } } |