summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-02-20 17:28:47 +0000
committerPaul Phillips <paulp@improving.org>2011-02-20 17:28:47 +0000
commita765a6ff9497b7cd992c212e5d6660c79f9c2ee8 (patch)
tree269463e232495b9498a858df9299befc1827f20a
parentd221cef8aaa2b8d80a94d1ce7b9525b6008e1c2a (diff)
downloadscala-a765a6ff9497b7cd992c212e5d6660c79f9c2ee8.tar.gz
scala-a765a6ff9497b7cd992c212e5d6660c79f9c2ee8.tar.bz2
scala-a765a6ff9497b7cd992c212e5d6660c79f9c2ee8.zip
More work on symbol trackers.
from one AST snapshot to the next, it displays the nodes which had until so recently been decorated with it. It's quite the symbol whisperer now, try it. scalac -Yshow-syms bippy.scala No review.
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala1
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolTrackers.scala62
2 files changed, 44 insertions, 19 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index ee5bb8dc93..90d1135517 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -107,6 +107,7 @@ trait Trees extends reflect.generic.Trees { self: SymbolTable =>
})
def shallowDuplicate: Tree = new ShallowDuplicator(tree) transform tree
+ def shortClass: String = tree.getClass.getName split "[.$]" last
}
private[scala] override def duplicateTree(tree: Tree): Tree = duplicator transform tree
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolTrackers.scala b/src/compiler/scala/tools/nsc/symtab/SymbolTrackers.scala
index aaa53c284a..870787a9ea 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolTrackers.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolTrackers.scala
@@ -6,6 +6,8 @@
package scala.tools.nsc
package symtab
+import scala.collection.{ mutable, immutable }
+
/** Printing the symbol graph (for those symbols attached to an AST node)
* after each phase.
*/
@@ -13,6 +15,9 @@ trait SymbolTrackers {
val global: Global
import global._
+ private implicit lazy val TreeOrdering: Ordering[Tree] =
+ Ordering by (x => (x.shortClass, x.symbol))
+
private implicit lazy val SymbolOrdering: Ordering[Symbol] =
Ordering by (x => (x.kindString, x.name.toString))
@@ -31,28 +36,35 @@ trait SymbolTrackers {
case class Change(
added: Set[Symbol],
removed: Set[Symbol],
- owners: Map[Symbol, Symbol], // symbol -> previous owner
- flags: Map[Symbol, Long] // symbol -> previous flags
+ trees: Map[Symbol, Set[Tree]], // symbol -> trees which proudly display it
+ owners: Map[Symbol, Symbol], // symbol -> previous owner
+ flags: Map[Symbol, Long] // symbol -> previous flags
)
object SymbolTracker {
def containsSymbol(t: Tree) = t.symbol != null && t.symbol != NoSymbol
- def symbolsInUnit(unit: CompilationUnit): Set[Symbol] = {
- if (unit.body == null) Set.empty[Symbol]
- else unit.body filter containsSymbol map (_.symbol) toSet
+ // This is noise reduction only.
+ def dropSymbol(sym: Symbol) = sym.ownerChain exists (_ hasFlag Flags.SPECIALIZED)
+
+ def symbolSnapshot(unit: CompilationUnit): Map[Symbol, Set[Tree]] = {
+ if (unit.body == null) Map()
+ else unit.body filter containsSymbol groupBy (_.symbol) mapValues (_.toSet) toMap
}
def apply(unit: CompilationUnit) = new SymbolTracker(
- () => symbolsInUnit(unit) filterNot (_.ownerChain.exists(_ hasFlag Flags.SPECIALIZED))
+ () => symbolSnapshot(unit) filterNot { case (k, _) => dropSymbol(k) }
)
}
- class SymbolTracker(sourceFn: () => Set[Symbol]) {
+ class SymbolTracker(snapshotFn: () => Map[Symbol, Set[Tree]]) {
def flagsMask: Long = Flags.PrintableFlags
- private var current = Set[Symbol]()
- private var history = List[Change](Change(Set(), Set(), Map(), Map()))
- private var prev = Set[Symbol]()
+ private var currentMap = Map[Symbol, Set[Tree]]()
+ private var prevMap = Map[Symbol, Set[Tree]]()
+ private def current = currentMap.keySet
+ private def prev = prevMap.keySet
+
+ private var history = List[Change](Change(Set(), Set(), Map(), Map(), Map()))
private var prevFlags = Map[Symbol, Long]()
private var prevOwners = Map[Symbol, Symbol]()
@@ -63,7 +75,6 @@ trait SymbolTrackers {
private implicit def NodeOrdering: Ordering[Node] = Ordering by (_.root)
private def ownersString(sym: Symbol, num: Int) = sym.ownerChain drop 1 take num mkString " -> "
- private def allOwnersString(sym: Symbol) = sym.ownerChain mkString " -> "
object Node {
def nodes(syms: Set[Symbol]): List[Node] = {
@@ -117,7 +128,7 @@ trait SymbolTrackers {
" " + strs.filterNot(_ == "").mkString("[", " ", "]")
case _ =>
if (masked == 0L) ""
- else " " + Flags.flagsToString(masked)
+ else " (" + Flags.flagsToString(masked) + ")"
}
def symString(sym: Symbol) = (
sym + changedOwnerString + flagSummaryString
@@ -137,7 +148,7 @@ trait SymbolTrackers {
}
def snapshot(): Unit = {
- current = sourceFn()
+ currentMap = snapshotFn()
val added = current filterNot prev
val removed = prev filterNot current
@@ -155,22 +166,35 @@ trait SymbolTrackers {
(sym, old)
}).toMap
- val change = Change(added, removed, owners, flags)
+ val change = Change(added, removed, prevMap, owners, flags)
- prev = current
+ prevMap = currentMap
prevOwners = current map (s => (s, s.owner)) toMap;
prevFlags = current map (s => (s, (s.flags & flagsMask))) toMap;
history = change :: history
}
def show(): String = {
val hierarchy = Node(current)
- val removed = history.head.removed
+ val Change(added, removed, symMap, owners, flags) = history.head
+ def detailString(sym: Symbol) = {
+ val ownerString = sym.ownerChain splitAt 3 match {
+ case (front, back) =>
+ val xs = if (back.isEmpty) front else front :+ "..."
+ xs mkString " -> "
+ }
+ val treeStrings = symMap(sym) map { t =>
+ "%10s: %s".format(t.shortClass, t)
+ }
+
+ ownerString :: treeStrings mkString "\n"
+ }
+ def removedString = (removed: List[Symbol]).zipWithIndex map {
+ case (t, i) => "(%2s) ".format(i + 1) + detailString(t)
+ } mkString "\n"
"" + hierarchy + (
if (removed.isEmpty) ""
- else removed map allOwnersString mkString (
- "\n\n!!! " + removed.size + " symbols vanished:\n", "\n", ""
- )
+ else "\n\n!!! %s symbols vanished:\n".format(removed.size) + removedString
)
}
}