diff options
author | Sean McDirmid <sean.mcdirmid@gmail.com> | 2006-01-11 08:04:06 +0000 |
---|---|---|
committer | Sean McDirmid <sean.mcdirmid@gmail.com> | 2006-01-11 08:04:06 +0000 |
commit | cfd33de80751bc0d3d4c80c140a78de0e1201c2e (patch) | |
tree | 86f2dfa3d11aff1180b94ffdfef1441cdb87ba12 /src/compiler/scala/tools/nsc/util/ClassPath.scala | |
parent | 5dfb1f07ada2698ed8e3078c820d0f8c47e1b21b (diff) | |
download | scala-cfd33de80751bc0d3d4c80c140a78de0e1201c2e.tar.gz scala-cfd33de80751bc0d3d4c80c140a78de0e1201c2e.tar.bz2 scala-cfd33de80751bc0d3d4c80c140a78de0e1201c2e.zip |
More stuff to support hte eclipse plugin.
* Added symbol positions to to the pickler.
* Deprecated util/ClassPath.java to use ClassPath.scala, which allows for source attachments.
-- maybe we should remove ClassPath.java since it is no longer used.
* Added support for content outline.
Diffstat (limited to 'src/compiler/scala/tools/nsc/util/ClassPath.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/util/ClassPath.scala | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/src/compiler/scala/tools/nsc/util/ClassPath.scala b/src/compiler/scala/tools/nsc/util/ClassPath.scala new file mode 100644 index 0000000000..a60f914ac6 --- /dev/null +++ b/src/compiler/scala/tools/nsc/util/ClassPath.scala @@ -0,0 +1,211 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2003-2004, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + +package scala.tools.nsc.util; + +import scala.tools.util.AbstractFile; +import scala.collection.mutable.ArrayBuffer; +import java.io.FileNotFoundException; +import java.io.File; +import java.util.StringTokenizer; + +/** Richer classpath abstraction than files. + * Roughly based on Eclipse's classpath abstractions. + * + * @author Sean McDirmid + */ +object ClassPath { + + class Source(val location : AbstractFile, val compile : Boolean); + + abstract class Entry { + def location : AbstractFile; + def source : Source; + } + + class Output(val location : AbstractFile, val sourceFile : AbstractFile) extends Entry { + def source = new Source(sourceFile, true); + } + class Library(val location : AbstractFile) extends Entry { + def doc : AbstractFile = null; + def sourceFile : AbstractFile = null; + def source = if (sourceFile == null) null else new Source(sourceFile, false); + } + + class Context(val classes : List[AbstractFile], val sources : List[Source]) { + def find(name : String, isDir : boolean) = { + assert(isPackage); + def find0(classes : List[AbstractFile], sources : List[Source]) : Context = { + assert(classes.length == sources.length); + if (classes.isEmpty) new Context(Nil, Nil); + else { + val ret = find0(classes.tail, sources.tail); + + val clazz = if (classes.head == null) null; else + classes.head.lookupPath(name + (if (!isDir) ".class" else ""), isDir); + + val source = { + if (sources.head == null) null; + else { + val source0 = sources.head.location.lookupPath(name + (if (!isDir) ".scala" else ""), isDir); + if (source0 != null) source0; + else if (clazz != null && !isDir) sources.head.location; // directory where we can find source. + else null; + } + } + if (clazz == null && source == null) ret; + else new Context(clazz :: ret.classes, + (if (source != null) new Source(source, sources.head.compile) else null) + :: ret.sources); + } + } + find0(classes, sources); + } + + def isPackage = { + if (classes.head != null) classes.head.isDirectory(); + else sources.head.location.isDirectory(); + } + def name = { + val name = if (classes.head != null) classes.head.getName() else sources.head.location.getName(); + if (isPackage) name; + else name.substring(0, name.length() - (".class").length()); + } + + override def toString() : String = toString(classes, sources); + + def toString(classes0 : List[AbstractFile], sources0 : List[Source]) : String = + if (classes0.isEmpty) ""; + else + ((if (classes0.head == null) "<none>" else classes0.head.toString()) + (if (sources0.head != null) { + "::" + sources0.head.location.toString(); + } else "")) + ":" + toString(classes0.tail, sources0.tail); + + def file = { + assert(!isPackage); + if (classes.isEmpty) null; + else if (sources.head == null || sources.head.location.isDirectory() || !sources.head.compile) { + assert(classes.head != null); + classes.head; + } else if (classes.head == null) { + sources.head.location; + } else if (sources.head.location.lastModified() >= classes.head.lastModified()) sources.head.location; + else classes.head; + } + def isSourceFile = file.getName().endsWith(".scala"); + + def sourceFile = + if (sources.isEmpty || sources.head == null) null; + else if (sources.head.location.isDirectory()) null; + else sources.head.location; + + def sourcePath = + if (sources.isEmpty || sources.head == null) null; + else if (!sources.head.location.isDirectory()) null; + else sources.head.location; + + def validPackage(name : String) : Boolean = + if (name.equals("META-INF")) false; + else if (name.startsWith(".")) false; + else true; + + def complete : List[Context] = { + assert(isPackage); + def complete0(classes : List[AbstractFile], sources : List[Source]) : List[Context] = + if (classes.isEmpty) Nil; + else if (classes.head == null && sources.head == null) complete0(classes.tail, sources.tail); + else { + var ret : List[Context] = Nil; + if (classes.head != null) { + val i = classes.head.list(); + while (i.hasNext()) { + val file = i.next().asInstanceOf[AbstractFile]; + if (!file.isDirectory() && file.getName().endsWith(".class")) { + val name = file.getName().substring(0, file.getName().length() - (".class").length()); + ret = find(name, false) :: ret; + } else if (file.isDirectory() && validPackage(file.getName())) { + ret = (find(file.getName(), true) :: ret); + // System.err.println("FILE: " + file.getName() + " RET=" + ret.head); + } + } + } + if (sources.head != null && sources.head.compile) { + val j = sources.head.location.list(); + while (j.hasNext()) { + val file = j.next().asInstanceOf[AbstractFile]; + if (!file.isDirectory() && file.getName().endsWith(".scala")) { + val name = file.getName().substring(0, file.getName().length() - (".scala").length()); + if (classes.head == null || + classes.head.lookupPath(name + ".class", false) == null) ret = find(name, false) :: ret; + } else if (file.isDirectory() && validPackage(file.getName())) { + if (classes.head == null || classes.head.lookupPath(file.getName(), true) == null) + ret = find(file.getName(), true) :: ret; + } + } + } + ret ::: complete0(classes.tail, sources.tail); + } + complete0(classes, sources); + } + } + + class Build(val output : Output) { + val entries = new ArrayBuffer[Entry]; + + def root = { + val classes = for (val entry <- entries.toList) yield entry.location; + val sources = for (val entry <- entries.toList) yield entry.source; + new Context(classes, sources); + } + + + def this(classpath : String, source : String, output : String, boot : String, extdirs : String) = { + this(new Output(AbstractFile.getDirectory(output), AbstractFile.getDirectory(source))); + + if (this.output.location == null) throw new FileNotFoundException("output location \"" + output + "\" not found"); + if (this.output.source == null) throw new FileNotFoundException("source location \"" + source + "\" not found"); + + addFilesInPath(boot); + addArchivesInExtDirPath(extdirs); + entries += this.output; + addFilesInPath(classpath); + } + def library(classes : String, sources : String) = { + assert(classes != null); + val location = AbstractFile.getDirectory(classes); + val sourceFile0 = (if (sources != null) AbstractFile.getDirectory(sources) else null); + class Library0 extends Library(location) { + override def sourceFile = sourceFile0; + } + entries += new Library0(); + } + + private def addFilesInPath(path : String) = { + val strtok = new StringTokenizer(path, File.pathSeparator); + while (strtok.hasMoreTokens()) { + val file = AbstractFile.getDirectory(strtok.nextToken()); + if (file != null) entries += (new Library(file)); + } + } + private def addArchivesInExtDirPath(path : String) = { + val strtok = new StringTokenizer(path, File.pathSeparator); + while (strtok.hasMoreTokens()) { + val file = AbstractFile.getDirectory(strtok.nextToken()); + val files = (if (file != null) file.list() else null); + if (files != null) while(files.hasNext()) { + val file0 = files.next().asInstanceOf[AbstractFile]; + val name = file0.getName(); + if (name.endsWith(".jar") || name.endsWith(".zip")) { + val archive = AbstractFile.getDirectory(new File(file.getFile(), name)); + if (archive != null) entries += (new Library(archive)); + } + } + } + } + } +} |