summaryrefslogtreecommitdiff
path: root/src/reflect
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2013-06-15 14:28:23 -0400
committerSimon Ochsenreither <simon@ochsenreither.de>2013-07-17 23:38:28 +0200
commit4d6be05c28c95dcd26922059d773a8bfed6014ef (patch)
tree4cbb711d44ad2b073dd21d03811fdf3d7198b4d0 /src/reflect
parentaeb733147881d8da68d1e520b14112dc826a3977 (diff)
downloadscala-4d6be05c28c95dcd26922059d773a8bfed6014ef.tar.gz
scala-4d6be05c28c95dcd26922059d773a8bfed6014ef.tar.bz2
scala-4d6be05c28c95dcd26922059d773a8bfed6014ef.zip
Make -Ytyper-debug output readable.
Diffstat (limited to 'src/reflect')
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala14
-rw-r--r--src/reflect/scala/reflect/internal/TypeDebugging.scala123
2 files changed, 117 insertions, 20 deletions
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index 424296c212..e41038cafc 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -3152,6 +3152,20 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
override def children = childSet
override def addChild(sym: Symbol) { childSet = childSet + sym }
+ def anonOrRefinementString = {
+ if (hasCompleteInfo) {
+ val label = if (isAnonymousClass) "$anon:" else "refinement of"
+ val parents = parentsString(info.parents map functionNBaseType filterNot (_.typeSymbol == SerializableClass))
+ s"<$label $parents>"
+ }
+ else if (isAnonymousClass) "$anon"
+ else nameString
+ }
+ override def toString = (
+ if (isAnonOrRefinementClass) anonOrRefinementString
+ else super.toString
+ )
+
if (Statistics.hotEnabled) Statistics.incCounter(classSymbolCount)
}
implicit val ClassSymbolTag = ClassTag[ClassSymbol](classOf[ClassSymbol])
diff --git a/src/reflect/scala/reflect/internal/TypeDebugging.scala b/src/reflect/scala/reflect/internal/TypeDebugging.scala
index 71f84ab557..9c1342e68e 100644
--- a/src/reflect/scala/reflect/internal/TypeDebugging.scala
+++ b/src/reflect/scala/reflect/internal/TypeDebugging.scala
@@ -7,11 +7,73 @@ package scala
package reflect
package internal
+import util.shortClassOfInstance
+
trait TypeDebugging {
self: SymbolTable =>
- // @M toString that is safe during debugging (does not normalize, ...)
+ import definitions._
+
+ /** There's a whole lot of implementation detail which is nothing but noise when
+ * you are trying to see what's going on. This is my attempt to filter it out.
+ */
+ object noPrint extends (Tree => Boolean) {
+ def skipScalaName(name: Name) = name match {
+ case tpnme.Any | tpnme.Nothing | tpnme.AnyRef => true
+ case _ => false
+ }
+ def skipRefTree(t: RefTree) = t match {
+ case Select(Select(Ident(nme.ROOTPKG), nme.scala_), name) if skipScalaName(name) => true
+ case Select(sel, name) if sel.symbol == ScalaPackage && skipScalaName(name) => true
+ case Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR) => true
+ case Ident(nme.ROOTPKG) => true
+ case _ => skipSym(t.symbol)
+ }
+ def skipSym(sym: Symbol): Boolean = sym match {
+ case null => false
+ case NothingClass | AnyClass => true
+ case PredefModule => true
+ case ObjectClass => true
+ case _ => sym.hasPackageFlag
+ }
+ def skipType(tpe: Type): Boolean = skipSym(tpe.typeSymbolDirect)
+
+ def skip(t: Tree): Boolean = t match {
+ case EmptyTree => true
+ case PackageDef(_, _) => true
+ case t: RefTree => skipRefTree(t)
+ case TypeBoundsTree(lo, hi) => skip(lo) && skip(hi)
+ case Block(Nil, expr) => skip(expr)
+ case Apply(fn, Nil) => skip(fn)
+ case Block(stmt :: Nil, expr) => skip(stmt) && skip(expr)
+ case DefDef(_, nme.CONSTRUCTOR, Nil, Nil :: Nil, _, rhs) => skip(rhs)
+ case Literal(Constant(())) => true
+ case tt @ TypeTree() => skipType(tt.tpe)
+ case _ => skipSym(t.symbol)
+ }
+ def apply(t: Tree) = skip(t)
+ }
+
+ /** Light color wrappers.
+ */
object typeDebug {
+ import scala.Console._
+
+ private val colorsOk = sys.props contains "scala.color"
+ private def inColor(s: String, color: String) = if (colorsOk && s != "") color + s + RESET else s
+ private def inBold(s: String, color: String) = if (colorsOk && s != "") color + BOLD + s + RESET else s
+
+ def inLightRed(s: String) = inColor(s, RED)
+ def inLightGreen(s: String) = inColor(s, GREEN)
+ def inLightMagenta(s: String) = inColor(s, MAGENTA)
+ def inLightCyan(s: String): String = inColor(s, CYAN)
+ def inGreen(s: String): String = inBold(s, GREEN)
+ def inRed(s: String): String = inBold(s, RED)
+ def inBlue(s: String): String = inBold(s, BLUE)
+ def inCyan(s: String): String = inBold(s, CYAN)
+ def inMagenta(s: String) = inBold(s, MAGENTA)
+ def resetColor(s: String): String = if (colorsOk) s + RESET else s
+
private def to_s(x: Any): String = x match {
// otherwise case classes are caught looking like products
case _: Tree | _: Type => "" + x
@@ -29,16 +91,32 @@ trait TypeDebugging {
strs.mkString(label + " {\n ", "\n ", "\n}")
}
}
- def ptLine(label: String, pairs: (String, Any)*): String = {
- val strs = pairs map { case (k, v) => k + "=" + to_s(v) }
- strs.mkString(label + ": ", ", ", "")
+ def ptLine(pairs: (String, Any)*): String = (
+ pairs
+ map { case (k, v) => (k, to_s(v)) }
+ filterNot { case (_, v) => v == "" }
+ map { case ("", v) => v ; case (k, v) => s"$k=$v" }
+ mkString ", "
+ )
+ def ptTree(t: Tree): String = t match {
+ case PackageDef(pid, _) => s"package $pid"
+ case ModuleDef(_, name, _) => s"object $name"
+ case DefDef(_, name, tparams, _, _, _) => "def " + name + ptTypeParams(tparams)
+ case ClassDef(_, name, Nil, _) if t.symbol != null && t.symbol.isModuleClass => s"module class $name"
+ case ClassDef(_, name, tparams, _) => "class " + name + ptTypeParams(tparams)
+ case td: TypeDef => ptTypeParam(td)
+ case TypeBoundsTree(lo, hi) =>
+ val lo_s = if (noPrint(lo)) "" else " >: " + ptTree(lo)
+ val hi_s = if (noPrint(hi)) "" else " <: " + ptTree(hi)
+ lo_s + hi_s
+ case _ if (t.symbol eq null) || (t.symbol eq NoSymbol) => to_s(t)
+ case _ => "" + t.symbol.tpe
}
- def ptTree(t: Tree) = t match {
- case PackageDef(pid, _) => "package " + pid
- case ModuleDef(_, name, _) => "object " + name
- case ClassDef(_, name, tparams, _) => "class " + name + str.brackets(tparams)
- case _ => to_s(t)
+ def ptTypeParam(td: TypeDef): String = {
+ val TypeDef(mods, name, tparams, rhs) = td
+ name + ptTypeParams(tparams) + ptTree(rhs)
}
+ def ptTypeParams(tparams: List[TypeDef]): String = str brackets (tparams map ptTypeParam)
object str {
def parentheses(xs: List[_]): String = xs.mkString("(", ", ", ")")
@@ -46,19 +124,24 @@ trait TypeDebugging {
def tparams(tparams: List[Type]): String = brackets(tparams map debug)
def parents(ps: List[Type]): String = (ps map debug).mkString(" with ")
def refine(defs: Scope): String = defs.toList.mkString("{", " ;\n ", "}")
+ def bounds(lo: Type, hi: Type): String = {
+ val lo_s = if (typeIsNothing(lo)) "" else s" >: $lo"
+ val hi_s = if (typeIsAny(hi)) "" else s" <: $hi"
+ lo_s + hi_s
+ }
}
-
+ import str._
private def debug(tp: Type): String = tp match {
- case TypeRef(pre, sym, args) => debug(pre) + "." + sym.nameString + str.tparams(args)
- case ThisType(sym) => sym.nameString + ".this"
- case SingleType(pre, sym) => debug(pre) +"."+ sym.nameString +".type"
- case RefinedType(parents, defs) => str.parents(parents) + str.refine(defs)
- case ClassInfoType(parents, defs, clazz) => "class "+ clazz.nameString + str.parents(parents) + str.refine(defs)
- case PolyType(tparams, result) => str.brackets(tparams) + " " + debug(result)
- case TypeBounds(lo, hi) => ">: "+ debug(lo) +" <: "+ debug(hi)
- case tv @ TypeVar(_, _) => tv.toString
- case ExistentialType(tparams, qtpe) => "forSome "+ str.brackets(tparams) + " " + debug(qtpe)
- case _ => "?"+tp.getClass.getName+"?"//tp.toString might produce cyclic error...
+ case TypeRef(pre, sym, args) => s"${debug(pre)}.${sym.nameString}.${tparams(args)}"
+ case ThisType(sym) => s"${sym.nameString}.this"
+ case SingleType(pre, sym) => s"${debug(pre)}.${sym.nameString}.type"
+ case RefinedType(ps, decls) => s"${parents(ps)} ${refine(decls)}"
+ case ClassInfoType(ps, decls, clazz) => s"class ${clazz.nameString} ${parents(ps)} ${refine(decls)}"
+ case PolyType(tparams, result) => s"${brackets(tparams)}${debug(result)}"
+ case TypeBounds(lo, hi) => bounds(lo, hi)
+ case tv @ TypeVar(_, _) => "" + tv
+ case ExistentialType(tparams, qtpe) => s"forSome ${brackets(tparams)} ${debug(qtpe)}"
+ case _ => s"?${shortClassOfInstance(tp)}?" // tp.toString might produce cyclic error...
}
def debugString(tp: Type) = debug(tp)
}