From 6995333a275d0d403869a1cd9d7e92b530bd0e86 Mon Sep 17 00:00:00 2001 From: Gilles Dubochet Date: Wed, 2 Dec 2009 17:31:28 +0000 Subject: [scaladoc] Types are links. --- src/compiler/scala/tools/ant/Scaladoc.scala | 2 +- src/compiler/scala/tools/nsc/ScalaDoc.scala | 2 +- src/compiler/scala/tools/nsc/doc/DocFactory.scala | 61 +++ src/compiler/scala/tools/nsc/doc/Processor.scala | 56 --- .../scala/tools/nsc/doc/html/HtmlFactory.scala | 79 ++++ .../scala/tools/nsc/doc/html/HtmlPage.scala | 36 +- .../scala/tools/nsc/doc/html/SiteFactory.scala | 79 ---- .../scala/tools/nsc/doc/html/page/Index.scala | 2 +- .../scala/tools/nsc/doc/html/page/Template.scala | 60 ++- .../scala/tools/nsc/doc/html/resource/index.html | 50 ++- .../tools/nsc/doc/html/resource/lib/index.css | 51 ++- .../scala/tools/nsc/doc/html/resource/lib/index.js | 47 ++- .../tools/nsc/doc/html/resource/lib/template.css | 192 ++++----- .../tools/nsc/doc/html/resource/lib/template.js | 14 + .../tools/nsc/doc/html/resource/template.html | 45 ++- .../scala/tools/nsc/doc/model/Entity.scala | 4 +- .../scala/tools/nsc/doc/model/EntityFactory.scala | 432 -------------------- .../scala/tools/nsc/doc/model/ModelFactory.scala | 443 +++++++++++++++++++++ .../scala/tools/nsc/doc/model/TypeEntity.scala | 2 +- 19 files changed, 869 insertions(+), 788 deletions(-) create mode 100644 src/compiler/scala/tools/nsc/doc/DocFactory.scala delete mode 100644 src/compiler/scala/tools/nsc/doc/Processor.scala create mode 100644 src/compiler/scala/tools/nsc/doc/html/HtmlFactory.scala delete mode 100644 src/compiler/scala/tools/nsc/doc/html/SiteFactory.scala delete mode 100644 src/compiler/scala/tools/nsc/doc/model/EntityFactory.scala create mode 100644 src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala (limited to 'src') diff --git a/src/compiler/scala/tools/ant/Scaladoc.scala b/src/compiler/scala/tools/ant/Scaladoc.scala index 622f9da19f..94b50ab045 100644 --- a/src/compiler/scala/tools/ant/Scaladoc.scala +++ b/src/compiler/scala/tools/ant/Scaladoc.scala @@ -518,7 +518,7 @@ class Scaladoc extends MatchingTask { val Pair(docSettings, sourceFiles) = initialize val reporter = new ConsoleReporter(docSettings) try { - val docProcessor = new scala.tools.nsc.doc.Processor(reporter, docSettings) + val docProcessor = new scala.tools.nsc.doc.DocFactory(reporter, docSettings) docProcessor.document(sourceFiles.map (_.toString)) if (reporter.ERROR.count > 0) error( diff --git a/src/compiler/scala/tools/nsc/ScalaDoc.scala b/src/compiler/scala/tools/nsc/ScalaDoc.scala index fcaced5b41..4936135c8d 100644 --- a/src/compiler/scala/tools/nsc/ScalaDoc.scala +++ b/src/compiler/scala/tools/nsc/ScalaDoc.scala @@ -62,7 +62,7 @@ object ScalaDoc { docSettings.assemrefs.value = docSettings.assemrefs.value + File.pathSeparator + libpath } - val docProcessor = new scala.tools.nsc.doc.Processor(reporter, docSettings) + val docProcessor = new scala.tools.nsc.doc.DocFactory(reporter, docSettings) docProcessor.document(command.files) } diff --git a/src/compiler/scala/tools/nsc/doc/DocFactory.scala b/src/compiler/scala/tools/nsc/doc/DocFactory.scala new file mode 100644 index 0000000000..14ff8012b8 --- /dev/null +++ b/src/compiler/scala/tools/nsc/doc/DocFactory.scala @@ -0,0 +1,61 @@ +/* NSC -- new Scala compiler -- Copyright 2007-2009 LAMP/EPFL */ + +// $Id$ + +package scala.tools.nsc +package doc + +import reporters.Reporter + +/** A documentation processor controls the process of generating Scala documentation, which is as follows. + * + * * A simplified compiler instance (with only the front-end phases enabled) is created, and additional + * ''sourceless'' comments are registered. + * * Documentable files are compiled, thereby filling the compiler's symbol table. + * * A documentation model is extracted from the post-compilation compiler's symbol table. + * * A generator is used to transform the model into the correct final format (HTML). + * + * A processor contains a single compiler instantiated from the processor's settings. Each call to the `run` method + * uses the same compiler instance with the same symbol table. In particular, this implies that the scaladoc site + * obtained from a call to `run` will contain documentation about files compiled during previous calls to the same + * processor's `run` method. + * + * @param reporter The reporter to which both documentation and compilation errors will be reported. + * @param settings The settings to be used by the documenter and compiler for generating documentation. + * + * @author Gilles Dubochet */ +class DocFactory(val reporter: Reporter, val settings: doc.Settings) { processor => + + /** The unique compiler instance used by this processor and constructed from its `settings`. */ + object compiler extends Global(settings, reporter) { + override protected def computeInternalPhases() { + phasesSet += syntaxAnalyzer + phasesSet += analyzer.namerFactory + phasesSet += analyzer.typerFactory + phasesSet += superAccessors + phasesSet += pickler + phasesSet += refchecks + } + override def onlyPresentation = true + lazy val addSourceless = { + val sless = new SourcelessComments { val global = compiler } + comments ++= sless.comments + } + } + + /** Creates a scaladoc site for all symbols defined in this call's `files`, as well as those defined in `files` of + * previous calls to the same processor. + * @param files The list of paths (relative to the compiler's source path, or absolute) of files to document. */ + def document(files: List[String]): Unit = { + (new compiler.Run()) compile files + compiler.addSourceless + if (!reporter.hasErrors) { + val modelFactory = (new model.ModelFactory(compiler, settings)) + val htmlFactory = (new html.HtmlFactory(reporter, settings)) + val docModel = modelFactory.makeModel + println("model contains " + modelFactory.templatesCount + " documentable templates") + htmlFactory generate docModel + } + } + +} diff --git a/src/compiler/scala/tools/nsc/doc/Processor.scala b/src/compiler/scala/tools/nsc/doc/Processor.scala deleted file mode 100644 index 8e08010f2c..0000000000 --- a/src/compiler/scala/tools/nsc/doc/Processor.scala +++ /dev/null @@ -1,56 +0,0 @@ -/* NSC -- new Scala compiler -- Copyright 2007-2009 LAMP/EPFL */ - -// $Id$ - -package scala.tools.nsc -package doc - -import reporters.Reporter - -/** A documentation processor controls the process of generating Scala documentation, which is as follows. - * - * * A simplified compiler instance (with only the front-end phases enabled) is created, and additional - * ''sourceless'' comments are registered. - * * Documentable files are compiled, thereby filling the compiler's symbol table. - * * A documentation model is extracted from the post-compilation compiler's symbol table. - * * A generator is used to transform the model into the correct final format (HTML). - * - * A processor contains a single compiler instantiated from the processor's settings. Each call to the `run` method - * uses the same compiler instance with the same symbol table. In particular, this implies that the scaladoc site - * obtained from a call to `run` will contain documentation about files compiled during previous calls to the same - * processor's `run` method. - * - * @param reporter The reporter to which both documentation and compilation errors will be reported. - * @param settings The settings to be used by the documenter and compiler for generating documentation. - * - * @author Gilles Dubochet */ -class Processor(val reporter: Reporter, val settings: doc.Settings) { processor => - - /** The unique compiler instance used by this processor and constructed from its `settings`. */ - object compiler extends Global(settings, reporter) { - override protected def computeInternalPhases() { - phasesSet += syntaxAnalyzer - phasesSet += analyzer.namerFactory - phasesSet += analyzer.typerFactory - phasesSet += superAccessors - phasesSet += pickler - phasesSet += refchecks - } - override def onlyPresentation = true - lazy val addSourceless = { - val sless = new SourcelessComments { val global = compiler } - comments ++= sless.comments - } - } - - /** Creates a scaladoc site for all symbols defined in this call's `files`, as well as those defined in `files` of - * previous calls to the same processor. - * @param files The list of paths (relative to the compiler's source path, or absolute) of files to document. */ - def document(files: List[String]): Unit = { - (new compiler.Run()) compile files - compiler.addSourceless - if (!reporter.hasErrors) - (new html.SiteFactory(reporter, settings)) generate (new model.EntityFactory(compiler, settings)).makeModel - } - -} diff --git a/src/compiler/scala/tools/nsc/doc/html/HtmlFactory.scala b/src/compiler/scala/tools/nsc/doc/html/HtmlFactory.scala new file mode 100644 index 0000000000..bb2201d6b5 --- /dev/null +++ b/src/compiler/scala/tools/nsc/doc/html/HtmlFactory.scala @@ -0,0 +1,79 @@ +/* NSC -- new Scala compiler + * Copyright 2007-2009 LAMP/EPFL + * @author David Bernard, Manohar Jonnalagedda + */ + +package scala.tools.nsc +package doc +package html + +import reporters.Reporter +import model._ + +import java.io.{FileOutputStream, File} +import scala.collection._ + +/** A class that can generate Scaladoc sites to some fixed root folder. + * @author David Bernard + * @author Gilles Dubochet */ +class HtmlFactory(val reporter: Reporter, val settings: Settings) { + + /** The character encoding to be used for generated Scaladoc sites. This value is currently always UTF-8. */ + def encoding: String = "UTF-8" + + /** The character encoding to be used for generated Scaladoc sites. This value is defined by the generator's + * settings. */ + def siteRoot: File = new File(settings.outdir.value) + + /** Generates the Scaladoc site for a model into the site toot. A scaladoc site is a set of HTML and related files + * that document a model extracted from a compiler run. + * @param model The model to generate in the form of a sequence of packages. */ + def generate(modelRoot: Package): Unit = { + + def copyResource(subPath: String) { + val buf = new Array[Byte](1024) + val in = getClass.getResourceAsStream("/scala/tools/nsc/doc/html/resource/" + subPath) + assert(in != null) + val dest = new File(siteRoot, subPath) + dest.getParentFile.mkdirs() + val out = new FileOutputStream(dest) + try { + var len = 0 + while ({len = in.read(buf); len != -1}) + out.write(buf, 0, len) + } + finally { + in.close() + out.close() + } + } + + copyResource("lib/jquery.js") + copyResource("lib/index.css") + copyResource("lib/index.js") + copyResource("lib/template.css") + copyResource("lib/template.js") + copyResource("lib/class.png") + copyResource("lib/class_big.png") + copyResource("lib/object.png") + copyResource("lib/object_big.png") + copyResource("lib/trait.png") + copyResource("lib/trait_big.png") + copyResource("lib/package.png") + copyResource("lib/package_big.png") + + new page.Index(modelRoot) writeFor this + + val written = mutable.HashSet.empty[DocTemplateEntity] + + def writeTemplate(tpl: DocTemplateEntity): Unit = { + new page.Template(tpl) writeFor this + written += tpl + tpl.templates filter { t => !(written contains t) } map (writeTemplate(_)) + } + + writeTemplate(modelRoot) + + } + +} diff --git a/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala b/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala index 48073f8e59..3760099a26 100644 --- a/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala +++ b/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala @@ -38,7 +38,7 @@ abstract class HtmlPage { thisPage => /** Writes this page as a file. The file's location is relative to the generator's site root, and the encoding is * also defined by the generator. * @param generator The generator that is writing this page. */ - def writeFor(site: SiteFactory): Unit = { + def writeFor(site: HtmlFactory): Unit = { val pageFile = new File(site.siteRoot, absoluteLinkTo(thisPage.path)) val pageFolder = pageFile.getParentFile if (!pageFolder.exists) pageFolder.mkdirs() @@ -145,12 +145,34 @@ abstract class HtmlPage { thisPage => case Text(text) => Unparsed(text) } - def typeToHtml(tpe: model.TypeEntity): NodeSeq = { - - // TODO: Generate links using tpe's refEntity map - - xml.Text(tpe.name) - + def typeToHtml(tpe: model.TypeEntity, hasLinks: Boolean): NodeSeq = { + val string = tpe.name + def toLinksOut(inPos: Int, starts: List[Int]): NodeSeq = { + if (starts.isEmpty && (inPos == string.length)) + NodeSeq.Empty + else if (starts.isEmpty) + xml.Text(string.slice(inPos, string.length)) + else if (inPos == starts.head) + toLinksIn(inPos, starts) + else { + xml.Text(string.slice(inPos, starts.head)) ++ toLinksIn(starts.head, starts) + } + } + def toLinksIn(inPos: Int, starts: List[Int]): NodeSeq = { + val (tpl, width) = tpe.refEntity(inPos) + (tpl match { + case dtpl:DocTemplateEntity if hasLinks => + { + string.slice(inPos, inPos + width) + } + case tpl => + { string.slice(inPos, inPos + width) } + }) ++ toLinksOut(inPos + width, starts.tail) + } + if (hasLinks) + toLinksOut(0, tpe.refEntity.keySet.toList) + else + xml.Text(string) } } diff --git a/src/compiler/scala/tools/nsc/doc/html/SiteFactory.scala b/src/compiler/scala/tools/nsc/doc/html/SiteFactory.scala deleted file mode 100644 index a605002b64..0000000000 --- a/src/compiler/scala/tools/nsc/doc/html/SiteFactory.scala +++ /dev/null @@ -1,79 +0,0 @@ -/* NSC -- new Scala compiler - * Copyright 2007-2009 LAMP/EPFL - * @author David Bernard, Manohar Jonnalagedda - */ - -package scala.tools.nsc -package doc -package html - -import reporters.Reporter -import model._ - -import java.io.{FileOutputStream, File} -import scala.collection._ - -/** A class that can generate Scaladoc sites to some fixed root folder. - * @author David Bernard - * @author Gilles Dubochet */ -class SiteFactory(val reporter: Reporter, val settings: Settings) { - - /** The character encoding to be used for generated Scaladoc sites. This value is currently always UTF-8. */ - def encoding: String = "UTF-8" - - /** The character encoding to be used for generated Scaladoc sites. This value is defined by the generator's - * settings. */ - def siteRoot: File = new File(settings.outdir.value) - - /** Generates the Scaladoc site for a model into the site toot. A scaladoc site is a set of HTML and related files - * that document a model extracted from a compiler run. - * @param model The model to generate in the form of a sequence of packages. */ - def generate(modelRoot: Package): Unit = { - - def copyResource(subPath: String) { - val buf = new Array[Byte](1024) - val in = getClass.getResourceAsStream("/scala/tools/nsc/doc/html/resource/" + subPath) - assert(in != null) - val dest = new File(siteRoot, subPath) - dest.getParentFile.mkdirs() - val out = new FileOutputStream(dest) - try { - var len = 0 - while ({len = in.read(buf); len != -1}) - out.write(buf, 0, len) - } - finally { - in.close() - out.close() - } - } - - copyResource("lib/jquery.js") - copyResource("lib/index.css") - copyResource("lib/index.js") - copyResource("lib/template.css") - copyResource("lib/template.js") - copyResource("lib/class.png") - copyResource("lib/class_big.png") - copyResource("lib/object.png") - copyResource("lib/object_big.png") - copyResource("lib/trait.png") - copyResource("lib/trait_big.png") - copyResource("lib/package.png") - copyResource("lib/package_big.png") - - new page.Index(modelRoot) writeFor this - - val written = mutable.HashSet.empty[DocTemplateEntity] - - def writeTemplate(tpl: DocTemplateEntity): Unit = { - new page.Template(tpl) writeFor this - written += tpl - tpl.templates filter { t => !(written contains t) } map (writeTemplate(_)) - } - - writeTemplate(modelRoot) - - } - -} diff --git a/src/compiler/scala/tools/nsc/doc/html/page/Index.scala b/src/compiler/scala/tools/nsc/doc/html/page/Index.scala index 5ad0005679..f671380a53 100644 --- a/src/compiler/scala/tools/nsc/doc/html/page/Index.scala +++ b/src/compiler/scala/tools/nsc/doc/html/page/Index.scala @@ -30,7 +30,7 @@ class Index(modelRoot: Package) extends HtmlPage { def body =
- +
{ def packageElem(pack: model.Package): NodeSeq = { diff --git a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala index 47f2d4abed..b5aba6a31b 100644 --- a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala +++ b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala @@ -137,30 +137,28 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage { if (tme.isDef) "def" else if (tme.isVal) "val" else if (tme.isVar) "var" else "type" } - def boundsToString(hi: Option[TypeEntity], lo: Option[TypeEntity]): String = { - def bound0(bnd: Option[TypeEntity], pre: String): String = bnd match { - case None => "" - case Some(tpe) => pre + typeToHtml(tpe) + def boundsToHtml(hi: Option[TypeEntity], lo: Option[TypeEntity], hasLinks: Boolean): NodeSeq = { + def bound0(bnd: Option[TypeEntity], pre: String): NodeSeq = bnd match { + case None => NodeSeq.Empty + case Some(tpe) => xml.Text(pre) ++ typeToHtml(tpe, hasLinks) } - bound0(hi, " <: ") + bound0(lo, " >: ") + bound0(hi, " <: ") ++ bound0(lo, " >: ") } /** name, tparams, params, result */ def signature(mbr: MemberEntity, isSelf: Boolean): NodeSeq = { - val inside: NodeSeq = + def inside(hasLinks: Boolean): NodeSeq = -
{ kindToString(mbr) }
-
- { if (mbr.isConstructor) tpl.name else mbr.name } - { def tparamsToHtml(tpss: List[TypeParam]): NodeSeq = + { kindToString(mbr) } + + { if (mbr.isConstructor) tpl.name else mbr.name }{ + def tparamsToHtml(tpss: List[TypeParam]): NodeSeq = if (tpss.isEmpty) NodeSeq.Empty else { def tparam0(tp: TypeParam): NodeSeq = - { - tp.variance + tp.name + boundsToString(tp.hi, tp.lo) - } + { tp.variance + tp.name }{ boundsToHtml(tp.hi, tp.lo, hasLinks)} def tparams0(tpss: List[TypeParam]): NodeSeq = (tpss: @unchecked) match { case tp :: Nil => tparam0(tp) - case tp :: tps => tparam0(tp) ++ Text(",") ++ tparams0(tps) + case tp :: tps => tparam0(tp) ++ Text(", ") ++ tparams0(tps) } [{ tparams0(tpss) }] } @@ -169,16 +167,14 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage { case dfe: Def => tparamsToHtml(dfe.typeParams) case _ => NodeSeq.Empty } - } - { def paramsToHtml(vlsss: List[List[ValueParam]]): NodeSeq = { + }{ + def paramsToHtml(vlsss: List[List[ValueParam]]): NodeSeq = { def param0(vl: ValueParam): NodeSeq = - { - vl.name + ": " + typeToHtml(vl.resultType) - } + { vl.name + ": " }{ typeToHtml(vl.resultType, hasLinks) } def params0(vlss: List[ValueParam]): NodeSeq = vlss match { case Nil => NodeSeq.Empty case vl :: Nil => param0(vl) - case vl :: vls => param0(vl) ++ Text(",") ++ params0(vls) + case vl :: vls => param0(vl) ++ Text(", ") ++ params0(vls) } vlsss map { vlss => ({ params0(vlss) }) } } @@ -188,32 +184,32 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage { case dfe: Def => paramsToHtml(dfe.valueParams) case _ => NodeSeq.Empty } - } - { mbr match { + }{ + mbr match { case tpl: DocTemplateEntity if (!tpl.isPackage) => tpl.parentType match { - case Some(st) => extends{ typeToHtml(st) } + case Some(st) => extends { typeToHtml(st, hasLinks) } case None =>NodeSeq.Empty } case tme: MemberEntity if (tme.isDef || tme.isVal || tme.isVar) => - :{ typeToHtml(tme.resultType) } + : { typeToHtml(tme.resultType, hasLinks) } case abt: AbstractType => - val b2s = boundsToString(abt.hi, abt.lo) - if (b2s != "") - { b2s } + val b2s = boundsToHtml(abt.hi, abt.lo, hasLinks) + if (b2s != NodeSeq.Empty) + { b2s } else NodeSeq.Empty case alt: AliasType => - ={ typeToHtml(alt.alias) } + = { typeToHtml(alt.alias, hasLinks) } case _ => NodeSeq.Empty } } -
-
+ +
mbr match { case dte: DocTemplateEntity if !isSelf => - { inside } + { inside(hasLinks = false) } case _ => -
{ inside }
+
{ inside(hasLinks = true) }
} } diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/index.html b/src/compiler/scala/tools/nsc/doc/html/resource/index.html index 7b86491ad9..95fae3176e 100644 --- a/src/compiler/scala/tools/nsc/doc/html/resource/index.html +++ b/src/compiler/scala/tools/nsc/doc/html/resource/index.html @@ -10,57 +10,69 @@ +

Documentation

- +
  1. -

    scala.collection

    +

    scala.collection

    1. - BitSet (class) - (object) + + (object) + + + (class) + BitSet +
    2. - BufferedIterator (trait) + + (trait) + BufferedIterator +
    3. - DefaultMap (object) + + (object) + DefaultMap +
    4. - Iterable (class) - (object) + Iterable (class) + (object)
    1. -

      scala.collection.mutable

      +

      scala.collection.mutable

      1. - DefaultMap (object) + DefaultMap (object)
      2. - Iterable (class) - (object) + Iterable (class) + (object)
      3. - Iterable (class) - (object) + Iterable (class) + (object)
      4. - Truc (class) + Truc (class)
    2. -

      scala.collection.immutable

      +

      scala.collection.immutable

      1. - DefaultMap (object) + DefaultMap (object)
      2. - Iterable (class) - (object) + Iterable (class) + (object)
    3. diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.css b/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.css index f9cd1f9ade..0b444eec13 100644 --- a/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.css +++ b/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.css @@ -1,13 +1,25 @@ * { - color: black; + color: inherit; + font-size: 10pt; text-decoration: none; - font-size: inherit; font-family: sans-serif; border-width: 0px; padding: 0px; margin: 0px; } +a { + cursor: pointer; +} + +a:hover { + text-decoration: underline; +} + +h1 { + display: none; +} + #browser { top: 0px; left: 0px; @@ -15,10 +27,11 @@ width: 300px; display: block; position: fixed; - overflow: auto; } #quickflt { + display: block; + position: fixed; height: 22px; right: 0px; left: 0px; @@ -28,11 +41,13 @@ font-weight: bold; color: #993300; padding: 5px; - font-size: 12px; background-color: white; } #tpl { + display: block; + position: fixed; + overflow: auto; right: 0px; left: 0px; bottom: 0px; @@ -41,29 +56,25 @@ display: block; } -#tpl h3 { - background-color: #142556; - color: white; - font-weight: bold; - padding: 2px; +#tpl .packhide { display: block; - font-size: 14px; - border-bottom-color: white; - border-bottom-style: solid; - border-bottom-width: 1px; + float: right; + font-weight: normal; + color: white; + padding: 1px 4px 1px 4px; } -#tpl h3 a { +#tpl .packages > li > h3 { + display: block; + background-color: #142556; color: white; + padding: 1px 4px 1px 4px; + font-weight: bold; + display: block; } #tpl ol > li { display: block; - font-size: 14px; - background-color: #cccccc; - border-bottom-color: white; - border-bottom-style: solid; - border-bottom-width: 1px; } #tpl ol > li .icon { @@ -74,7 +85,7 @@ #content { border-left-width: 1px; border-left-color: black; - border-left-style: solid; + border-left-style: white; right: 0px; left: 0px; bottom: 0px; diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js b/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js index 4ea93c74f1..8f9b366ea9 100644 --- a/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js +++ b/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js @@ -1,21 +1,24 @@ $(document).ready(function(){ cleanPackage($("#tpl")); - $("#tpl ol > li span.class").replaceWith(""); - $("#tpl ol > li span.object").replaceWith(""); - $("#tpl ol > li span.trait").replaceWith(""); - $("#tpl ol > li span.package").replaceWith(""); - $("#tpl a.tplshow").click(function(event){ + $("#tpl ol > li span:contains('(class)')").replaceWith(""); + $("#tpl ol > li span:contains('(object)')").replaceWith(""); + $("#tpl ol > li span:contains('(trait)')").replaceWith(""); + $("#tpl ol > li span:contains('(package)')").replaceWith(""); + $("#tpl a[href]").click(function(event){ $("#content>iframe").attr("src", event.currentTarget.href); return false; }); $("#quickflt").focus(function(event) { $("#quickflt").select(); }); - $("#quickflt").keyup(function(event) { - var b = $("#quickflt").attr("value"); + $("#quickflt").bind("keyup", function(event) { + var query = $("#quickflt").attr("value"); + // Regexp that matches CamelCase subbits: "BiSe" is + // "[a-z]*Bi[a-z]*Se" and matches "BitSet", "ABitSet", ... + var queryRegExp = new RegExp(query.replace(/([A-Z])/g,"[a-z]*$1")); $("#tpl ol.templates > li").each(function(){ - var a = $(this).attr("title"); - if (a == "" || a.indexOf(b) >= 0) { + var item = $(this).attr("title"); + if (item == "" || queryRegExp.test(item)) { $(this).show(); $(this).removeClass("hide"); } @@ -26,8 +29,22 @@ $(document).ready(function(){ }); cleanPackage($("#tpl")); }); + $("#tpl .packages > li").prepend("hide"); + $("#tpl .packages > li > a.packhide").click(function(event){ + var action = $(this).text(); + if (action == "hide") { + $("~ ol", $(this)).hide(); + $(this).text("show"); + } + else { + $("~ ol", $(this)).show(); + $(this).text("hide"); + } + return false; + }); }); +/* Recusively go through the packages and show only those which contain visible items. */ function cleanPackage(pack) { $("> ol.packages > li", pack).each(function(){ cleanPackage($(this)); }); if ($("> ol > li:not(.hide)", pack).length > 0) { @@ -38,7 +55,13 @@ function cleanPackage(pack) { pack.addClass("hide"); pack.hide(); }; - if ($("> ol.templates > li:not(.hide)", pack).length > 0) { $("> h3", pack).show(); } - else { $("> h3", pack).hide(); }; + if ($("> ol.templates > li:not(.hide)", pack).length > 0) { + $("> h3", pack).show(); + $("> .packhide", pack).show(); + } + else { + $("> h3", pack).hide(); + $("> .packhide", pack).hide(); + }; return false; -} \ No newline at end of file +} diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.css b/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.css index 39df51e4f2..00d95138e7 100644 --- a/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.css +++ b/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.css @@ -1,17 +1,29 @@ * { color: black; text-decoration: none; - font-size: 11pt; - font-family: sans-serif; + font-family: inherit; + font-size: inherit; border-width: 0px; padding: 0px; margin: 0px; } +body { + font-family: sans-serif; + font-size: 10pt; +} + +a { + cursor: pointer; +} + +a:hover { + text-decoration: underline; +} + #owner { - padding: 12px; + padding: 4px; font-size: 12pt; - position: relative; display: block; } @@ -47,141 +59,71 @@ background-color: #561414; } -.signature { - clear: both; - display: block; - background-color: #cccccc; +#comment { + padding-left: 8px; } -.value #definition + .signature { - background-color: #ced8f4; -} - -.type #definition + .signature { - background-color: #f4cece; -} - -.signature .kind { - font-weight: bold; - font-size: 12pt; +#values > h3 { + color: white; padding: 4px; - text-align: right; - float: left; - width: 72px; -} - -.signature .symbol { - display: block; + background-color: #142556; font-size: 12pt; - margin-left: 80px; -} - -.signature .name { - display: inline-block; - padding-bottom: 4px; - padding-top: 4px; font-weight: bold; } -.signature .tparams { - padding: 4px; -} - -.signature .tparams > span { - margin-right: 2px; - margin-left: 2px; - padding: 4px; -} - -.signature .params { - padding: 4px; -} - -.signature .params > span { - margin-right: 2px; - margin-left: 2px; +#types > h3 { padding: 4px; + color: white; + font-weight: bold; + font-size: 12pt; + background-color: #561414; } -.signature .result { - padding-left: 0px; - padding-bottom: 4px; - padding-right: 4px; - padding-top: 4px; -} - -.signature .result span { - margin-right: 2px; - margin-left: 2px; +#constructors > h3 { padding: 4px; + color: white; + font-weight: bold; + font-size: 12pt; + background-color: #000000; } -#comment > p { - margin: 8px; -} - -#mbrsel { - padding: 4px; - background-color: #cccccc; +.signature { + padding: 1px; + font-family: monospace; + font-size: 10pt; + clear: both; display: block; + background-color: #dddddd; } -#mbrsel > div > h3 { - padding: 4px; - display: block; +.signature .kind { + text-align: right; float: left; + width: 72px; } -#mbrsel > div > ol { +.signature .symbol { + display: block; margin-left: 80px; } -#mbrsel > div > ol > li { - display: block; - padding: 4px 8px 4px 8px; - font-weight: bold; - background-color: white; +.signature .name { display: inline-block; - cursor: crosshair; + font-weight: bold; } -#mbrsel > div > ol > li.in { - background-color: white; +#values .signature .name { + color: #142556; } -#mbrsel > div > ol > li.out { - color: #888888; - background-color: #bbbbbb; +#types .signature .name { + color: #561414; } #template > div.members > ol { background-color: white; } -#values > h3 { - color: white; - padding: 4px; - background-color: #142556; - font-size: 12pt; - font-weight: bold; -} - -#types > h3 { - padding: 4px; - color: white; - font-weight: bold; - font-size: 12pt; - background-color: #561414; -} - -#constructors > h3 { - padding: 4px; - color: white; - font-weight: bold; - font-size: 12pt; - background-color: #000000; -} - .members > ol > li { display: block; } @@ -218,11 +160,43 @@ margin-left: 80px; } -.members .comment > p { - margin-left: 0px; +.comment > p { margin-bottom: 4px; - margin-right: 4px; margin-top: 4px; display: block; } +#mbrsel { + padding: 4px; + background-color: #cccccc; + display: block; +} + +#mbrsel > div > h3 { + padding: 4px; + display: block; + float: left; +} + +#mbrsel > div > ol { + margin-left: 80px; +} + +#mbrsel > div > ol > li { + display: block; + padding: 4px 8px 4px 8px; + font-weight: bold; + background-color: white; + display: inline-block; + cursor: crosshair; +} + +#mbrsel > div > ol > li.in { + background-color: white; +} + +#mbrsel > div > ol > li.out { + color: #888888; + background-color: #bbbbbb; +} + diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.js b/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.js index 4da8b28882..f1b864137d 100644 --- a/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.js +++ b/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.js @@ -17,6 +17,20 @@ $(document).ready(function(){ }; filterInherit(); }); + $(".signature .symbol .extype").hover( + function(event){ + var full = $(this).attr("name"); + var short = $(this).text(); + $(this).attr("name", short); + $(this).text(full); + }, + function(event){ + var short = $(this).attr("name"); + var full = $(this).text(); + $(this).attr("name", full); + $(this).text(short); + } + ); }); function filterInherit() { diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/template.html b/src/compiler/scala/tools/nsc/doc/html/resource/template.html index 66c3fbc9ce..6bf91d96ee 100644 --- a/src/compiler/scala/tools/nsc/doc/html/resource/template.html +++ b/src/compiler/scala/tools/nsc/doc/html/resource/template.html @@ -23,10 +23,15 @@ extendsA[X] with C[Y] with B
-
+

This class can be used as an adaptor to create mutable maps from immutable map implementations. Only method empty has to be redefined if the immutable map on which this mutable map is originally based is not empty. empty is supposed to return the representation of an empty map.

A subtrait of collection.IndexedSeq which represents sequences that can be mutated.

-

The canonical builder for collections that are addable, i.e. that support an efficient + method which adds an element to the collection. Collections are built from their empty element using this + method.

+

The canonical builder for collections that are addable, i.e. that support an efficient + method which adds an element to the collection. Collections are built from their empty element using this + method.

+ + Once upon a time
+ In a land far far away
+ There was a man +
@@ -53,8 +58,8 @@
def
transform - [T,U ⊲ Int] - (f: (A, B) => B,b: Double) + [T, U ⊲ Int] + (f: (A, B) => B, b: Double) :ImmutableMapAdaptor[A, B]
@@ -83,8 +88,7 @@
def
curry - (f: (A, B) => B,b: Double)(g: Int => B,c: Double) - :ImmutableMapAdaptor[A, B] + (f: (A, B) => B, b: Double)(g: Int => B, c: Double): ImmutableMapAdaptor[A, B]
@@ -92,8 +96,7 @@
val
- randomize - :ImmutableMapAdaptor[A, B] + randomize: ImmutableMapAdaptor[A, B]
@@ -181,22 +184,32 @@
  • -
    type
    -
    + type + U - =ImmutableMapAdaptor[A, B] -
    -
    -
    -

    A subtrait of collection.IndexedSeq which represents sequences that can be mutated.

    + =ImmutableMapAdaptor[A, B] +
  • +
  • + + trait + + CountedIterator + [+A] + extends Iterator[A] + + +
    +

    Counted iterators keep track of the number of elements seen so far

    +
    +
  • type
    V - IntBoolean + ⊲ Int ⊳ Boolean
    diff --git a/src/compiler/scala/tools/nsc/doc/model/Entity.scala b/src/compiler/scala/tools/nsc/doc/model/Entity.scala index 6314af39be..84cd76ef5f 100644 --- a/src/compiler/scala/tools/nsc/doc/model/Entity.scala +++ b/src/compiler/scala/tools/nsc/doc/model/Entity.scala @@ -31,13 +31,14 @@ trait TemplateEntity extends Entity { def isTrait: Boolean def isClass: Boolean def isObject: Boolean + def isDocTemplate: Boolean } trait NoDocTemplate extends TemplateEntity /** A member of a class, trait, object or package. */ trait MemberEntity extends Entity { def inTemplate: DocTemplateEntity - def toRoot: List[DocTemplateEntity] + def toRoot: List[MemberEntity] def inDefinitionTemplate: TemplateEntity def definitionName: String def visibility: Option[Paragraph] @@ -123,7 +124,6 @@ trait AliasType extends NonTemplateMemberEntity { trait ParameterEntity extends Entity { def inTemplate: DocTemplateEntity - def toRoot: List[DocTemplateEntity] def isTypeParam: Boolean def isValueParam: Boolean } diff --git a/src/compiler/scala/tools/nsc/doc/model/EntityFactory.scala b/src/compiler/scala/tools/nsc/doc/model/EntityFactory.scala deleted file mode 100644 index 033b51e3e7..0000000000 --- a/src/compiler/scala/tools/nsc/doc/model/EntityFactory.scala +++ /dev/null @@ -1,432 +0,0 @@ -/* NSC -- new Scala compiler -- Copyright 2007-2009 LAMP/EPFL */ - -package scala.tools.nsc -package doc -package model - -import comment._ - -import scala.collection._ -import symtab.Flags - -/** This trait extracts all required information for documentation from compilation units */ -class EntityFactory(val global: Global, val settings: doc.Settings) { extractor => - - import global._ - import definitions.{ ObjectClass, ScalaObjectClass, RootPackage, EmptyPackage } - - /** */ - def makeModel: Package = - makePackage(RootPackage, null) getOrElse { throw new Error("no documentable class found in compilation units") } - - /** */ - protected val commentFactory = new CommentFactory(reporter) - - /** */ - protected val commentCache = mutable.Map.empty[Symbol, comment.Comment] - - /** */ - protected val templatesCache = - new mutable.LinkedHashMap[(Symbol, TemplateImpl), DocTemplateImpl] - - /* ============== IMPLEMENTATION PROVIDING ENTITY TYPES ============== */ - - /** Provides a default implementation for instances of the `Entity` type. */ - abstract class EntityImpl(val sym: Symbol, inTpl: => TemplateImpl) extends Entity { - val name = sym.nameString - def inTemplate = inTpl - def toRoot: List[EntityImpl] = inTpl :: inTpl.toRoot - def qualifiedName = name - val comment = { - val whichSym = - if (comments isDefinedAt sym) Some(sym) else sym.allOverriddenSymbols find (comments isDefinedAt _) - whichSym map { s => - commentCache.getOrElse(s, { - val c = commentFactory.parse(comments(s), s.pos) - commentCache += s -> c - c - }) - } - } - } - - /** Provides a default implementation for instances of the `WeakTemplateEntity` type. It must be instantiated as a - * `SymbolicEntity` to access the compiler symbol that underlies the entity. */ - trait TemplateImpl extends EntityImpl with TemplateEntity { - override def qualifiedName = if (inTemplate.isRootPackage) name else (inTemplate.qualifiedName + "." + name) - val isPackage = sym.isPackage - val isTrait = sym.isTrait - val isClass = sym.isClass && !sym.isTrait - val isObject = sym.isModule && !sym.isPackage - val isRootPackage = false - } - - /** Provides a default implementation for instances of the `WeakTemplateEntity` type. It must be instantiated as a - * `SymbolicEntity` to access the compiler symbol that underlies the entity. */ - class NoDocTemplateImpl(sym: Symbol, inTpl: => TemplateImpl) extends EntityImpl(sym, inTpl) with TemplateImpl with NoDocTemplate - - /** Provides a default implementation for instances of the `MemberEntity` type. It must be instantiated as a - * `SymbolicEntity` to access the compiler symbol that underlies the entity. */ - abstract class MemberImpl(sym: Symbol, inTpl: => DocTemplateImpl) extends EntityImpl(sym, inTpl) with MemberEntity { - override def inTemplate = inTpl - override def toRoot: List[DocTemplateImpl] = inTpl :: inTpl.toRoot - lazy val inDefinitionTemplate = if (sym.owner == inTpl.sym) inTpl else makeTemplate(sym.owner) - val visibility = { - def qual = { - val qq = - if (sym hasFlag Flags.LOCAL) - Some("this") - else if (sym.privateWithin != null && sym.privateWithin != NoSymbol) - Some(sym.privateWithin.nameString) // TODO: create an inline link to the qualifier entity - else None - qq match { case Some(q) => "[" + q + "]" case None => "" } - } - if (sym hasFlag Flags.PRIVATE) Some(Paragraph(Text("private" + qual))) - else if (sym hasFlag Flags.PROTECTED) Some(Paragraph(Text("protected" + qual))) - else None - } - val flags = { - val fgs = mutable.ListBuffer.empty[Paragraph] - if (sym hasFlag Flags.IMPLICIT) fgs += Paragraph(Text("implicit")) - if (sym hasFlag Flags.SEALED) fgs += Paragraph(Text("sealed")) - if (sym hasFlag Flags.OVERRIDE) fgs += Paragraph(Text("override")) - if (!sym.isTrait && (sym hasFlag Flags.ABSTRACT)) fgs += Paragraph(Text("abstract")) - if (!sym.isTrait && (sym hasFlag Flags.DEFERRED)) fgs += Paragraph(Text("abstract")) - if (!sym.isModule && (sym hasFlag Flags.FINAL)) fgs += Paragraph(Text("final")) - fgs.toList - } - lazy val inheritedFrom = - if (inTemplate.sym == this.sym.owner || inTemplate.sym.isPackage) Nil else - makeTemplate(this.sym.owner) :: (sym.allOverriddenSymbols map { os => makeTemplate(os.owner) }) - val isDeprecated = sym.isDeprecated - lazy val resultType = makeType(sym.tpe.finalResultType, inTemplate, sym) - val isDef = false - val isVal = false - val isVar = false - val isConstructor = false - val isAliasType = false - val isAbstractType = false - val isTemplate = false - } - - /** Provides a default implementation for instances of the `TemplateEntity` type. It must be instantiated as a - * `TemplateSymbolicEntity` to access the compiler symbol that underlies the entity and to be registered with the - * `templatesCache` at the very start of its instantiation. - * - * The instantiation of `TemplateImpl` triggers the creation of the following entities. - * * The owner of the template (as a full template); - * * All ancestors of the template (as weak templates); - * * All non-package members (including other templates, as full templates). */ - abstract class DocTemplateImpl(sym: Symbol, inTpl: => DocTemplateImpl) extends MemberImpl(sym, inTpl) with TemplateImpl with DocTemplateEntity { - templatesCache += ((sym, inTpl) -> this) - override def definitionName = inDefinitionTemplate.qualifiedName + "." + name - val inSource = if (sym.sourceFile != null) Some(sym.sourceFile, sym.pos.line) else None - val typeParams = if (sym.isClass) sym.typeParams map (makeTypeParam(_, this)) else Nil - val parentType = - if (sym.isPackage) None else - Some(makeType(RefinedType(sym.tpe.parents filter (_ != ScalaObjectClass.tpe), EmptyScope))) - val linearization = { - sym.ancestors filter (_ != ScalaObjectClass) map (makeTemplate(_)) - // TODO: Register subclasses - } - private val subClassesCache = mutable.Buffer.empty[DocTemplateEntity] - def registerSubClass(sc: DocTemplateEntity) = subClassesCache += sc - def subClasses = subClassesCache.toList - def memberSyms = sym.info.nonPrivateMembers - val members: List[MemberEntity] = memberSyms flatMap (makeMember(_, this)) - val templates = members partialMap { case c: DocTemplateEntity => c } - val methods = members partialMap { case d: Def => d } - val values = members partialMap { case v: Val => v } - val abstractTypes = members partialMap { case t: AbstractType => t } - val aliasTypes = members partialMap { case t: AliasType => t } - override val isTemplate = true - } - - abstract class PackageImpl(sym: Symbol, inTpl: => PackageImpl) extends DocTemplateImpl(sym, inTpl) with Package { - override def inTemplate = inTpl - override def toRoot: List[PackageImpl] = inTpl :: inTpl.toRoot - val packages = members partialMap { case p: Package => p } - } - - abstract class NonTemplateMemberImpl(sym: Symbol, inTpl: => DocTemplateImpl) extends MemberImpl(sym, inTpl) with NonTemplateMemberEntity { - override def qualifiedName = inTemplate.qualifiedName + "#" + name - override def definitionName = inDefinitionTemplate.qualifiedName + "#" + name - } - - abstract class ParameterImpl(sym: Symbol, inTpl: => DocTemplateImpl) extends EntityImpl(sym, inTpl) with ParameterEntity { - override def inTemplate = inTpl - override def toRoot: List[DocTemplateImpl] = inTpl :: inTpl.toRoot - } - - /* ============== MAKER METHODS ============== */ - - /** */ - def normalizeTemplate(aSym: Symbol): Symbol = { - if (aSym == null || aSym == EmptyPackage || aSym == NoSymbol) - normalizeTemplate(RootPackage) - else if (aSym == ScalaObjectClass || aSym == ObjectClass) - normalizeTemplate(definitions.AnyRefClass) - else if (aSym.isModuleClass || aSym.isPackageObject) - normalizeTemplate(aSym.sourceModule) - else - aSym - } - - /** Creates a package entity for the given symbol or returns `None` if the symbol does not denote a package that - * contains at least one ''documentable'' class, trait or object. Creating a package entity */ - def makePackage(aSym: Symbol, inTpl: => PackageImpl): Option[PackageImpl] = { - val bSym = normalizeTemplate(aSym) - if (templatesCache isDefinedAt (bSym, inTpl)) - Some(templatesCache(bSym, inTpl) match {case p: PackageImpl => p}) - else { - val pack = - if (bSym == RootPackage) - new PackageImpl(bSym, null) { - override val name = "root" - override def inTemplate = this - override def toRoot = Nil - override def qualifiedName = "_root_" - override lazy val inheritedFrom = Nil - override val isRootPackage = true - override def memberSyms = - (bSym.info.members ++ EmptyPackage.info.members) filter { s => - s != EmptyPackage && s != RootPackage - } - } - else - new PackageImpl(bSym, inTpl) {} - if (pack.templates.isEmpty) None else Some(pack) - } - - } - - /** */ - def makeTemplate(aSym: Symbol): TemplateImpl = { - val bSym = normalizeTemplate(aSym) - if (bSym == RootPackage) - makePackage(bSym, null).get - else - makeTemplate(bSym, makeTemplate(bSym.owner)) - } - - /** */ - def makeTemplate(aSym: Symbol, inTpl: => TemplateImpl): TemplateImpl = { - val bSym = normalizeTemplate(aSym) - if (bSym.isPackage) inTpl match { - case inPkg: PackageImpl => makePackage(bSym, inPkg) getOrElse (new NoDocTemplateImpl(bSym, inPkg)) - case _ => throw new Error("'" + bSym + "' must be in a package") - } - else if ((bSym.sourceFile != null) && bSym.isPublic && !bSym.isLocal) inTpl match { - case inDTpl: DocTemplateImpl => makeDocTemplate(bSym, inDTpl) - case _ => throw new Error("documentable '" + bSym + "' must be in a documentable template") - } - else - new NoDocTemplateImpl(bSym, inTpl) - } - - /** */ - def makeDocTemplate(aSym: Symbol, inTpl: => DocTemplateImpl): DocTemplateImpl = { - val bSym = normalizeTemplate(aSym) - val firstInTpl = { // to prevent a complexity explosion in some cases. - def sInTpl0(inTpl: DocTemplateImpl): DocTemplateImpl = - if ((aSym.owner != inTpl.inTemplate.sym) && (inTpl.inTemplate.sym.info.members contains aSym)) - sInTpl0(inTpl.inTemplate) - else inTpl - sInTpl0(inTpl) - } - if (templatesCache isDefinedAt (bSym, firstInTpl)) - templatesCache((bSym, firstInTpl)) - else if (bSym.isModule || (bSym.isAliasType && bSym.tpe.typeSymbol.isModule)) - new DocTemplateImpl(bSym, firstInTpl) with Object - else if (bSym.isTrait || (bSym.isAliasType && bSym.tpe.typeSymbol.isTrait)) - new DocTemplateImpl(bSym, firstInTpl) with Trait { - val valueParams = - List(sym.constrParamAccessors map (makeValueParam(_, this))) - } - else if (bSym.isClass || (bSym.isAliasType && bSym.tpe.typeSymbol.isClass)) - new DocTemplateImpl(bSym, firstInTpl) with Class { - val valueParams = - List(sym.constrParamAccessors map (makeValueParam(_, this))) - val constructors = - members partialMap { case d: Constructor => d } - val primaryConstructor = (constructors find (_.isPrimary)) - val isCaseClass = sym.isClass && sym.hasFlag(Flags.CASE) - } - else - throw new Error("'" + bSym + "' that isn't a class, trait or object cannot be built as a documentable template") - } - - /** */ - def makeMember(aSym: Symbol, inTpl: => DocTemplateImpl): Option[MemberImpl] = { - if (!aSym.isPublic || (aSym hasFlag Flags.SYNTHETIC) || (aSym hasFlag Flags.BRIDGE) || aSym.isLocal || aSym.isModuleClass || aSym.isPackageObject || aSym.isMixinConstructor) - None - else if (aSym.isGetter && (aSym.accessed hasFlag Flags.MUTABLE)) - Some(new NonTemplateMemberImpl(aSym, inTpl) with Val { - override val isVar = true - }) - else if (aSym.isMethod && !(aSym hasFlag Flags.ACCESSOR) && !aSym.isConstructor && !(aSym hasFlag Flags.FINAL)) - Some(new NonTemplateMemberImpl(aSym, inTpl) with Def { - override val isDef = true - val typeParams = - sym.tpe.typeParams map (makeTypeParam(_, inTpl)) - val valueParams = - sym.paramss map { ps => (ps.zipWithIndex) map { case (p, i) => - if (p.nameString contains "$") makeValueParam(p, inTpl, "arg" + i) else makeValueParam(p, inTpl) - }} - }) - else if (aSym.isConstructor) - Some(new NonTemplateMemberImpl(aSym, inTpl) with Constructor { - override val isConstructor = true - val isPrimary = sym.isPrimaryConstructor - val valueParams = - sym.paramss map { ps => (ps.zipWithIndex) map { case (p, i) => - if (p.nameString contains "$") makeValueParam(p, inTpl, "arg" + i) else makeValueParam(p, inTpl) - }} - }) - else if (aSym.isGetter) // Scala field accessor or Java field - Some(new NonTemplateMemberImpl(aSym, inTpl) with Val { - override val isVal = true - }) - else if (aSym.isAbstractType) - Some(new NonTemplateMemberImpl(aSym, inTpl) with AbstractType { - override val isAbstractType = true - val lo = sym.info.normalize match { - case TypeBounds(lo, hi) if lo.typeSymbol != definitions.NothingClass => Some(makeType(lo, inTpl, sym)) - case _ => None - } - val hi = sym.info.normalize match { - case TypeBounds(lo, hi) if hi.typeSymbol != definitions.AnyClass => Some(makeType(hi, inTpl, sym)) - case _ => None - } - }) - else if (aSym.isAliasType) - Some(new NonTemplateMemberImpl(aSym, inTpl) with AliasType { - override val isAliasType = true - val alias = makeType(sym.tpe, inTpl, sym) - }) - else if (aSym.isPackage) - inTpl match { case inPkg: PackageImpl => makePackage(aSym, inPkg) } - else if ((aSym.isClass || aSym.isModule) && (aSym.sourceFile != null) && aSym.isPublic && !aSym.isLocal) - (inTpl.toRoot find (_.sym == aSym )) orElse Some(makeDocTemplate(aSym, inTpl)) - else - None - } - - /** */ - def makeTypeParam(aSym: Symbol, inTpl: => DocTemplateImpl): TypeParam = { - new ParameterImpl(aSym, inTpl) with TypeParam { - val isTypeParam = true - val isValueParam = false - val variance: String = { - if (sym hasFlag Flags.COVARIANT) "+" - else if (sym hasFlag Flags.CONTRAVARIANT) "-" - else "" - } - val lo = sym.info.normalize match { - case TypeBounds(lo, hi) if lo.typeSymbol != definitions.NothingClass => - Some(makeType(lo, inTpl, sym)) - case _ => None - } - val hi = sym.info.normalize match { - case TypeBounds(lo, hi) if hi.typeSymbol != definitions.AnyClass => - Some(makeType(hi, inTpl, sym)) - case _ => None - } - } - } - - /** */ - def makeValueParam(aSym: Symbol, inTpl: => DocTemplateImpl): ValueParam = { - makeValueParam(aSym, inTpl, aSym.nameString) - } - - /** */ - def makeValueParam(aSym: Symbol, inTpl: => DocTemplateImpl, newName: String): ValueParam = { - new ParameterImpl(aSym, inTpl) with ValueParam { - val isTypeParam = false - val isValueParam = true - val resultType = { - makeType(sym.tpe, inTpl, sym) - } - override val name = newName - } - } - - /** */ - def makeType(aType: Type, seeInTpl: => TemplateImpl, dclSym: Symbol): TypeEntity = { - def ownerTpl(sym: Symbol): Symbol = - if (sym.isClass || sym.isModule || sym == NoSymbol) sym else ownerTpl(sym.owner) - makeType(aType.asSeenFrom(seeInTpl.sym.thisType, ownerTpl(dclSym))) - } - - /** */ - def makeType(aType: Type): TypeEntity = - new TypeEntity { - private val nameBuffer = new StringBuilder - private var refBuffer = new immutable.TreeMap[Int, (Entity, Int)] - private def appendTypes0(types: List[Type], sep: String): Unit = types match { - case Nil => - case tp :: Nil => - appendType0(tp) - case tp :: tps => - appendType0(tp) - nameBuffer append sep - appendTypes0(tps, sep) - } - private def appendType0(tpe: Type): Unit = tpe.normalize match { - /* Type refs */ - case tp: TypeRef if (definitions.isFunctionType(tp)) => - nameBuffer append '(' - appendTypes0(tp.args.init, ", ") - nameBuffer append ") ⇒ " - appendType0(tp.args.last) - case tp: TypeRef if (tp.typeSymbol == definitions.RepeatedParamClass) => - appendType0(tp.args.head) - nameBuffer append '*' - case tp: TypeRef if (tp.typeSymbol == definitions.ByNameParamClass) => - nameBuffer append "⇒ " - appendType0(tp.args.head) - case tp: TypeRef if (definitions.isTupleType(tp)) => - nameBuffer append '(' - appendTypes0(tp.args, ", ") - nameBuffer append ')' - case TypeRef(pre, aSym, targs) => - val bSym = normalizeTemplate(aSym) - if (bSym.isType) - nameBuffer append bSym.name - else { - val refClass = makeTemplate(bSym) - val pos0 = nameBuffer.length - nameBuffer append refClass.name - refBuffer += pos0 -> (refClass, nameBuffer.length) - } - if (!targs.isEmpty) { - nameBuffer append '[' - appendTypes0(targs, ", ") - nameBuffer append ']' - } - /* Refined types */ - case RefinedType(parents, defs) => - appendTypes0((if (parents.length > 1) parents filterNot (_ == ObjectClass.tpe) else parents), " with ") - if (!defs.isEmpty) { - nameBuffer append " {...}" // TODO: actually print the refinement - } - /* Polymorphic types */ - case PolyType(tparams, result) if (!tparams.isEmpty) => - appendType0(result) - nameBuffer append '[' - appendTypes0(tparams map (_.tpe), ", ") // TODO: actually print the polytype's symbols (not just types) - nameBuffer append ']' - /* Eval-by-name types */ - case PolyType(tparams, result) if (tparams.isEmpty) => - nameBuffer append '⇒' - appendType0(result) - case tpen => - nameBuffer append tpen.toString - } - appendType0(aType) - val refEntity = refBuffer - val name = nameBuffer.toString - } - -} diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala new file mode 100644 index 0000000000..4e96b17da5 --- /dev/null +++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala @@ -0,0 +1,443 @@ +/* NSC -- new Scala compiler -- Copyright 2007-2009 LAMP/EPFL */ + +package scala.tools.nsc +package doc +package model + +import comment._ + +import scala.collection._ +import symtab.Flags + +/** This trait extracts all required information for documentation from compilation units */ +class ModelFactory(val global: Global, val settings: doc.Settings) { extractor => + + import global._ + import definitions.{ ObjectClass, ScalaObjectClass, RootPackage, EmptyPackage } + + private var droppedPackages = 0 + def templatesCount = templatesCache.size - droppedPackages + + /** */ + def makeModel: Package = + makePackage(RootPackage, null) getOrElse { throw new Error("no documentable class found in compilation units") } + + /** */ + protected val commentFactory = new CommentFactory(reporter) + + /** */ + protected val commentCache = mutable.Map.empty[Symbol, comment.Comment] + + /** */ + protected val templatesCache = + new mutable.LinkedHashMap[(Symbol, TemplateImpl), DocTemplateImpl] + + /* ============== IMPLEMENTATION PROVIDING ENTITY TYPES ============== */ + + /** Provides a default implementation for instances of the `Entity` type. */ + abstract class EntityImpl(val sym: Symbol, inTpl: => TemplateImpl) extends Entity { + val name = sym.nameString + def inTemplate = inTpl + def toRoot: List[EntityImpl] = this :: inTpl.toRoot + def qualifiedName = name + val comment = { + val whichSym = + if (comments isDefinedAt sym) Some(sym) else sym.allOverriddenSymbols find (comments isDefinedAt _) + whichSym map { s => + commentCache.getOrElse(s, { + val c = commentFactory.parse(comments(s), s.pos) + commentCache += s -> c + c + }) + } + } + } + + /** Provides a default implementation for instances of the `WeakTemplateEntity` type. It must be instantiated as a + * `SymbolicEntity` to access the compiler symbol that underlies the entity. */ + trait TemplateImpl extends EntityImpl with TemplateEntity { + override def qualifiedName = if (inTemplate.isRootPackage) name else (inTemplate.qualifiedName + "." + name) + val isPackage = sym.isPackage + val isTrait = sym.isTrait + val isClass = sym.isClass && !sym.isTrait + val isObject = sym.isModule && !sym.isPackage + val isRootPackage = false + } + + /** Provides a default implementation for instances of the `WeakTemplateEntity` type. It must be instantiated as a + * `SymbolicEntity` to access the compiler symbol that underlies the entity. */ + class NoDocTemplateImpl(sym: Symbol, inTpl: => TemplateImpl) extends EntityImpl(sym, inTpl) with TemplateImpl with NoDocTemplate { + def isDocTemplate = false + } + + /** Provides a default implementation for instances of the `MemberEntity` type. It must be instantiated as a + * `SymbolicEntity` to access the compiler symbol that underlies the entity. */ + abstract class MemberImpl(sym: Symbol, inTpl: => DocTemplateImpl) extends EntityImpl(sym, inTpl) with MemberEntity { + override def inTemplate = inTpl + override def toRoot: List[MemberImpl] = this :: inTpl.toRoot + lazy val inDefinitionTemplate = if (sym.owner == inTpl.sym) inTpl else makeTemplate(sym.owner) + val visibility = { + def qual = { + val qq = + if (sym hasFlag Flags.LOCAL) + Some("this") + else if (sym.privateWithin != null && sym.privateWithin != NoSymbol) + Some(sym.privateWithin.nameString) // TODO: create an inline link to the qualifier entity + else None + qq match { case Some(q) => "[" + q + "]" case None => "" } + } + if (sym hasFlag Flags.PRIVATE) Some(Paragraph(Text("private" + qual))) + else if (sym hasFlag Flags.PROTECTED) Some(Paragraph(Text("protected" + qual))) + else None + } + val flags = { + val fgs = mutable.ListBuffer.empty[Paragraph] + if (sym hasFlag Flags.IMPLICIT) fgs += Paragraph(Text("implicit")) + if (sym hasFlag Flags.SEALED) fgs += Paragraph(Text("sealed")) + if (sym hasFlag Flags.OVERRIDE) fgs += Paragraph(Text("override")) + if (!sym.isTrait && (sym hasFlag Flags.ABSTRACT)) fgs += Paragraph(Text("abstract")) + if (!sym.isTrait && (sym hasFlag Flags.DEFERRED)) fgs += Paragraph(Text("abstract")) + if (!sym.isModule && (sym hasFlag Flags.FINAL)) fgs += Paragraph(Text("final")) + fgs.toList + } + lazy val inheritedFrom = + if (inTemplate.sym == this.sym.owner || inTemplate.sym.isPackage) Nil else + makeTemplate(this.sym.owner) :: (sym.allOverriddenSymbols map { os => makeTemplate(os.owner) }) + val isDeprecated = sym.isDeprecated + lazy val resultType = makeType(sym.tpe.finalResultType, inTemplate, sym) + val isDef = false + val isVal = false + val isVar = false + val isConstructor = false + val isAliasType = false + val isAbstractType = false + val isTemplate = false + } + + /** Provides a default implementation for instances of the `TemplateEntity` type. It must be instantiated as a + * `TemplateSymbolicEntity` to access the compiler symbol that underlies the entity and to be registered with the + * `templatesCache` at the very start of its instantiation. + * + * The instantiation of `TemplateImpl` triggers the creation of the following entities. + * * The owner of the template (as a full template); + * * All ancestors of the template (as weak templates); + * * All non-package members (including other templates, as full templates). */ + abstract class DocTemplateImpl(sym: Symbol, inTpl: => DocTemplateImpl) extends MemberImpl(sym, inTpl) with TemplateImpl with DocTemplateEntity { + //if (inTpl != null) println("mbr " + sym + " in " + (inTpl.toRoot map (_.sym)).mkString(" > ")) + templatesCache += ((sym, inTpl) -> this) + override def definitionName = inDefinitionTemplate.qualifiedName + "." + name + val inSource = if (sym.sourceFile != null) Some(sym.sourceFile, sym.pos.line) else None + val typeParams = if (sym.isClass) sym.typeParams map (makeTypeParam(_, this)) else Nil + val parentType = + if (sym.isPackage) None else + Some(makeType(RefinedType(sym.tpe.parents filter (_ != ScalaObjectClass.tpe), EmptyScope))) + val linearization = { + sym.ancestors filter (_ != ScalaObjectClass) map (makeTemplate(_)) + // TODO: Register subclasses + } + private val subClassesCache = mutable.Buffer.empty[DocTemplateEntity] + def registerSubClass(sc: DocTemplateEntity) = subClassesCache += sc + def subClasses = subClassesCache.toList + def memberSyms = sym.info.nonPrivateMembers + val members: List[MemberEntity] = memberSyms flatMap (makeMember(_, this)) + val templates = members partialMap { case c: DocTemplateEntity => c } + val methods = members partialMap { case d: Def => d } + val values = members partialMap { case v: Val => v } + val abstractTypes = members partialMap { case t: AbstractType => t } + val aliasTypes = members partialMap { case t: AliasType => t } + override val isTemplate = true + def isDocTemplate = true + } + + abstract class PackageImpl(sym: Symbol, inTpl: => PackageImpl) extends DocTemplateImpl(sym, inTpl) with Package { + override def inTemplate = inTpl + override def toRoot: List[PackageImpl] = this :: inTpl.toRoot + val packages = members partialMap { case p: Package => p } + } + + abstract class NonTemplateMemberImpl(sym: Symbol, inTpl: => DocTemplateImpl) extends MemberImpl(sym, inTpl) with NonTemplateMemberEntity { + override def qualifiedName = inTemplate.qualifiedName + "#" + name + override def definitionName = inDefinitionTemplate.qualifiedName + "#" + name + } + + abstract class ParameterImpl(sym: Symbol, inTpl: => DocTemplateImpl) extends EntityImpl(sym, inTpl) with ParameterEntity { + override def inTemplate = inTpl + } + + /* ============== MAKER METHODS ============== */ + + /** */ + def normalizeTemplate(aSym: Symbol): Symbol = { + if (aSym == null || aSym == EmptyPackage || aSym == NoSymbol) + normalizeTemplate(RootPackage) + else if (aSym == ScalaObjectClass || aSym == ObjectClass) + normalizeTemplate(definitions.AnyRefClass) + else if (aSym.isModuleClass || aSym.isPackageObject) + normalizeTemplate(aSym.sourceModule) + else + aSym + } + + /** Creates a package entity for the given symbol or returns `None` if the symbol does not denote a package that + * contains at least one ''documentable'' class, trait or object. Creating a package entity */ + def makePackage(aSym: Symbol, inTpl: => PackageImpl): Option[PackageImpl] = { + val bSym = normalizeTemplate(aSym) + if (templatesCache isDefinedAt (bSym, inTpl)) + Some(templatesCache(bSym, inTpl) match {case p: PackageImpl => p}) + else { + val pack = + if (bSym == RootPackage) + new PackageImpl(bSym, null) { + override val name = "root" + override def inTemplate = this + override def toRoot = this :: Nil + override def qualifiedName = "_root_" + override lazy val inheritedFrom = Nil + override val isRootPackage = true + override def memberSyms = + (bSym.info.members ++ EmptyPackage.info.members) filter { s => + s != EmptyPackage && s != RootPackage + } + } + else + new PackageImpl(bSym, inTpl) {} + if (pack.templates.isEmpty) { + droppedPackages += 1 + None + } + else Some(pack) + } + + } + + /** */ + def makeTemplate(aSym: Symbol): TemplateImpl = { + val bSym = normalizeTemplate(aSym) + if (bSym == RootPackage) + makePackage(bSym, null).get + else + makeTemplate(bSym, makeTemplate(bSym.owner)) + } + + /** */ + def makeTemplate(aSym: Symbol, inTpl: => TemplateImpl): TemplateImpl = { + val bSym = normalizeTemplate(aSym) + if (bSym.isPackage) inTpl match { + case inPkg: PackageImpl => makePackage(bSym, inPkg) getOrElse (new NoDocTemplateImpl(bSym, inPkg)) + case _ => throw new Error("'" + bSym + "' must be in a package") + } + else if ((bSym.sourceFile != null) && bSym.isPublic && !bSym.isLocal) inTpl match { + case inDTpl: DocTemplateImpl => makeDocTemplate(bSym, inDTpl) + case _ => throw new Error("documentable '" + bSym + "' must be in a documentable template") + } + else + new NoDocTemplateImpl(bSym, inTpl) + } + + /** */ + def makeDocTemplate(aSym: Symbol, inTpl: => DocTemplateImpl): DocTemplateImpl = { + val bSym = normalizeTemplate(aSym) + val firstInTpl = { // to prevent a complexity explosion in some cases. + def sInTpl0(inTpl: DocTemplateImpl): DocTemplateImpl = + if ((aSym.owner != inTpl.inTemplate.sym) && (inTpl.inTemplate.sym.info.members contains aSym)) + sInTpl0(inTpl.inTemplate) + else inTpl + sInTpl0(inTpl) + } + if (templatesCache isDefinedAt (bSym, firstInTpl)) + templatesCache((bSym, firstInTpl)) + else if (bSym.isModule || (bSym.isAliasType && bSym.tpe.typeSymbol.isModule)) + new DocTemplateImpl(bSym, firstInTpl) with Object + else if (bSym.isTrait || (bSym.isAliasType && bSym.tpe.typeSymbol.isTrait)) + new DocTemplateImpl(bSym, firstInTpl) with Trait { + val valueParams = + List(sym.constrParamAccessors map (makeValueParam(_, this))) + } + else if (bSym.isClass || (bSym.isAliasType && bSym.tpe.typeSymbol.isClass)) + new DocTemplateImpl(bSym, firstInTpl) with Class { + val valueParams = + List(sym.constrParamAccessors map (makeValueParam(_, this))) + val constructors = + members partialMap { case d: Constructor => d } + val primaryConstructor = (constructors find (_.isPrimary)) + val isCaseClass = sym.isClass && sym.hasFlag(Flags.CASE) + } + else + throw new Error("'" + bSym + "' that isn't a class, trait or object cannot be built as a documentable template") + } + + /** */ + def makeMember(aSym: Symbol, inTpl: => DocTemplateImpl): Option[MemberImpl] = { + if (!aSym.isPublic || (aSym hasFlag Flags.SYNTHETIC) || (aSym hasFlag Flags.BRIDGE) || aSym.isLocal || aSym.isModuleClass || aSym.isPackageObject || aSym.isMixinConstructor) + None + else if (aSym.isGetter && (aSym.accessed hasFlag Flags.MUTABLE)) + Some(new NonTemplateMemberImpl(aSym, inTpl) with Val { + override val isVar = true + }) + else if (aSym.isMethod && !(aSym hasFlag Flags.ACCESSOR) && !aSym.isConstructor && !(aSym hasFlag Flags.FINAL)) + Some(new NonTemplateMemberImpl(aSym, inTpl) with Def { + override val isDef = true + val typeParams = + sym.tpe.typeParams map (makeTypeParam(_, inTpl)) + val valueParams = + sym.paramss map { ps => (ps.zipWithIndex) map { case (p, i) => + if (p.nameString contains "$") makeValueParam(p, inTpl, "arg" + i) else makeValueParam(p, inTpl) + }} + }) + else if (aSym.isConstructor) + Some(new NonTemplateMemberImpl(aSym, inTpl) with Constructor { + override val isConstructor = true + val isPrimary = sym.isPrimaryConstructor + val valueParams = + sym.paramss map { ps => (ps.zipWithIndex) map { case (p, i) => + if (p.nameString contains "$") makeValueParam(p, inTpl, "arg" + i) else makeValueParam(p, inTpl) + }} + }) + else if (aSym.isGetter) // Scala field accessor or Java field + Some(new NonTemplateMemberImpl(aSym, inTpl) with Val { + override val isVal = true + }) + else if (aSym.isAbstractType) + Some(new NonTemplateMemberImpl(aSym, inTpl) with AbstractType { + override val isAbstractType = true + val lo = sym.info.normalize match { + case TypeBounds(lo, hi) if lo.typeSymbol != definitions.NothingClass => Some(makeType(lo, inTpl, sym)) + case _ => None + } + val hi = sym.info.normalize match { + case TypeBounds(lo, hi) if hi.typeSymbol != definitions.AnyClass => Some(makeType(hi, inTpl, sym)) + case _ => None + } + }) + else if (aSym.isAliasType) + Some(new NonTemplateMemberImpl(aSym, inTpl) with AliasType { + override val isAliasType = true + val alias = makeType(sym.tpe, inTpl, sym) + }) + else if (aSym.isPackage) + inTpl match { case inPkg: PackageImpl => makePackage(aSym, inPkg) } + else if ((aSym.isClass || aSym.isModule) && (aSym.sourceFile != null) && aSym.isPublic && !aSym.isLocal) { + (inTpl.toRoot find (_.sym == aSym )) orElse Some(makeDocTemplate(aSym, inTpl)) + } + else + None + } + + /** */ + def makeTypeParam(aSym: Symbol, inTpl: => DocTemplateImpl): TypeParam = { + new ParameterImpl(aSym, inTpl) with TypeParam { + val isTypeParam = true + val isValueParam = false + val variance: String = { + if (sym hasFlag Flags.COVARIANT) "+" + else if (sym hasFlag Flags.CONTRAVARIANT) "-" + else "" + } + val lo = sym.info.normalize match { + case TypeBounds(lo, hi) if lo.typeSymbol != definitions.NothingClass => + Some(makeType(lo, inTpl, sym)) + case _ => None + } + val hi = sym.info.normalize match { + case TypeBounds(lo, hi) if hi.typeSymbol != definitions.AnyClass => + Some(makeType(hi, inTpl, sym)) + case _ => None + } + } + } + + /** */ + def makeValueParam(aSym: Symbol, inTpl: => DocTemplateImpl): ValueParam = { + makeValueParam(aSym, inTpl, aSym.nameString) + } + + /** */ + def makeValueParam(aSym: Symbol, inTpl: => DocTemplateImpl, newName: String): ValueParam = { + new ParameterImpl(aSym, inTpl) with ValueParam { + val isTypeParam = false + val isValueParam = true + val resultType = { + makeType(sym.tpe, inTpl, sym) + } + override val name = newName + } + } + + /** */ + def makeType(aType: Type, seeInTpl: => TemplateImpl, dclSym: Symbol): TypeEntity = { + def ownerTpl(sym: Symbol): Symbol = + if (sym.isClass || sym.isModule || sym == NoSymbol) sym else ownerTpl(sym.owner) + makeType(aType.asSeenFrom(seeInTpl.sym.thisType, ownerTpl(dclSym))) + } + + /** */ + def makeType(aType: Type): TypeEntity = + new TypeEntity { + private val nameBuffer = new StringBuilder + private var refBuffer = new immutable.TreeMap[Int, (TemplateEntity, Int)] + private def appendTypes0(types: List[Type], sep: String): Unit = types match { + case Nil => + case tp :: Nil => + appendType0(tp) + case tp :: tps => + appendType0(tp) + nameBuffer append sep + appendTypes0(tps, sep) + } + private def appendType0(tpe: Type): Unit = tpe.normalize match { + /* Type refs */ + case tp: TypeRef if (definitions.isFunctionType(tp)) => + nameBuffer append '(' + appendTypes0(tp.args.init, ", ") + nameBuffer append ") ⇒ " + appendType0(tp.args.last) + case tp: TypeRef if (tp.typeSymbol == definitions.RepeatedParamClass) => + appendType0(tp.args.head) + nameBuffer append '*' + case tp: TypeRef if (tp.typeSymbol == definitions.ByNameParamClass) => + nameBuffer append "⇒ " + appendType0(tp.args.head) + case tp: TypeRef if (definitions.isTupleType(tp)) => + nameBuffer append '(' + appendTypes0(tp.args, ", ") + nameBuffer append ')' + case TypeRef(pre, aSym, targs) => + val bSym = normalizeTemplate(aSym) + if (bSym.isTypeMember) + nameBuffer append bSym.name + else { + val tpl = makeTemplate(bSym) + val pos0 = nameBuffer.length + refBuffer += pos0 -> (tpl, tpl.name.length) + nameBuffer append tpl.name + } + if (!targs.isEmpty) { + nameBuffer append '[' + appendTypes0(targs, ", ") + nameBuffer append ']' + } + /* Refined types */ + case RefinedType(parents, defs) => + appendTypes0((if (parents.length > 1) parents filterNot (_ == ObjectClass.tpe) else parents), " with ") + if (!defs.isEmpty) { + nameBuffer append " {...}" // TODO: actually print the refinement + } + /* Polymorphic types */ + case PolyType(tparams, result) if (!tparams.isEmpty) => + appendType0(result) + nameBuffer append '[' + appendTypes0(tparams map (_.tpe), ", ") // TODO: actually print the polytype's symbols (not just types) + nameBuffer append ']' + /* Eval-by-name types */ + case PolyType(tparams, result) if (tparams.isEmpty) => + nameBuffer append '⇒' + appendType0(result) + case tpen => + nameBuffer append tpen.toString + } + appendType0(aType) + val refEntity = refBuffer + val name = nameBuffer.toString + } + +} diff --git a/src/compiler/scala/tools/nsc/doc/model/TypeEntity.scala b/src/compiler/scala/tools/nsc/doc/model/TypeEntity.scala index 2a0e4b9831..5e18e0d9bc 100644 --- a/src/compiler/scala/tools/nsc/doc/model/TypeEntity.scala +++ b/src/compiler/scala/tools/nsc/doc/model/TypeEntity.scala @@ -17,7 +17,7 @@ abstract class TypeEntity { /** Maps which parts of this type's name reference other entities. The map is indexed by the position of the first * character that reference some entity, and contains the entity and the position of the last referenced * character. The referenced character ranges do not to overlap or nest. The map is sorted by position. */ - def refEntity: SortedMap[Int, (Entity, Int)] + def refEntity: SortedMap[Int, (TemplateEntity, Int)] override def toString = name -- cgit v1.2.3