From 58c64abc66708912ea67a6934fb84f4fa8217e18 Mon Sep 17 00:00:00 2001 From: michelou Date: Wed, 25 Apr 2007 14:07:05 +0000 Subject: uses new options in scaladoc generated docu --- src/compiler/scala/tools/ant/Scaladoc.scala | 86 +++++++++++++--- src/compiler/scala/tools/nsc/Main.scala | 10 +- src/compiler/scala/tools/nsc/Settings.scala | 4 +- src/compiler/scala/tools/nsc/doc/DocDriver.scala | 24 +++-- src/compiler/scala/tools/nsc/doc/DocUtil.scala | 42 ++++---- src/compiler/scala/tools/nsc/doc/ModelFrames.scala | 112 ++++++++++++--------- src/compiler/scala/tools/nsc/doc/ModelToXML.scala | 38 ++++--- 7 files changed, 205 insertions(+), 111 deletions(-) (limited to 'src') diff --git a/src/compiler/scala/tools/ant/Scaladoc.scala b/src/compiler/scala/tools/ant/Scaladoc.scala index 33ba2f1ded..eef194c8e0 100644 --- a/src/compiler/scala/tools/ant/Scaladoc.scala +++ b/src/compiler/scala/tools/ant/Scaladoc.scala @@ -42,6 +42,11 @@ import scala.tools.nsc.reporters.{Reporter, ConsoleReporter} *
  • encoding,
  • *
  • windowtitle,
  • *
  • doctitle,
  • + *
  • stylesheetfile,
  • + *
  • header,
  • + *
  • footer,
  • + *
  • top,
  • + *
  • bottom,
  • *
  • addparams,
  • *
  • deprecation,
  • *
  • unchecked.
  • @@ -100,13 +105,25 @@ class Scaladoc extends MatchingTask { /** The window title of the generated HTML documentation. */ private var windowtitle: Option[String] = None + /** The document title of the generated HTML documentation. */ private var doctitle: Option[String] = None + /** The user-specified stylesheet file. */ + private var stylesheetfile: Option[String] = None + + /** The user-specified header/footer and top/bottom texts. */ + private var pageheader: Option[String] = None + private var pagefooter: Option[String] = None + private var pagetop : Option[String] = None + private var pagebottom: Option[String] = None + /** Instruct the compiler to use additional parameters */ private var addParams: String = "" + /** Instruct the compiler to generate deprecation information. */ private var deprecation: Boolean = false + /** Instruct the compiler to generate unchecked information. */ private var unchecked: Boolean = false @@ -264,6 +281,41 @@ class Scaladoc extends MatchingTask { def setDoctitle(input: String): Unit = doctitle = Some(input) + /** Sets the stylesheetfile attribute. + * + * @param input The value of stylesheetfile. + */ + def setStylesheetfile(input: String): Unit = + stylesheetfile = Some(input) + + /** Sets the header attribute. + * + * @param input The value of header. + */ + def setHeader(input: String): Unit = + pageheader = Some(input) + + /** Sets the footer attribute. + * + * @param input The value of footer. + */ + def setFooter(input: String): Unit = + pagefooter = Some(input) + + /** Sets the top attribute. + * + * @param input The value of top. + */ + def setTop(input: String): Unit = + pagetop = Some(input) + + /** Sets the bottom attribute. + * + * @param input The value of bottom. + */ + def setBottom(input: String): Unit = + pagebottom = Some(input) + /** Set the addparams info attribute. * * @param input The value for addparams. @@ -460,6 +512,16 @@ class Scaladoc extends MatchingTask { nameToFile(originDir)(originFile) } + def decodeEscapes(s: String): String = { + // In Ant script characters '<' and '>' must be encoded when + // used in attribute values, e.g. for attributes "doctitle", "header", .. + // in task Scaladoc you may write: + // doctitle="<div>Scala</div>" + // so we have to decode them here. + s.replaceAll("<", "<").replaceAll(">",">") + .replaceAll("&", "&").replaceAll(""", "\"") + } + // Builds-up the compilation settings for Scalac with the existing Ant // parameters. val settings = new Settings(error) @@ -476,14 +538,12 @@ class Scaladoc extends MatchingTask { if (!extdirs.isEmpty) settings.extdirs.value = asString(getExtdirs) if (!encoding.isEmpty) settings.encoding.value = encoding.get if (!windowtitle.isEmpty) settings.windowtitle.value = windowtitle.get - if (!doctitle.isEmpty) settings.doctitle.value = - // In Ant script characters '<' and '>' must be encoded when - // used in attribute values, e.g. for attribute "doctitle" - // in task Scaladoc you may write: - // doctitle="<div>Scala</div>" - // so we have to decode them here. - doctitle.get.replaceAll("<", "<").replaceAll(">",">") - .replaceAll("&", "&").replaceAll(""", "\"") + if (!doctitle.isEmpty) settings.doctitle.value = decodeEscapes(doctitle.get) + if (!stylesheetfile.isEmpty) settings.stylesheetfile.value = stylesheetfile.get + if (!pageheader.isEmpty) settings.pageheader.value = decodeEscapes(pageheader.get) + if (!pagefooter.isEmpty) settings.pagefooter.value = decodeEscapes(pagefooter.get) + if (!pagetop.isEmpty) settings.pagetop.value = decodeEscapes(pagetop.get) + if (!pagebottom.isEmpty) settings.pagebottom.value = decodeEscapes(pagebottom.get) settings.deprecation.value = deprecation settings.unchecked.value = unchecked log("Scaladoc params = '" + addParams + "'", Project.MSG_DEBUG) @@ -504,19 +564,17 @@ class Scaladoc extends MatchingTask { /** Performs the compilation. */ override def execute() = { - val Pair(settings, sourceFiles) = initialize - val reporter = new ConsoleReporter(settings) + val Pair(commandSettings, sourceFiles) = initialize + val reporter = new ConsoleReporter(commandSettings) // Compiles the actual code - val compiler = new Global(settings, reporter) + val compiler = new Global(commandSettings, reporter) try { val run = new compiler.Run run.compile(sourceFiles.map (.toString())) object generator extends DocDriver { val global: compiler.type = compiler - def outdir = settings.outdir.value - def windowTitle = settings.windowtitle.value - def docTitle = settings.doctitle.value + def settings = commandSettings } generator.process(run.units) if (reporter.ERROR.count > 0) diff --git a/src/compiler/scala/tools/nsc/Main.scala b/src/compiler/scala/tools/nsc/Main.scala index 31796d2f36..97a0666d6c 100644 --- a/src/compiler/scala/tools/nsc/Main.scala +++ b/src/compiler/scala/tools/nsc/Main.scala @@ -57,11 +57,9 @@ object Main extends AnyRef with EvalLoop { run compile command.files if (command.settings.doc.value) { object generator extends DocGenerator { - val global : compiler.type = compiler - def outdir = command.settings.outdir.value - def windowTitle = command.settings.windowtitle.value - def docTitle = command.settings.doctitle.value - }; + val global: compiler.type = compiler + def settings = command.settings + } generator.process(run.units) } } @@ -75,7 +73,7 @@ object Main extends AnyRef with EvalLoop { } } - def main(args: Array[String]): unit = { + def main(args: Array[String]) { process(args) exit(if (reporter.hasErrors) 1 else 0) } diff --git a/src/compiler/scala/tools/nsc/Settings.scala b/src/compiler/scala/tools/nsc/Settings.scala index 30b8ad8913..b984a97469 100644 --- a/src/compiler/scala/tools/nsc/Settings.scala +++ b/src/compiler/scala/tools/nsc/Settings.scala @@ -136,10 +136,10 @@ class Settings(error: String => unit) { /** scaladoc specific options */ val windowtitle = StringSetting("-windowtitle", "windowtitle", "Specify window title of generated HTML documentation", - /*default*/"Scala 2 API Specification").dependsOn(doc) + /*default*/"Scala 2").dependsOn(doc) val doctitle = StringSetting("-doctitle", "doctitle", "Include title for the overview page", - /*default*/"Scala 2").dependsOn(doc) + /*default*/"Scala 2
    API Specification").dependsOn(doc) val stylesheetfile = StringSetting("-stylesheetfile", "stylesheetfile", "File to change style of the generated documentation", /*default*/"style.css").dependsOn(doc) diff --git a/src/compiler/scala/tools/nsc/doc/DocDriver.scala b/src/compiler/scala/tools/nsc/doc/DocDriver.scala index 2560cb6027..2fc4be7e84 100644 --- a/src/compiler/scala/tools/nsc/doc/DocDriver.scala +++ b/src/compiler/scala/tools/nsc/doc/DocDriver.scala @@ -142,18 +142,20 @@ abstract class DocDriver extends ModelFrames with ModelToXML { add.kind + " " + add.name + " in package " + add.sym.owner.fullNameString('.') } } - new RootFrame with Frame; + 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); + 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); + 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 = + + import DocUtil._ + override def classBody(entity: ClassOrObject)(implicit from: Frame): NodeSeq = (subClasses.get(entity.sym) match { case Some(symbols) =>
    @@ -162,9 +164,11 @@ abstract class DocDriver extends ModelFrames with ModelToXML { aref(urlFor(cls.sym), cls.path.map(.name).mkString("",".","")); })}

    ; - case None => NodeSeq.Empty; + case None => + NodeSeq.Empty })++super.classBody(entity); - protected def urlFor(sym : Symbol)(implicit frame : Frame) = frame.urlFor(sym); + + protected def urlFor(sym: Symbol)(implicit frame: Frame) = frame.urlFor(sym) override protected def decodeTag(tag: String): String = tag match { case "exception" => "Throws" diff --git a/src/compiler/scala/tools/nsc/doc/DocUtil.scala b/src/compiler/scala/tools/nsc/doc/DocUtil.scala index a10289c721..e76c94ab02 100644 --- a/src/compiler/scala/tools/nsc/doc/DocUtil.scala +++ b/src/compiler/scala/tools/nsc/doc/DocUtil.scala @@ -9,7 +9,7 @@ package scala.tools.nsc.doc import java.io.StringReader import org.xml.sax.InputSource -import scala.collection.immutable._ +import scala.collection.immutable.{ListMap, TreeSet} import scala.xml._ object DocUtil { @@ -17,12 +17,15 @@ object DocUtil { //def dquote(str: String): NodeSeq = // DQUOTE :: Text(str) :: DQUOTE :: Nil - def load(str: String): NodeSeq = { - val xmlSrc = - if (str.matches("^()*<[^>]+>.*<[^>]+>()*$")) str - else "" + str + "" - XML.load(new StringReader(xmlSrc)) - } + def load(str: String): NodeSeq = + if ((str == null) || (str.length == 0)) + NodeSeq.Empty + else { + val xmlSrc = + if (str.matches("^()*<[^>]+>.*<[^>]+>()*$")) str + else "
    " + str + "
    " + XML.load(new StringReader(xmlSrc)) + } //object DQUOTE extends SpecialNode { // def toString(sb: StringBuffer) = { @@ -95,26 +98,27 @@ object DocUtil { } ts } - implicit def coerceIterable[T](list : Iterable[T]) = NodeWrapper(list.elements); - implicit def coerceIterator[T](list : Iterator[T]) = NodeWrapper(list); + implicit def coerceIterable[T](list : Iterable[T]) = NodeWrapper(list.elements) + implicit def coerceIterator[T](list : Iterator[T]) = NodeWrapper(list) + case class NodeWrapper[T](list : Iterator[T]) { - def mkXML(begin : NodeSeq, separator : NodeSeq, end : NodeSeq)(f : T => NodeSeq) : NodeSeq = { - var seq : NodeSeq = begin; - val i = list; + + def mkXML(begin: NodeSeq, separator: NodeSeq, end: NodeSeq)(f: T => NodeSeq): NodeSeq = { + var seq: NodeSeq = begin + val i = list while (i.hasNext) { seq = seq ++ f(i.next); if (i.hasNext) seq = seq ++ separator; } - seq ++ end; + seq ++ end } - - def mkXML(begin : String, separator : String, end : String)(f : T => NodeSeq) : NodeSeq = { + def mkXML(begin: String, separator: String, end: String)(f: T => NodeSeq): NodeSeq = { this.mkXML(Text(begin),Text(separator),Text(end))(f); } - def surround(open : String, close : String)(f : T => NodeSeq) = { - if (list.hasNext) mkXML(open, ", ", close)(f); - else NodeSeq.Empty; - } + + def surround(open: String, close: String)(f: T => NodeSeq) = + if (list.hasNext) mkXML(open, ", ", close)(f) + else NodeSeq.Empty } } diff --git a/src/compiler/scala/tools/nsc/doc/ModelFrames.scala b/src/compiler/scala/tools/nsc/doc/ModelFrames.scala index 315ad493f6..42421ac07f 100644 --- a/src/compiler/scala/tools/nsc/doc/ModelFrames.scala +++ b/src/compiler/scala/tools/nsc/doc/ModelFrames.scala @@ -18,9 +18,19 @@ import scala.xml.{NodeSeq, Text, Unparsed, Utility} */ trait ModelFrames extends ModelExtractor { import DocUtil._ - def outdir: String - def windowTitle: String - def docTitle: String + def settings: Settings + + val outdir = settings.outdir.value + val windowTitle = settings.windowtitle.value + val docTitle = load(settings.doctitle.value) + + val stylesheetSetting = settings.stylesheetfile + + def pageHeader = load(settings.pageheader.value) + def pageFooter = load(settings.pagefooter.value) + def pageTop = load(settings.pagetop.value) + def pageBottom = load(settings.pagebottom.value) + def contentFrame = "contentFrame" def classesFrame = "classesFrame" def modulesFrame = "modulesFrame" @@ -29,10 +39,9 @@ trait ModelFrames extends ModelExtractor { protected val NAME_SUFFIX_OBJECT = "$object" protected val NAME_SUFFIX_PACKAGE = "$package" - def rootTitle = -
    {load(docTitle)}
    API Specification
    ; + def rootTitle =
    {docTitle}
    ; def rootDesc = -

    {load("This document is the API specification for " + docTitle)}

    ; +

    {load("This document is the API specification for " + windowTitle)}

    ; final def hasLink(sym: global.Symbol): Boolean = if (sym == global.NoSymbol) false @@ -148,16 +157,13 @@ trait ModelFrames extends ModelExtractor { } protected def rootFor(sym: global.Symbol) = "" - private val doctitle: NodeSeq = -
    {load(docTitle)}
    ; - abstract class AllPackagesFrame extends Frame { override val path = "modules" override val title = "List of all packages" def packages: Iterable[Package] override def body: NodeSeq =
    - {doctitle} +
    {windowTitle}
    {"All objects and classes"}
    Packages
    @@ -184,7 +190,7 @@ trait ModelFrames extends ModelExtractor { ; } - val classFrameKinds = Objects :: Classes :: Nil; + val classFrameKinds = Objects :: Classes :: Nil abstract class ListClassFrame extends Frame { def classes: Iterable[ClassOrObject] def navLabel: String @@ -227,13 +233,13 @@ trait ModelFrames extends ModelExtractor { })}; nav ++ body } - def optional(cls : ClassOrObject) : NodeSeq = NodeSeq.Empty; + def optional(cls: ClassOrObject): NodeSeq = NodeSeq.Empty } abstract class PackageContentFrame extends Frame { - override def path = pkg.fullName('/') + "$content"; - override def title = "All classes and objects in " + pkg.fullName('.'); - protected def pkg : Package; - protected def classes : Iterable[ClassOrObject]; + override def path = pkg.fullName('/') + "$content" + override def title = "All classes and objects in " + pkg.fullName('.') + protected def pkg: Package + protected def classes: Iterable[ClassOrObject] def body: NodeSeq = {rootTitle} ++ {rootDesc} ++ {classFrameKinds.mkXML("","\n","")(kind => { val classes = sort(this.classes.filter(e => kind.f(e.sym) && e.isInstanceOf[TopLevel])); @@ -245,31 +251,37 @@ trait ModelFrames extends ModelExtractor { })}; } abstract class ClassContentFrame extends Frame { - def clazz: ClassOrObject; - def body: NodeSeq = {navigation}{header0}{longHeader(clazz)}; + def clazz: ClassOrObject + def body: NodeSeq = + + {pageHeader}{navigation}{pageTop} + {header0}{longHeader(clazz)} + {pageBottom}{navigation}{pageFooter} + ; final def path = urlFor0(clazz.sym, clazz.sym) private def navigation: NodeSeq = ; - private def header0: NodeSeq = -
    - {Text(clazz.kind)} - {Text(clazz.name)} in - {aref(urlFor(decode(clazz.sym.owner)), "_self", decode(clazz.sym.owner).fullNameString('.'))} -

    -
    ; + private def header0: NodeSeq = + +
    + {Text(clazz.kind)} + {Text(clazz.name)} in + {aref(urlFor(decode(clazz.sym.owner)), "_self", decode(clazz.sym.owner).fullNameString('.'))} +
    +
    +
    ; } - def longComment(cmnt : Comment) : NodeSeq; + def longComment(cmnt: Comment): NodeSeq val index = @@ -313,28 +325,36 @@ trait ModelFrames extends ModelExtractor { } - private val loader = getClass().getClassLoader() def copyResources = { import java.io._ - // The name of a resource is a '/'-separated path name that identifies the resource. - val rsrcdir = "scala/tools/nsc/doc/" - for (base <- List("style.css", "script.js")) { - try { - val in = loader.getResourceAsStream(rsrcdir + base) - val out = new FileOutputStream(new File(outdir + File.separator + base)) - val buf = new Array[byte](1024) - var len = 0 - while (len != -1) { - out.write(buf, 0, len) - len = in.read(buf) + val loader = this.getClass().getClassLoader() + def basename(path: String): String = { + val pos = path lastIndexOf System.getProperty("file.separator", "/") + if (pos != -1) path.substring(pos + 1) else path + } + def copyResource(name: String, isFile: boolean) = try { + val (in, outfile) = + if (isFile) + (new FileInputStream(name), basename(name)) + else { + // The name of a resource is a '/'-separated path name that identifies the resource. + (loader.getResourceAsStream("scala/tools/nsc/doc/" + name), name) } - in.close() - out.close() - } catch { - case _ => - System.err.println("Resource file '" + rsrcdir + base + "' not found") + val out = new FileOutputStream(new File(outdir + File.separator + outfile)) + val buf = new Array[byte](1024) + var len = 0 + while (len != -1) { + out.write(buf, 0, len) + len = in.read(buf) } + in.close() + out.close() + } catch { + case _ => + System.err.println("Resource file '" + name + "' not found") } + copyResource(stylesheetSetting.value, !stylesheetSetting.isDefault) + copyResource("script.js", false) } private val patVal = java.util.regex.Pattern.compile( "scala\\.(Byte|Boolean|Char|Double|Float|Int|Long|Short)") diff --git a/src/compiler/scala/tools/nsc/doc/ModelToXML.scala b/src/compiler/scala/tools/nsc/doc/ModelToXML.scala index 7e3e36cfa0..6ad9791bc1 100644 --- a/src/compiler/scala/tools/nsc/doc/ModelToXML.scala +++ b/src/compiler/scala/tools/nsc/doc/ModelToXML.scala @@ -13,22 +13,25 @@ import scala.xml._ * @author Sean McDirmid, Stephane Micheloud */ trait ModelToXML extends ModelExtractor { - import global._; - import DocUtil._; + import global._ + import DocUtil._ // decode entity into XML. - type Frame; + type Frame - protected def urlFor(sym : Symbol)(implicit frame : Frame) : String; - protected def anchor(sym : Symbol)(implicit frame : Frame) : NodeSeq; - def aref(href : String, label : String)(implicit frame : Frame) : NodeSeq; - def link(entity : Symbol)(implicit frame : Frame) : NodeSeq = { + protected def urlFor(sym: Symbol)(implicit frame: Frame): String + protected def anchor(sym: Symbol)(implicit frame: Frame): NodeSeq + + def aref(href: String, label: String)(implicit frame: Frame): NodeSeq + + def link(entity: Symbol)(implicit frame: Frame): NodeSeq = { val url = urlFor(entity); // nothing to do but be verbose. if (url == null) Text({ entity.owner.fullNameString('.') + '.' + entity.nameString; }) else aref(url, entity.nameString); } - def link(tpe : Type)(implicit frame : Frame) : NodeSeq = { + + def link(tpe: Type)(implicit frame : Frame) : NodeSeq = { if (!tpe.typeArgs.isEmpty) { if (definitions.isFunctionType(tpe)) { val (args,r) = tpe.typeArgs.splitAt(tpe.typeArgs.length - 1); @@ -57,13 +60,15 @@ trait ModelToXML extends ModelExtractor { } } } + private def printIf[T](what : Option[T], before : String, after : String)(f : T => NodeSeq) : NodeSeq = { if (what.isEmpty) return Text(""); var seq : NodeSeq = Text(before); seq = seq ++ f(what.get); seq = seq ++ Text(after); - seq; + seq } + def bodyFor(entity : Entity)(implicit frame : Frame) : NodeSeq = { var seq = {entity.typeParams.surround("[", "]")(e => { Text(e.variance) ++ {e.name} ++ @@ -86,11 +91,13 @@ trait ModelToXML extends ModelExtractor { })}; seq ++ {printIf(entity.resultType, " : ", "")(tpe => link(tpe))} } + def extendsFor(entity : Entity)(implicit frame : Frame) : NodeSeq = { if (entity.parents.isEmpty) NodeSeq.Empty; else extends ++ entity.parents.mkXML(Text(""), with , Text(""))(link); } + def parse(str: String): NodeSeq = { new SpecialNode { def label = "#PCDATA" @@ -100,6 +107,7 @@ trait ModelToXML extends ModelExtractor { } } } + def longHeader(entity : Entity)(implicit from : Frame) : NodeSeq = Group({ anchor(entity.sym) ++
    @@ -122,7 +130,7 @@ trait ModelToXML extends ModelExtractor { if (!overridden.isEmpty) { var seq : NodeSeq = Text("Overrides "); seq = seq ++ overridden.mkXML("",", ", "")(sym => link(decode(sym.owner)) ++ Text(".") ++ link(sym)); - seq; + seq } else NodeSeq.Empty; } ++
    ); @@ -200,11 +208,13 @@ trait ModelToXML extends ModelExtractor { seq; } - protected def decodeOption(tag: String, string: String): NodeSeq = {Text(string + " - ")}; + protected def decodeOption(tag: String, string: String): NodeSeq = + {Text(string + " - ")}; + protected def decodeTag(tag: String): String = "" + Character.toUpperCase(tag.charAt(0)) + tag.substring(1); - def shortHeader(entity : Entity)(implicit from : Frame) : NodeSeq = { + def shortHeader(entity: Entity)(implicit from: Frame): NodeSeq = {Text(entity.flagsString)} {Text(entity.kind)} @@ -216,9 +226,9 @@ trait ModelToXML extends ModelExtractor { if (cmnt.isEmpty) NodeSeq.Empty; else
    {parse(cmnt.get.body)}
    ; } - + - } + def attrsFor(entity : Entity)(implicit from : Frame) : NodeSeq = { def attrFor(attr: AnnotationInfo[Constant]): Node = { val buf = new StringBuilder -- cgit v1.2.3