diff options
author | Paul Phillips <paulp@improving.org> | 2010-11-08 14:25:01 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2010-11-08 14:25:01 +0000 |
commit | 948f4228c1a279f49093dbc7dc042eea749c463d (patch) | |
tree | 851295427a1ce42d810005a2c945a76c345d7046 /src/compiler/scala/tools/nsc/Global.scala | |
parent | 7f8ccd778d34016e6fb63b218524783da3916573 (diff) | |
download | scala-948f4228c1a279f49093dbc7dc042eea749c463d.tar.gz scala-948f4228c1a279f49093dbc7dc042eea749c463d.tar.bz2 scala-948f4228c1a279f49093dbc7dc042eea749c463d.zip |
A bit of -Xshow-class / -Xshow-object which did...
A bit of -Xshow-class / -Xshow-object which didn't quite make the Global
patch. Now type selections should do the right thing, e.g.
scalac -Xshow-class Global#Run
src/compiler/scala/tools/nsc/Global.scala
will show you interesting things about Run. Or see the test case for
even more thrills. No review.
Diffstat (limited to 'src/compiler/scala/tools/nsc/Global.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/Global.scala | 60 |
1 files changed, 45 insertions, 15 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 60b43a3d17..f3d6b9f41d 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -973,25 +973,55 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable atPhase(phase.next) { currentRun.units foreach treePrinter.print } } - def showDef(name: Name) { - val segments = name.toString split '.' - val container = segments.init.foldLeft(definitions.RootClass: Symbol)(_.info member _) - val target = if (name.isTypeName) newTypeName(segments.last) else newTermName(segments.last) - - // If the name as given resolves to an existing symbol, show that. - // Otherwise we'll show every symbol in the current run with a matching name. - val syms = (container.info member target) match { - case NoSymbol => currentRun.symSource.keys filter (_.name == name) toList - case sym => List(sym) + /** We resolve the class/object ambiguity by passing a type/term name. + */ + def showDef(fullName: Name, ph: Phase = currentRun.typerPhase.next) = { + def phased[T](body: => T): T = atPhase(ph)(body) + + def walker(sym: Symbol, n: Name) = sym.info member n + def walk(root: Symbol, segs: List[Name]) = phased(segs.foldLeft(root)(walker)) + def defs(sym: Symbol) = phased(sym.info.members map (x => if (x.isTerm) x.defString else x.toString)) + def bases(sym: Symbol) = phased(sym.info.baseClasses map (_.fullName)) + def mkName(str: String, term: Boolean) = + if (term) newTermName(str) + else newTypeName(str) + + def nameSegments(name: String): List[Name] = { + name.indexWhere(ch => ch == '.' || ch == '#') match { + // it's the last segment: the argument to showDef tells us whether type or term + case -1 => if (name == "") Nil else List(mkName(name, fullName.isTermName)) + // otherwise, we can tell based on whether '#' or '.' is the following char. + case idx => + val (id, div, rest) = (name take idx, name charAt idx, name drop (idx + 1)) + mkName(id, div == '.') :: nameSegments(rest) + } + } + + val syms = { + // creates a list of simple type and term names. + val segments = nameSegments(fullName.toString) + + // make the type/term selections walking from the root. + walk(definitions.RootClass, segments) match { + // The name as given was not found, so we'll sift through every symbol in + // the run looking for plausible matches. + case NoSymbol => phased { + currentRun.symSource.keys.toList . + filter (_.simpleName == segments.head) . + map (sym => walk(sym, segments.tail)) . + filterNot (_ == NoSymbol) + } + // The name as given matched, so show only that. + case sym => List(sym) + } } syms foreach { sym => - val name = "\n<<-- " + sym.kindString + " " + sym.fullName + " -->>\n" - val baseClasses = sym.info.baseClasses map (_.fullName) mkString ("Base classes:\n ", "\n ", "\n") - val members = atPhase(currentRun.typerPhase.next)(sym.info.members map (_.defString)) - val memberStr = members.mkString("Members after phase typer:\n ", "\n ", "\n") + val name = phased("\n<<-- " + sym.kindString + " " + sym.fullName + " -->>\n") + val baseClasses = bases(sym).mkString("Base classes:\n ", "\n ", "\n") + val members = defs(sym).mkString("Members after phase typer:\n ", "\n ", "\n") - inform(List(name, baseClasses, memberStr) mkString "\n") + inform(List(name, baseClasses, members) mkString "\n") } } |