diff options
author | Lukas Rytz <lukas.rytz@gmail.com> | 2016-01-19 15:30:51 +0100 |
---|---|---|
committer | Lukas Rytz <lukas.rytz@gmail.com> | 2016-01-19 16:27:41 +0100 |
commit | a3e62cc194699254aa689030b155a29af8356619 (patch) | |
tree | 1aec1b5af65d5483df58314e219dfce14f064c52 /src/reflect | |
parent | ed74a84113fab294391eda19efab6d172f414c01 (diff) | |
download | scala-a3e62cc194699254aa689030b155a29af8356619.tar.gz scala-a3e62cc194699254aa689030b155a29af8356619.tar.bz2 scala-a3e62cc194699254aa689030b155a29af8356619.zip |
SD-70 Don't share footnotes across multiple calls to universe.showRaw
Before this commit, multiple invocations of universe.showRaw used a
shared weak map that caches footnotes. If the two printed objects
have equal components printed as footnotes, e.g., an equal TypeRef,
the result of the second invocation depends on whether the object
has been collected (and removed from the weak map) or not.
See https://github.com/scala/scala-dev/issues/70#issuecomment-171701671
Diffstat (limited to 'src/reflect')
-rw-r--r-- | src/reflect/scala/reflect/api/Printers.scala | 2 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/Printers.scala | 48 |
2 files changed, 24 insertions, 26 deletions
diff --git a/src/reflect/scala/reflect/api/Printers.scala b/src/reflect/scala/reflect/api/Printers.scala index c0abc5120c..257dd6c43e 100644 --- a/src/reflect/scala/reflect/api/Printers.scala +++ b/src/reflect/scala/reflect/api/Printers.scala @@ -232,7 +232,7 @@ trait Printers { self: Universe => * @group Printers */ def showRaw(any: Any, printTypes: BooleanFlag = None, printIds: BooleanFlag = None, printOwners: BooleanFlag = None, printKinds: BooleanFlag = None, printMirrors: BooleanFlag = None, printPositions: BooleanFlag = None): String = - render(any, newRawTreePrinter(_), printTypes, printIds, printOwners, printKinds, printMirrors, printPositions) + render(any, newRawTreePrinter, printTypes, printIds, printOwners, printKinds, printMirrors, printPositions) /** Hook to define what `showRaw(...)` means. * @group Printers diff --git a/src/reflect/scala/reflect/internal/Printers.scala b/src/reflect/scala/reflect/internal/Printers.scala index 8fb7a0c1d0..37b99c4345 100644 --- a/src/reflect/scala/reflect/internal/Printers.scala +++ b/src/reflect/scala/reflect/internal/Printers.scala @@ -1134,11 +1134,12 @@ trait Printers extends api.Printers { self: SymbolTable => def newRawTreePrinter(writer: PrintWriter): RawTreePrinter = new RawTreePrinter(writer) // provides footnotes for types and mirrors - import scala.collection.mutable.{Map, WeakHashMap, SortedSet} - private val footnoteIndex = new FootnoteIndex - private class FootnoteIndex { + private class Footnotes { + import scala.collection.mutable.{Map, WeakHashMap, SortedSet} + private val index = Map[Class[_], WeakHashMap[Any, Int]]() private def classIndex[T: ClassTag] = index.getOrElseUpdate(classTag[T].runtimeClass, WeakHashMap[Any, Int]()) + private val counters = Map[Class[_], Int]() private def nextCounter[T: ClassTag] = { val clazz = classTag[T].runtimeClass @@ -1147,29 +1148,26 @@ trait Printers extends api.Printers { self: SymbolTable => counters(clazz) } - def mkFootnotes() = new Footnotes - class Footnotes { - private val footnotes = Map[Class[_], SortedSet[Int]]() - private def classFootnotes[T: ClassTag] = footnotes.getOrElseUpdate(classTag[T].runtimeClass, SortedSet[Int]()) + private val footnotes = Map[Class[_], SortedSet[Int]]() + private def classFootnotes[T: ClassTag] = footnotes.getOrElseUpdate(classTag[T].runtimeClass, SortedSet[Int]()) - def put[T: ClassTag](any: T): Int = { - val index = classIndex[T].getOrElseUpdate(any, nextCounter[T]) - classFootnotes[T] += index - index - } + def put[T: ClassTag](any: T): Int = { + val index = classIndex[T].getOrElseUpdate(any, nextCounter[T]) + classFootnotes[T] += index + index + } - def get[T: ClassTag]: List[(Int, Any)] = - classFootnotes[T].toList map (fi => (fi, classIndex[T].find{ case (any, ii) => ii == fi }.get._1)) - - def print[T: ClassTag](printer: Printers.super.TreePrinter): Unit = { - val footnotes = get[T] - if (footnotes.nonEmpty) { - printer.print(EOL) - footnotes.zipWithIndex foreach { - case ((fi, any), ii) => - printer.print("[", fi, "] ", any) - if (ii < footnotes.length - 1) printer.print(EOL) - } + def get[T: ClassTag]: List[(Int, Any)] = + classFootnotes[T].toList map (fi => (fi, classIndex[T].find{ case (any, ii) => ii == fi }.get._1)) + + def print[T: ClassTag](printer: Printers.super.TreePrinter): Unit = { + val footnotes = get[T] + if (footnotes.nonEmpty) { + printer.print(EOL) + footnotes.zipWithIndex foreach { + case ((fi, any), ii) => + printer.print("[", fi, "] ", any) + if (ii < footnotes.length - 1) printer.print(EOL) } } } @@ -1180,7 +1178,7 @@ trait Printers extends api.Printers { self: SymbolTable => private var depth = 0 private var printTypesInFootnotes = true private var printingFootnotes = false - private val footnotes = footnoteIndex.mkFootnotes() + private val footnotes = new Footnotes() def print(args: Any*): Unit = { // don't print type footnotes if the argument is a mere type |