1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
/* NSC -- new Scala compiler
* Copyright 2005-2013 LAMP/EPFL
* @author Paul Phillips
*/
package scala
package reflect
package internal
import util._
trait TypeDebugging {
self: SymbolTable =>
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 = (tpe eq null) || 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, ListOfNil, _, 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
case x: TraversableOnce[_] => x mkString ", "
case x: Product => x.productIterator mkString ("(", ", ", ")")
case _ => "" + x
}
def ptBlock(label: String, pairs: (String, Any)*): String = {
if (pairs.isEmpty) label + "{ }"
else {
val width = (pairs map (_._1.length)).max
val fmt = "%-" + (width + 1) + "s %s"
val strs = pairs map { case (k, v) => fmt.format(k, to_s(v)) }
strs.mkString(label + " {\n ", "\n ", "\n}")
}
}
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 ptTypeParam(td: TypeDef): String = {
val TypeDef(_, 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("(", ", ", ")")
def brackets(xs: List[_]): String = if (xs.isEmpty) "" else xs.mkString("[", ", ", "]")
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) => 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)
}
def paramString(tp: Type) = typeDebug.str parentheses (tp.params map (_.defString))
def typeParamsString(tp: Type) = typeDebug.str brackets (tp.typeParams map (_.defString))
def debugString(tp: Type) = typeDebug debugString tp
}
|