diff options
Diffstat (limited to 'src')
8 files changed, 189 insertions, 105 deletions
diff --git a/src/compiler/scala/tools/nsc/doc/DocFactory.scala b/src/compiler/scala/tools/nsc/doc/DocFactory.scala index c4d231d750..ca72f6581b 100644 --- a/src/compiler/scala/tools/nsc/doc/DocFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/DocFactory.scala @@ -54,9 +54,8 @@ class DocFactory(val reporter: Reporter, val settings: doc.Settings) { processor if (!reporter.hasErrors) { val modelFactory = (new model.ModelFactory(compiler, settings)) val docModel = modelFactory.makeModel - val htmlFactory = (new html.HtmlFactory(docModel)) println("model contains " + modelFactory.templatesCount + " documentable templates") - htmlFactory generate docModel + (new html.HtmlFactory(docModel)) generate docModel } } diff --git a/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala b/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala index cea8d04caa..74ec740204 100644 --- a/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala +++ b/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala @@ -40,9 +40,6 @@ abstract class HtmlPage { thisPage => * also defined by the generator. * @param generator The generator that is writing this page. */ def writeFor(site: HtmlFactory): Unit = { - val pageFile = new File(site.siteRoot, absoluteLinkTo(thisPage.path)) - val pageFolder = pageFile.getParentFile - if (!pageFolder.exists) pageFolder.mkdirs() val doctype = DocType("html", PublicID("-//W3C//DTD XHTML 1.1//EN", "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"), Nil) val html = @@ -55,6 +52,9 @@ abstract class HtmlPage { thisPage => </head> { body } </html> + val pageFile = new File(site.siteRoot, absoluteLinkTo(thisPage.path)) + val pageFolder = pageFile.getParentFile + if (!pageFolder.exists) pageFolder.mkdirs() val fos = new FileOutputStream(pageFile.getPath) val w = Channels.newWriter(fos.getChannel, site.encoding) try { @@ -62,7 +62,10 @@ abstract class HtmlPage { thisPage => w.write( doctype.toString + "\n") w.write(xml.Xhtml.toXhtml(html)) } - finally { w.close() ; fos.close() } + finally { + w.close() + fos.close() + } //XML.save(pageFile.getPath, html, site.encoding, xmlDecl = false, doctype = doctype) } 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 5fb4e499b6..77b8d96e1c 100644 --- a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala +++ b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala @@ -57,15 +57,19 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage { <div id="template"> - { if (tpl.linearization.isEmpty) NodeSeq.Empty else - <div id="mbrsel"> + <div id="mbrsel"> + { if (tpl.linearization.isEmpty) NodeSeq.Empty else <div id="ancestors"> - <h3>Inherits</h3> - <ol id="linearizationtoggle"><li class="hideall">Hide All</li><li class="showall">Show all</li></ol> + <h3>Inherited</h3> + <ol><li class="hideall">Hide All</li><li class="showall">Show all</li></ol> <ol id="linearization">{ tpl.linearization map { wte => <li class="in" name={ wte.qualifiedName }>{ wte.name }</li> } }</ol> </div> - </div> - } + } + <div id="visbl"> + <h3>Visibility</h3> + <ol><li class="public in">Public</li><li class="all out">All</li></ol> + </div> + </div> { if (typeMembers.isEmpty) NodeSeq.Empty else <div id="types" class="members"> @@ -96,7 +100,7 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage { def memberToHtml(mbr: MemberEntity): NodeSeq = { val attributes: List[comment.Body] = Nil - <li name={ mbr.definitionName }> + <li name={ mbr.definitionName } visbl={ if (mbr.visibility.isProtected) "prt" else "pub" }> { signature(mbr, false) } { memberToCommentHtml(mbr, false) } </li> @@ -166,7 +170,7 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage { }</dl> } } - { val fvs: List[comment.Paragraph] = mbr.visibility.toList ::: mbr.flags + { val fvs: List[comment.Paragraph] = visibility(mbr).toList ::: mbr.flags if (fvs.isEmpty) NodeSeq.Empty else <div class="block"> attributes: { fvs map { fv => { inlineToHtml(fv.text) ++ xml.Text(" ") } } } @@ -260,6 +264,27 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage { bound0(hi, " <: ") ++ bound0(lo, " >: ") } + def visibility(mbr: MemberEntity): Option[comment.Paragraph] = { + import comment._ + import comment.{ Text => CText } + mbr.visibility match { + case PrivateInInstance() => + Some(Paragraph(CText("private[this]"))) + case PrivateInTemplate(owner) if (owner == mbr.inTemplate) => + Some(Paragraph(CText("private"))) + case PrivateInTemplate(owner) => + Some(Paragraph(Chain(List(CText("private["), EntityLink(owner), CText("]"))))) + case ProtectedInInstance() => + Some(Paragraph(CText("protected[this]"))) + case ProtectedInTemplate(owner) if (owner == mbr.inTemplate) => + Some(Paragraph(CText("protected"))) + case ProtectedInTemplate(owner) => + Some(Paragraph(Chain(List(CText("protected["), EntityLink(owner), CText("]"))))) + case Public() => + None + } + } + /** name, tparams, params, result */ def signature(mbr: MemberEntity, isSelf: Boolean): NodeSeq = { def inside(hasLinks: Boolean): NodeSeq = 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 cb159a97c0..47de01f6e2 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 @@ -8,7 +8,7 @@ $(document).ready(function(){ }); prefilters.removeClass("in"); prefilters.addClass("out"); - filterInherit(); + filter(); $("#ancestors > ol > li").click(function(){ if ($(this).hasClass("in")) { $(this).removeClass("in"); @@ -18,19 +18,34 @@ $(document).ready(function(){ $(this).removeClass("out"); $(this).addClass("in"); }; - filterInherit(); + filter(); }); $("#ancestors > ol > li.hideall").click(function() { - $("#ancestors > ol > li.in").removeClass("in").addClass("out"); - filterInherit(); + $("#ancestors > ol > li.in").removeClass("in").addClass("out"); + filter(); }) $("#ancestors > ol > li.showall").click(function() { - var filtered=$("#ancestors > ol > li.out").filter(function() { - var name = $(this).attr("name"); - return !(name == "scala.Any" || name == "scala.AnyRef"); - }) + var filtered = + $("#ancestors > ol > li.out").filter(function() { + var name = $(this).attr("name"); + return !(name == "scala.Any" || name == "scala.AnyRef"); + }); filtered.removeClass("out").addClass("in"); - filterInherit(); + filter(); + }); + $("#visbl > ol > li.public").click(function() { + if ($(this).hasClass("out")) { + $(this).removeClass("out").addClass("in"); + $("#visbl > ol > li.all").removeClass("in").addClass("out"); + filter(); + }; + }) + $("#visbl > ol > li.all").click(function() { + if ($(this).hasClass("out")) { + $(this).removeClass("out").addClass("in"); + $("#visbl > ol > li.public").removeClass("in").addClass("out"); + filter(); + }; }); //http://flowplayer.org/tools/tooltip.html $(".extype").tooltip({ @@ -82,28 +97,33 @@ $(document).ready(function(){ }); }); -function filterInherit() { - $("#mbrsel > div > ol > li.in").each(function(){ - findMembersByOwner($(this).attr("name")).show(); - }); - $("#mbrsel > div > ol > li.out").each(function(){ - findMembersByOwner($(this).attr("name")).hide(); - }); - return false; -}; - -function findMembersByOwner(owner0) { - return $(".members > ol > li").filter(function(){ +function filter() { + var outOwners = + $("#mbrsel > div > ol > li.out").map(function(){ + $(this).attr("name") + }).get(); + var prtVisbl = $("#visbl > ol > li.all").hasClass("in"); + $(".members > ol > li").each(function(){ + var vis1 = $(this).attr("visbl"); var qualName1 = $(this).attr("name"); - if (qualName1 == undefined) return false; - return owner0 == qualName1.slice(0, qualName1.indexOf("#")); + var owner1 = qualName1.slice(0, qualName1.indexOf("#")); + //var name1 = qualName1.slice(qualName1.indexOf("#") + 1); + var showByOwned = true; + for (out in outOwners) { + if (out == owner1) { + showByOwned = false; + }; + }; + var showByVis = true + if (vis1 == "prt") { + showByVis = prtVisbl; + }; + if (showByOwned && showByVis) { + $(this).show(); + } + else { + $(this).hide(); + }; }); -}; - -function findMemberByName(name0) { - return $(".members > ol > li").filter(function(){ - var qualName1 = $(this).attr("name"); - if (qualName1 == undefined) return false; - return name0 == qualName1.slice(qualName1.indexOf("#") + 1); - }).eq(0); + return false }; diff --git a/src/compiler/scala/tools/nsc/doc/model/Entity.scala b/src/compiler/scala/tools/nsc/doc/model/Entity.scala index f3cf0518f1..7aa2c234ea 100644 --- a/src/compiler/scala/tools/nsc/doc/model/Entity.scala +++ b/src/compiler/scala/tools/nsc/doc/model/Entity.scala @@ -41,7 +41,7 @@ trait MemberEntity extends Entity { def toRoot: List[MemberEntity] def inDefinitionTemplates: List[TemplateEntity] def definitionName: String - def visibility: Option[Paragraph] + def visibility: Visibility def flags: List[Paragraph] def deprecation: Option[Body] def inheritedFrom: List[TemplateEntity] @@ -164,3 +164,34 @@ trait ValueParam extends ParameterEntity { def defaultValue: Option[String] def isImplicit: Boolean } + +/** An type that represents visibility of members. */ +sealed trait Visibility { + def isProtected: Boolean = false + def isPublic: Boolean = false +} + +/** The visibility of `private[this]` members. */ +case class PrivateInInstance extends Visibility + +/** The visibility of `protected[this]` members. */ +case class ProtectedInInstance extends Visibility { + override def isProtected = true +} + +/** The visibility of `private[owner]` members. An unqualified private members is encoded with `owner` equal to the + * members's `inTemplate`. */ +case class PrivateInTemplate(owner: TemplateEntity) extends Visibility + +/** The visibility of `protected[owner]` members. An unqualified protected members is encoded with `owner` equal to the + * members's `inTemplate`. + * Note that whilst the member is visible in any template owned by `owner`, it is only visible in subclasses of the + * member's `inTemplate`. */ +case class ProtectedInTemplate(owner: TemplateEntity) extends Visibility { + override def isProtected = true +} + +/** The visibility of public members. */ +case class Public extends Visibility { + override def isPublic = true +} diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala index 41de091055..3f2e53db04 100644 --- a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala @@ -34,7 +34,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) extends Comme /** */ protected val templatesCache = - new mutable.LinkedHashMap[(Symbol, TemplateImpl), DocTemplateImpl] + new mutable.LinkedHashMap[Symbol, DocTemplateImpl] def findTemplate(query: String): Option[DocTemplateImpl] = { if (!modelFinished) throw new Error("cannot find template in unfinished universe") @@ -84,18 +84,20 @@ class ModelFactory(val global: Global, val settings: doc.Settings) extends Comme else makeTemplate(sym.owner) :: (sym.allOverriddenSymbols map { inhSym => makeTemplate(inhSym.owner) }) def 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 + if (sym hasFlag Flags.LOCAL) { + if (sym hasFlag Flags.PRIVATE) PrivateInInstance() + else ProtectedInInstance() + } + else { + val qual = + if (sym.privateWithin != null && sym.privateWithin != NoSymbol) + Some(makeTemplate(sym.privateWithin)) else None - qq match { case Some(q) => "[" + q + "]" case None => "" } + if (sym hasFlag Flags.PRIVATE) PrivateInTemplate(inTpl) + else if (sym hasFlag Flags.PROTECTED) ProtectedInTemplate(qual getOrElse inTpl) + else if (qual.isDefined) PrivateInTemplate(qual.get) + else Public() } - if (sym hasFlag Flags.PRIVATE) Some(Paragraph(Text(optimize("private" + qual)))) - else if (sym hasFlag Flags.PROTECTED) Some(Paragraph(Text(optimize("protected" + qual)))) - else None } def flags = { val fgs = mutable.ListBuffer.empty[Paragraph] @@ -138,8 +140,8 @@ class ModelFactory(val global: Global, val settings: doc.Settings) extends Comme * * 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 = optimize(inDefinitionTemplates.head.qualifiedName + "." + name) + templatesCache += (sym -> this) + lazy val definitionName = optimize(inDefinitionTemplates.head.qualifiedName + "." + name) override def toRoot: List[DocTemplateImpl] = this :: inTpl.toRoot def inSource = if (sym.sourceFile != null) Some(sym.sourceFile, sym.pos.line) else None def sourceUrl = { @@ -175,7 +177,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) extends Comme def subClasses = subClassesCache.toList protected lazy val memberSyms = // Only this class's constructors are part of its members, inherited constructors are not. - sym.info.nonPrivateMembers.filter(x => (!x.isConstructor || x.owner==sym)) + sym.info.members.filter(s => localShouldDocument(s) && (!s.isConstructor || s.owner == sym)) val members = memberSyms flatMap (makeMember(_, this)) val templates = members collect { case c: DocTemplateEntity => c } val methods = members collect { case d: Def => d } @@ -200,7 +202,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) extends Comme abstract class NonTemplateMemberImpl(sym: Symbol, inTpl: => DocTemplateImpl) extends MemberImpl(sym, inTpl) with NonTemplateMemberEntity { override def qualifiedName = optimize(inTemplate.qualifiedName + "#" + name) - override def definitionName = optimize(inDefinitionTemplates.head.qualifiedName + "#" + name) + lazy val definitionName = optimize(inDefinitionTemplates.head.qualifiedName + "#" + name) } abstract class ParameterImpl(sym: Symbol, inTpl: => DocTemplateImpl) extends EntityImpl(sym, inTpl) with ParameterEntity { @@ -228,8 +230,8 @@ class ModelFactory(val global: Global, val settings: doc.Settings) extends Comme * 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}) + if (templatesCache isDefinedAt (bSym)) + Some(templatesCache(bSym) match {case p: PackageImpl => p}) else { val pack = if (bSym == RootPackage) @@ -260,47 +262,43 @@ class ModelFactory(val global: Global, val settings: doc.Settings) extends Comme 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 _ => new NoDocTemplateImpl(bSym, inTpl) // The owner is private - } + makeRootPackage.get + else if (bSym.isPackage) + makeTemplate(bSym.owner) match { + case inPkg: PackageImpl => makePackage(bSym, inPkg) getOrElse (new NoDocTemplateImpl(bSym, inPkg)) + case _ => throw new Error("'" + bSym + "' must be in a package") + } + else if (templateShouldDocument(bSym)) + makeTemplate(bSym.owner) match { + case inDTpl: DocTemplateImpl => makeDocTemplate(bSym, inDTpl) + case _ => throw new Error("'" + bSym + "' must be in documentable template") + } else - new NoDocTemplateImpl(bSym, inTpl) + new NoDocTemplateImpl(bSym, makeTemplate(bSym.owner)) } /** */ 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)) + val minimumInTpl = + if (bSym.owner != inTpl.sym) + makeTemplate(aSym.owner) match { + case inDTpl: DocTemplateImpl => inDTpl + case inNDTpl => throw new Error("'" + bSym + "' is owned by '" + inNDTpl + "' which is not documented") + } + else + inTpl + if (templatesCache isDefinedAt (bSym)) + templatesCache(bSym) else if (bSym.isModule || (bSym.isAliasType && bSym.tpe.typeSymbol.isModule)) - new DocTemplateImpl(bSym, firstInTpl) with Object + new DocTemplateImpl(bSym, minimumInTpl) with Object else if (bSym.isTrait || (bSym.isAliasType && bSym.tpe.typeSymbol.isTrait)) - new DocTemplateImpl(bSym, firstInTpl) with Trait { + new DocTemplateImpl(bSym, minimumInTpl) with Trait { def valueParams = List(sym.constrParamAccessors map (makeValueParam(_, this))) } else if (bSym.isClass || (bSym.isAliasType && bSym.tpe.typeSymbol.isClass)) - new DocTemplateImpl(bSym, firstInTpl) with Class { + new DocTemplateImpl(bSym, minimumInTpl) with Class { def valueParams = List(sym.constrParamAccessors map (makeValueParam(_, this))) val constructors = @@ -367,13 +365,12 @@ class ModelFactory(val global: Global, val settings: doc.Settings) extends Comme }) else if (bSym.isPackage) inTpl match { case inPkg: PackageImpl => makePackage(bSym, inPkg) } - else if ((bSym.isClass || bSym.isModule) && bSym.isPublic && !bSym.isLocal) { - (inTpl.toRoot find (_.sym == bSym )) orElse Some(makeDocTemplate(bSym, inTpl)) - } + else if ((bSym.isClass || bSym.isModule) && templateShouldDocument(bSym)) + Some(makeDocTemplate(bSym, inTpl)) else None } - if ((!aSym.isPackage && aSym.sourceFile == null) || !aSym.isPublic || (aSym hasFlag Flags.SYNTHETIC) || aSym.isLocal || aSym.isModuleClass || aSym.isPackageObject || aSym.isMixinConstructor) + if ((!aSym.isPackage && aSym.sourceFile == null) || !localShouldDocument(aSym) || aSym.isModuleClass || aSym.isPackageObject || aSym.isMixinConstructor) Nil else { val allSyms = useCases(aSym, inTpl.sym) map { case (bSym, bComment, bPos) => @@ -511,4 +508,12 @@ class ModelFactory(val global: Global, val settings: doc.Settings) extends Comme val name = optimize(nameBuffer.toString) } + def templateShouldDocument(aSym: Symbol): Boolean = { + (aSym.isPackageClass || (aSym.sourceFile != null)) && localShouldDocument(aSym) && ( aSym.owner == NoSymbol || templateShouldDocument(aSym.owner) ) + } + + def localShouldDocument(aSym: Symbol): Boolean = { + !(aSym hasFlag Flags.PRIVATE) && ((aSym hasFlag Flags.PROTECTED) || aSym.privateWithin == NoSymbol) && !(aSym hasFlag Flags.SYNTHETIC) + } + } diff --git a/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala b/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala index 2159ee2a50..1f4794baf8 100644 --- a/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala @@ -359,13 +359,7 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory => /** {{{ para ::= inline '\n' }}} */ def para(): Block = { - def checkParaEnd(): Boolean = { - check(Array(endOfLine, endOfLine)) || - check(Array(endOfLine, '=')) || - check(Array(endOfLine, '{', '{', '{')) || - check(Array(endOfLine, ' ', '-', ' ')) - } - val p = Paragraph(inline(checkParaEnd())) + val p = Paragraph(inline(checkParaEnded())) while (char == endOfLine && char != endOfText) nextChar() p @@ -508,7 +502,14 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory => } def checkParaEnded(): Boolean = { - char == endOfText || check(Array(endOfLine, endOfLine)) || check(Array(endOfLine, '{', '{', '{')) || check(Array(endOfLine, '\u003D')) + (char == endOfText) || + ((char == endOfLine) && { + check(Array(endOfLine, endOfLine)) || + check(Array(endOfLine, '=')) || + check(Array(endOfLine, '{', '{', '{')) || + check(Array(endOfLine, ' ', '-', ' ')) || + check(Array(endOfLine, '\u003D')) + }) } def reportError(pos: Position, message: String): Unit = diff --git a/src/library/scala/collection/BitSetLike.scala b/src/library/scala/collection/BitSetLike.scala index 4b87e75dcb..8476ede7b5 100644 --- a/src/library/scala/collection/BitSetLike.scala +++ b/src/library/scala/collection/BitSetLike.scala @@ -41,7 +41,7 @@ trait BitSetLike[+This <: BitSetLike[This] with Set[Int]] extends SetLike[Int, T protected def nwords: Int /** The words at index `idx', or 0L if outside the range of the set - * @pre idx >= 0 + * @note Requires `idx >= 0` */ protected def word(idx: Int): Long |