summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/doc/DocFactory.scala4
-rw-r--r--src/compiler/scala/tools/nsc/doc/Settings.scala19
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/Page.scala2
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/page/Template.scala36
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/Entity.scala53
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala567
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala46
-rwxr-xr-xsrc/compiler/scala/tools/nsc/doc/model/TreeFactory.scala2
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala8
9 files changed, 460 insertions, 277 deletions
diff --git a/src/compiler/scala/tools/nsc/doc/DocFactory.scala b/src/compiler/scala/tools/nsc/doc/DocFactory.scala
index e2e1ddf065..37e3b626e8 100644
--- a/src/compiler/scala/tools/nsc/doc/DocFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/DocFactory.scala
@@ -83,8 +83,8 @@ class DocFactory(val reporter: Reporter, val settings: doc.Settings) { processor
with model.ModelFactoryImplicitSupport
with model.comment.CommentFactory
with model.TreeFactory {
- override def templateShouldDocument(sym: compiler.Symbol) =
- extraTemplatesToDocument(sym) || super.templateShouldDocument(sym)
+ override def templateShouldDocument(sym: compiler.Symbol, inTpl: TemplateImpl) =
+ extraTemplatesToDocument(sym) || super.templateShouldDocument(sym, inTpl)
}
)
diff --git a/src/compiler/scala/tools/nsc/doc/Settings.scala b/src/compiler/scala/tools/nsc/doc/Settings.scala
index d7b61bc129..1cc1f98fba 100644
--- a/src/compiler/scala/tools/nsc/doc/Settings.scala
+++ b/src/compiler/scala/tools/nsc/doc/Settings.scala
@@ -155,15 +155,16 @@ class Settings(error: String => Unit) extends scala.tools.nsc.Settings(error) {
* the function result should be a humanly-understandable description of the type class
*/
val knownTypeClasses: Map[String, String => String] = Map() +
- ("<root>.scala.package.Numeric" -> ((tparam: String) => tparam + " is a numeric class, such as Int, Long, Float or Double")) +
- ("<root>.scala.package.Integral" -> ((tparam: String) => tparam + " is an integral numeric class, such as Int or Long")) +
- ("<root>.scala.package.Fractional" -> ((tparam: String) => tparam + " is a fractional numeric class, such as Float or Double")) +
- ("<root>.scala.reflect.Manifest" -> ((tparam: String) => tparam + " is accompanied by a Manifest, which is a runtime representation of its type that survives erasure")) +
- ("<root>.scala.reflect.ClassManifest" -> ((tparam: String) => tparam + " is accompanied by a ClassManifest, which is a runtime representation of its type that survives erasure")) +
- ("<root>.scala.reflect.OptManifest" -> ((tparam: String) => tparam + " is accompanied by an OptManifest, which can be either a runtime representation of its type or the NoManifest, which means the runtime type is not available")) +
- ("<root>.scala.reflect.ClassTag" -> ((tparam: String) => tparam + " is accompanied by a ClassTag, which is a runtime representation of its type that survives erasure")) +
- ("<root>.scala.reflect.AbsTypeTag" -> ((tparam: String) => tparam + " is accompanied by an AbsTypeTag, which is a runtime representation of its type that survives erasure")) +
- ("<root>.scala.reflect.TypeTag" -> ((tparam: String) => tparam + " is accompanied by a TypeTag, which is a runtime representation of its type that survives erasure"))
+ // TODO: Bring up to date and test these
+ ("scala.package.Numeric" -> ((tparam: String) => tparam + " is a numeric class, such as Int, Long, Float or Double")) +
+ ("scala.package.Integral" -> ((tparam: String) => tparam + " is an integral numeric class, such as Int or Long")) +
+ ("scala.package.Fractional" -> ((tparam: String) => tparam + " is a fractional numeric class, such as Float or Double")) +
+ ("scala.reflect.Manifest" -> ((tparam: String) => tparam + " is accompanied by a Manifest, which is a runtime representation of its type that survives erasure")) +
+ ("scala.reflect.ClassManifest" -> ((tparam: String) => tparam + " is accompanied by a ClassManifest, which is a runtime representation of its type that survives erasure")) +
+ ("scala.reflect.OptManifest" -> ((tparam: String) => tparam + " is accompanied by an OptManifest, which can be either a runtime representation of its type or the NoManifest, which means the runtime type is not available")) +
+ ("scala.reflect.ClassTag" -> ((tparam: String) => tparam + " is accompanied by a ClassTag, which is a runtime representation of its type that survives erasure")) +
+ ("scala.reflect.AbsTypeTag" -> ((tparam: String) => tparam + " is accompanied by an AbsTypeTag, which is a runtime representation of its type that survives erasure")) +
+ ("scala.reflect.TypeTag" -> ((tparam: String) => tparam + " is accompanied by a TypeTag, which is a runtime representation of its type that survives erasure"))
/**
* Set of classes to exclude from index and diagrams
diff --git a/src/compiler/scala/tools/nsc/doc/html/Page.scala b/src/compiler/scala/tools/nsc/doc/html/Page.scala
index 72b62dd482..40ae65a37a 100644
--- a/src/compiler/scala/tools/nsc/doc/html/Page.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/Page.scala
@@ -58,7 +58,7 @@ abstract class Page {
def templateToPath(tpl: TemplateEntity): List[String] = {
def doName(tpl: TemplateEntity): String =
- NameTransformer.encode(tpl.name) + (if (tpl.isObject) "$" else "")
+ (if (tpl.inPackageObject) "package$$" else "") + NameTransformer.encode(tpl.name) + (if (tpl.isObject) "$" else "")
def downPacks(pack: Package): List[String] =
if (pack.isRootPackage) Nil else (doName(pack) :: downPacks(pack.inTemplate))
def downInner(nme: String, tpl: TemplateEntity): (String, Package) = {
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 66189a6854..975ff8fb89 100644
--- a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
@@ -84,7 +84,7 @@ class Template(universe: doc.Universe, tpl: DocTemplateEntity) extends HtmlPage
</div>
{ signature(tpl, true) }
- { memberToCommentHtml(tpl, true) }
+ { memberToCommentHtml(tpl, tpl.inTemplate, true) }
<div id="mbrsel">
<div id='textfilter'><span class='pre'/><span class='input'><input id='mbrsel-input' type='text' accesskey='/'/></span><span class='post'/></div>
@@ -96,7 +96,7 @@ class Template(universe: doc.Universe, tpl: DocTemplateEntity) extends HtmlPage
}
{ if (tpl.linearizationTemplates.isEmpty && tpl.conversions.isEmpty) NodeSeq.Empty else
{
- if (!tpl.linearization.isEmpty)
+ if (!tpl.linearizationTemplates.isEmpty)
<div id="ancestors">
<span class="filtertype">Inherited<br/>
</span>
@@ -138,35 +138,35 @@ class Template(universe: doc.Universe, tpl: DocTemplateEntity) extends HtmlPage
{ if (constructors.isEmpty) NodeSeq.Empty else
<div id="constructors" class="members">
<h3>Instance Constructors</h3>
- <ol>{ constructors map (memberToHtml(_)) }</ol>
+ <ol>{ constructors map (memberToHtml(_, tpl)) }</ol>
</div>
}
{ if (typeMembers.isEmpty) NodeSeq.Empty else
<div id="types" class="types members">
<h3>Type Members</h3>
- <ol>{ typeMembers map (memberToHtml(_)) }</ol>
+ <ol>{ typeMembers map (memberToHtml(_, tpl)) }</ol>
</div>
}
{ if (absValueMembers.isEmpty) NodeSeq.Empty else
<div id="values" class="values members">
<h3>Abstract Value Members</h3>
- <ol>{ absValueMembers map (memberToHtml(_)) }</ol>
+ <ol>{ absValueMembers map (memberToHtml(_, tpl)) }</ol>
</div>
}
{ if (concValueMembers.isEmpty) NodeSeq.Empty else
<div id="values" class="values members">
<h3>{ if (absValueMembers.isEmpty) "Value Members" else "Concrete Value Members" }</h3>
- <ol>{ concValueMembers map (memberToHtml(_)) }</ol>
+ <ol>{ concValueMembers map (memberToHtml(_, tpl)) }</ol>
</div>
}
{ if (deprValueMembers.isEmpty) NodeSeq.Empty else
<div id="values" class="values members">
<h3>Deprecated Value Members</h3>
- <ol>{ deprValueMembers map (memberToHtml(_)) }</ol>
+ <ol>{ deprValueMembers map (memberToHtml(_, tpl)) }</ol>
</div>
}
</div>
@@ -237,12 +237,12 @@ class Template(universe: doc.Universe, tpl: DocTemplateEntity) extends HtmlPage
tparamsToString(d.typeParams) + paramLists.mkString
}
- def memberToHtml(mbr: MemberEntity): NodeSeq = {
+ def memberToHtml(mbr: MemberEntity, inTpl: DocTemplateEntity): NodeSeq = {
val defParamsString = mbr match {
case d:MemberEntity with Def => defParamsToString(d)
case _ => ""
}
- val memberComment = memberToCommentHtml(mbr, false)
+ val memberComment = memberToCommentHtml(mbr, inTpl, false)
<li name={ mbr.definitionName } visbl={ if (mbr.visibility.isProtected) "prt" else "pub" }
data-isabs={ mbr.isAbstract.toString } fullComment={ if(memberComment.isEmpty) "no" else "yes" }>
<a id={ mbr.name +defParamsString +":"+ mbr.resultType.name}/>
@@ -251,24 +251,24 @@ class Template(universe: doc.Universe, tpl: DocTemplateEntity) extends HtmlPage
</li>
}
- def memberToCommentHtml(mbr: MemberEntity, isSelf: Boolean): NodeSeq = {
+ def memberToCommentHtml(mbr: MemberEntity, inTpl: DocTemplateEntity, isSelf: Boolean): NodeSeq = {
mbr match {
case dte: DocTemplateEntity if isSelf =>
// comment of class itself
<xml:group>
- <div id="comment" class="fullcommenttop">{ memberToCommentBodyHtml(mbr, isSelf = true) }</div>
+ <div id="comment" class="fullcommenttop">{ memberToCommentBodyHtml(mbr, inTpl, isSelf = true) }</div>
</xml:group>
case dte: DocTemplateEntity if mbr.comment.isDefined =>
// comment of inner, documented class (only short comment, full comment is on the class' own page)
memberToInlineCommentHtml(mbr, isSelf)
case _ =>
// comment of non-class member or non-documentented inner class
- val commentBody = memberToCommentBodyHtml(mbr, isSelf = false)
+ val commentBody = memberToCommentBodyHtml(mbr, inTpl, isSelf = false)
if (commentBody.isEmpty)
NodeSeq.Empty
else {
val shortComment = memberToShortCommentHtml(mbr, isSelf)
- val longComment = memberToUseCaseCommentHtml(mbr, isSelf) ++ memberToCommentBodyHtml(mbr, isSelf)
+ val longComment = memberToUseCaseCommentHtml(mbr, isSelf) ++ memberToCommentBodyHtml(mbr, inTpl, isSelf)
val includedLongComment = if (shortComment.text.trim == longComment.text.trim)
NodeSeq.Empty
@@ -298,7 +298,7 @@ class Template(universe: doc.Universe, tpl: DocTemplateEntity) extends HtmlPage
def memberToInlineCommentHtml(mbr: MemberEntity, isSelf: Boolean): NodeSeq =
<p class="comment cmt">{ inlineToHtml(mbr.comment.get.short) }</p>
- def memberToCommentBodyHtml(mbr: MemberEntity, isSelf: Boolean, isReduced: Boolean = false): NodeSeq = {
+ def memberToCommentBodyHtml(mbr: MemberEntity, inTpl: DocTemplateEntity, isSelf: Boolean, isReduced: Boolean = false): NodeSeq = {
val memberComment =
if (mbr.comment.isEmpty) NodeSeq.Empty
@@ -383,7 +383,7 @@ class Template(universe: doc.Universe, tpl: DocTemplateEntity) extends HtmlPage
}
<dd>
- This member is added by an implicit conversion from { typeToHtml(mbr.inTemplate.resultType, true) } to
+ This member is added by an implicit conversion from { typeToHtml(inTpl.resultType, true) } to
{ targetType } performed by method { conversionMethod } in { conversionOwner }.
{ constraintText }
</dd>
@@ -404,7 +404,7 @@ class Template(universe: doc.Universe, tpl: DocTemplateEntity) extends HtmlPage
val definitionClasses: Seq[scala.xml.Node] = {
val inDefTpls = mbr.inDefinitionTemplates
- if ((inDefTpls.tail.isEmpty && (inDefTpls.head == mbr.inTemplate)) || isReduced) NodeSeq.Empty
+ if ((inDefTpls.tail.isEmpty && (inDefTpls.head == inTpl)) || isReduced) NodeSeq.Empty
else {
<dt>Definition Classes</dt>
<dd>{ templatesToHtml(inDefTpls, xml.Text(" → ")) }</dd>
@@ -650,7 +650,7 @@ class Template(universe: doc.Universe, tpl: DocTemplateEntity) extends HtmlPage
<a href={nameLink}>{nameHtml}</a>
else nameHtml
}{
- def tparamsToHtml(mbr: Entity): NodeSeq = mbr match {
+ def tparamsToHtml(mbr: Any): NodeSeq = mbr match {
case hk: HigherKinded =>
val tpss = hk.typeParams
if (tpss.isEmpty) NodeSeq.Empty else {
@@ -662,7 +662,7 @@ class Template(universe: doc.Universe, tpl: DocTemplateEntity) extends HtmlPage
}
<span class="tparams">[{ tparams0(tpss) }]</span>
}
- case _ => NodeSeq.Empty
+ case _ => NodeSeq.Empty
}
tparamsToHtml(mbr)
}{
diff --git a/src/compiler/scala/tools/nsc/doc/model/Entity.scala b/src/compiler/scala/tools/nsc/doc/model/Entity.scala
index 6488847049..8c6fa53fbc 100644
--- a/src/compiler/scala/tools/nsc/doc/model/Entity.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/Entity.scala
@@ -24,6 +24,9 @@ import comment._
* - annotations. */
trait Entity {
+ /** Similar to symbols, so we can track entities */
+ def id: Int
+
/** The name of the entity. Note that the name does not qualify this entity uniquely; use its `qualifiedName`
* instead. */
def name : String
@@ -48,6 +51,8 @@ trait Entity {
/** The annotations attached to this entity, if any. */
def annotations: List[Annotation]
+ /** The kind of the entity */
+ def kind: String
}
object Entity {
@@ -86,9 +91,11 @@ trait TemplateEntity extends Entity {
/** Whether this template is a case class. */
def isCaseClass: Boolean
+ /** Whether or not the template was defined in a package object */
+ def inPackageObject: Boolean
+
/** The self-type of this template, if it differs from the template type. */
def selfType : Option[TypeEntity]
-
}
@@ -177,7 +184,7 @@ object MemberEntity {
}
/** An entity that is parameterized by types */
-trait HigherKinded extends Entity {
+trait HigherKinded {
/** The type parameters of this entity. */
def typeParams: List[TypeParam]
@@ -187,8 +194,14 @@ trait HigherKinded extends Entity {
/** A template (class, trait, object or package) which is referenced in the universe, but for which no further
* documentation is available. Only templates for which a source file is given are documented by Scaladoc. */
-trait NoDocTemplate extends TemplateEntity
+trait NoDocTemplate extends TemplateEntity {
+ def kind = "<no doc>"
+}
+/** TODO: Document */
+trait NoDocTemplateMemberEntity extends TemplateEntity with MemberEntity {
+ def kind = "<no doc, mbr>"
+}
/** A template (class, trait, object or package) for which documentation is available. Only templates for which
* a source file is given are documented by Scaladoc. */
@@ -209,9 +222,6 @@ trait DocTemplateEntity extends TemplateEntity with MemberEntity {
/** The direct super-type of this template. */
def parentType: Option[TypeEntity]
- @deprecated("Use `linearizationTemplates` and `linearizationTypes` instead", "2.9.0")
- def linearization: List[(TemplateEntity, TypeEntity)]
-
/** All class, trait and object templates which are part of this template's linearization, in lineratization order.
* This template's linearization contains all of its direct and indirect super-classes and super-traits. */
def linearizationTemplates: List[TemplateEntity]
@@ -254,7 +264,9 @@ trait DocTemplateEntity extends TemplateEntity with MemberEntity {
/** A trait template. */
-trait Trait extends DocTemplateEntity with HigherKinded
+trait Trait extends DocTemplateEntity with HigherKinded {
+ def kind = "trait"
+}
/** A class template. */
@@ -270,11 +282,14 @@ trait Class extends Trait with HigherKinded {
* parameters cannot be curried, the outer list has exactly one element. */
def valueParams: List[List[ValueParam]]
+ override def kind = "class"
}
/** An object template. */
-trait Object extends DocTemplateEntity
+trait Object extends DocTemplateEntity {
+ def kind = "object"
+}
/** A package template. A package is in the universe if it is declared as a package object, or if it
@@ -290,6 +305,8 @@ trait Package extends Object {
/** All packages that are member of this package. */
def packages: List[Package]
+
+ override def kind = "package"
}
@@ -323,6 +340,7 @@ trait Def extends NonTemplateMemberEntity with HigherKinded {
* Each parameter block is a list of value parameters. */
def valueParams : List[List[ValueParam]]
+ def kind = "method"
}
@@ -337,11 +355,14 @@ trait Constructor extends NonTemplateMemberEntity {
* element. */
def valueParams : List[List[ValueParam]]
+ def kind = "constructor"
}
/** A value (`val`), lazy val (`lazy val`) or variable (`var`) of a template. */
-trait Val extends NonTemplateMemberEntity
+trait Val extends NonTemplateMemberEntity {
+ def kind = "[lazy] value/variable"
+}
/** An abstract type member of a template. */
@@ -353,6 +374,7 @@ trait AbstractType extends NonTemplateMemberEntity with HigherKinded {
/** The upper bound for this abstract type, if it has been defined. */
def hi: Option[TypeEntity]
+ def kind = "abstract type"
}
@@ -362,18 +384,14 @@ trait AliasType extends NonTemplateMemberEntity with HigherKinded {
/** The type aliased by this type alias. */
def alias: TypeEntity
+ def kind = "type alias"
}
/** A parameter to an entity. */
-trait ParameterEntity extends Entity {
-
- /** Whether this parameter is a type parameter. */
- def isTypeParam: Boolean
-
- /** Whether this parameter is a value parameter. */
- def isValueParam: Boolean
+trait ParameterEntity {
+ def name: String
}
@@ -388,7 +406,6 @@ trait TypeParam extends ParameterEntity with HigherKinded {
/** The upper bound for this type parameter, if it has been defined. */
def hi: Option[TypeEntity]
-
}
@@ -403,7 +420,6 @@ trait ValueParam extends ParameterEntity {
/** Whether this value parameter is implicit. */
def isImplicit: Boolean
-
}
@@ -416,6 +432,7 @@ trait Annotation extends Entity {
/** The arguments passed to the constructor of the annotation class. */
def arguments: List[ValueArgument]
+ def kind = "annotation"
}
/** A trait that signals the member results from an implicit conversion */
diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
index 3dd77d47da..9a8df1fd0e 100644
--- a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
@@ -21,10 +21,9 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
import global._
import definitions.{ ObjectClass, NothingClass, AnyClass, AnyValClass, AnyRefClass }
- import rootMirror.{ RootPackage, EmptyPackage }
+ import rootMirror.{ RootPackage, RootClass, EmptyPackage }
- private var droppedPackages = 0
- def templatesCount = templatesCache.size - droppedPackages
+ def templatesCount = docTemplatesCache.count(_._2.isDocTemplate) - droppedPackages.size
private var modelFinished = false
private var universe: Universe = null
@@ -45,44 +44,49 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
private lazy val noSubclassCache = Set[Symbol](AnyClass, AnyRefClass, ObjectClass)
- /** */
def makeModel: Option[Universe] = {
val universe = new Universe { thisUniverse =>
thisFactory.universe = thisUniverse
val settings = thisFactory.settings
- private val rootPackageMaybe = makeRootPackage
- val rootPackage = rootPackageMaybe.orNull
+ val rootPackage = modelCreation.createRootPackage
}
modelFinished = true
+ // complete the links between model entities, everthing that couldn't have been done before
+ universe.rootPackage.completeModel
+
Some(universe) filter (_.rootPackage != null)
}
- /** */
- protected val templatesCache =
- new mutable.LinkedHashMap[Symbol, DocTemplateImpl]
-
- def findTemplate(query: String): Option[DocTemplateImpl] = {
- if (!modelFinished) sys.error("cannot find template in unfinished universe")
- templatesCache.values find { tpl => tpl.qualifiedName == query && !tpl.isObject }
- }
+ // state:
+ var ids = 0
+ private val droppedPackages = mutable.Set[PackageImpl]()
+ protected val docTemplatesCache = new mutable.LinkedHashMap[Symbol, DocTemplateImpl]
+ protected val noDocTemplatesCache = new mutable.LinkedHashMap[Symbol, NoDocTemplateImpl]
+ protected var typeCache = new mutable.LinkedHashMap[Type, TypeEntity]
def optimize(str: String): String =
if (str.length < 16) str.intern else str
/* ============== IMPLEMENTATION PROVIDING ENTITY TYPES ============== */
- abstract class EntityImpl(val sym: Symbol, inTpl: => TemplateImpl) extends Entity {
+ abstract class EntityImpl(val sym: Symbol, val inTpl: TemplateImpl) extends Entity {
+ val id = { ids += 1; ids }
val name = optimize(sym.nameString)
+ val universe = thisFactory.universe
+
+ // Debugging:
+ // assert(id != 36, sym + " " + sym.getClass)
+ //println("Creating entity #" + id + " [" + kind + " " + qualifiedName + "] for sym " + sym.kindString + " " + sym.ownerChain.reverse.map(_.name).mkString("."))
+
def inTemplate: TemplateImpl = inTpl
def toRoot: List[EntityImpl] = this :: inTpl.toRoot
def qualifiedName = name
- val universe = thisFactory.universe
def annotations = sym.annotations.map(makeAnnotation)
}
trait TemplateImpl extends EntityImpl with TemplateEntity {
override def qualifiedName: String =
- if (inTemplate.isRootPackage) name else optimize(inTemplate.qualifiedName + "." + name)
+ if (inTemplate == null || inTemplate.isRootPackage) name else optimize(inTemplate.qualifiedName + "." + name)
def isPackage = sym.isPackage
def isTrait = sym.isTrait
def isClass = sym.isClass && !sym.isTrait
@@ -90,15 +94,11 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
def isCaseClass = sym.isCaseClass
def isRootPackage = false
def selfType = if (sym.thisSym eq sym) None else Some(makeType(sym.thisSym.typeOfThis, this))
+ def inPackageObject: Boolean = sym.owner.isModuleClass && sym.owner.sourceModule.isPackageObject
}
- class NoDocTemplateImpl(sym: Symbol, inTpl: => TemplateImpl) extends EntityImpl(sym, inTpl) with TemplateImpl with NoDocTemplate {
- def isDocTemplate = false
- }
-
- abstract class MemberImpl(sym: Symbol, implConv: ImplicitConversionImpl = null, inTpl: => DocTemplateImpl) extends EntityImpl(sym, inTpl) with MemberEntity {
- lazy val comment =
- if (inTpl == null) None else thisFactory.comment(sym, inTpl)
+ abstract class MemberImpl(sym: Symbol, implConv: ImplicitConversionImpl, inTpl: DocTemplateImpl) extends EntityImpl(sym, inTpl) with MemberEntity {
+ lazy val comment = if (inTpl != null) thisFactory.comment(sym, inTpl) else None
override def inTemplate = inTpl
override def toRoot: List[MemberImpl] = this :: inTpl.toRoot
def inDefinitionTemplates = this match {
@@ -106,9 +106,9 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
mb.useCaseOf.get.inDefinitionTemplates
case _ =>
if (inTpl == null)
- makeRootPackage.toList
+ List(makeRootPackage)
else
- makeTemplate(sym.owner) :: (sym.allOverriddenSymbols map { inhSym => makeTemplate(inhSym.owner) })
+ makeTemplate(sym.owner)::(sym.allOverriddenSymbols map { inhSym => makeTemplate(inhSym.owner) })
}
def visibility = {
if (sym.isPrivateLocal) PrivateInInstance()
@@ -189,16 +189,40 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
def byConversion = if (implConv ne null) Some(implConv) else None
}
+ /** A template that is not documented at all. The class is instantiated during lookups, to indicate that the class
+ * exists, but should not be documented (either it's not included in the source or it's not visible)
+ */
+ class NoDocTemplateImpl(sym: Symbol, inTpl: TemplateImpl) extends EntityImpl(sym, inTpl) with TemplateImpl with HigherKindedImpl with NoDocTemplate {
+ assert(modelFinished)
+ assert(!(noDocTemplatesCache isDefinedAt sym))
+ noDocTemplatesCache += (sym -> this)
+
+ def isDocTemplate = false
+ }
+
+ /** An inherited template that was not documented in its original owner - example:
+ * in classpath: trait T { class C } -- T (and implicitly C) are not documented
+ * in the source: trait U extends T -- C appears in U as a NoDocTemplateMemberImpl -- that is, U has a member for it
+ * but C doesn't get its own page
+ */
+ class NoDocTemplateMemberImpl(sym: Symbol, inTpl: DocTemplateImpl) extends MemberImpl(sym, null, inTpl) with TemplateImpl with HigherKindedImpl with NoDocTemplateMemberEntity {
+ assert(modelFinished)
+
+ def isDocTemplate = false
+ lazy val definitionName = optimize(inDefinitionTemplates.head.qualifiedName + "." + name)
+ }
+
/** The instantiation of `TemplateImpl` triggers the creation of the following entities:
* All ancestors of the template and all non-package members.
*/
- abstract class DocTemplateImpl(sym: Symbol, inTpl: => DocTemplateImpl) extends MemberImpl(sym, null, inTpl) with TemplateImpl with HigherKindedImpl with DocTemplateEntity {
- //if (inTpl != null) println("mbr " + sym + " in " + (inTpl.toRoot map (_.sym)).mkString(" > "))
+ abstract class DocTemplateImpl(sym: Symbol, inTpl: DocTemplateImpl) extends MemberImpl(sym, null, inTpl) with TemplateImpl with HigherKindedImpl with DocTemplateEntity {
+ assert(!modelFinished)
+ assert(!(docTemplatesCache isDefinedAt sym), sym)
+ docTemplatesCache += (sym -> this)
+
if (settings.verbose.value)
inform("Creating doc template for " + sym)
- 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 && ! sym.isSynthetic)
@@ -244,7 +268,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
}
}
- val linearization = linearizationFromSymbol(sym)
+ lazy val linearization = linearizationFromSymbol(sym)
def linearizationTemplates = linearization map { _._1 }
def linearizationTypes = linearization map { _._2 }
@@ -258,45 +282,65 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
}
def subClasses = if (subClassesCache == null) Nil else subClassesCache.toList
- val conversions = if (settings.docImplicits.value) makeImplicitConversions(sym, this) else Nil
+ val conversions: List[ImplicitConversionImpl] =
+ if (settings.docImplicits.value) makeImplicitConversions(sym, this) else Nil
+
+ lazy val memberSyms = sym.info.members.filter(s => membersShouldDocument(s, this))
+
+ var memberSymsLazy = memberSyms.filter(t => templateShouldDocument(t, this) && !inOriginalOnwer(t, this))
+ var memberSymsEager = memberSyms.filter(!memberSymsLazy.contains(_))
+
+ var members: List[MemberImpl] = (memberSymsEager.flatMap(makeMember(_, null, this))) :::
+ (conversions.flatMap((_.members))) // also take in the members from implicit conversions
+
+ def templates = members collect { case c: DocTemplateEntity => c }
+ def methods = members collect { case d: Def => d }
+ def values = members collect { case v: Val => v }
+ def abstractTypes = members collect { case t: AbstractType => t }
+ def aliasTypes = members collect { case t: AliasType => t }
+
+ def completeModel: Unit = {
+ for (member <- members)
+ member match {
+ case d: DocTemplateImpl => d.completeModel
+ case _ =>
+ }
- lazy val memberSyms =
- // Only this class's constructors are part of its members, inherited constructors are not.
- sym.info.members.filter(s => localShouldDocument(s) && (!s.isConstructor || s.owner == sym) && !isPureBridge(sym) )
+ members :::= memberSymsLazy.map(modelCreation.createLazyTemplateMember(_, inTpl))
- val members = (memberSyms.flatMap(makeMember(_, null, this))) :::
- (conversions.flatMap((_.members))) // also take in the members from implicit conversions
+ // compute linearization to register subclasses
+ linearization
+ }
- val templates = members collect { case c: DocTemplateEntity => c }
- val methods = members collect { case d: Def => d }
- val values = members collect { case v: Val => v }
- val abstractTypes = members collect { case t: AbstractType => t }
- val aliasTypes = members collect { case t: AliasType => t }
override def isTemplate = true
+ lazy val definitionName = optimize(inDefinitionTemplates.head.qualifiedName + "." + name)
def isDocTemplate = true
def companion = sym.companionSymbol match {
case NoSymbol => None
case comSym if !isEmptyJavaObject(comSym) && (comSym.isClass || comSym.isModule) =>
- Some(makeDocTemplate(comSym, inTpl))
+ makeTemplate(comSym) match {
+ case d: DocTemplateImpl => Some(d)
+ case _ => None
+ }
case _ => None
}
}
- abstract class PackageImpl(sym: Symbol, inTpl: => PackageImpl) extends DocTemplateImpl(sym, inTpl) with Package {
+ 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
- override val linearization = {
+ override lazy val linearization = {
val symbol = sym.info.members.find {
s => s.isPackageObject
} getOrElse sym
linearizationFromSymbol(symbol)
}
- val packages = members collect { case p: Package => p }
+ def packages = members collect { case p: PackageImpl if !(droppedPackages contains p) => p }
}
abstract class RootPackageImpl(sym: Symbol) extends PackageImpl(sym, null) with RootPackageEntity
- abstract class NonTemplateMemberImpl(sym: Symbol, implConv: ImplicitConversionImpl, inTpl: => DocTemplateImpl) extends MemberImpl(sym, implConv, inTpl) with NonTemplateMemberEntity {
+ abstract class NonTemplateMemberImpl(sym: Symbol, implConv: ImplicitConversionImpl, inTpl: DocTemplateImpl) extends MemberImpl(sym, implConv, inTpl) with NonTemplateMemberEntity {
override def qualifiedName = optimize(inTemplate.qualifiedName + "#" + name)
lazy val definitionName =
if (implConv == null) optimize(inDefinitionTemplates.head.qualifiedName + "#" + name)
@@ -305,7 +349,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
def isBridge = sym.isBridge
}
- abstract class NonTemplateParamMemberImpl(sym: Symbol, implConv: ImplicitConversionImpl, inTpl: => DocTemplateImpl) extends NonTemplateMemberImpl(sym, implConv, inTpl) {
+ abstract class NonTemplateParamMemberImpl(sym: Symbol, implConv: ImplicitConversionImpl, inTpl: DocTemplateImpl) extends NonTemplateMemberImpl(sym, implConv, inTpl) {
def valueParams = {
val info = if (implConv eq null) sym.info else implConv.toType memberInfo sym
info.paramss map { ps => (ps.zipWithIndex) map { case (p, i) =>
@@ -314,26 +358,30 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
}
}
- abstract class ParameterImpl(sym: Symbol, inTpl: => TemplateImpl) extends EntityImpl(sym, inTpl) with ParameterEntity {
- override def inTemplate = inTpl
+ abstract class ParameterImpl(val sym: Symbol, val inTpl: TemplateImpl) extends ParameterEntity {
+ val name = optimize(sym.nameString)
}
- private trait TypeBoundsImpl extends EntityImpl {
+ private trait TypeBoundsImpl {
+ def sym: Symbol
+ def inTpl: TemplateImpl
def lo = sym.info.bounds match {
case TypeBounds(lo, hi) if lo.typeSymbol != NothingClass =>
- Some(makeTypeInTemplateContext(appliedType(lo, sym.info.typeParams map {_.tpe}), inTemplate, sym))
+ Some(makeTypeInTemplateContext(appliedType(lo, sym.info.typeParams map {_.tpe}), inTpl, sym))
case _ => None
}
def hi = sym.info.bounds match {
case TypeBounds(lo, hi) if hi.typeSymbol != AnyClass =>
- Some(makeTypeInTemplateContext(appliedType(hi, sym.info.typeParams map {_.tpe}), inTemplate, sym))
+ Some(makeTypeInTemplateContext(appliedType(hi, sym.info.typeParams map {_.tpe}), inTpl, sym))
case _ => None
}
}
- trait HigherKindedImpl extends EntityImpl with HigherKinded {
+ trait HigherKindedImpl extends HigherKinded {
+ def sym: Symbol
+ def inTpl: TemplateImpl
def typeParams =
- sym.typeParams map (makeTypeParam(_, inTemplate))
+ sym.typeParams map (makeTypeParam(_, inTpl))
}
/* ============== MAKER METHODS ============== */
@@ -352,145 +400,133 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
aSym
}
- def makeRootPackage: Option[PackageImpl] =
- makePackage(RootPackage, null)
+ /**
+ * These are all model construction methods. Please do not use them directly, they are calling each other recursively
+ * starting from makeModel. On the other hand, makeTemplate, makeAnnotation, makeMember, makeType should only be used
+ * after the model was created (modelFinished=true) otherwise assertions will start failing.
+ */
+ object modelCreation {
- /** 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))
- Some(templatesCache(bSym) match {case p: PackageImpl => p})
- else {
- val pack =
- if (bSym == RootPackage)
- new RootPackageImpl(bSym) {
- override lazy val comment =
- if(settings.docRootContent.isDefault) None
- else {
- import Streamable._
- Path(settings.docRootContent.value) match {
- case f : File => {
- val rootComment = closing(f.inputStream)(is => parse(slurp(is), "", NoPosition))
- Some(rootComment)
- }
- case _ => None
- }
- }
- override val name = "root"
- override def inTemplate = this
- override def toRoot = this :: Nil
- override def qualifiedName = "_root_"
- override def inheritedFrom = Nil
- override def isRootPackage = true
- override lazy val 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 createRootPackage: PackageImpl = docTemplatesCache.get(RootPackage) match {
+ case Some(root: PackageImpl) => root
+ case _ => modelCreation.createTemplate(RootPackage, null).asInstanceOf[PackageImpl]
}
- }
-
- /** */
- def makeTemplate(aSym: Symbol): TemplateImpl = {
- val bSym = normalizeTemplate(aSym)
- if (bSym == RootPackage)
- makeRootPackage.get
- else if (bSym.isPackage)
- makeTemplate(bSym.owner) match {
- case inPkg: PackageImpl => makePackage(bSym, inPkg) getOrElse (new NoDocTemplateImpl(bSym, inPkg))
- case inNoDocTpl: NoDocTemplateImpl => new NoDocTemplateImpl(bSym, inNoDocTpl)
- 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 inNoDocTpl: NoDocTemplateImpl => new NoDocTemplateImpl(bSym, inNoDocTpl)
- case _ => throw new Error("'" + bSym + "' must be in documentable template")
- }
- else
- new NoDocTemplateImpl(bSym, makeTemplate(bSym.owner))
- }
-
- /** */
- def makeDocTemplate(aSym: Symbol, inTpl: => DocTemplateImpl): DocTemplateImpl = {
- val bSym = normalizeTemplate(aSym)
- 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")
+ /**
+ * Create a template, either a package, class, trait or object
+ */
+ def createTemplate(aSym: Symbol, inTpl: DocTemplateImpl): DocTemplateImpl = {
+ // don't call this after the model finished!
+ assert(!modelFinished)
+
+ def createRootPackageComment: Option[Comment] =
+ if(settings.docRootContent.isDefault) None
+ else {
+ import Streamable._
+ Path(settings.docRootContent.value) match {
+ case f : File => {
+ val rootComment = closing(f.inputStream)(is => parse(slurp(is), "", NoPosition))
+ Some(rootComment)
+ }
+ case _ => None
+ }
}
- else
- inTpl
- if (templatesCache isDefinedAt (bSym))
- templatesCache(bSym)
- else if (bSym.isModule || (bSym.isAliasType && bSym.tpe.typeSymbol.isModule))
- new DocTemplateImpl(bSym, minimumInTpl) with Object
- else if (bSym.isTrait || (bSym.isAliasType && bSym.tpe.typeSymbol.isTrait))
- new DocTemplateImpl(bSym, minimumInTpl) with Trait
- else if (bSym.isClass || (bSym.isAliasType && bSym.tpe.typeSymbol.isClass))
- new DocTemplateImpl(bSym, minimumInTpl) with Class {
- def valueParams =
- // we don't want params on a class (non case class) signature
- if (isCaseClass) List(sym.constrParamAccessors map (makeValueParam(_, this)))
- else List.empty
- val constructors =
- members collect { case d: Constructor => d }
- def primaryConstructor = constructors find { _.isPrimary }
+
+ def createDocTemplate(bSym: Symbol, inTpl: DocTemplateImpl): DocTemplateImpl = {
+ if (bSym.isModule || (bSym.isAliasType && bSym.tpe.typeSymbol.isModule))
+ new DocTemplateImpl(bSym, inTpl) with Object
+ else if (bSym.isTrait || (bSym.isAliasType && bSym.tpe.typeSymbol.isTrait))
+ new DocTemplateImpl(bSym, inTpl) with Trait
+ else if (bSym.isClass || (bSym.isAliasType && bSym.tpe.typeSymbol.isClass))
+ new DocTemplateImpl(bSym, inTpl) with Class {
+ def valueParams =
+ // we don't want params on a class (non case class) signature
+ if (isCaseClass) List(sym.constrParamAccessors map (makeValueParam(_, this)))
+ else List.empty
+ val constructors =
+ members collect { case d: Constructor => d }
+ def primaryConstructor = constructors find { _.isPrimary }
+ }
+ else
+ sys.error("'" + bSym + "' isn't a class, trait or object thus cannot be built as a documentable template")
}
- else
- throw new Error("'" + bSym + "' that isn't a class, trait or object cannot be built as a documentable template")
- }
- /** */
- def makeAnnotation(annot: AnnotationInfo): Annotation = {
- val aSym = annot.symbol
- new EntityImpl(aSym, makeTemplate(aSym.owner)) with Annotation {
- lazy val annotationClass =
- makeTemplate(annot.symbol)
- val arguments = { // lazy
- def noParams = annot.args map { _ => None }
- val params: List[Option[ValueParam]] = annotationClass match {
- case aClass: Class =>
- (aClass.primaryConstructor map { _.valueParams.head }) match {
- case Some(vps) => vps map { Some(_) }
- case None => noParams
+ val bSym = normalizeTemplate(aSym)
+ if (docTemplatesCache isDefinedAt bSym)
+ return docTemplatesCache(bSym)
+
+ /* Three cases of templates:
+ * (1) root package -- special cased for bootstrapping
+ * (2) package
+ * (3) class/object/trait
+ */
+ if (bSym == RootPackage) // (1)
+ new RootPackageImpl(bSym) {
+ override lazy val comment = createRootPackageComment
+ override val name = "root"
+ override def inTemplate = this
+ override def toRoot = this :: Nil
+ override def qualifiedName = "_root_"
+ override def inheritedFrom = Nil
+ override def isRootPackage = true
+ override lazy val memberSyms =
+ (bSym.info.members ++ EmptyPackage.info.members) filter { s =>
+ s != EmptyPackage && s != RootPackage
}
- case _ => noParams
}
- assert(params.length == annot.args.length)
- (params zip annot.args) flatMap { case (param, arg) =>
- makeTree(arg) match {
- case Some(tree) =>
- Some(new ValueArgument {
- def parameter = param
- def value = tree
- })
- case None => None
- }
+ else if (bSym.isPackage) // (2)
+ inTpl match {
+ case inPkg: PackageImpl =>
+ val pack = new PackageImpl(bSym, inPkg) {}
+ if (pack.templates.isEmpty && pack.memberSymsLazy.isEmpty)
+ droppedPackages += pack
+ pack
+ case _ =>
+ sys.error("'" + bSym + "' must be in a package")
}
+ else {
+ // no class inheritance at this point
+ assert(inOriginalOnwer(bSym, inTpl))
+ createDocTemplate(bSym, inTpl)
}
}
+
+ /**
+ * After the model is completed, no more DocTemplateEntities are created.
+ * Therefore any symbol that still appears is:
+ * - NoDocTemplateMemberEntity (created here)
+ * - NoDocTemplateEntity (created in makeTemplate)
+ */
+ def createLazyTemplateMember(aSym: Symbol, inTpl: DocTemplateImpl): MemberImpl = {
+ assert(modelFinished)
+ val bSym = normalizeTemplate(aSym)
+
+ if (docTemplatesCache isDefinedAt bSym)
+ docTemplatesCache(bSym)
+ else
+ docTemplatesCache.get(bSym.owner) match {
+ case Some(inTpl) =>
+ val mbrs = inTpl.members.collect({ case mbr: MemberImpl if mbr.sym == bSym => mbr })
+ assert(mbrs.length == 1)
+ mbrs.head
+ case _ =>
+ // move the class completely to the new location
+ new NoDocTemplateMemberImpl(aSym, inTpl)
+ }
+ }
}
- /** */
+ /** Get the root package */
+ def makeRootPackage: PackageImpl = docTemplatesCache(RootPackage).asInstanceOf[PackageImpl]
+
// TODO: Should be able to override the type
- def makeMember(aSym: Symbol, implConv: ImplicitConversionImpl, inTpl: => DocTemplateImpl): List[MemberImpl] = {
+ def makeMember(aSym: Symbol, implConv: ImplicitConversionImpl, inTpl: DocTemplateImpl): List[MemberImpl] = {
def makeMember0(bSym: Symbol, _useCaseOf: Option[MemberImpl]): Option[MemberImpl] = {
if (bSym.isGetter && bSym.isLazy)
Some(new NonTemplateMemberImpl(bSym, implConv, inTpl) with Val {
override lazy val comment = // The analyser does not duplicate the lazy val's DocDef when it introduces its accessor.
- thisFactory.comment(bSym.accessed, inTpl) // This hack should be removed after analyser is fixed.
+ thisFactory.comment(bSym.accessed, inTpl.asInstanceOf[DocTemplateImpl]) // This hack should be removed after analyser is fixed.
override def isLazyVal = true
override def useCaseOf = _useCaseOf
})
@@ -538,10 +574,18 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
def alias = makeTypeInTemplateContext(sym.tpe.dealias, inTpl, sym)
override def useCaseOf = _useCaseOf
})
- else if (bSym.isPackage)
- inTpl match { case inPkg: PackageImpl => makePackage(bSym, inPkg) }
- else if ((bSym.isClass || bSym.isModule || bSym == AnyRefClass) && templateShouldDocument(bSym))
- Some(makeDocTemplate(bSym, inTpl))
+ else if (bSym.isPackage && !modelFinished)
+ inTpl match {
+ case inPkg: PackageImpl => modelCreation.createTemplate(bSym, inTpl) match {
+ case p: PackageImpl if droppedPackages contains p => None
+ case p: PackageImpl => Some(p)
+ case _ => sys.error("'" + bSym + "' must be a package")
+ }
+ case _ =>
+ sys.error("'" + bSym + "' must be in a package")
+ }
+ else if (!modelFinished && templateShouldDocument(bSym, inTpl) && inOriginalOnwer(bSym, inTpl))
+ Some(modelCreation.createTemplate(bSym, inTpl))
else
None
}
@@ -561,14 +605,78 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
// Use cases replace the original definitions - SI-5054
allSyms flatMap { makeMember0(_, member) }
}
+ }
+
+ def findMember(aSym: Symbol, inTpl: DocTemplateImpl): Option[MemberImpl] = {
+ val tplSym = normalizeTemplate(aSym.owner)
+ inTpl.members.find(_.sym == aSym)
+ }
+
+ def findTemplate(query: String): Option[DocTemplateImpl] = {
+ assert(modelFinished)
+ docTemplatesCache.values find { (tpl: TemplateImpl) => tpl.qualifiedName == query && !tpl.isObject }
+ }
+
+ def findTemplateMaybe(aSym: Symbol): Option[DocTemplateImpl] = {
+ assert(modelFinished)
+ docTemplatesCache.get(normalizeTemplate(aSym))
+ }
+
+ def makeTemplate(aSym: Symbol): TemplateImpl = {
+ assert(modelFinished)
+ def makeNoDocTemplate(aSym: Symbol, inTpl: TemplateImpl): NoDocTemplateImpl = {
+ val bSym = normalizeTemplate(aSym)
+ noDocTemplatesCache.get(bSym) match {
+ case Some(noDocTpl) => noDocTpl
+ case None => new NoDocTemplateImpl(bSym, inTpl)
+ }
+ }
+
+ findTemplateMaybe(aSym) match {
+ case Some(dtpl) =>
+ dtpl
+ case None =>
+ val bSym = normalizeTemplate(aSym)
+ makeNoDocTemplate(bSym, makeTemplate(bSym.owner))
+ }
+ }
+
+
+ /** */
+ def makeAnnotation(annot: AnnotationInfo): Annotation = {
+ val aSym = annot.symbol
+ new EntityImpl(aSym, makeTemplate(aSym.owner)) with Annotation {
+ lazy val annotationClass =
+ makeTemplate(annot.symbol)
+ val arguments = { // lazy
+ def noParams = annot.args map { _ => None }
+ val params: List[Option[ValueParam]] = annotationClass match {
+ case aClass: Class =>
+ (aClass.primaryConstructor map { _.valueParams.head }) match {
+ case Some(vps) => vps map { Some(_) }
+ case None => noParams
+ }
+ case _ => noParams
+ }
+ assert(params.length == annot.args.length)
+ (params zip annot.args) flatMap { case (param, arg) =>
+ makeTree(arg) match {
+ case Some(tree) =>
+ Some(new ValueArgument {
+ def parameter = param
+ def value = tree
+ })
+ case None => None
+ }
+ }
+ }
+ }
}
/** */
- def makeTypeParam(aSym: Symbol, inTpl: => TemplateImpl): TypeParam =
+ def makeTypeParam(aSym: Symbol, inTpl: TemplateImpl): TypeParam =
new ParameterImpl(aSym, inTpl) with TypeBoundsImpl with HigherKindedImpl with TypeParam {
- def isTypeParam = true
- def isValueParam = false
def variance: String = {
if (sym hasFlag Flags.COVARIANT) "+"
else if (sym hasFlag Flags.CONTRAVARIANT) "-"
@@ -577,16 +685,15 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
}
/** */
- def makeValueParam(aSym: Symbol, inTpl: => DocTemplateImpl): ValueParam = {
+ def makeValueParam(aSym: Symbol, inTpl: DocTemplateImpl): ValueParam = {
makeValueParam(aSym, inTpl, aSym.nameString)
}
+
/** */
- def makeValueParam(aSym: Symbol, inTpl: => DocTemplateImpl, newName: String): ValueParam =
+ def makeValueParam(aSym: Symbol, inTpl: DocTemplateImpl, newName: String): ValueParam =
new ParameterImpl(aSym, inTpl) with ValueParam {
override val name = newName
- def isTypeParam = false
- def isValueParam = true
def defaultValue =
if (aSym.hasDefault) {
// units.filter should return only one element
@@ -601,12 +708,12 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
}
else None
def resultType =
- makeTypeInTemplateContext(sym.tpe, inTpl, sym)
+ makeTypeInTemplateContext(aSym.tpe, inTpl, aSym)
def isImplicit = aSym.isImplicit
}
/** */
- def makeTypeInTemplateContext(aType: Type, inTpl: => TemplateImpl, dclSym: Symbol): TypeEntity = {
+ def makeTypeInTemplateContext(aType: Type, inTpl: TemplateImpl, dclSym: Symbol): TypeEntity = {
def ownerTpl(sym: Symbol): Symbol =
if (sym.isClass || sym.isModule || sym == NoSymbol) sym else ownerTpl(sym.owner)
val tpe =
@@ -620,10 +727,10 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
}
/** */
- def makeType(aType: Type, inTpl: => TemplateImpl): TypeEntity = {
+ def makeType(aType: Type, inTpl: TemplateImpl): TypeEntity = {
def templatePackage = closestPackage(inTpl.sym)
- new TypeEntity {
+ def createTypeEntity = 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 {
@@ -719,23 +826,81 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
val refEntity = refBuffer
val name = optimize(nameBuffer.toString)
}
- }
- def templateShouldDocument(aSym: Symbol): Boolean = {
- // TODO: document sourceless entities (e.g., Any, etc), based on a new Setting to be added
- (aSym.isPackageClass || (aSym.sourceFile != null)) && localShouldDocument(aSym) &&
- ( aSym.owner == NoSymbol || templateShouldDocument(aSym.owner) ) && !isEmptyJavaObject(aSym)
+ if (aType.isTrivial)
+ typeCache.get(aType) match {
+ case Some(typeEntity) => typeEntity
+ case None =>
+ val typeEntity = createTypeEntity
+ typeCache += aType -> typeEntity
+ typeEntity
+ }
+ else
+ createTypeEntity
}
- def isEmptyJavaObject(aSym: Symbol): Boolean = {
- def hasMembers = aSym.info.members.exists(s => localShouldDocument(s) && (!s.isConstructor || s.owner == aSym))
- aSym.isModule && aSym.isJavaDefined && !hasMembers
- }
+ def normalizeOwner(aSym: Symbol): Symbol =
+ /*
+ * Okay, here's the explanation of what happens. The code:
+ *
+ * package foo {
+ * object `package` {
+ * class Bar
+ * }
+ * }
+ *
+ * will yield this Symbol structure:
+ *
+ * +---------------+ +--------------------------+
+ * | package foo#1 ----(1)---> module class foo#2 |
+ * +---------------+ | +----------------------+ | +-------------------------+
+ * | | package object foo#3 ------(1)---> module class package#4 |
+ * | +----------------------+ | | +---------------------+ |
+ * +--------------------------+ | | class package$Bar#5 | |
+ * | +---------------------+ |
+ * +-------------------------+
+ * (1) sourceModule
+ * (2) you get out of owners with .owner
+ */
+ normalizeTemplate(aSym) match {
+ case bSym if bSym.isPackageObject =>
+ normalizeOwner(bSym.owner)
+ case bSym =>
+ bSym
+ }
- def localShouldDocument(aSym: Symbol): Boolean = {
+ def inOriginalOnwer(aSym: Symbol, inTpl: TemplateImpl): Boolean =
+ normalizeOwner(aSym.owner) == normalizeOwner(inTpl.sym)
+
+ def templateShouldDocument(aSym: Symbol, inTpl: TemplateImpl): Boolean =
+ (aSym.isClass || aSym.isModule || aSym == AnyRefClass) &&
+ localShouldDocument(aSym) &&
+ !isEmptyJavaObject(aSym) &&
+ // either it's inside the original owner or we can document it later:
+ (!inOriginalOnwer(aSym, inTpl) || (aSym.isPackageClass || (aSym.sourceFile != null)))
+
+ def membersShouldDocument(sym: Symbol, inTpl: TemplateImpl) =
+ // pruning modules that shouldn't be documented
+ // Why Symbol.isInitialized? Well, because we need to avoid exploring all the space available to scaladoc
+ // from the classpath -- scaladoc is a hog, it will explore everything starting from the root package unless we
+ // somehow prune the tree. And isInitialized is a good heuristic for prunning -- if the package was not explored
+ // during typer and refchecks, it's not necessary for the current application and there's no need to explore it.
+ (!sym.isModule || sym.moduleClass.isInitialized) &&
+ // documenting only public and protected members
+ localShouldDocument(sym) &&
+ // Only this class's constructors are part of its members, inherited constructors are not.
+ (!sym.isConstructor || sym.owner == inTpl.sym) &&
+ // If the @bridge annotation overrides a normal member, show it
+ !isPureBridge(sym)
+
+ def isEmptyJavaObject(aSym: Symbol): Boolean =
+ aSym.isModule && aSym.isJavaDefined &&
+ aSym.info.members.exists(s => localShouldDocument(s) && (!s.isConstructor || s.owner == aSym))
+
+ def localShouldDocument(aSym: Symbol): Boolean =
!aSym.isPrivate && (aSym.isProtected || aSym.privateWithin == NoSymbol) && !aSym.isSynthetic
- }
/** Filter '@bridge' methods only if *they don't override non-bridge methods*. See SI-5373 for details */
def isPureBridge(sym: Symbol) = sym.isBridge && sym.allOverriddenSymbols.forall(_.isBridge)
}
+
diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala
index c3525037cd..2a0fcea0ea 100644
--- a/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala
@@ -58,6 +58,7 @@ trait ModelFactoryImplicitSupport {
import global._
import global.analyzer._
import global.definitions._
+ import rootMirror.{RootPackage, RootClass, EmptyPackage, EmptyPackageClass}
import settings.hardcoded
// debugging:
@@ -96,13 +97,7 @@ trait ModelFactoryImplicitSupport {
def targetType: TypeEntity = makeType(toType, inTpl)
- def convertorOwner: TemplateEntity =
- if (convSym != NoSymbol)
- makeTemplate(convSym.owner)
- else {
- error("Scaladoc implicits: Implicit conversion from " + sym.tpe + " to " + toType + " done by " + convSym + " = NoSymbol!")
- makeRootPackage.get // surely the root package was created :)
- }
+ def convertorOwner: TemplateEntity = makeTemplate(convSym.owner)
def convertorMethod: Either[MemberEntity, String] = {
var convertor: MemberEntity = null
@@ -122,11 +117,11 @@ trait ModelFactoryImplicitSupport {
def conversionShortName = convSym.nameString
- def conversionQualifiedName = convertorOwner.qualifiedName + "." + convSym.nameString
+ def conversionQualifiedName = makeQualifiedName(convSym)
lazy val constraints: List[Constraint] = constrs
- val members: List[MemberEntity] = {
+ val members: List[MemberImpl] = {
// Obtain the members inherited by the implicit conversion
var memberSyms = toType.members.filter(implicitShouldDocument(_))
val existingMembers = sym.info.members
@@ -162,7 +157,7 @@ trait ModelFactoryImplicitSupport {
* default Scala imports (Predef._ for example) and the companion object of the current class, if one exists. In the
* future we might want to extend this to more complex scopes.
*/
- def makeImplicitConversions(sym: Symbol, inTpl: => DocTemplateImpl): List[ImplicitConversion] =
+ def makeImplicitConversions(sym: Symbol, inTpl: => DocTemplateImpl): List[ImplicitConversionImpl] =
// Nothing and Null are somewhat special -- they can be transformed by any implicit conversion available in scope.
// But we don't want that, so we'll simply refuse to find implicit conversions on for Nothing and Null
if (!(sym.isClass || sym.isTrait || sym == AnyRefClass) || sym == NothingClass || sym == NullClass) Nil
@@ -218,7 +213,7 @@ trait ModelFactoryImplicitSupport {
* - we also need to transform implicit parameters in the view's signature into constraints, such that Numeric[T4]
* appears as a constraint
*/
- def makeImplicitConversion(sym: Symbol, result: SearchResult, constrs: List[TypeConstraint], context: Context, inTpl: => DocTemplateImpl): List[ImplicitConversion] =
+ def makeImplicitConversion(sym: Symbol, result: SearchResult, constrs: List[TypeConstraint], context: Context, inTpl: => DocTemplateImpl): List[ImplicitConversionImpl] =
if (result.tree == EmptyTree) Nil
else {
// `result` will contain the type of the view (= implicit conversion method)
@@ -280,7 +275,7 @@ trait ModelFactoryImplicitSupport {
types.flatMap((tpe:Type) => {
// TODO: Before creating constraints, map typeVarToOriginOrWildcard on the implicitTypes
val implType = typeVarToOriginOrWildcard(tpe)
- val qualifiedName = implType.typeSymbol.ownerChain.reverse.map(_.nameString).mkString(".")
+ val qualifiedName = makeQualifiedName(implType.typeSymbol)
var available: Option[Boolean] = None
@@ -333,20 +328,20 @@ trait ModelFactoryImplicitSupport {
case Some(explanation) =>
List(new KnownTypeClassConstraint {
val typeParamName = targ.nameString
- val typeExplanation = explanation
- val typeClassEntity = makeTemplate(sym)
- val implicitType: TypeEntity = makeType(implType, inTpl)
+ lazy val typeExplanation = explanation
+ lazy val typeClassEntity = makeTemplate(sym)
+ lazy val implicitType: TypeEntity = makeType(implType, inTpl)
})
case None =>
List(new TypeClassConstraint {
val typeParamName = targ.nameString
- val typeClassEntity = makeTemplate(sym)
- val implicitType: TypeEntity = makeType(implType, inTpl)
+ lazy val typeClassEntity = makeTemplate(sym)
+ lazy val implicitType: TypeEntity = makeType(implType, inTpl)
})
}
case _ =>
List(new ImplicitInScopeConstraint{
- val implicitType: TypeEntity = makeType(implType, inTpl)
+ lazy val implicitType: TypeEntity = makeType(implType, inTpl)
})
}
}
@@ -372,23 +367,23 @@ trait ModelFactoryImplicitSupport {
case (List(lo), List(up)) if (lo == up) =>
List(new EqualTypeParamConstraint {
val typeParamName = tparam.nameString
- val rhs = makeType(lo, inTpl)
+ lazy val rhs = makeType(lo, inTpl)
})
case (List(lo), List(up)) =>
List(new BoundedTypeParamConstraint {
val typeParamName = tparam.nameString
- val lowerBound = makeType(lo, inTpl)
- val upperBound = makeType(up, inTpl)
+ lazy val lowerBound = makeType(lo, inTpl)
+ lazy val upperBound = makeType(up, inTpl)
})
case (List(lo), Nil) =>
List(new LowerBoundedTypeParamConstraint {
val typeParamName = tparam.nameString
- val lowerBound = makeType(lo, inTpl)
+ lazy val lowerBound = makeType(lo, inTpl)
})
case (Nil, List(up)) =>
List(new UpperBoundedTypeParamConstraint {
val typeParamName = tparam.nameString
- val upperBound = makeType(up, inTpl)
+ lazy val upperBound = makeType(up, inTpl)
})
case other =>
// this is likely an error on the lub/glb side
@@ -399,6 +394,11 @@ trait ModelFactoryImplicitSupport {
}
}
+ def makeQualifiedName(sym: Symbol): String = {
+ val remove = Set[Symbol](RootPackage, RootClass, EmptyPackage, EmptyPackageClass)
+ sym.ownerChain.filterNot(remove.contains(_)).reverse.map(_.nameString).mkString(".")
+ }
+
/**
* uniteConstraints takes a TypeConstraint instance and simplifies the constraints inside
*
diff --git a/src/compiler/scala/tools/nsc/doc/model/TreeFactory.scala b/src/compiler/scala/tools/nsc/doc/model/TreeFactory.scala
index fe586c4996..bd7534ded4 100755
--- a/src/compiler/scala/tools/nsc/doc/model/TreeFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/TreeFactory.scala
@@ -52,7 +52,7 @@ trait TreeFactory { thisTreeFactory: ModelFactory with TreeFactory =>
if (asym.isSetter) asym = asym.getter(asym.owner)
makeTemplate(asym.owner) match {
case docTmpl: DocTemplateImpl =>
- val mbrs: List[MemberImpl] = makeMember(asym, null, docTmpl)
+ val mbrs: Option[MemberImpl] = findMember(asym, docTmpl)
mbrs foreach { mbr => refs += ((start, (mbr,end))) }
case _ =>
}
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 996223b9f9..c749d30267 100644
--- a/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala
@@ -733,8 +733,8 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory =>
nextChar()
}
- /**
- * Eliminates the (common) leading spaces in all lines, based on the first line
+ /**
+ * Eliminates the (common) leading spaces in all lines, based on the first line
* For indented pieces of code, it reduces the indent to the least whitespace prefix:
* {{{
* indented example
@@ -757,11 +757,11 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory =>
while (index < code.length) {
code(index) match {
case ' ' =>
- if (wsArea)
+ if (wsArea)
crtSkip += 1
case c =>
wsArea = (c == '\n')
- maxSkip = if (firstLine || emptyLine) maxSkip else if (maxSkip <= crtSkip) maxSkip else crtSkip
+ maxSkip = if (firstLine || emptyLine) maxSkip else if (maxSkip <= crtSkip) maxSkip else crtSkip
crtSkip = if (c == '\n') 0 else crtSkip
firstLine = if (c == '\n') false else firstLine
emptyLine = if (c == '\n') true else false