From 4224d2a7b0a6beb47760fc323e9c946813f6bdb0 Mon Sep 17 00:00:00 2001 From: Eugene Burmako Date: Sat, 28 Jan 2012 07:49:20 +0100 Subject: -Yshow-symkinds: prints kinds next to symbol names This very situational option proved to be very useful when debugging https://issues.scala-lang.org/browse/SI-5415 With the help of -Yshow-symkinds, it became possible to distinguish a free var from a module symbol, which gave precise indication of the root of the bug. --- src/compiler/scala/reflect/internal/Symbols.scala | 74 ++++++++++++++-------- .../scala/reflect/internal/TreePrinters.scala | 18 ++++-- src/compiler/scala/reflect/internal/Types.scala | 2 +- .../internal/settings/MutableSettings.scala | 1 + src/compiler/scala/reflect/runtime/Settings.scala | 1 + src/compiler/scala/reflect/runtime/ToolBoxes.scala | 20 ++++-- .../scala/tools/nsc/settings/ScalaSettings.scala | 1 + 7 files changed, 78 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala index 9f8476a6fe..408ff9593a 100644 --- a/src/compiler/scala/reflect/internal/Symbols.scala +++ b/src/compiler/scala/reflect/internal/Symbols.scala @@ -1898,36 +1898,43 @@ trait Symbols extends api.Symbols { self: SymbolTable => else if (isTerm && (!isParameter || isParamAccessor)) "val" else "" + private case class SymbolKind(accurate: String, sanitized: String, abbreviation: String) + private def symbolKind: SymbolKind = { + val kind = + if (isInstanceOf[FreeVar]) ("free variable", "free variable", "FV") + else if (isPackage) ("package", "package", "PK") + else if (isPackageClass) ("package class", "package", "PKC") + else if (isPackageObject) ("package object", "package", "PKO") + else if (isPackageObjectClass) ("package object class", "package", "PKOC") + else if (isAnonymousClass) ("anonymous class", "anonymous class", "AC") + else if (isRefinementClass) ("refinement class", "", "RC") + else if (isModule) ("module", "object", "MOD") + else if (isModuleClass) ("module class", "object", "MODC") + else if (isGetter) ("getter", if (isSourceMethod) "method" else "value", "GET") + else if (isSetter) ("setter", if (isSourceMethod) "method" else "value", "SET") + else if (isTerm && isLazy) ("lazy value", "lazy value", "LAZ") + else if (isVariable) ("field", "variable", "VAR") + else if (isTrait) ("trait", "trait", "TRT") + else if (isClass) ("class", "class", "CLS") + else if (isType) ("type", "type", "TPE") + else if (isClassConstructor) ("constructor", "constructor", "CTOR") + else if (isSourceMethod) ("method", "method", "METH") + else if (isTerm) ("value", "value", "VAL") + else ("", "", "???") + SymbolKind(kind._1, kind._2, kind._3) + } + /** Accurate string representation of symbols' kind, suitable for developers. */ final def accurateKindString: String = - if (isPackage) "package" - else if (isPackageClass) "package class" - else if (isPackageObject) "package object" - else if (isPackageObjectClass) "package object class" - else if (isRefinementClass) "refinement class" - else if (isModule) "module" - else if (isModuleClass) "module class" - else if (isGetter) "getter" - else if (isSetter) "setter" - else if (isVariable) "field" - else sanitizedKindString + symbolKind.accurate /** String representation of symbol's kind, suitable for the masses. */ private def sanitizedKindString: String = - if (isPackage || isPackageClass) "package" - else if (isModule || isModuleClass) "object" - else if (isAnonymousClass) "anonymous class" - else if (isRefinementClass) "" - else if (isTrait) "trait" - else if (isClass) "class" - else if (isType) "type" - else if (isInstanceOf[FreeVar]) "free variable" - else if (isTerm && isLazy) "lazy value" - else if (isVariable) "variable" - else if (isClassConstructor) "constructor" - else if (isSourceMethod) "method" - else if (isTerm) "value" - else "" + symbolKind.sanitized + + /** String representation of symbol's kind, suitable for the masses. */ + protected[scala] def abbreviatedKindString: String = + symbolKind.abbreviation final def kindString: String = if (settings.debug.value) accurateKindString @@ -1950,12 +1957,25 @@ trait Symbols extends api.Symbols { self: SymbolTable => * If !settings.debug translates expansions of operators back to operator symbol. * E.g. $eq => =. * If settings.uniqid, adds id. + * If settings.Yshowsymkinds, adds abbreviated symbol kind. */ def nameString: String = ( - if (settings.uniqid.value) decodedName + "#" + id - else "" + decodedName + if (!settings.uniqid.value && !settings.Yshowsymkinds.value) "" + decodedName + else if (settings.uniqid.value && !settings.Yshowsymkinds.value) decodedName + "#" + id + else if (!settings.uniqid.value && settings.Yshowsymkinds.value) decodedName + "#" + abbreviatedKindString + else decodedName + "#" + id + "#" + abbreviatedKindString ) + def fullNameString: String = { + def recur(sym: Symbol): String = { + if (sym.isRoot || sym.isRootPackage || sym == NoSymbol) sym.nameString + else if (sym.owner.isEffectiveRoot) sym.nameString + else recur(sym.effectiveOwner.enclClass) + "." + sym.nameString + } + + recur(this) + } + /** If settings.uniqid is set, the symbol's id, else "" */ final def idString = if (settings.uniqid.value) "#"+id else "" diff --git a/src/compiler/scala/reflect/internal/TreePrinters.scala b/src/compiler/scala/reflect/internal/TreePrinters.scala index 3a0717d344..63e4c9f1fa 100644 --- a/src/compiler/scala/reflect/internal/TreePrinters.scala +++ b/src/compiler/scala/reflect/internal/TreePrinters.scala @@ -27,10 +27,20 @@ trait TreePrinters extends api.TreePrinters { self: SymbolTable => /** Turns a path into a String, introducing backquotes * as necessary. */ - def backquotedPath(t: Tree): String = t match { - case Select(qual, name) => "%s.%s".format(backquotedPath(qual), quotedName(name)) - case Ident(name) => quotedName(name) - case _ => t.toString + def backquotedPath(t: Tree): String = { + def suffix(t: Tree) = { + var suffix = "" + if (t.hasSymbol && settings.uniqid.value) suffix += ("#" + t.symbol.id) + if (t.hasSymbol && settings.Yshowsymkinds.value) suffix += ("#" + t.symbol.abbreviatedKindString) + suffix + } + + t match { + case Select(qual, name) if name.isTermName => "%s.%s".format(backquotedPath(qual), quotedName(name)) + suffix(t) + case Select(qual, name) if name.isTypeName => "%s#%s".format(backquotedPath(qual), quotedName(name)) + suffix(t) + case Ident(name) => quotedName(name) + suffix(t) + case _ => t.toString + } } class TreePrinter(out: PrintWriter) extends super.TreePrinter { diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala index 35d26493f8..fab10f7896 100644 --- a/src/compiler/scala/reflect/internal/Types.scala +++ b/src/compiler/scala/reflect/internal/Types.scala @@ -1205,7 +1205,7 @@ trait Types extends api.Types { self: SymbolTable => if (settings.debug.value) sym.nameString + ".this." else if (sym.isAnonOrRefinementClass) "this." else if (sym.isOmittablePrefix) "" - else if (sym.isModuleClass) sym.fullName + "." + else if (sym.isModuleClass) sym.fullNameString + "." else sym.nameString + ".this." override def safeToString: String = if (sym.isRoot) "" diff --git a/src/compiler/scala/reflect/internal/settings/MutableSettings.scala b/src/compiler/scala/reflect/internal/settings/MutableSettings.scala index 6980d28bfb..0092f73fe3 100644 --- a/src/compiler/scala/reflect/internal/settings/MutableSettings.scala +++ b/src/compiler/scala/reflect/internal/settings/MutableSettings.scala @@ -38,6 +38,7 @@ abstract class MutableSettings extends AbsSettings { def explaintypes: BooleanSetting def verbose: BooleanSetting def uniqid: BooleanSetting + def Yshowsymkinds: BooleanSetting def Xprintpos: BooleanSetting def Yrecursion: IntSetting def maxClassfileName: IntSetting diff --git a/src/compiler/scala/reflect/runtime/Settings.scala b/src/compiler/scala/reflect/runtime/Settings.scala index 2a6cdea519..b4f0123114 100644 --- a/src/compiler/scala/reflect/runtime/Settings.scala +++ b/src/compiler/scala/reflect/runtime/Settings.scala @@ -28,6 +28,7 @@ class Settings extends internal.settings.MutableSettings { val explaintypes = new BooleanSetting(false) val verbose = new BooleanSetting(false) val uniqid = new BooleanSetting(false) + val Yshowsymkinds = new BooleanSetting(false) val Xprintpos = new BooleanSetting(false) val printtypes = new BooleanSetting(false) val Yrecursion = new IntSetting(0) diff --git a/src/compiler/scala/reflect/runtime/ToolBoxes.scala b/src/compiler/scala/reflect/runtime/ToolBoxes.scala index 9ab12c6a86..46d890c5d1 100644 --- a/src/compiler/scala/reflect/runtime/ToolBoxes.scala +++ b/src/compiler/scala/reflect/runtime/ToolBoxes.scala @@ -123,15 +123,21 @@ trait ToolBoxes extends { self: Universe => applyMeth.invoke(result) } } - - def showAttributed(tree: Tree): String = { - val saved = settings.printtypes.value + + def showAttributed(tree: Tree, printTypes: Boolean = true, printIds: Boolean = true, printKinds: Boolean = false): String = { + val saved1 = settings.printtypes.value + val saved2 = settings.uniqid.value + val saved3 = settings.Yshowsymkinds.value try { - settings.printtypes.value = true - //settings.uniqid.value = true + settings.printtypes.value = printTypes + settings.uniqid.value = printIds + settings.uniqid.value = printKinds tree.toString - } finally - compiler.settings.printtypes.value = saved + } finally { + settings.printtypes.value = saved1 + settings.uniqid.value = saved2 + settings.Yshowsymkinds.value = saved3 + } } } diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index 6806ca03ba..107ffc35c6 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -140,6 +140,7 @@ trait ScalaSettings extends AbsScalaSettings val selfInAnnots = BooleanSetting ("-Yself-in-annots", "Include a \"self\" identifier inside of annotations.") val Xshowtrees = BooleanSetting ("-Yshow-trees", "(Requires -Xprint:) Print detailed ASTs.") val Yshowsyms = BooleanSetting ("-Yshow-syms", "Print the AST symbol hierarchy after each phase.") + val Yshowsymkinds = BooleanSetting ("-Yshow-symkinds", "Print abbreviated symbol kinds next to symbol names.") val skip = PhasesSetting ("-Yskip", "Skip") val Ygenjavap = StringSetting ("-Ygen-javap", "dir", "Generate a parallel output directory of .javap files.", "") val Ydumpclasses = StringSetting ("-Ydump-classes", "dir", "Dump the generated bytecode to .class files (useful for reflective compilation that utilizes in-memory classloaders).", "") -- cgit v1.2.3