summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@gmail.com>2016-01-19 15:30:51 +0100
committerLukas Rytz <lukas.rytz@gmail.com>2016-01-19 16:27:41 +0100
commita3e62cc194699254aa689030b155a29af8356619 (patch)
tree1aec1b5af65d5483df58314e219dfce14f064c52
parented74a84113fab294391eda19efab6d172f414c01 (diff)
downloadscala-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
-rw-r--r--src/reflect/scala/reflect/api/Printers.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Printers.scala48
-rw-r--r--test/files/run/showraw_tree_types_ids.check8
-rw-r--r--test/files/run/showraw_tree_types_typed.check8
-rw-r--r--test/files/run/showraw_tree_ultimate.check8
5 files changed, 36 insertions, 38 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
diff --git a/test/files/run/showraw_tree_types_ids.check b/test/files/run/showraw_tree_types_ids.check
index 75347463cb..e122148040 100644
--- a/test/files/run/showraw_tree_types_ids.check
+++ b/test/files/run/showraw_tree_types_ids.check
@@ -4,9 +4,9 @@ Apply[1](Select[2](New[1](TypeTree[1]().setOriginal(AppliedTypeTree(Ident[3](sca
[3] TypeRef(ThisType(scala.collection.immutable#<id>), scala.collection.immutable.HashMap#<id>, List())
[4] TypeRef(SingleType(ThisType(scala#<id>), scala.Predef#<id>), TypeName("String")#<id>, List())
[5] SingleType(ThisType(scala#<id>), scala.Predef#<id>)
-Apply[6](Select[7](New[6](TypeTree[6]().setOriginal(AppliedTypeTree(Ident[8](scala.collection.mutable.HashMap#<id>), List(TypeTree[4]().setOriginal(Select[4](Ident[5](scala.Predef#<id>), TypeName("String")#<id>)), TypeTree[4]().setOriginal(Select[4](Ident[5](scala.Predef#<id>), TypeName("String")#<id>)))))), termNames.CONSTRUCTOR#<id>), List())
+Apply[1](Select[2](New[1](TypeTree[1]().setOriginal(AppliedTypeTree(Ident[3](scala.collection.mutable.HashMap#<id>), List(TypeTree[4]().setOriginal(Select[4](Ident[5](scala.Predef#<id>), TypeName("String")#<id>)), TypeTree[4]().setOriginal(Select[4](Ident[5](scala.Predef#<id>), TypeName("String")#<id>)))))), termNames.CONSTRUCTOR#<id>), List())
+[1] TypeRef(ThisType(scala.collection.mutable#<id>), scala.collection.mutable.HashMap#<id>, List(TypeRef(SingleType(ThisType(scala#<id>), scala.Predef#<id>), TypeName("String")#<id>, List()), TypeRef(SingleType(ThisType(scala#<id>), scala.Predef#<id>), TypeName("String")#<id>, List())))
+[2] MethodType(List(), TypeRef(ThisType(scala.collection.mutable#<id>), scala.collection.mutable.HashMap#<id>, List(TypeRef(SingleType(ThisType(scala#<id>), scala.Predef#<id>), TypeName("String")#<id>, List()), TypeRef(SingleType(ThisType(scala#<id>), scala.Predef#<id>), TypeName("String")#<id>, List()))))
+[3] TypeRef(ThisType(scala.collection.mutable#<id>), scala.collection.mutable.HashMap#<id>, List())
[4] TypeRef(SingleType(ThisType(scala#<id>), scala.Predef#<id>), TypeName("String")#<id>, List())
[5] SingleType(ThisType(scala#<id>), scala.Predef#<id>)
-[6] TypeRef(ThisType(scala.collection.mutable#<id>), scala.collection.mutable.HashMap#<id>, List(TypeRef(SingleType(ThisType(scala#<id>), scala.Predef#<id>), TypeName("String")#<id>, List()), TypeRef(SingleType(ThisType(scala#<id>), scala.Predef#<id>), TypeName("String")#<id>, List())))
-[7] MethodType(List(), TypeRef(ThisType(scala.collection.mutable#<id>), scala.collection.mutable.HashMap#<id>, List(TypeRef(SingleType(ThisType(scala#<id>), scala.Predef#<id>), TypeName("String")#<id>, List()), TypeRef(SingleType(ThisType(scala#<id>), scala.Predef#<id>), TypeName("String")#<id>, List()))))
-[8] TypeRef(ThisType(scala.collection.mutable#<id>), scala.collection.mutable.HashMap#<id>, List())
diff --git a/test/files/run/showraw_tree_types_typed.check b/test/files/run/showraw_tree_types_typed.check
index de691e369e..4934ed41dc 100644
--- a/test/files/run/showraw_tree_types_typed.check
+++ b/test/files/run/showraw_tree_types_typed.check
@@ -4,9 +4,9 @@ Apply[1](Select[2](New[1](TypeTree[1]().setOriginal(AppliedTypeTree(Ident[3](sca
[3] TypeRef(ThisType(scala.collection.immutable), scala.collection.immutable.HashMap, List())
[4] TypeRef(SingleType(ThisType(scala), scala.Predef), TypeName("String"), List())
[5] SingleType(ThisType(scala), scala.Predef)
-Apply[6](Select[7](New[6](TypeTree[6]().setOriginal(AppliedTypeTree(Ident[8](scala.collection.mutable.HashMap), List(TypeTree[4]().setOriginal(Select[4](Ident[5](scala.Predef), TypeName("String"))), TypeTree[4]().setOriginal(Select[4](Ident[5](scala.Predef), TypeName("String"))))))), termNames.CONSTRUCTOR), List())
+Apply[1](Select[2](New[1](TypeTree[1]().setOriginal(AppliedTypeTree(Ident[3](scala.collection.mutable.HashMap), List(TypeTree[4]().setOriginal(Select[4](Ident[5](scala.Predef), TypeName("String"))), TypeTree[4]().setOriginal(Select[4](Ident[5](scala.Predef), TypeName("String"))))))), termNames.CONSTRUCTOR), List())
+[1] TypeRef(ThisType(scala.collection.mutable), scala.collection.mutable.HashMap, List(TypeRef(SingleType(ThisType(scala), scala.Predef), TypeName("String"), List()), TypeRef(SingleType(ThisType(scala), scala.Predef), TypeName("String"), List())))
+[2] MethodType(List(), TypeRef(ThisType(scala.collection.mutable), scala.collection.mutable.HashMap, List(TypeRef(SingleType(ThisType(scala), scala.Predef), TypeName("String"), List()), TypeRef(SingleType(ThisType(scala), scala.Predef), TypeName("String"), List()))))
+[3] TypeRef(ThisType(scala.collection.mutable), scala.collection.mutable.HashMap, List())
[4] TypeRef(SingleType(ThisType(scala), scala.Predef), TypeName("String"), List())
[5] SingleType(ThisType(scala), scala.Predef)
-[6] TypeRef(ThisType(scala.collection.mutable), scala.collection.mutable.HashMap, List(TypeRef(SingleType(ThisType(scala), scala.Predef), TypeName("String"), List()), TypeRef(SingleType(ThisType(scala), scala.Predef), TypeName("String"), List())))
-[7] MethodType(List(), TypeRef(ThisType(scala.collection.mutable), scala.collection.mutable.HashMap, List(TypeRef(SingleType(ThisType(scala), scala.Predef), TypeName("String"), List()), TypeRef(SingleType(ThisType(scala), scala.Predef), TypeName("String"), List()))))
-[8] TypeRef(ThisType(scala.collection.mutable), scala.collection.mutable.HashMap, List())
diff --git a/test/files/run/showraw_tree_ultimate.check b/test/files/run/showraw_tree_ultimate.check
index 81efcc05ab..b94d568a75 100644
--- a/test/files/run/showraw_tree_ultimate.check
+++ b/test/files/run/showraw_tree_ultimate.check
@@ -4,9 +4,9 @@ Apply[1](Select[2](New[1](TypeTree[1]().setOriginal(AppliedTypeTree(Ident[3](sca
[3] TypeRef(ThisType(scala.collection.immutable#<id>#PKC), scala.collection.immutable.HashMap#<id>#CLS, List())
[4] TypeRef(SingleType(ThisType(scala#<id>#PKC), scala.Predef#<id>#MOD), TypeName("String")#<id>#TPE, List())
[5] SingleType(ThisType(scala#<id>#PKC), scala.Predef#<id>#MOD)
-Apply[6](Select[7](New[6](TypeTree[6]().setOriginal(AppliedTypeTree(Ident[8](scala.collection.mutable.HashMap#<id>#CLS), List(TypeTree[4]().setOriginal(Select[4](Ident[5](scala.Predef#<id>#MOD), TypeName("String")#<id>#TPE)), TypeTree[4]().setOriginal(Select[4](Ident[5](scala.Predef#<id>#MOD), TypeName("String")#<id>#TPE)))))), termNames.CONSTRUCTOR#<id>#CTOR), List())
+Apply[1](Select[2](New[1](TypeTree[1]().setOriginal(AppliedTypeTree(Ident[3](scala.collection.mutable.HashMap#<id>#CLS), List(TypeTree[4]().setOriginal(Select[4](Ident[5](scala.Predef#<id>#MOD), TypeName("String")#<id>#TPE)), TypeTree[4]().setOriginal(Select[4](Ident[5](scala.Predef#<id>#MOD), TypeName("String")#<id>#TPE)))))), termNames.CONSTRUCTOR#<id>#CTOR), List())
+[1] TypeRef(ThisType(scala.collection.mutable#<id>#PKC), scala.collection.mutable.HashMap#<id>#CLS, List(TypeRef(SingleType(ThisType(scala#<id>#PKC), scala.Predef#<id>#MOD), TypeName("String")#<id>#TPE, List()), TypeRef(SingleType(ThisType(scala#<id>#PKC), scala.Predef#<id>#MOD), TypeName("String")#<id>#TPE, List())))
+[2] MethodType(List(), TypeRef(ThisType(scala.collection.mutable#<id>#PKC), scala.collection.mutable.HashMap#<id>#CLS, List(TypeRef(SingleType(ThisType(scala#<id>#PKC), scala.Predef#<id>#MOD), TypeName("String")#<id>#TPE, List()), TypeRef(SingleType(ThisType(scala#<id>#PKC), scala.Predef#<id>#MOD), TypeName("String")#<id>#TPE, List()))))
+[3] TypeRef(ThisType(scala.collection.mutable#<id>#PKC), scala.collection.mutable.HashMap#<id>#CLS, List())
[4] TypeRef(SingleType(ThisType(scala#<id>#PKC), scala.Predef#<id>#MOD), TypeName("String")#<id>#TPE, List())
[5] SingleType(ThisType(scala#<id>#PKC), scala.Predef#<id>#MOD)
-[6] TypeRef(ThisType(scala.collection.mutable#<id>#PKC), scala.collection.mutable.HashMap#<id>#CLS, List(TypeRef(SingleType(ThisType(scala#<id>#PKC), scala.Predef#<id>#MOD), TypeName("String")#<id>#TPE, List()), TypeRef(SingleType(ThisType(scala#<id>#PKC), scala.Predef#<id>#MOD), TypeName("String")#<id>#TPE, List())))
-[7] MethodType(List(), TypeRef(ThisType(scala.collection.mutable#<id>#PKC), scala.collection.mutable.HashMap#<id>#CLS, List(TypeRef(SingleType(ThisType(scala#<id>#PKC), scala.Predef#<id>#MOD), TypeName("String")#<id>#TPE, List()), TypeRef(SingleType(ThisType(scala#<id>#PKC), scala.Predef#<id>#MOD), TypeName("String")#<id>#TPE, List()))))
-[8] TypeRef(ThisType(scala.collection.mutable#<id>#PKC), scala.collection.mutable.HashMap#<id>#CLS, List())