diff options
author | Lukas Rytz <lukas.rytz@gmail.com> | 2016-10-26 17:12:36 +0200 |
---|---|---|
committer | Lukas Rytz <lukas.rytz@gmail.com> | 2016-10-27 10:39:51 +0200 |
commit | bde2854588eea4e3199fc97e0af92a8b35ce1705 (patch) | |
tree | f4764af5811cbdb6cf8310ec8b63f7a04fc9858c /src/compiler/scala/tools/nsc/symtab/classfile | |
parent | 4e3ffd4bf00ab71ef64c31a45d5c3e2838aa78ee (diff) | |
download | scala-bde2854588eea4e3199fc97e0af92a8b35ce1705.tar.gz scala-bde2854588eea4e3199fc97e0af92a8b35ce1705.tar.bz2 scala-bde2854588eea4e3199fc97e0af92a8b35ce1705.zip |
Clean up lookup class by name in the classfile parser
There was a piece of logic essentially duplicating getClassByName
in Mirrors (split up a fully qualified class name by ".", look up
pieces). That piece of code was added in 0ce0ad5 to fix one example in
SI-2464.
However, since 020053c (2012, 2.10) that code was broken: the line
ss = name.subName(0, start)
should be
ss = name.subName(start, name.length).toTypeName
As a result, the code would always create a stub symbol. Returning a
stub seems to be the right thing to do anyway, and the fact that we were
doing so during two major releases is a good proof.
Diffstat (limited to 'src/compiler/scala/tools/nsc/symtab/classfile')
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala | 72 |
1 files changed, 26 insertions, 46 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index f8c1a0d082..e96be74ba1 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -356,63 +356,43 @@ abstract class ClassfileParser { abort(s"bad constant pool tag ${in.buf(start)} at byte $start") } - private def loadClassSymbol(name: Name): Symbol = { - val file = classPath findClassFile name.toString getOrElse { - // SI-5593 Scaladoc's current strategy is to visit all packages in search of user code that can be documented - // therefore, it will rummage through the classpath triggering errors whenever it encounters package objects - // that are not in their correct place (see bug for details) - - // TODO More consistency with use of stub symbols in `Unpickler` - // - better owner than `NoSymbol` - // - remove eager warning - val msg = s"Class $name not found - continuing with a stub." - if ((!settings.isScaladoc) && (settings.verbose || settings.developer)) warning(msg) - return NoSymbol.newStubSymbol(name.toTypeName, msg) - } - val completer = new loaders.ClassfileLoader(file) - var owner: Symbol = rootMirror.RootClass - var sym: Symbol = NoSymbol - var ss: Name = null - var start = 0 - var end = name indexOf '.' - - while (end > 0) { - ss = name.subName(start, end) - sym = owner.info.decls lookup ss - if (sym == NoSymbol) { - sym = owner.newPackage(ss.toTermName) setInfo completer - sym.moduleClass setInfo completer - owner.info.decls enter sym - } - owner = sym.moduleClass - start = end + 1 - end = name.indexOf('.', start) - } - ss = name.subName(0, start) - owner.info.decls lookup ss orElse { - sym = owner.newClass(ss.toTypeName) setInfoAndEnter completer - debuglog("loaded "+sym+" from file "+file) - sym - } + def stubClassSymbol(name: Name): Symbol = { + // SI-5593 Scaladoc's current strategy is to visit all packages in search of user code that can be documented + // therefore, it will rummage through the classpath triggering errors whenever it encounters package objects + // that are not in their correct place (see bug for details) + + // TODO More consistency with use of stub symbols in `Unpickler` + // - better owner than `NoSymbol` + // - remove eager warning + val msg = s"Class $name not found - continuing with a stub." + if ((!settings.isScaladoc) && (settings.verbose || settings.developer)) warning(msg) + NoSymbol.newStubSymbol(name.toTypeName, msg) } - /** FIXME - we shouldn't be doing ad hoc lookups in the empty package. - * The method called "getClassByName" should either return the class or not. - */ - private def lookupClass(name: Name) = ( + private def lookupClass(name: Name) = try { if (name containsChar '.') - rootMirror getClassByName name // see tickets #2464, #3756 + rootMirror getClassByName name else + // FIXME - we shouldn't be doing ad hoc lookups in the empty package, getClassByName should return the class definitions.getMember(rootMirror.EmptyPackageClass, name.toTypeName) - ) + } catch { + // The handler + // - prevents crashes with deficient InnerClassAttributes (SI-2464, 0ce0ad5) + // - was referenced in the bugfix commit for SI-3756 (4fb0d53), not sure why + // - covers the case when a type alias in a package object shadows a class symbol, + // getClassByName throws a MissingRequirementError (scala-dev#248) + case _: FatalError => + // getClassByName can throw a MissingRequirementError (which extends FatalError) + // definitions.getMember can throw a FatalError, for example in pos/t5165b + stubClassSymbol(name) + } /** Return the class symbol of the given name. */ def classNameToSymbol(name: Name): Symbol = { if (innerClasses contains name) innerClasses innerSymbol name else - try lookupClass(name) - catch { case _: FatalError => loadClassSymbol(name) } + lookupClass(name) } def parseClass() { |