diff options
author | Geoffrey Washburn <geoffrey.washburn@epfl.ch> | 2008-02-21 10:28:57 +0000 |
---|---|---|
committer | Geoffrey Washburn <geoffrey.washburn@epfl.ch> | 2008-02-21 10:28:57 +0000 |
commit | 05096f361b7f8c8912a70db5ec15609e6a333df5 (patch) | |
tree | 9446160568e2b74dc207249a5375a6b7701d13a7 | |
parent | d46b616171ea7b858d3b82e57e8aa37e32b33e5c (diff) | |
download | scala-05096f361b7f8c8912a70db5ec15609e6a333df5.tar.gz scala-05096f361b7f8c8912a70db5ec15609e6a333df5.tar.bz2 scala-05096f361b7f8c8912a70db5ec15609e6a333df5.zip |
Split DocDriver into DocDriver and DefaultDocDr...
Split DocDriver into DocDriver and DefaultDocDriver in moving towards
support documentation plugins.
-rw-r--r-- | src/compiler/scala/tools/nsc/Main.scala | 6 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/doc/DefaultDocDriver.scala | 275 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/doc/DocDriver.scala | 258 | ||||
-rw-r--r-- | test/files/run/docgenerator.scala | 4 |
4 files changed, 286 insertions, 257 deletions
diff --git a/src/compiler/scala/tools/nsc/Main.scala b/src/compiler/scala/tools/nsc/Main.scala index cf858409b2..9dbbda50b4 100644 --- a/src/compiler/scala/tools/nsc/Main.scala +++ b/src/compiler/scala/tools/nsc/Main.scala @@ -8,7 +8,7 @@ package scala.tools.nsc import java.io.File -import scala.tools.nsc.doc.DocDriver +import scala.tools.nsc.doc.DefaultDocDriver import scala.tools.nsc.reporters.{Reporter, ConsoleReporter} import scala.tools.nsc.util.FakePos //{Position} @@ -85,11 +85,11 @@ object Main extends AnyRef with EvalLoop { val run = new compiler.Run run compile command.files if (command.settings.doc.value) { - object generator extends DocDriver { + val generator = new DefaultDocDriver { lazy val global: compiler.type = compiler def settings = command.settings } - generator process run.units + generator.process(command.settings, run.units) } reporter.printSummary() } diff --git a/src/compiler/scala/tools/nsc/doc/DefaultDocDriver.scala b/src/compiler/scala/tools/nsc/doc/DefaultDocDriver.scala new file mode 100644 index 0000000000..2d836e1297 --- /dev/null +++ b/src/compiler/scala/tools/nsc/doc/DefaultDocDriver.scala @@ -0,0 +1,275 @@ +/* NSC -- new Scala compiler + * Copyright 2007-2008 LAMP/EPFL + * @author Sean McDirmid + */ +// $Id$ + +package scala.tools.nsc.doc + +import java.util.zip.ZipFile + +import scala.collection.jcl +import symtab.Flags._ +import scala.xml._ + +/** + * @author Sean McDirmid + */ +abstract class DefaultDocDriver extends DocDriver with ModelFrames with ModelToXML { + import global._ + object additions extends jcl.LinkedHashSet[Symbol] + object additions0 extends ModelAdditions(global) { + override def addition(sym: global.Symbol) = { + super.addition(sym) + sym match { + case sym : global.ClassSymbol => additions += sym.asInstanceOf[Symbol] + case sym : global.ModuleSymbol => additions += sym.asInstanceOf[Symbol] + case sym : global.TypeSymbol => additions += sym.asInstanceOf[Symbol] + case _ => + } + } + def init {} + } + + def process(settings: Settings, units: Iterator[CompilationUnit]) { + process(units) + } + + def process(units: Iterator[CompilationUnit]) { + + assert(global.definitions != null) + + def g(pkg: Package, clazz: ClassOrObject) { + if (isAccessible(clazz.sym)) { + allClasses(pkg) += clazz + clazz.decls.map(_._2).foreach { + case clazz : ClassOrObject => g(pkg, clazz) + case _ => + } + } + } + def f(pkg: Package, tree: Tree) { + if (tree != EmptyTree && tree.hasSymbol) { + val sym = tree.symbol + if (sym != NoSymbol && !sym.hasFlag(symtab.Flags.PRIVATE)) tree match { + case tree : PackageDef => + val pkg1 = new Package(sym.asInstanceOf[ModuleSymbol]) + tree.stats.foreach(stat => f(pkg1, stat)) + case tree : ClassDef => + assert(pkg != null) + g(pkg, new TopLevelClass(sym.asInstanceOf[ClassSymbol])) + case tree : ModuleDef => + assert(pkg != null) + g(pkg, new TopLevelObject(sym.asInstanceOf[ModuleSymbol])) + case _ => + } + } + } + units.foreach(unit => f(null, unit.body)) + + for (p <- allClasses; d <- p._2) { + symbols += d.sym + for (pp <- d.sym.tpe.parents) subClasses(pp.typeSymbol) += d + } + additions0.init + copyResources + val packages0 = sort(allClasses.keySet) + new AllPackagesFrame with Frame { def packages = packages0; } + new PackagesContentFrame with Frame { def packages = packages0; } + new NavigationFrame with Frame { } + new ListClassFrame with Frame { + def classes = for (p <- allClasses; d <- p._2) yield d + object organized extends jcl.LinkedHashMap[(List[String],Boolean),List[ClassOrObject]] { + override def default(key : (List[String],Boolean)) = Nil; + classes.foreach(cls => { + val path = cls.path.map(_.name); + this((path,cls.isInstanceOf[Clazz])) = cls :: this((path,cls.isInstanceOf[Clazz])); + }); + } + + def title = "List of all classes and objects" + def path = "all-classes" + def navLabel = null // "root-page" + // override protected def navSuffix = ".html"; + override def optional(cls: ClassOrObject): NodeSeq = { + val path = cls.path.map(_.name) + val key = (cls.path.map(_.name), cls.isInstanceOf[Clazz]) + assert(!organized(key).isEmpty); + (if (!organized(key).tail.isEmpty) Text(" (" +{ + //Console.println("CONFLICT: " + path + " " + organized(key)); + val str = cls.path(0).sym.owner.fullNameString('.'); + val idx = str.lastIndexOf('.'); + if (idx == -1) str; + else str.substring(idx + 1); + }+ ")"); + else NodeSeq.Empty) ++ super.optional(cls); + } + + } + for ((pkg0, classes0) <- allClasses) { + new ListClassFrame with Frame { + def title = + "List of classes and objects in package " + pkg0.fullName('.') + def classes = classes0; + def path = pkgPath(pkg0.sym) + NAME_SUFFIX_PACKAGE; + def navLabel = pkg0.fullName('.'); + } + new PackageContentFrame with Frame { + def classes = classes0; + def pkg = pkg0; + } + for (clazz0 <- classes0) { + new ClassContentFrame with Frame { + def clazz = clazz0; + def title = + clazz0.kind + " " + clazz0.name + " in " + (clazz0.sym.owner.fullNameString('.')); + } + } + } + for (sym <- additions) sym match { + case sym: ClassSymbol => + val add = new TopLevelClass(sym) + new ClassContentFrame with Frame { + def clazz = add + def title = + add.kind + " " + add.name + " in package " + add.sym.owner.fullNameString('.') + } + case sym: TypeSymbol => + val add = new TopLevelClass(sym) + new ClassContentFrame with Frame { + def clazz = add + def title = + add.kind + " " + add.name + " in package " + add.sym.owner.fullNameString('.') + } + case sym: ModuleSymbol => + val add = new TopLevelObject(sym) + new ClassContentFrame with Frame { + def clazz = add + def title = + add.kind + " " + add.name + " in package " + add.sym.owner.fullNameString('.') + } + } + new RootFrame with Frame + } + override def longList(entity: ClassOrObject, category: Category)(implicit from: Frame) : NodeSeq = category match { + case Classes | Objects => NodeSeq.Empty + case _ => super.longList(entity, category) + } + + trait Frame extends super.Frame { + def longHeader(entity : Entity) = DefaultDocDriver.this.longHeader(entity)(this) + def shortHeader(entity : Entity) = DefaultDocDriver.this.shortHeader(entity)(this) + } + + import DocUtil._ + override def classBody(entity: ClassOrObject)(implicit from: Frame): NodeSeq = + (subClasses.get(entity.sym) match { + case Some(symbols) => + <dl> + <dt style="margin:10px 0 0 20px;"><b>Direct Known Subclasses:</b></dt> + <dd>{symbols.mkXML("",", ","")(cls => { + aref(urlFor(cls.sym), cls.path.map(_.name).mkString("",".","")); + })}</dd> + </dl><hr/>; + case None => + NodeSeq.Empty + })++super.classBody(entity); + + protected def urlFor(sym: Symbol)(implicit frame: Frame) = frame.urlFor(sym) + + override protected def decodeTag(tag: String): String = tag match { + case "exception" => "Throws" + case "ex" => "Examples" + case "param" => "Parameters" + case "pre" => "Precondition" + case "return" => "Returns" + case "note" => "Notes" + case "see" => "See Also" + case tag => super.decodeTag(tag) + } + + override protected def decodeOption(tag: String, option: String): NodeSeq = tag match { + case "throws" if additions0.exceptions.contains(option) => + val (sym, s) = additions0.exceptions(option); + val path = "../" //todo: fix path + val href = path + sym.fullNameString('/') + + (if (sym.isModule || sym.isModuleClass) NAME_SUFFIX_OBJECT else "") + + "#" + s + <a href={href}>{option}</a> ++ {Text(" - ")}; + case _ => + super.decodeOption(tag,option) + } + + object roots extends jcl.LinkedHashMap[String,String]; + roots("classes") = "http://java.sun.com/j2se/1.5.0/docs/api"; + roots("rt") = roots("classes"); + roots("scala-library") = "http://www.scala-lang.org/docu/files/api"; + + private def keyFor(file: ZipFile): String = { + var name = file.getName + var idx = name.lastIndexOf(java.io.File.pathSeparator) + if (idx == -1) idx = name.lastIndexOf('/') + if (idx != -1) name = name.substring(idx + 1) + if (name endsWith ".jar") name.substring(0, name.length - (".jar").length) + else null + } + + // <code>{Text(string + " - ")}</code>; + override def hasLink0(sym: Symbol): Boolean = { + if (sym == NoSymbol) return false; + val ret = super.hasLink0(sym) && (additions.contains(sym) || symbols.contains(sym)); + if (ret) return true; + if (sym.toplevelClass == NoSymbol) return false; + val clazz = sym.toplevelClass.asInstanceOf[ClassSymbol]; + import scala.tools.nsc.io._; + clazz.classFile match { + case file : ZipArchive#FileEntry => + val key = keyFor(file.archive); + if (key != null && roots.contains(key)) return true; + case null => + case _ => + } + false + } + + def aref(href: String, label: String)(implicit frame: Frame) = + frame.aref(href, "_self", label) + + protected def anchor(entity: Symbol)(implicit frame: Frame): NodeSeq = + <a name={Text(frame.docName(entity))}></a> + + object symbols extends jcl.LinkedHashSet[Symbol] + + object allClasses extends jcl.LinkedHashMap[Package, jcl.LinkedHashSet[ClassOrObject]] { + override def default(pkg: Package): jcl.LinkedHashSet[ClassOrObject] = { + object ret extends jcl.LinkedHashSet[ClassOrObject] + this(pkg) = ret + ret + } + } + + object subClasses extends jcl.LinkedHashMap[Symbol, jcl.LinkedHashSet[ClassOrObject]] { + override def default(key: Symbol) = { + val ret = new jcl.LinkedHashSet[ClassOrObject] + this(key) = ret + ret + } + } + + override def rootFor(sym: Symbol): String = { + assert(sym != NoSymbol) + if (sym.toplevelClass == NoSymbol) return super.rootFor(sym) + if (symbols.contains(sym.toplevelClass)) return super.rootFor(sym) + val clazz = sym.toplevelClass.asInstanceOf[ClassSymbol] + import scala.tools.nsc.io._; + clazz.classFile match { + case file : ZipArchive#FileEntry => + val key = keyFor(file.archive) + if (key != null && roots.contains(key)) { + return roots(key) + '/' + } + case _ => + } + super.rootFor(sym) + } +} diff --git a/src/compiler/scala/tools/nsc/doc/DocDriver.scala b/src/compiler/scala/tools/nsc/doc/DocDriver.scala index 21a91a4f50..ceb252dff6 100644 --- a/src/compiler/scala/tools/nsc/doc/DocDriver.scala +++ b/src/compiler/scala/tools/nsc/doc/DocDriver.scala @@ -13,258 +13,12 @@ import symtab.Flags._ import scala.xml._ /** - * @author Sean McDirmid + * @author Geoffrey Washburn + * This is an abstract class for documentation plugins. */ -abstract class DocDriver extends ModelFrames with ModelToXML { - import global._ - object additions extends jcl.LinkedHashSet[Symbol] - object additions0 extends ModelAdditions(global) { - override def addition(sym: global.Symbol) = { - super.addition(sym) - sym match { - case sym : global.ClassSymbol => additions += sym.asInstanceOf[Symbol] - case sym : global.ModuleSymbol => additions += sym.asInstanceOf[Symbol] - case sym : global.TypeSymbol => additions += sym.asInstanceOf[Symbol] - case _ => - } - } - def init {} - } +abstract class DocDriver { + val global: Global + import global._ - def process(units: Iterator[CompilationUnit]) { - assert(global.definitions != null) - - def g(pkg: Package, clazz: ClassOrObject) { - if (isAccessible(clazz.sym)) { - allClasses(pkg) += clazz - clazz.decls.map(_._2).foreach { - case clazz : ClassOrObject => g(pkg, clazz) - case _ => - } - } - } - def f(pkg: Package, tree: Tree) { - if (tree != EmptyTree && tree.hasSymbol) { - val sym = tree.symbol - if (sym != NoSymbol && !sym.hasFlag(symtab.Flags.PRIVATE)) tree match { - case tree : PackageDef => - val pkg1 = new Package(sym.asInstanceOf[ModuleSymbol]) - tree.stats.foreach(stat => f(pkg1, stat)) - case tree : ClassDef => - assert(pkg != null) - g(pkg, new TopLevelClass(sym.asInstanceOf[ClassSymbol])) - case tree : ModuleDef => - assert(pkg != null) - g(pkg, new TopLevelObject(sym.asInstanceOf[ModuleSymbol])) - case _ => - } - } - } - units.foreach(unit => f(null, unit.body)) - - for (p <- allClasses; d <- p._2) { - symbols += d.sym - for (pp <- d.sym.tpe.parents) subClasses(pp.typeSymbol) += d - } - additions0.init - copyResources - val packages0 = sort(allClasses.keySet) - new AllPackagesFrame with Frame { def packages = packages0; } - new PackagesContentFrame with Frame { def packages = packages0; } - new NavigationFrame with Frame { } - new ListClassFrame with Frame { - def classes = for (p <- allClasses; d <- p._2) yield d - object organized extends jcl.LinkedHashMap[(List[String],Boolean),List[ClassOrObject]] { - override def default(key : (List[String],Boolean)) = Nil; - classes.foreach(cls => { - val path = cls.path.map(_.name); - this((path,cls.isInstanceOf[Clazz])) = cls :: this((path,cls.isInstanceOf[Clazz])); - }); - } - - def title = "List of all classes and objects" - def path = "all-classes" - def navLabel = null // "root-page" - // override protected def navSuffix = ".html"; - override def optional(cls: ClassOrObject): NodeSeq = { - val path = cls.path.map(_.name) - val key = (cls.path.map(_.name), cls.isInstanceOf[Clazz]) - assert(!organized(key).isEmpty); - (if (!organized(key).tail.isEmpty) Text(" (" +{ - //Console.println("CONFLICT: " + path + " " + organized(key)); - val str = cls.path(0).sym.owner.fullNameString('.'); - val idx = str.lastIndexOf('.'); - if (idx == -1) str; - else str.substring(idx + 1); - }+ ")"); - else NodeSeq.Empty) ++ super.optional(cls); - } - - } - for ((pkg0, classes0) <- allClasses) { - new ListClassFrame with Frame { - def title = - "List of classes and objects in package " + pkg0.fullName('.') - def classes = classes0; - def path = pkgPath(pkg0.sym) + NAME_SUFFIX_PACKAGE; - def navLabel = pkg0.fullName('.'); - } - new PackageContentFrame with Frame { - def classes = classes0; - def pkg = pkg0; - } - for (clazz0 <- classes0) { - new ClassContentFrame with Frame { - def clazz = clazz0; - def title = - clazz0.kind + " " + clazz0.name + " in " + (clazz0.sym.owner.fullNameString('.')); - } - } - } - for (sym <- additions) sym match { - case sym: ClassSymbol => - val add = new TopLevelClass(sym) - new ClassContentFrame with Frame { - def clazz = add - def title = - add.kind + " " + add.name + " in package " + add.sym.owner.fullNameString('.') - } - case sym: TypeSymbol => - val add = new TopLevelClass(sym) - new ClassContentFrame with Frame { - def clazz = add - def title = - add.kind + " " + add.name + " in package " + add.sym.owner.fullNameString('.') - } - case sym: ModuleSymbol => - val add = new TopLevelObject(sym) - new ClassContentFrame with Frame { - def clazz = add - def title = - add.kind + " " + add.name + " in package " + add.sym.owner.fullNameString('.') - } - } - new RootFrame with Frame - } - override def longList(entity: ClassOrObject, category: Category)(implicit from: Frame) : NodeSeq = category match { - case Classes | Objects => NodeSeq.Empty - case _ => super.longList(entity, category) - } - - trait Frame extends super.Frame { - def longHeader(entity : Entity) = DocDriver.this.longHeader(entity)(this) - def shortHeader(entity : Entity) = DocDriver.this.shortHeader(entity)(this) - } - - import DocUtil._ - override def classBody(entity: ClassOrObject)(implicit from: Frame): NodeSeq = - (subClasses.get(entity.sym) match { - case Some(symbols) => - <dl> - <dt style="margin:10px 0 0 20px;"><b>Direct Known Subclasses:</b></dt> - <dd>{symbols.mkXML("",", ","")(cls => { - aref(urlFor(cls.sym), cls.path.map(_.name).mkString("",".","")); - })}</dd> - </dl><hr/>; - case None => - NodeSeq.Empty - })++super.classBody(entity); - - protected def urlFor(sym: Symbol)(implicit frame: Frame) = frame.urlFor(sym) - - override protected def decodeTag(tag: String): String = tag match { - case "exception" => "Throws" - case "ex" => "Examples" - case "param" => "Parameters" - case "pre" => "Precondition" - case "return" => "Returns" - case "note" => "Notes" - case "see" => "See Also" - case tag => super.decodeTag(tag) - } - - override protected def decodeOption(tag: String, option: String): NodeSeq = tag match { - case "throws" if additions0.exceptions.contains(option) => - val (sym, s) = additions0.exceptions(option); - val path = "../" //todo: fix path - val href = path + sym.fullNameString('/') + - (if (sym.isModule || sym.isModuleClass) NAME_SUFFIX_OBJECT else "") + - "#" + s - <a href={href}>{option}</a> ++ {Text(" - ")}; - case _ => - super.decodeOption(tag,option) - } - - object roots extends jcl.LinkedHashMap[String,String]; - roots("classes") = "http://java.sun.com/j2se/1.5.0/docs/api"; - roots("rt") = roots("classes"); - roots("scala-library") = "http://www.scala-lang.org/docu/files/api"; - - private def keyFor(file: ZipFile): String = { - var name = file.getName - var idx = name.lastIndexOf(java.io.File.pathSeparator) - if (idx == -1) idx = name.lastIndexOf('/') - if (idx != -1) name = name.substring(idx + 1) - if (name endsWith ".jar") name.substring(0, name.length - (".jar").length) - else null - } - - // <code>{Text(string + " - ")}</code>; - override def hasLink0(sym: Symbol): Boolean = { - if (sym == NoSymbol) return false; - val ret = super.hasLink0(sym) && (additions.contains(sym) || symbols.contains(sym)); - if (ret) return true; - if (sym.toplevelClass == NoSymbol) return false; - val clazz = sym.toplevelClass.asInstanceOf[ClassSymbol]; - import scala.tools.nsc.io._; - clazz.classFile match { - case file : ZipArchive#FileEntry => - val key = keyFor(file.archive); - if (key != null && roots.contains(key)) return true; - case null => - case _ => - } - false - } - - def aref(href: String, label: String)(implicit frame: Frame) = - frame.aref(href, "_self", label) - - protected def anchor(entity: Symbol)(implicit frame: Frame): NodeSeq = - <a name={Text(frame.docName(entity))}></a> - - object symbols extends jcl.LinkedHashSet[Symbol] - - object allClasses extends jcl.LinkedHashMap[Package, jcl.LinkedHashSet[ClassOrObject]] { - override def default(pkg: Package): jcl.LinkedHashSet[ClassOrObject] = { - object ret extends jcl.LinkedHashSet[ClassOrObject] - this(pkg) = ret - ret - } - } - - object subClasses extends jcl.LinkedHashMap[Symbol, jcl.LinkedHashSet[ClassOrObject]] { - override def default(key: Symbol) = { - val ret = new jcl.LinkedHashSet[ClassOrObject] - this(key) = ret - ret - } - } - - override def rootFor(sym: Symbol): String = { - assert(sym != NoSymbol) - if (sym.toplevelClass == NoSymbol) return super.rootFor(sym) - if (symbols.contains(sym.toplevelClass)) return super.rootFor(sym) - val clazz = sym.toplevelClass.asInstanceOf[ClassSymbol] - import scala.tools.nsc.io._; - clazz.classFile match { - case file : ZipArchive#FileEntry => - val key = keyFor(file.archive) - if (key != null && roots.contains(key)) { - return roots(key) + '/' - } - case _ => - } - super.rootFor(sym) - } + def process(settings: Settings, units: Iterator[CompilationUnit]) : Unit } diff --git a/test/files/run/docgenerator.scala b/test/files/run/docgenerator.scala index db214b2c4d..d36700f82b 100644 --- a/test/files/run/docgenerator.scala +++ b/test/files/run/docgenerator.scala @@ -107,7 +107,7 @@ object Foo2 { object MainDoc { import scala.tools.nsc._ - import scala.tools.nsc.doc.DocDriver + import scala.tools.nsc.doc.DefaultDocDriver import scala.tools.nsc.reporters.ConsoleReporter def error(msg: String) { Console.err.println(msg) } var reporter: ConsoleReporter = _ @@ -123,7 +123,7 @@ object Foo2 { } val run = new compiler.Run run compile command.files - object generator extends DocDriver { + object generator extends DefaultDocDriver { lazy val global: compiler.type = compiler def settings = command.settings } |