summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala7
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Dossiers.scala53
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ILoop.scala74
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/IMain.scala300
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala67
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala39
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/NamedParam.scala3
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ReflectionCompletion.scala109
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala30
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Names.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Symbols.scala21
11 files changed, 409 insertions, 296 deletions
diff --git a/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala b/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala
index 0dc35559a6..9c34565928 100644
--- a/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/CompletionOutput.scala
@@ -13,11 +13,10 @@ package interpreter
*/
trait CompletionOutput {
val global: Global
+
import global._
import definitions.{ NothingClass, AnyClass, isTupleTypeOrSubtype, isFunctionType, isRepeatedParamType }
- def DBG(msg: => Any): Unit
-
/** Reducing fully qualified noise for some common packages.
*/
val typeTransforms = List(
@@ -81,9 +80,7 @@ trait CompletionOutput {
case NullaryMethodType(resType) => ": " + typeToString(resType)
case PolyType(tparams, resType) => tparamsString(tparams) + typeToString(resType)
case mt @ MethodType(_, _) => methodTypeToString(mt)
- case x =>
- DBG("methodString(): %s / %s".format(x.getClass, x))
- x.toString
+ case x => x.toString
})
}
}
diff --git a/src/compiler/scala/tools/nsc/interpreter/Dossiers.scala b/src/compiler/scala/tools/nsc/interpreter/Dossiers.scala
new file mode 100644
index 0000000000..bfa6576b25
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/interpreter/Dossiers.scala
@@ -0,0 +1,53 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.tools.nsc
+package interpreter
+
+// Coming soon
+trait Dossiers {
+ val intp: IMain
+
+ import intp._
+ import intp.global._
+
+ trait Dossier {
+ def symbol: Symbol
+ def staticType: Type
+
+ def id = name.toString
+ def name = symbol.name
+ def normalizedType = staticType.typeSymbolDirect.tpe.normalize
+ def simpleNameOfType = staticType.typeSymbol.simpleName
+ def staticTypeString = staticType.toString
+
+ override def toString = "Dossier on %s:\n static type %s (normalized %s)".format(
+ symbol, staticType, normalizedType
+ )
+ }
+
+ class TypeDossier(val symbol: TypeSymbol, val staticType: Type) extends Dossier {
+ override def toString = super.toString
+ }
+
+ class TermDossier(val symbol: TermSymbol, val staticType: Type, val value: AnyRef) extends Dossier {
+ def runtimeClass: Class[_] = value.getClass
+ def runtimeSymbol: Symbol = safeClass(runtimeClass.getName) getOrElse NoSymbol
+ def runtimeType: Type = runtimeSymbol.tpe
+ def runtimeTypeString = TypeStrings.fromClazz(runtimeClass)
+
+ def runtimeTypedParam = NamedParamClass(id, runtimeTypeString, value)
+ def staticTypedParam = NamedParamClass(id, staticTypeString, value)
+
+ def isRuntimeTypeTighter = runtimeSymbol.ancestors contains normalizedType.typeSymbol
+
+ override def toString = super.toString + (
+ "\n runtime type %s/%s\n value %s".format(
+ runtimeType, runtimeTypeString, value
+ )
+ )
+ }
+}
+
diff --git a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
index a075fe5bb0..c7739b8a8a 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
@@ -196,6 +196,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: PrintWriter)
NoArgs("help", "print this help message", printHelp),
VarArgs("history", "show the history (optional arg: lines to show)", printHistory),
LineArg("h?", "search the history", searchHistory),
+ LineArg("implicits", "show the implicits in scope (-v to include Predef)", implicitsCommand),
LineArg("javap", "disassemble a file or class name", javapCommand),
LineArg("keybindings", "show how ctrl-[A-Z] and other keys are bound", keybindingsCommand),
OneArg("load", "load and interpret a Scala file", load),
@@ -216,6 +217,79 @@ class ILoop(in0: Option[BufferedReader], protected val out: PrintWriter)
LineArg("wrap", "code to wrap around all executions", wrapCommand)
)
}
+
+ private val typeTransforms = List(
+ "scala.collection.immutable." -> "immutable.",
+ "scala.collection.mutable." -> "mutable.",
+ "scala.collection.generic." -> "generic.",
+ "java.lang." -> "jl.",
+ "scala.runtime." -> "runtime."
+ )
+
+ private def implicitsCommand(line: String): Result = {
+ val intp = ILoop.this.intp
+ import intp._
+ import global.Symbol
+
+ def p(x: Any) = intp.reporter.printMessage("" + x)
+ def toDefString(sym: Symbol) = {
+ TypeStrings.quieter(
+ intp.afterTyper(sym.defString),
+ sym.owner.name + ".this.",
+ sym.owner.fullName + "."
+ )
+ }
+
+ // If an argument is given, only show a source with that
+ // in its name somewhere.
+ val args = line split "\\s+"
+ val filtered = intp.implicitSymbolsBySource filter {
+ case (source, syms) =>
+ (args contains "-v") || {
+ if (line == "") (source.fullName.toString != "scala.Predef")
+ else (args exists (source.name.toString contains _))
+ }
+ }
+
+ if (filtered.isEmpty)
+ return "No implicits have been imported other than those in Predef."
+
+ filtered foreach {
+ case (source, syms) =>
+ p("/* " + syms.size + " implicit members imported from " + source.fullName + " */")
+
+ // This groups the members by where the symbol is defined
+ val byOwner = syms groupBy (_.owner)
+ val sortedOwners = byOwner.toList sortBy { case (owner, _) => intp.afterTyper(source.info.baseClasses indexOf owner) }
+
+ sortedOwners foreach {
+ case (owner, members) =>
+ // Within each owner, we cluster results based on the final result type
+ // if there are more than a couple, and sort each cluster based on name.
+ // This is really just trying to make the 100 or so implicits imported
+ // by default into something readable.
+ val memberGroups: List[List[Symbol]] = {
+ val groups = members groupBy (_.tpe.finalResultType) toList
+ val (big, small) = groups partition (_._2.size > 3)
+ val xss = (
+ (big sortBy (_._1.toString) map (_._2)) :+
+ (small flatMap (_._2))
+ )
+
+ xss map (xs => xs sortBy (_.name.toString))
+ }
+
+ val ownerMessage = if (owner == source) " defined in " else " inherited from "
+ p(" /* " + members.size + ownerMessage + owner.fullName + " */")
+
+ memberGroups foreach { group =>
+ group foreach (s => p(" " + toDefString(s)))
+ p("")
+ }
+ }
+ p("")
+ }
+ }
private def javapCommand(line: String): Result = {
if (line == "")
return ":javap <filename or classname>"
diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala
index 3c54c18fe1..21c9dd735e 100644
--- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/IMain.scala
@@ -58,7 +58,7 @@ import IMain._
* @author Lex Spoon
*/
class IMain(val settings: Settings, protected val out: PrintWriter) {
- intp =>
+ imain =>
/** construct an interpreter that reports to Console */
def this(settings: Settings) = this(settings, new NewLinePrintWriter(new ConsoleWriter, true))
@@ -150,10 +150,11 @@ class IMain(val settings: Settings, protected val out: PrintWriter) {
lazy val compiler = global
import global._
+ import definitions.{ ScalaPackage, JavaLangPackage, PredefModule, RootClass }
import nme.{ INTERPRETER_IMPORT_WRAPPER }
object naming extends {
- val global: intp.global.type = intp.global
+ val global: imain.global.type = imain.global
} with Naming {
// make sure we don't overwrite their unwisely named res3 etc.
override def freshUserVarName(): String = {
@@ -164,16 +165,26 @@ class IMain(val settings: Settings, protected val out: PrintWriter) {
}
import naming._
+ // object dossiers extends {
+ // val intp: imain.type = imain
+ // } with Dossiers { }
+ // import dossiers._
+
lazy val memberHandlers = new {
- val intp: IMain.this.type = IMain.this
+ val intp: imain.type = imain
} with MemberHandlers
import memberHandlers._
+ def atPickler[T](op: => T): T = atPhase(currentRun.picklerPhase)(op)
+ def afterTyper[T](op: => T): T = atPhase(currentRun.typerPhase.next)(op)
+
/** Temporarily be quiet */
def beQuietDuring[T](operation: => T): T = {
val wasPrinting = printResults
ultimately(printResults = wasPrinting) {
- printResults = false
+ if (isReplDebug) echo(">> beQuietDuring")
+ else printResults = false
+
operation
}
}
@@ -259,14 +270,6 @@ class IMain(val settings: Settings, protected val out: PrintWriter) {
// Set the current Java "context" class loader to this interpreter's class loader
def setContextClassLoader() = classLoader.setAsContext()
- /** the previous requests this interpreter has processed */
- private lazy val prevRequests = mutable.ArrayBuffer[Request]()
- private lazy val referencedNameMap = mutable.Map[Name, Request]()
- private lazy val definedNameMap = mutable.Map[Name, Request]()
- private def allHandlers = prevRequests.toList flatMap (_.handlers)
- private def allReqAndHandlers = prevRequests.toList flatMap (req => req.handlers map (req -> _))
- private def importHandlers = allHandlers collect { case x: ImportHandler => x }
-
/** Given a simple repl-defined name, returns the real name of
* the class representing it, e.g. for "Bippy" it may return
*
@@ -278,6 +281,7 @@ class IMain(val settings: Settings, protected val out: PrintWriter) {
case _ => id
}
}
+
def allDefinedNames = definedNameMap.keys.toList sortBy (_.toString)
def pathToType(id: String): String = pathToName(newTypeName(id))
def pathToTerm(id: String): String = pathToName(newTermName(id))
@@ -330,10 +334,6 @@ class IMain(val settings: Settings, protected val out: PrintWriter) {
}
}
- def allSeenTypes = prevRequests.toList flatMap (_.typeOf.values.toList) distinct
- def allDefinedTypes = prevRequests.toList flatMap (_.definedTypes.values.toList) distinct
- def allImplicits = allHandlers filter (_.definesImplicit) flatMap (_.definedNames)
-
/** Compute imports that allow definitions from previous
* requests to be visible in a new request. Returns
* three pieces of related code:
@@ -592,6 +592,15 @@ class IMain(val settings: Settings, protected val out: PrintWriter) {
case _ => DBG("Set failed in bind(%s, %s, %s)".format(name, boundType, value)) ; IR.Error
}
}
+ def rebind(p: NamedParam): IR.Result = {
+ val name = p.name
+ val oldType = typeOfTerm(name) getOrElse { return IR.Error }
+ val newType = p.tpe
+ val tempName = freshInternalVarName()
+
+ quietRun("val %s = %s".format(tempName, name))
+ quietRun("val %s = %s.asInstanceOf[%s]".format(name, tempName, newType))
+ }
def quietBind(p: NamedParam): IR.Result = beQuietDuring(bind(p))
def bind(p: NamedParam): IR.Result = bind(p.name, p.tpe, p.value)
@@ -651,16 +660,26 @@ class IMain(val settings: Settings, protected val out: PrintWriter) {
None
}
- lazy val readRoot = definitions.getModule(readPath) // the outermost wrapper
lazy val evalClass = loadByName(evalPath)
lazy val evalValue = callOpt(valueMethod)
def compile(source: String): Boolean = compileAndSaveRun("<console>", source)
- def afterTyper[T](op: => T): T = {
+ def lineAfterTyper[T](op: => T): T = {
assert(lastRun != null, "Internal error: trying to use atPhase, but Run is null." + this)
atPhase(lastRun.typerPhase.next)(op)
}
+ /** The innermost object inside the wrapper, found by
+ * following accessPath into the outer one.
+ */
+ def resolvePathToSymbol(accessPath: String): Symbol = {
+ val readRoot = definitions.getModule(readPath) // the outermost wrapper
+ (accessPath split '.').foldLeft(readRoot) { (sym, name) =>
+ if (name == "") sym else
+ lineAfterTyper(sym.info member newTermName(name))
+ }
+ }
+
// def compileAndTypeExpr(expr: String): Option[Typer] = {
// class TyperRun extends Run {
// override def stopPhase(name: String) = name == "superaccessors"
@@ -685,7 +704,7 @@ class IMain(val settings: Settings, protected val out: PrintWriter) {
// private
class Request(val line: String, val trees: List[Tree]) {
val lineRep = new ReadEvalPrint()
- import lineRep.{ afterTyper }
+ import lineRep.lineAfterTyper
private var _originalLine: String = null
def withOriginalLine(s: String): this.type = { _originalLine = s ; this }
@@ -778,7 +797,7 @@ class IMain(val settings: Settings, protected val out: PrintWriter) {
// ensure it has been compiled
compile
// try to load it and call the value method
- lineRep.evalValue
+ lineRep.evalValue filterNot (_ == null)
}
/** Compile the object file. Returns whether the compilation succeeded.
@@ -791,20 +810,15 @@ class IMain(val settings: Settings, protected val out: PrintWriter) {
lineRep.compile(ObjectSourceCode(handlers)) && {
// extract and remember types
typeOf
- definedTypes
+ typesOfDefinedTerms
// compile the result-extraction object
lineRep compile ResultObjectSourceCode(handlers)
}
}
- /** The innermost object inside the wrapper, found by
- * following accessPath into the outer one. */
- lazy val resObjSym =
- accessPath.split("\\.").foldLeft(lineRep.readRoot) { (sym, name) =>
- if (name == "") sym else
- afterTyper(sym.info member newTermName(name))
- }
+ lazy val resultSymbol = lineRep.resolvePathToSymbol(accessPath)
+ def applyToResultMember[T](name: Name, f: Symbol => T) = lineAfterTyper(f(resultSymbol.info.nonPrivateDecl(name)))
/* typeOf lookup with encoding */
def lookupTypeOf(name: Name) = typeOf.getOrElse(name, typeOf(global.encode(name.toString)))
@@ -813,12 +827,12 @@ class IMain(val settings: Settings, protected val out: PrintWriter) {
private def typeMap[T](f: Type => T): Map[Name, T] = {
def toType(name: Name): T = {
// the types are all =>T; remove the =>
- val tp1 = afterTyper(resObjSym.info.nonPrivateDecl(name).tpe match {
+ val tp1 = lineAfterTyper(resultSymbol.info.nonPrivateDecl(name).tpe match {
case NullaryMethodType(tp) => tp
case tp => tp
})
// normalize non-public types so we don't see protected aliases like Self
- afterTyper(tp1 match {
+ lineAfterTyper(tp1 match {
case TypeRef(_, sym, _) if !sym.isPublic => f(tp1.normalize)
case tp => f(tp)
})
@@ -830,9 +844,14 @@ class IMain(val settings: Settings, protected val out: PrintWriter) {
/** String representations of same. */
lazy val typeOf = typeMap[String](_.toString)
- lazy val definedTypes: Map[Name, Type] = {
- typeNames map (x => x -> afterTyper(resObjSym.info.nonPrivateDecl(x).tpe)) toMap
- }
+ // lazy val definedTypes: Map[Name, Type] = {
+ // typeNames map (x => x -> afterTyper(resultSymbol.info.nonPrivateDecl(x).tpe)) toMap
+ // }
+ lazy val definedSymbols: Map[Name, Symbol] =
+ termNames map (x => x -> applyToResultMember(x, x => x)) toMap
+
+ lazy val typesOfDefinedTerms: Map[Name, Type] =
+ termNames map (x => x -> applyToResultMember(x, _.tpe)) toMap
private def bindExceptionally(t: Throwable) = {
val ex: Exceptional =
@@ -866,9 +885,7 @@ class IMain(val settings: Settings, protected val out: PrintWriter) {
}
try {
- val execution = lineManager.set(originalLine) {
- lineRep call "$export"
- }
+ val execution = lineManager.set(originalLine)(lineRep call "$export")
execution.await()
execution.state match {
@@ -903,26 +920,62 @@ class IMain(val settings: Settings, protected val out: PrintWriter) {
private def requestForIdent(line: String): Option[Request] =
requestForName(newTermName(line)) orElse requestForName(newTypeName(line))
+ def safeClass(name: String): Option[Symbol] = {
+ try Some(definitions.getClass(newTypeName(name)))
+ catch { case _: MissingRequirementError => None }
+ }
+ def safeModule(name: String): Option[Symbol] = {
+ try Some(definitions.getModule(newTermName(name)))
+ catch { case _: MissingRequirementError => None }
+ }
+
def definitionForName(name: Name): Option[MemberHandler] =
requestForName(name) flatMap { req =>
req.handlers find (_.definedNames contains name)
}
+ //
+
+ def valueOfTerm(id: String): Option[AnyRef] =
+ requestForIdent(id) flatMap (_.getEval)
+
+ def classOfTerm(id: String): Option[Class[_]] =
+ valueOfTerm(id) map (_.getClass)
- def typeOfDefinedName(name: Name): Option[Type] =
- if (name == nme.ROOTPKG) Some(definitions.RootClass.tpe)
- else requestForName(name) flatMap (_.compilerTypeOf get name)
+ def typeOfTerm(id: String): Option[Type] = newTermName(id) match {
+ case nme.ROOTPKG => Some(RootClass.tpe)
+ case name => requestForName(name) flatMap (_.compilerTypeOf get name)
+ }
+ def symbolOfTerm(id: String): Symbol =
+ requestForIdent(id) flatMap (_.definedSymbols get newTermName(id)) getOrElse NoSymbol
+
+ def runtimeClassAndTypeOfTerm(id: String): Option[(Class[_], Type)] =
+ for (clazz <- classOfTerm(id) ; tpe <- runtimeTypeOfTerm(id)) yield ((clazz, tpe))
+
+ def runtimeTypeOfTerm(id: String): Option[Type] = {
+ for {
+ tpe <- typeOfTerm(id)
+ clazz <- classOfTerm(id)
+ val staticSym = tpe.typeSymbol
+ runtimeSym <- safeClass(clazz.getName)
+ if runtimeSym != staticSym
+ if runtimeSym isSubClass staticSym
+ } yield {
+ runtimeSym.info
+ }
+ }
// XXX literals.
// 1) Identifiers defined in the repl.
// 2) A path loadable via getModule.
// 3) Try interpreting it as an expression.
+ private var typeOfExpressionDepth = 0
def typeOfExpression(expr: String): Option[Type] = {
- val name = newTermName(expr)
-
- def asModule = {
- try Some(definitions.getModule(name).tpe)
- catch { case _: MissingRequirementError => None }
+ if (typeOfExpressionDepth > 2) {
+ DBG("Terminating typeOfExpression recursion for expression: " + expr)
+ return None
}
+
+ def asModule = safeModule(expr) map (_.tpe)
def asExpr = beSilentDuring {
val lhs = freshInternalVarName()
interpret("val " + lhs + " = { " + expr + " } ") match {
@@ -931,91 +984,40 @@ class IMain(val settings: Settings, protected val out: PrintWriter) {
}
}
- typeOfDefinedName(name) orElse asModule orElse asExpr
- }
-
- def clazzForIdent(id: String): Option[Class[_]] =
- for (res <- getEvalForIdent(id); v <- Option(res)) yield v.getClass
-
- def methodsOf(name: String) =
- evalExpr[List[String]](methodsCode(name)) map (x => NameTransformer.decode(getOriginalName(x)))
-
- def completionAware(name: String) = {
- // XXX working around "object is not a value" crash, i.e.
- // import java.util.ArrayList ; ArrayList.<tab>
- clazzForIdent(name) flatMap (_ => evalExpr[Option[CompletionAware]](asCompletionAwareCode(name)))
- }
-
- def getEvalForIdent(id: String): Option[AnyRef] =
- requestForIdent(id) flatMap (_.getEval)
-
- /** Executes code looking for a manifest of type T.
- */
- def manifestFor[T: Manifest] =
- evalExpr[Manifest[T]]("""manifest[%s]""".format(manifest[T]))
-
- /** Executes code looking for an implicit value of type T.
- */
- def implicitFor[T: Manifest] = {
- val s = manifest[T].toString
- evalExpr[Option[T]]("{ def f(implicit x: %s = null): %s = x ; Option(f) }".format(s, s))
- // We don't use implicitly so as to fail without failing.
- // evalExpr[T]("""implicitly[%s]""".format(manifest[T]))
+ typeOfExpressionDepth += 1
+ try typeOfTerm(expr) orElse asModule orElse asExpr
+ finally typeOfExpressionDepth -= 1
}
+ // def compileAndTypeExpr(expr: String): Option[Typer] = {
+ // class TyperRun extends Run {
+ // override def stopPhase(name: String) = name == "superaccessors"
+ // }
+ // }
- private def methodsCode(name: String) =
- "%s.%s(%s)".format(classOf[ReflectionCompletion].getName, "methodsOf", name)
-
- private def asCompletionAwareCode(name: String) =
- "%s.%s(%s)".format(classOf[CompletionAware].getName, "unapply", name)
-
- private def getOriginalName(name: String): String =
- nme.originalName(newTermName(name)).toString
+ private def onlyTerms(xs: List[Name]) = xs collect { case x: TermName => x }
+ private def onlyTypes(xs: List[Name]) = xs collect { case x: TypeName => x }
- case class InterpreterEvalException(msg: String) extends Exception(msg)
- def evalError(msg: String) = throw InterpreterEvalException(msg)
+ def importHandlers = allHandlers collect { case x: ImportHandler => x }
+ def definedTerms = onlyTerms(allDefinedNames) filterNot isInternalVarName
+ def definedTypes = onlyTypes(allDefinedNames)
+ def importedTerms = onlyTerms(importHandlers flatMap (_.importedNames))
+ def importedTypes = onlyTypes(importHandlers flatMap (_.importedNames))
- /** The user-facing eval in :power mode wraps an Option.
- */
- def eval[T: Manifest](line: String): Option[T] =
- try Some(evalExpr[T](line))
- catch { case InterpreterEvalException(msg) => out println indentCode(msg) ; None }
-
- def evalExpr[T: Manifest](line: String): T = {
- // Nothing means the type could not be inferred.
- if (manifest[T] eq Manifest.Nothing)
- evalError("Could not infer type: try 'eval[SomeType](%s)' instead".format(line))
-
- val lhs = freshInternalVarName()
- beQuietDuring { interpret("val " + lhs + " = { " + line + " } ") }
-
- // TODO - can we meaningfully compare the inferred type T with
- // the internal compiler Type assigned to lhs?
- // def assignedType = prevRequests.last.typeOf(newTermName(lhs))
-
- val req = requestFromLine(lhs, true) match {
- case Left(result) => evalError(result.toString)
- case Right(req) => req
- }
- if (req == null || !req.compile || req.handlers.size != 1)
- evalError("Eval error.")
-
- try req.getEvalTyped[T] getOrElse evalError("No result.")
- catch { case e: Exception => evalError(e.getMessage) }
- }
+ /** the previous requests this interpreter has processed */
+ private lazy val prevRequests = mutable.ArrayBuffer[Request]()
+ private lazy val referencedNameMap = mutable.Map[Name, Request]()
+ private lazy val definedNameMap = mutable.Map[Name, Request]()
+ private def allHandlers = prevRequests.toList flatMap (_.handlers)
+ private def allReqAndHandlers = prevRequests.toList flatMap (req => req.handlers map (req -> _))
+ def allSeenTypes = prevRequests.toList flatMap (_.typeOf.values.toList) distinct
+ def allImplicits = allHandlers filter (_.definesImplicit) flatMap (_.definedNames)
- def interpretExpr[T: Manifest](code: String): Option[T] = beQuietDuring {
- interpret(code) match {
- case IR.Success =>
- try prevRequests.last.getEvalTyped[T]
- catch { case e: Exception => out println e ; None }
- case _ => None
- }
- }
+ private def membersAtPickler(sym: Symbol): List[Symbol] =
+ atPickler(sym.info.nonPrivateMembers)
- /** Another entry point for tab-completion, ids in scope */
- private def simpleTermNames =
- allHandlers flatMap (_.definedOrImported) filter (x => x.isTermName && !isInternalVarName(x))
+ /** Symbols whose contents are language-defined to be imported. */
+ def languageWildcardSyms: List[Symbol] = List(JavaLangPackage, ScalaPackage, PredefModule)
+ def languageWildcards: List[Type] = languageWildcardSyms map (_.tpe)
/** Types which have been wildcard imported, such as:
* val x = "abc" ; import x._ // type java.lang.String
@@ -1028,36 +1030,68 @@ class IMain(val settings: Settings, protected val out: PrintWriter) {
* scope twiddling which should be swept away in favor of digging
* into the compiler scopes.
*/
- def wildcardImportedTypes(): List[Type] = {
+ def sessionWildcards: List[Type] = {
importHandlers flatMap {
case x if x.importsWildcard => x.targetType
case _ => None
} distinct
}
+ def wildcardTypes = languageWildcards ++ sessionWildcards
- /** Another entry point for tab-completion, ids in scope */
- def unqualifiedIds() = (simpleTermNames map (_.toString)).distinct.sorted
+ def languageSymbols = languageWildcardSyms flatMap membersAtPickler
+ def sessionSymbols = importHandlers flatMap (_.importedSymbols)
+ def importedSymbols = languageSymbols ++ sessionSymbols
+ def implicitSymbols = importedSymbols filter (_.isImplicit)
+
+ /** Tuples of (source, imported symbols) in the order they were imported.
+ */
+ def importedSymbolsBySource: List[(Symbol, List[Symbol])] = {
+ val lang = languageWildcardSyms map (sym => (sym, membersAtPickler(sym)))
+ val session = importHandlers filter (_.targetType.isDefined) map { mh =>
+ (mh.targetType.get.typeSymbol, mh.importedSymbols)
+ }
+
+ lang ++ session
+ }
+ def implicitSymbolsBySource: List[(Symbol, List[Symbol])] = {
+ importedSymbolsBySource map {
+ case (k, vs) => (k, vs filter (_.isImplicit))
+ } filterNot (_._2.isEmpty)
+ }
+
+ def visibleTermNames: List[Name] = definedTerms ++ importedTerms distinct
- /** For static/object method completion */
- def getClassObject(path: String): Option[Class[_]] = classLoader tryToLoadClass path
+ /** Another entry point for tab-completion, ids in scope */
+ def unqualifiedIds = visibleTermNames map (_.toString) filterNot (_ contains "$") sorted
/** Parse the ScalaSig to find type aliases */
def aliasForType(path: String) = ByteCode.aliasForType(path)
+ def withoutUnwrapping(op: => Unit): Unit = {
+ val saved = isettings.unwrapStrings
+ isettings.unwrapStrings = false
+ try op
+ finally isettings.unwrapStrings = saved
+ }
+
def showCodeIfDebugging(code: String) {
/** Secret bookcase entrance for repl debuggers: end the line
* with "// show" and see what's going on.
*/
if (code.lines exists (_.trim endsWith "// show")) {
echo(code)
- parse(code) foreach (ts => ts foreach (t => DBG(asCompactString(t))))
+ parse(code) foreach (ts => ts foreach (t => withoutUnwrapping(DBG(asCompactString(t)))))
}
}
// debugging
- def isCompletionDebug = settings.Ycompletion.value
- def DBG(s: => String) =
- try if (isReplDebug) repldbg(s)
+ def debugging[T](msg: String)(res: T) = {
+ DBG(msg + " " + res)
+ res
+ }
+ def DBG(s: => String) = if (isReplDebug) {
+ try repldbg(s)
catch { case x: AssertionError => repldbg("Assertion error printing debug string:\n " + x) }
+ }
}
/** Utility methods for the Interpreter. */
@@ -1121,7 +1155,7 @@ object IMain {
// $line3.$read.$iw.$iw.Bippy =
// $line3.$read$$iw$$iw$Bippy@4a6a00ca
private def removeLineWrapper(s: String) = s.replaceAll("""\$line\d+[./]\$(read|eval|print)[$.]""", "")
- private def removeIWPackages(s: String) = s.replaceAll("""\$iw[$.]""", "")
+ private def removeIWPackages(s: String) = s.replaceAll("""\$(iw|read|eval|print)[$.]""", "")
}
class ReplReporter(intp: IMain) extends ConsoleReporter(intp.settings, null, new ReplStrippingWriter(intp)) {
diff --git a/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala b/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala
index 8093ae1d3c..2a19c6fb95 100644
--- a/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala
@@ -20,24 +20,12 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput
import global._
import definitions.{ PredefModule, RootClass, AnyClass, AnyRefClass, ScalaPackage, JavaLangPackage }
type ExecResult = Any
+ import intp.{ DBG, debugging, afterTyper }
// verbosity goes up with consecutive tabs
private var verbosity: Int = 0
def resetVerbosity() = verbosity = 0
- def isCompletionDebug = intp.isCompletionDebug
- def DBG(msg: => Any) = if (isCompletionDebug) println(msg.toString)
- def debugging[T](msg: String): T => T = (res: T) => returning[T](res)(x => DBG(msg + x))
-
- // XXX not yet used.
- lazy val dottedPaths = {
- def walk(tp: Type): scala.List[Symbol] = {
- val pkgs = tp.nonPrivateMembers filter (_.isPackage)
- pkgs ++ (pkgs map (_.tpe) flatMap walk)
- }
- walk(RootClass.tpe)
- }
-
def getType(name: String, isModule: Boolean) = {
val f = if (isModule) definitions.getModule(_: Name) else definitions.getClass(_: Name)
try Some(f(name).tpe)
@@ -66,7 +54,7 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput
// XXX we'd like to say "filterNot (_.isDeprecated)" but this causes the
// compiler to crash for reasons not yet known.
- def members = (effectiveTp.nonPrivateMembers ++ anyMembers) filter (_.isPublic)
+ def members = afterTyper((effectiveTp.nonPrivateMembers ++ anyMembers) filter (_.isPublic))
def methods = members filter (_.isMethod)
def packages = members filter (_.isPackage)
def aliases = members filter (_.isAliasType)
@@ -78,6 +66,31 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput
}
object TypeMemberCompletion {
+ def apply(tp: Type, runtimeType: Type, param: NamedParam): TypeMemberCompletion = {
+ new TypeMemberCompletion(tp) {
+ var upgraded = false
+ lazy val upgrade = {
+ intp rebind param
+ intp.reporter.printMessage("\nRebinding stable value %s from %s to %s".format(param.name, tp, param.tpe))
+ upgraded = true
+ new TypeMemberCompletion(runtimeType)
+ }
+ override def completions(verbosity: Int) = {
+ super.completions(verbosity) ++ (
+ if (verbosity == 0) Nil
+ else upgrade.completions(verbosity)
+ )
+ }
+ override def follow(s: String) = super.follow(s) orElse {
+ if (upgraded) upgrade.follow(s)
+ else None
+ }
+ override def alternativesFor(id: String) = super.alternativesFor(id) ++ (
+ if (upgraded) upgrade.alternativesFor(id)
+ else Nil
+ ) distinct
+ }
+ }
def apply(tp: Type): TypeMemberCompletion = {
if (tp.typeSymbol.isPackageClass) new PackageCompletion(tp)
else new TypeMemberCompletion(tp)
@@ -91,10 +104,7 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput
def excludeStartsWith: List[String] = List("<") // <byname>, <repeated>, etc.
def excludeNames: List[String] = (anyref.methodNames filterNot anyRefMethodsToShow) :+ "_root_"
- def methodSignatureString(sym: Symbol) = {
- def asString = new MethodSymbolOutput(sym).methodString()
- atPhase(currentRun.typerPhase)(asString)
- }
+ def methodSignatureString(sym: Symbol) = afterTyper(new MethodSymbolOutput(sym).methodString())
def exclude(name: String): Boolean = (
(name contains "$") ||
@@ -146,16 +156,29 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput
override def completions(verbosity: Int) = intp.unqualifiedIds ++ List("classOf") //, "_root_")
// now we use the compiler for everything.
override def follow(id: String) = {
- if (completions(0) contains id)
- intp typeOfExpression id map (tpe => TypeMemberCompletion(tpe))
+ if (completions(0) contains id) {
+ intp typeOfExpression id map { tpe =>
+ intp runtimeClassAndTypeOfTerm id match {
+ case Some((clazz, runtimeType)) =>
+ val sym = intp.symbolOfTerm(id)
+ if (sym.isStable) {
+ val param = new NamedParam.Untyped(id, intp valueOfTerm id getOrElse null)
+ TypeMemberCompletion(tpe, runtimeType, param)
+ }
+ else TypeMemberCompletion(tpe)
+ case _ =>
+ TypeMemberCompletion(tpe)
+ }
+ }
+ }
else
None
}
override def toString = "<repl ids> (%s)".format(completions(0).size)
}
- // wildcard imports in the repl like "import global._" or "import String._"
- private def imported = intp.wildcardImportedTypes map TypeMemberCompletion.imported
+ // user-issued wildcard imports like "import global._" or "import String._"
+ private def imported = intp.sessionWildcards map TypeMemberCompletion.imported
// literal Ints, Strings, etc.
object literals extends CompletionAware {
diff --git a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala b/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala
index 3992a0bdfa..29c31f50d6 100644
--- a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala
@@ -14,7 +14,7 @@ import util.Chars
trait MemberHandlers {
val intp: IMain
- import intp.{ Request, global, naming }
+ import intp.{ Request, global, naming, atPickler }
import global._
import naming._
@@ -81,10 +81,10 @@ trait MemberHandlers {
}
sealed abstract class MemberDefHandler(override val member: MemberDef) extends MemberHandler(member) {
- def name: Name = member.name
+ def name: Name = member.name
def mods: Modifiers = member.mods
- def keyword = member.keyword
- def prettyName = NameTransformer.decode(name)
+ def keyword = member.keyword
+ def prettyName = NameTransformer.decode(name)
override def definesImplicit = member.mods.isImplicit
override def definesTerm: Option[TermName] = Some(name.toTermName) filter (_ => name.isTermName)
@@ -95,7 +95,6 @@ trait MemberHandlers {
* in a single interpreter request.
*/
sealed abstract class MemberHandler(val member: Tree) {
- def tpe = member.tpe
def definesImplicit = false
def definesValue = false
def isLegalTopLevel = member match {
@@ -192,24 +191,30 @@ trait MemberHandlers {
val Import(expr, selectors) = imp
def targetType = intp.typeOfExpression("" + expr)
- private def selectorWild = selectors filter (_.name == nme.USCOREkw) // wildcard imports, e.g. import foo._
+ // wildcard imports, e.g. import foo._
+ private def selectorWild = selectors filter (_.name == nme.USCOREkw)
+ // renamed imports, e.g. import foo.{ bar => baz }
private def selectorRenames = selectors map (_.rename) filterNot (_ == null)
/** Whether this import includes a wildcard import */
val importsWildcard = selectorWild.nonEmpty
+ def implicitSymbols = importedSymbols filter (_.isImplicit)
+ def importedSymbols = individualSymbols ++ wildcardSymbols
+
+ lazy val individualSymbols: List[Symbol] =
+ atPickler(targetType.toList flatMap (tp => individualNames map (tp nonPrivateMember _)))
+
+ lazy val wildcardSymbols: List[Symbol] =
+ if (importsWildcard) atPickler(targetType.toList flatMap (_.nonPrivateMembers))
+ else Nil
+
/** Complete list of names imported by a wildcard */
- def wildcardImportedNames: List[Name] = (
- for (tpe <- targetType ; if importsWildcard) yield
- tpe.nonPrivateMembers filter (x => x.isMethod && x.isPublic) map (_.name) distinct
- ).toList.flatten
-
- /** The individual names imported by this statement */
- /** XXX come back to this and see what can be done with wildcards now that
- * we know how to enumerate the identifiers.
- */
- override lazy val importedNames: List[Name] =
- selectorRenames filterNot (_ == nme.USCOREkw) flatMap (_.bothNames)
+ lazy val wildcardNames: List[Name] = wildcardSymbols map (_.name)
+ lazy val individualNames: List[Name] = selectorRenames filterNot (_ == nme.USCOREkw) flatMap (_.bothNames)
+
+ /** The names imported by this statement */
+ override lazy val importedNames: List[Name] = wildcardNames ++ individualNames
override def resultExtractionCode(req: Request) = codegenln(imp.toString) + "\n"
}
diff --git a/src/compiler/scala/tools/nsc/interpreter/NamedParam.scala b/src/compiler/scala/tools/nsc/interpreter/NamedParam.scala
index 878c5b20b1..e92888d89b 100644
--- a/src/compiler/scala/tools/nsc/interpreter/NamedParam.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/NamedParam.scala
@@ -11,6 +11,7 @@ import NamedParam._
trait NamedParamCreator {
protected def freshName: () => String
+ def apply(name: String, tpe: String, value: Any): NamedParam = NamedParamClass(name, tpe, value)
def apply[T: Manifest](name: String, x: T): NamedParam = new Typed[T](name, x)
def apply[T: Manifest](x: T): NamedParam = apply(freshName(), x)
@@ -35,6 +36,8 @@ object NamedParam extends NamedParamCreator {
}
}
+case class NamedParamClass(name: String, tpe: String, value: Any) extends NamedParam { }
+
trait NamedParam {
def name: String
def tpe: String
diff --git a/src/compiler/scala/tools/nsc/interpreter/ReflectionCompletion.scala b/src/compiler/scala/tools/nsc/interpreter/ReflectionCompletion.scala
deleted file mode 100644
index 0cbac2d0d6..0000000000
--- a/src/compiler/scala/tools/nsc/interpreter/ReflectionCompletion.scala
+++ /dev/null
@@ -1,109 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2011 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-
-import java.lang.reflect
-import reflect.{ Modifier, AccessibleObject }
-import Modifier.{ isPrivate, isProtected, isStatic }
-import ReflectionCompletion._
-
-trait ReflectionCompletion extends CompletionAware {
- def clazz: JClass
- protected def visibleMembers: List[AccessibleObject]
- protected def memberCompletions = visibleMembers filter isPublic map reflectName
-
- def reflectName(m: AccessibleObject) = m match {
- case x: reflect.Method => x.getName
- case x: reflect.Field => x.getName
- case x => sys.error(x.toString)
- }
- def isPublic(m: AccessibleObject) = m match {
- case x: reflect.Method => Modifier isPublic x.getModifiers
- case x: reflect.Field => Modifier isPublic x.getModifiers
- case x => sys.error(x.toString)
- }
-
- lazy val (staticMethods, instanceMethods) = clazz.getMethods.toList partition (x => isStatic(x.getModifiers))
- lazy val (staticFields, instanceFields) = clazz.getFields.toList partition (x => isStatic(x.getModifiers))
-
- /** Oops, mirror classes don't descend from scalaobject.
- */
- def isScalaClazz(cl: JClass) = {
- (allInterfacesFor(cl) exists (_.getName == "scala.ScalaObject")) ||
- (classForName(cl.getName + "$").isDefined)
- }
- def allInterfacesFor(cl: JClass): List[JClass] = allInterfacesFor(cl, Nil)
-
- private def allInterfacesFor(cl: JClass, acc: List[JClass]): List[JClass] = {
- if (cl == null) acc.distinct
- else allInterfacesFor(cl.getSuperclass, acc ::: cl.getInterfaces.toList)
- }
-}
-
-/** A completion aware object representing a single instance of some class.
- * It completes to instance fields and methods, and delegates to another
- * InstanceCompletion object if it can determine the result type of the element.
- */
-class InstanceCompletion(val clazz: JClass) extends ReflectionCompletion {
- protected def visibleMembers = instanceMethods ::: instanceFields
- def extras = List("isInstanceOf", "asInstanceOf", "toString")
- lazy val completions = memberCompletions ::: extras
- def completions(verbosity: Int) = completions
-
- val (zeroArg, otherArg) = instanceMethods partition (_.getParameterTypes.size == 0)
- override def follow(id: String) = {
- val nextClazz = zeroArg find (m => m.getName == id) map (_.getReturnType)
- if (nextClazz.isDefined) nextClazz map (x => new InstanceCompletion(x))
- else instanceFields find (_.getName == id) map (x => new InstanceCompletion(x.getType))
- }
-}
-
-/** The complementary class to InstanceCompletion. It has logic to deal with
- * java static members and scala companion object members.
- */
-class StaticCompletion(val clazz: JClass) extends ReflectionCompletion {
- protected def visibleMembers = whichMethods ::: whichFields
- lazy val completions = memberCompletions
- def completions(verbosity: Int) = completions
-
- def className = clazz.getName
- def isJava = !isScalaClazz(clazz)
-
- private def whichMethods = if (isJava) staticMethods else instanceMethods
- private def whichFields = if (isJava) staticFields else instanceFields
- val (zeroArg, otherArg) = whichMethods partition (_.getParameterTypes.size == 0)
-
- override def follow(id: String) = {
- val nextClazz = zeroArg find (m => m.getName == id) map (_.getReturnType)
- if (nextClazz.isDefined) nextClazz map (x => new InstanceCompletion(x))
- else staticFields find (_.getName == id) map (x => new InstanceCompletion(x.getType))
- }
-
- override def toString = "StaticCompletion(%s) => %s".format(clazz.getName, completions)
-}
-
-object ReflectionCompletion {
- import java.io.File
- import java.util.jar.{ JarEntry, JarFile }
- import scala.tools.nsc.io.Streamable
-
- // XXX at the moment this is imperfect because scala's protected semantics
- // differ from java's, so protected methods appear public via reflection;
- // yet scala enforces the protection. The result is that protected members
- // appear in completion yet cannot actually be called. Fixing this
- // properly requires a scala.reflect.* API. Fixing it uglily is possible
- // too (cast to structural type!) but I deem poor use of energy.
- private def skipModifiers(m: reflect.Method) = {
- import java.lang.reflect.Modifier._
- val flags = STATIC | PRIVATE | PROTECTED
- (m.getModifiers & flags) == 0
- }
- private def getAnyClass(x: Any): JClass = x.asInstanceOf[AnyRef].getClass
-
- def methodsOf(target: Any): List[String] =
- getAnyClass(target).getMethods filter skipModifiers map (_.getName) toList
-}
diff --git a/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala b/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala
index f72409c8e7..4bc2246468 100644
--- a/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala
@@ -41,7 +41,18 @@ trait TypeStrings {
else if (primitives(s)) "scala." + s.capitalize
else primitiveMap.getOrElse(s, NameTransformer decode s)
}
- def scalaName(clazz: JClass): String = scalaName(clazz.getName)
+ def scalaName(clazz: JClass): String = {
+ val name = clazz.getName
+ scalaName(clazz.getEnclosingClass match {
+ case null => name
+ case encl =>
+ val enclName = encl.getName
+ if (name startsWith (enclName + "$"))
+ enclName + "." + (name stripPrefix (enclName + "$"))
+ else
+ name
+ })
+ }
def scalaName(m: ClassManifest[_]): String = scalaName(m.erasure)
def anyClass(x: Any): JClass = if (x == null) null else x.asInstanceOf[AnyRef].getClass
@@ -55,8 +66,9 @@ trait TypeStrings {
if (xs.isEmpty) "_"
else scalaName(xs.head)
}
- private def tparamString(clazz: JClass): String =
+ private def tparamString(clazz: JClass): String = {
brackets(clazz.getTypeParameters map tvarString: _*)
+ }
private def tparamString[T: Manifest] : String =
brackets(manifest[T].typeArguments map (m => tvarString(List(m.erasure))): _*)
@@ -76,6 +88,20 @@ trait TypeStrings {
/** Reducing fully qualified noise for some common packages.
*/
+ def quieter(tpe: String, alsoStrip: String*): String = {
+ val transforms = List(
+ "scala.collection.immutable." -> "immutable.",
+ "scala.collection.mutable." -> "mutable.",
+ "scala.collection.generic." -> "generic.",
+ "java.lang." -> "jl.",
+ "scala.runtime." -> "runtime."
+ ) ++ (alsoStrip map (_ -> ""))
+
+ transforms.foldLeft(tpe) {
+ case (res, (k, v)) => res.replaceAll(k, v)
+ }
+ }
+
val typeTransforms = List(
"java.lang." -> "",
"scala.collection.immutable." -> "immutable.",
diff --git a/src/compiler/scala/tools/nsc/symtab/Names.scala b/src/compiler/scala/tools/nsc/symtab/Names.scala
index 6772b8d5e2..4ca4880d35 100644
--- a/src/compiler/scala/tools/nsc/symtab/Names.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Names.scala
@@ -401,6 +401,8 @@ trait Names extends reflect.generic.Names {
(if (nameDebug && isTypeName) "!" else ""))//debug
def isOperatorName: Boolean = decode != toString
+ def nameKind: String = if (isTypeName) "type" else "term"
+ def longString: String = nameKind + " " + NameTransformer.decode(toString)
}
final class TermName(_index: Int, _len: Int, hash: Int) extends Name(_index, _len) {
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
index f64af26b1c..6a15c929b9 100644
--- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala
@@ -597,6 +597,14 @@ trait Symbols extends reflect.generic.Symbols { self: SymbolTable =>
rawowner = owner
}
+ private[Symbols] def flattenName(): Name = {
+ // TODO: this assertion causes me a lot of trouble in the interpeter in situations
+ // where everything proceeds smoothly if there's no assert. I don't think calling "name"
+ // on a symbol is the right place to throw fatal exceptions if things don't look right.
+ // It really hampers exploration.
+ assert(rawowner.isClass, "fatal: %s has non-class owner %s after flatten.".format(rawname + idString, rawowner))
+ nme.flattenedName(rawowner.name, rawname)
+ }
def ownerChain: List[Symbol] = this :: owner.ownerChain
@@ -1757,10 +1765,9 @@ trait Symbols extends reflect.generic.Symbols { self: SymbolTable =>
override def name: TermName =
if (isFlatAdjusted) {
- if (flatname == null) {
- assert(rawowner.isClass, "fatal: %s has non-class owner %s after flatten.".format(rawname, rawowner))
- flatname = nme.flattenedName(rawowner.name, rawname)
- }
+ if (flatname == null)
+ flatname = flattenName().toTermName
+
flatname
} else rawname
@@ -1961,10 +1968,8 @@ trait Symbols extends reflect.generic.Symbols { self: SymbolTable =>
override def name: TypeName =
if (needsFlatClasses) {
- if (flatname == null) {
- assert(rawowner.isClass, "fatal: %s has owner %s, but a class owner is required".format(rawname+idString, rawowner))
- flatname = tpnme.flattenedName(rawowner.name, rawname)
- }
+ if (flatname == null)
+ flatname = flattenName().toTypeName
flatname
}
else rawname.asInstanceOf[TypeName]