diff options
author | Martin Odersky <odersky@gmail.com> | 2011-01-09 14:48:16 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2011-01-09 14:48:16 +0000 |
commit | 34d82221cca365ce6b57d7baaed58bac8152ac53 (patch) | |
tree | c062409d9e42ef93928bdc46a43b2966f66f39ef /src/compiler | |
parent | 785621901acb1888f168c2b2075e85a64af70fb8 (diff) | |
download | scala-34d82221cca365ce6b57d7baaed58bac8152ac53.tar.gz scala-34d82221cca365ce6b57d7baaed58bac8152ac53.tar.bz2 scala-34d82221cca365ce6b57d7baaed58bac8152ac53.zip |
Refactored browsing loaders so that they can be...
Refactored browsing loaders so that they can be more easily reused from
the builder. Review by plocinik.
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/scala/tools/nsc/interactive/Global.scala | 90 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala | 111 |
2 files changed, 112 insertions, 89 deletions
diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala index cb8c4a8a60..8af350c8b7 100644 --- a/src/compiler/scala/tools/nsc/interactive/Global.scala +++ b/src/compiler/scala/tools/nsc/interactive/Global.scala @@ -161,96 +161,8 @@ self => * top-level idents. Therefore, we can detect top-level symbols that have a name * different from their source file */ - override lazy val loaders = new SymbolLoaders { + override lazy val loaders = new BrowsingLoaders { val global: Global.this.type = Global.this - - import syntaxAnalyzer.{OutlineParser, MalformedInput} - - /** In browse mode, it can happen that an encountered symbol is already - * present. For instance, if the source file has a name different from - * the classes and objects it contains, the symbol loader will always - * reparse the source file. The symbols it encounters might already be loaded - * as class files. In this case we return the one which has a sourcefile - * (and the other has not), and issue an error if both have sourcefiles. - */ - override def enterIfNew(owner: Symbol, member: Symbol, completer: SymbolLoader): Symbol = { - completer.sourcefile match { - case Some(src) => - (if (member.isModule) member.moduleClass else member).sourceFile = src - case _ => - } - val decls = owner.info.decls - val existing = decls.lookup(member.name) - if (existing == NoSymbol) { - decls enter member - member - } else if (existing.sourceFile == null) { - decls unlink existing - decls enter member - member - } else { - if (member.sourceFile != null) { - if (existing.sourceFile != member.sourceFile) - error(member+"is defined twice,"+ - "\n in "+existing.sourceFile+ - "\n and also in "+member.sourceFile) - } - existing - } - } - - def browseTopLevel(root: Symbol, src: AbstractFile) { - - class BrowserTraverser extends Traverser { - var packagePrefix = "" - var entered = 0 - def addPackagePrefix(pkg: Tree): Unit = pkg match { - case Select(pre, name) => - addPackagePrefix(pre) - packagePrefix += ("." + name) - case Ident(name) => - if (packagePrefix.length != 0) packagePrefix += "." - packagePrefix += name - case _ => - throw new MalformedInput(pkg.pos.point, "illegal tree node in package prefix: "+pkg) - } - override def traverse(tree: Tree): Unit = tree match { - case PackageDef(pkg, body) => - addPackagePrefix(pkg) - body foreach traverse - case ClassDef(_, name, _, _) => - if (packagePrefix == root.fullName) { - enterClass(root, name.toString, new SourcefileLoader(src)) - entered += 1 - } else println("prefixes differ: "+packagePrefix+","+root.fullName) - case ModuleDef(_, name, _) => - if (packagePrefix == root.fullName) { - enterModule(root, name.toString, new SourcefileLoader(src)) - entered += 1 - } else println("prefixes differ: "+packagePrefix+","+root.fullName) - case _ => - } - } - - System.out.println("Browsing "+src) - val source = new BatchSourceFile(src) - val body = new OutlineParser(source).parse() - System.out.println(body) - val browser = new BrowserTraverser - browser.traverse(body) - if (browser.entered == 0) - warning("No classes or objects found in "+source+" that go in "+root) - } - - override def enterToplevelsFromSource(root: Symbol, name: String, src: AbstractFile) { - try { - browseTopLevel(root, src) - } catch { - case ex: syntaxAnalyzer.MalformedInput => - println("caught malformed input exception at offset "+ex.offset+": "+ex.msg) - super.enterToplevelsFromSource(root, name, src) - } - } } // ----------------- Polling --------------------------------------- diff --git a/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala b/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala new file mode 100644 index 0000000000..1f2553d11e --- /dev/null +++ b/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala @@ -0,0 +1,111 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2010 LAMP/EPFL + * @author Martin Odersky + */ + +package scala.tools.nsc +package symtab + +import scala.tools.nsc.io.AbstractFile +import scala.tools.nsc.util.BatchSourceFile + +/** A subclass of SymbolLoaders that implements browsing behavior. + * This class should be used whenever file dependencies and recompile sets + * are managed automoatically. + */ +abstract class BrowsingLoaders extends SymbolLoaders { + import global._ + + import syntaxAnalyzer.{OutlineParser, MalformedInput} + + /** In browse mode, it can happen that an encountered symbol is already + * present. For instance, if the source file has a name different from + * the classes and objects it contains, the symbol loader will always + * reparse the source file. The symbols it encounters might already be loaded + * as class files. In this case we return the one which has a sourcefile + * (and the other has not), and issue an error if both have sourcefiles. + */ + override protected def enterIfNew(owner: Symbol, member: Symbol, completer: SymbolLoader): Symbol = { + completer.sourcefile match { + case Some(src) => + (if (member.isModule) member.moduleClass else member).sourceFile = src + case _ => + } + val decls = owner.info.decls + val existing = decls.lookup(member.name) + if (existing == NoSymbol) { + decls enter member + member + } else if (existing.sourceFile == null) { + decls unlink existing + decls enter member + member + } else { + if (member.sourceFile != null) { + if (existing.sourceFile != member.sourceFile) + error(member+"is defined twice,"+ + "\n in "+existing.sourceFile+ + "\n and also in "+member.sourceFile) + } + existing + } + } + + /** Browse the top-level of given abstract file `src` and enter + * eny encountered top-level classes and modules in `root` + */ + def browseTopLevel(root: Symbol, src: AbstractFile) { + + class BrowserTraverser extends Traverser { + var packagePrefix = "" + var entered = 0 + def addPackagePrefix(pkg: Tree): Unit = pkg match { + case Select(pre, name) => + addPackagePrefix(pre) + packagePrefix += ("." + name) + case Ident(name) => + if (packagePrefix.length != 0) packagePrefix += "." + packagePrefix += name + case _ => + throw new MalformedInput(pkg.pos.point, "illegal tree node in package prefix: "+pkg) + } + override def traverse(tree: Tree): Unit = tree match { + case PackageDef(pkg, body) => + addPackagePrefix(pkg) + body foreach traverse + case ClassDef(_, name, _, _) => + if (packagePrefix == root.fullName) { + enterClass(root, name.toString, new SourcefileLoader(src)) + entered += 1 + } else println("prefixes differ: "+packagePrefix+","+root.fullName) + case ModuleDef(_, name, _) => + if (packagePrefix == root.fullName) { + enterModule(root, name.toString, new SourcefileLoader(src)) + entered += 1 + } else println("prefixes differ: "+packagePrefix+","+root.fullName) + case _ => + } + } + + System.out.println("Browsing "+src) + val source = new BatchSourceFile(src) + val body = new OutlineParser(source).parse() + System.out.println(body) + val browser = new BrowserTraverser + browser.traverse(body) + if (browser.entered == 0) + warning("No classes or objects found in "+source+" that go in "+root) + } + + /** Enter top-level symbols from a source file + */ + override def enterToplevelsFromSource(root: Symbol, name: String, src: AbstractFile) { + try { + browseTopLevel(root, src) + } catch { + case ex: syntaxAnalyzer.MalformedInput => + println("caught malformed input exception at offset "+ex.offset+": "+ex.msg) + super.enterToplevelsFromSource(root, name, src) + } + } +} |