aboutsummaryrefslogtreecommitdiff
path: root/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala')
-rw-r--r--compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala79
1 files changed, 79 insertions, 0 deletions
diff --git a/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala
new file mode 100644
index 000000000..546894a9e
--- /dev/null
+++ b/compiler/src/dotty/tools/dotc/core/tasty/PositionPickler.scala
@@ -0,0 +1,79 @@
+package dotty.tools
+package dotc
+package core
+package tasty
+
+import ast._
+import ast.Trees._
+import ast.Trees.WithLazyField
+import TastyFormat._
+import core._
+import Contexts._, Symbols._, Types._, Names._, Constants._, Decorators._, Annotations._
+import collection.mutable
+import TastyBuffer._
+import util.Positions._
+
+class PositionPickler(pickler: TastyPickler, addrOfTree: tpd.Tree => Option[Addr]) {
+ val buf = new TastyBuffer(5000)
+ pickler.newSection("Positions", buf)
+ import buf._
+ import ast.tpd._
+
+ private val remainingAddrs = new java.util.IdentityHashMap[Tree, Iterator[Addr]]
+
+ def header(addrDelta: Int, hasStartDelta: Boolean, hasEndDelta: Boolean, hasPoint: Boolean) = {
+ def toInt(b: Boolean) = if (b) 1 else 0
+ (addrDelta << 3) | (toInt(hasStartDelta) << 2) | (toInt(hasEndDelta) << 1) | toInt(hasPoint)
+ }
+
+ def picklePositions(roots: List[Tree])(implicit ctx: Context) = {
+ var lastIndex = 0
+ var lastPos = Position(0, 0)
+ def pickleDeltas(index: Int, pos: Position) = {
+ val addrDelta = index - lastIndex
+ val startDelta = pos.start - lastPos.start
+ val endDelta = pos.end - lastPos.end
+ 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
+ }
+
+ /** 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 _ => false
+ }
+
+ def traverse(x: Any): Unit = x match {
+ case x: Tree @unchecked =>
+ val pos = if (x.isInstanceOf[MemberDef]) x.pos else x.pos.toSynthetic
+ if (pos.exists && (pos != x.initialPos.toSynthetic || alwaysNeedsPos(x))) {
+ addrOfTree(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 =>
+ for (ann <- x.symbol.annotations) traverse(ann.tree)
+ case _ =>
+ }
+ traverse(x.productIterator)
+ case xs: TraversableOnce[_] =>
+ xs.foreach(traverse)
+ case x: Annotation =>
+ traverse(x.tree)
+ case _ =>
+ }
+ traverse(roots)
+ }
+}