aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/SymbolLoaders.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotty/tools/dotc/core/SymbolLoaders.scala')
-rw-r--r--src/dotty/tools/dotc/core/SymbolLoaders.scala267
1 files changed, 0 insertions, 267 deletions
diff --git a/src/dotty/tools/dotc/core/SymbolLoaders.scala b/src/dotty/tools/dotc/core/SymbolLoaders.scala
deleted file mode 100644
index 4ae28c10b..000000000
--- a/src/dotty/tools/dotc/core/SymbolLoaders.scala
+++ /dev/null
@@ -1,267 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2012 LAMP/EPFL
- * @author Martin Odersky
- */
-
-package dotty.tools
-package dotc
-package core
-
-import java.io.IOException
-import scala.compat.Platform.currentTime
-import dotty.tools.io.{ ClassPath, AbstractFile }
-import Contexts._, Symbols._, Flags._, SymDenotations._, Types._, Scopes._, util.Positions._, Names._
-import StdNames._, NameOps._
-import Decorators.{StringDecorator, StringInterpolators}
-import classfile.ClassfileParser
-import scala.util.control.NonFatal
-
-object SymbolLoaders {
- /** A marker trait for a completer that replaces the original
- * Symbol loader for an unpickled root.
- */
- trait SecondCompleter
-}
-
-/** A base class for Symbol loaders with some overridable behavior */
-class SymbolLoaders {
-
- protected def enterNew(
- owner: Symbol, member: Symbol,
- completer: SymbolLoader, scope: Scope = EmptyScope)(implicit ctx: Context): Symbol = {
- assert(scope.lookup(member.name) == NoSymbol, s"${owner.fullName}.${member.name} already has a symbol")
- owner.asClass.enter(member, scope)
- member
- }
-
- /** Enter class with given `name` into scope of `owner`.
- */
- def enterClass(
- owner: Symbol, name: PreName, completer: SymbolLoader,
- flags: FlagSet = EmptyFlags, scope: Scope = EmptyScope)(implicit ctx: Context): Symbol = {
- val cls = ctx.newClassSymbol(owner, name.toTypeName, flags, completer, assocFile = completer.sourceFileOrNull)
- enterNew(owner, cls, completer, scope)
- }
-
- /** Enter module with given `name` into scope of `owner`.
- */
- def enterModule(
- owner: Symbol, name: PreName, completer: SymbolLoader,
- modFlags: FlagSet = EmptyFlags, clsFlags: FlagSet = EmptyFlags, scope: Scope = EmptyScope)(implicit ctx: Context): Symbol = {
- val module = ctx.newModuleSymbol(
- owner, name.toTermName, modFlags, clsFlags,
- (module, _) => completer.proxy withDecls newScope withSourceModule (_ => module),
- assocFile = completer.sourceFileOrNull)
- enterNew(owner, module, completer, scope)
- enterNew(owner, module.moduleClass, completer, scope)
- }
-
- /** Enter package with given `name` into scope of `owner`
- * and give them `completer` as type.
- */
- def enterPackage(owner: Symbol, pkg: ClassPath)(implicit ctx: Context): Symbol = {
- val pname = pkg.name.toTermName
- val preExisting = owner.info.decls lookup pname
- if (preExisting != NoSymbol) {
- // Some jars (often, obfuscated ones) include a package and
- // object with the same name. Rather than render them unusable,
- // offer a setting to resolve the conflict one way or the other.
- // This was motivated by the desire to use YourKit probes, which
- // require yjp.jar at runtime. See SI-2089.
- if (ctx.settings.termConflict.isDefault)
- throw new TypeError(
- i"""$owner contains object and package with same name: $pname
- |one of them needs to be removed from classpath""")
- else if (ctx.settings.termConflict.value == "package") {
- ctx.warning(
- s"Resolving package/object name conflict in favor of package ${preExisting.fullName}. The object will be inaccessible.")
- owner.asClass.delete(preExisting)
- } else {
- ctx.warning(
- s"Resolving package/object name conflict in favor of object ${preExisting.fullName}. The package will be inaccessible.")
- return NoSymbol
- }
- }
- ctx.newModuleSymbol(owner, pname, PackageCreationFlags, PackageCreationFlags,
- (module, modcls) => new PackageLoader(module, pkg)).entered
- }
-
- /** Enter class and module with given `name` into scope of `owner`
- * and give them `completer` as type.
- */
- def enterClassAndModule(
- owner: Symbol, name: PreName, completer: SymbolLoader,
- flags: FlagSet = EmptyFlags, scope: Scope = EmptyScope)(implicit ctx: Context): Unit = {
- val clazz = enterClass(owner, name, completer, flags, scope)
- val module = enterModule(
- owner, name, completer,
- modFlags = flags.toTermFlags & RetainedModuleValFlags,
- clsFlags = flags.toTypeFlags & RetainedModuleClassFlags,
- scope = scope)
- }
-
- /** In batch mode: Enter class and module with given `name` into scope of `owner`
- * and give them a source completer for given `src` as type.
- * In IDE mode: Find all toplevel definitions in `src` and enter then into scope of `owner`
- * with source completer for given `src` as type.
- * (overridden in interactive.Global).
- */
- def enterToplevelsFromSource(
- owner: Symbol, name: PreName, src: AbstractFile,
- scope: Scope = EmptyScope)(implicit ctx: Context): Unit = {
- enterClassAndModule(owner, name, new SourcefileLoader(src), scope = scope)
- }
-
- /** The package objects of scala and scala.reflect should always
- * be loaded in binary if classfiles are available, even if sourcefiles
- * are newer. Late-compiling these objects from source leads to compilation
- * order issues.
- * Note: We do a name-base comparison here because the method is called before we even
- * have ReflectPackage defined.
- */
- def binaryOnly(owner: Symbol, name: String)(implicit ctx: Context): Boolean =
- name == "package" &&
- (owner.fullName.toString == "scala" || owner.fullName.toString == "scala.reflect")
-
- /** Initialize toplevel class and module symbols in `owner` from class path representation `classRep`
- */
- def initializeFromClassPath(owner: Symbol, classRep: ClassPath#ClassRep)(implicit ctx: Context): Unit = {
- ((classRep.binary, classRep.source): @unchecked) match {
- case (Some(bin), Some(src)) if needCompile(bin, src) && !binaryOnly(owner, classRep.name) =>
- if (ctx.settings.verbose.value) ctx.inform("[symloader] picked up newer source file for " + src.path)
- enterToplevelsFromSource(owner, classRep.name, src)
- case (None, Some(src)) =>
- if (ctx.settings.verbose.value) ctx.inform("[symloader] no class, picked up source file for " + src.path)
- enterToplevelsFromSource(owner, classRep.name, src)
- case (Some(bin), _) =>
- enterClassAndModule(owner, classRep.name, ctx.platform.newClassLoader(bin))
- }
- }
-
- def needCompile(bin: AbstractFile, src: AbstractFile) =
- src.lastModified >= bin.lastModified
-
- /** Load contents of a package
- */
- class PackageLoader(_sourceModule: TermSymbol, classpath: ClassPath)
- extends SymbolLoader {
- override def sourceModule(implicit ctx: Context) = _sourceModule
- def description = "package loader " + classpath.name
-
- private[core] val currentDecls: MutableScope = newScope
-
- def doComplete(root: SymDenotation)(implicit ctx: Context): Unit = {
- assert(root is PackageClass, root)
- def maybeModuleClass(classRep: ClassPath#ClassRep) = classRep.name.last == '$'
- val pre = root.owner.thisType
- root.info = ClassInfo(pre, root.symbol.asClass, Nil, currentDecls, pre select sourceModule)
- if (!sourceModule.isCompleted)
- sourceModule.completer.complete(sourceModule)
- if (!root.isRoot) {
- for (classRep <- classpath.classes)
- if (!maybeModuleClass(classRep))
- initializeFromClassPath(root.symbol, classRep)
- for (classRep <- classpath.classes)
- if (maybeModuleClass(classRep) && !root.unforcedDecls.lookup(classRep.name.toTypeName).exists)
- initializeFromClassPath(root.symbol, classRep)
- }
- if (!root.isEmptyPackage)
- for (pkg <- classpath.packages)
- enterPackage(root.symbol, pkg)
- }
- }
-}
-
-/** A lazy type that completes itself by calling parameter doComplete.
- * Any linked modules/classes or module classes are also initialized.
- */
-abstract class SymbolLoader extends LazyType {
-
- /** Load source or class file for `root`, return */
- def doComplete(root: SymDenotation)(implicit ctx: Context): Unit
-
- def sourceFileOrNull: AbstractFile = null
-
- /** Description of the resource (ClassPath, AbstractFile)
- * being processed by this loader
- */
- def description: String
-
- override def complete(root: SymDenotation)(implicit ctx: Context): Unit = {
- def signalError(ex: Exception): Unit = {
- if (ctx.debug) ex.printStackTrace()
- val msg = ex.getMessage()
- ctx.error(
- if (msg eq null) "i/o error while loading " + root.name
- else "error while loading " + root.name + ",\n " + msg)
- }
- try {
- val start = currentTime
- if (ctx.settings.debugTrace.value)
- ctx.doTraceIndented(s">>>> loading ${root.debugString}", _ => s"<<<< loaded ${root.debugString}") {
- doComplete(root)
- }
- else
- doComplete(root)
- ctx.informTime("loaded " + description, start)
- } catch {
- case ex: IOException =>
- signalError(ex)
- case NonFatal(ex) =>
- println(s"exception caught when loading $root: $ex")
- throw ex
- } finally {
- def postProcess(denot: SymDenotation) =
- if (!denot.isCompleted &&
- !denot.completer.isInstanceOf[SymbolLoaders.SecondCompleter])
- denot.markAbsent()
- postProcess(root)
- if (!root.isRoot)
- postProcess(root.scalacLinkedClass.denot)
- }
- }
-}
-
-class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader {
-
- override def sourceFileOrNull: AbstractFile = classfile
-
- def description = "class file " + classfile.toString
-
- def rootDenots(rootDenot: ClassDenotation)(implicit ctx: Context): (ClassDenotation, ClassDenotation) = {
- val linkedDenot = rootDenot.scalacLinkedClass.denot match {
- case d: ClassDenotation => d
- case d =>
- // this can happen if the companion if shadowed by a val or type
- // in a package object; in this case, we make up some dummy denotation
- // as a stand in for loading.
- // An example for this situation is scala.reflect.Manifest, which exists
- // as a class in scala.reflect and as a val in scala.reflect.package.
- if (rootDenot is ModuleClass)
- ctx.newClassSymbol(
- rootDenot.owner, rootDenot.name.stripModuleClassSuffix.asTypeName, Synthetic,
- _ => NoType).classDenot
- else
- ctx.newModuleSymbol(
- rootDenot.owner, rootDenot.name.toTermName, Synthetic, Synthetic,
- (module, _) => new NoCompleter() withDecls newScope withSourceModule (_ => module))
- .moduleClass.denot.asClass
- }
- if (rootDenot is ModuleClass) (linkedDenot, rootDenot)
- else (rootDenot, linkedDenot)
- }
-
- override def doComplete(root: SymDenotation)(implicit ctx: Context): Unit =
- load(root)
-
- def load(root: SymDenotation)(implicit ctx: Context): Option[ClassfileParser.Embedded] = {
- val (classRoot, moduleRoot) = rootDenots(root.asClass)
- new ClassfileParser(classfile, classRoot, moduleRoot)(ctx).run()
- }
-}
-
-class SourcefileLoader(val srcfile: AbstractFile) extends SymbolLoader {
- def description = "source file " + srcfile.toString
- override def sourceFileOrNull = srcfile
- def doComplete(root: SymDenotation)(implicit ctx: Context): Unit = unsupported("doComplete")
-}