aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/tasty/PositionPickler.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotty/tools/dotc/core/tasty/PositionPickler.scala')
-rw-r--r--src/dotty/tools/dotc/core/tasty/PositionPickler.scala92
1 files changed, 38 insertions, 54 deletions
diff --git a/src/dotty/tools/dotc/core/tasty/PositionPickler.scala b/src/dotty/tools/dotc/core/tasty/PositionPickler.scala
index b0550b70a..63bb00a71 100644
--- a/src/dotty/tools/dotc/core/tasty/PositionPickler.scala
+++ b/src/dotty/tools/dotc/core/tasty/PositionPickler.scala
@@ -3,7 +3,8 @@ package dotc
package core
package tasty
-import ast.tpd._
+import ast._
+import ast.Trees._
import ast.Trees.WithLazyField
import TastyFormat._
import core._
@@ -12,64 +13,47 @@ import collection.mutable
import TastyBuffer._
import util.Positions._
-object PositionPickler {
-
- trait DeferredPosition {
- var parentPos: Position = NoPosition
- }
-
- def traverse(x: Any, parentPos: Position, op: (Tree, Position) => Unit)(implicit ctx: Context): Unit =
- if (parentPos.exists)
- x match {
- case x: Tree @unchecked =>
- op(x, parentPos)
- x match {
- case x: MemberDef @unchecked => traverse(x.symbol.annotations, x.pos, op)
- case _ =>
- }
- traverse(x.productIterator, x.pos, op)
- case x: DeferredPosition =>
- x.parentPos = parentPos
- case xs: TraversableOnce[_] =>
- xs.foreach(traverse(_, parentPos, op))
- case _ =>
- }
-}
-import PositionPickler._
-
-class PositionPickler(pickler: TastyPickler, addrOfTree: Tree => Option[Addr]) {
+class PositionPickler(pickler: TastyPickler, addrOfTree: tpd.Tree => Option[Addr]) {
val buf = new TastyBuffer(5000)
pickler.newSection("Positions", buf)
import buf._
+ import ast.tpd._
+
+ def header(addrDelta: Int, hasStartDelta: Boolean, hasEndDelta: Boolean) = {
+ def toInt(b: Boolean) = if (b) 1 else 0
+ (addrDelta << 2) | (toInt(hasStartDelta) << 1) | toInt(hasEndDelta)
+ }
- def picklePositions(roots: List[Tree], totalRange: Position)(implicit ctx: Context) = {
+ def picklePositions(roots: List[Tree])(implicit ctx: Context) = {
var lastIndex = 0
- def record(tree: Tree, parentPos: Position): Unit =
- if (tree.pos.exists) {
- def msg = s"failure to pickle $tree at ${tree.pos}, parent = $parentPos"
- val endPos = tree.pos.end min parentPos.end
- // end positions can be larger than their parents
- // e.g. in the case of synthetic empty ranges, which are placed at the next token after
- // the current construct.
- val endDelta = endPos - parentPos.end
- val startPos =
- if (endDelta == 0) tree.pos.start max parentPos.start else tree.pos.start min endPos
- // Since end positions are corrected above, start positions have to follow suit.
- val startDelta = startPos - parentPos.start
- if (startDelta != 0 || endDelta != 0)
- for (addr <- addrOfTree(tree)) {
- buf.writeInt(addr.index - lastIndex)
- lastIndex = addr.index
- if (startDelta != 0) buf.writeInt(startDelta)
- if (endDelta != 0) {
- assert(endDelta < 0, msg)
- buf.writeInt(endDelta)
- } else
- assert(startDelta >= 0, msg)
+ 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))
+ if (startDelta != 0) buf.writeInt(startDelta)
+ if (endDelta != 0) buf.writeInt(endDelta)
+ lastIndex = index
+ lastPos = pos
+ }
+ def traverse(x: Any, parentPos: Position): 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)
+ case _ =>
}
- }
-
- buf.writeNat(totalRange.end)
- traverse(roots, totalRange, record)
+ }
+ x match {
+ case x: MemberDef @unchecked => traverse(x.symbol.annotations, x.pos)
+ case _ =>
+ }
+ traverse(x.productIterator, x.pos)
+ case xs: TraversableOnce[_] =>
+ xs.foreach(traverse(_, parentPos))
+ case _ =>
+ }
+ traverse(roots, NoPosition)
}
}