summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGilles Dubochet <gilles.dubochet@epfl.ch>2010-07-06 16:07:31 +0000
committerGilles Dubochet <gilles.dubochet@epfl.ch>2010-07-06 16:07:31 +0000
commitc66d3b0d445bdb96cb363a1bf492672aff3bdcf0 (patch)
treea09f3322d5d3ccfdf5605a22401f9ce714c3da7c
parent8a2c52b105e49045dbd3bc11888351452cc4fbb3 (diff)
downloadscala-c66d3b0d445bdb96cb363a1bf492672aff3bdcf0.tar.gz
scala-c66d3b0d445bdb96cb363a1bf492672aff3bdcf0.tar.bz2
scala-c66d3b0d445bdb96cb363a1bf492672aff3bdcf0.zip
[scaladoc] Implements documentation of higher-k...
[scaladoc] Implements documentation of higher-kinded entities. Closes #3618. Review by moors.
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/page/Template.scala37
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/Entity.scala22
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala60
3 files changed, 63 insertions, 56 deletions
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 a43c89adad..06a2aaee6b 100644
--- a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
@@ -349,7 +349,7 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage {
case None => NodeSeq.Empty
case Some(tpe) => xml.Text(pre) ++ typeToHtml(tpe, hasLinks)
}
- bound0(hi, " <: ") ++ bound0(lo, " >: ")
+ bound0(lo, " >: ") ++ bound0(hi, " <: ")
}
def visibility(mbr: MemberEntity): Option[comment.Paragraph] = {
@@ -379,23 +379,25 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage {
<xml:group>
<span class="kind">{ kindToString(mbr) }</span>
<span class="symbol">
- <span class={"name" + (if (mbr.deprecation.isDefined) " deprecated" else "") }>{ if (mbr.isConstructor) tpl.name else mbr.name }</span>{
- def tparamsToHtml(tpss: List[TypeParam]): NodeSeq =
- if (tpss.isEmpty) NodeSeq.Empty else {
- def tparam0(tp: TypeParam): NodeSeq =
- <span name={ tp.name }>{ tp.variance + tp.name }{ boundsToHtml(tp.hi, tp.lo, hasLinks)}</span>
- def tparams0(tpss: List[TypeParam]): NodeSeq = (tpss: @unchecked) match {
- case tp :: Nil => tparam0(tp)
- case tp :: tps => tparam0(tp) ++ Text(", ") ++ tparams0(tps)
+ <span class={"name" + (if (mbr.deprecation.isDefined) " deprecated" else "") }>{ if (mbr.isConstructor) tpl.name else mbr.name }</span>
+ {
+ def tparamsToHtml(mbr: Entity): NodeSeq = mbr match {
+ case hk: HigherKinded =>
+ val tpss = hk.typeParams
+ if (tpss.isEmpty) NodeSeq.Empty else {
+ def tparam0(tp: TypeParam): NodeSeq =
+ <span name={ tp.name }>{ tp.variance + tp.name }{ tparamsToHtml(tp) }{ boundsToHtml(tp.hi, tp.lo, hasLinks)}</span>
+ def tparams0(tpss: List[TypeParam]): NodeSeq = (tpss: @unchecked) match {
+ case tp :: Nil => tparam0(tp)
+ case tp :: tps => tparam0(tp) ++ Text(", ") ++ tparams0(tps)
+ }
+ <span class="tparams">[{ tparams0(tpss) }]</span>
}
- <span class="tparams">[{ tparams0(tpss) }]</span>
- }
- mbr match {
- case trt: Trait => tparamsToHtml(trt.typeParams)
- case dfe: Def => tparamsToHtml(dfe.typeParams)
- case _ => NodeSeq.Empty
+ case _ => NodeSeq.Empty
}
- }{
+ tparamsToHtml(mbr)
+ }
+ {
def paramsToHtml(vlsss: List[List[ValueParam]]): NodeSeq = {
def param0(vl: ValueParam): NodeSeq =
// notice the }{ in the next lines, they are necessary to avoid a undesired withspace in output
@@ -423,7 +425,8 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage {
case dfe: Def => paramsToHtml(dfe.valueParams)
case _ => NodeSeq.Empty
}
- }{
+ }
+ {
mbr match {
case tpl: DocTemplateEntity if (!tpl.isPackage) =>
tpl.parentType match {
diff --git a/src/compiler/scala/tools/nsc/doc/model/Entity.scala b/src/compiler/scala/tools/nsc/doc/model/Entity.scala
index f36f560777..8c47fd7fbb 100644
--- a/src/compiler/scala/tools/nsc/doc/model/Entity.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/Entity.scala
@@ -19,7 +19,6 @@ trait Entity {
override def toString = qualifiedName
}
-
/** A class, trait, object or package. A package is represented as an instance
* of the `Package` subclass. A class, trait, object or package may be
* directly an instance of `WeakTemplateEntity` if it is not ''documentable''
@@ -61,13 +60,16 @@ trait MemberEntity extends Entity {
def isTemplate: Boolean
}
+trait HigherKinded extends Entity {
+ def typeParams: List[TypeParam]
+}
+
/** A ''documentable'' class, trait or object (that is, a documentation page
* will be generated for it in the current site). */
trait DocTemplateEntity extends TemplateEntity with MemberEntity {
def toRoot: List[DocTemplateEntity]
def inSource: Option[(io.AbstractFile, Int)]
def sourceUrl: Option[java.net.URL]
- def typeParams: List[TypeParam]
def parentType: Option[TypeEntity]
def parentTemplates: List[TemplateEntity]
def linearization: List[TemplateEntity]
@@ -98,12 +100,12 @@ trait DocTemplateEntity extends TemplateEntity with MemberEntity {
}
/** A ''documentable'' trait. */
-trait Trait extends DocTemplateEntity {
+trait Trait extends DocTemplateEntity with HigherKinded {
def valueParams : List[List[ValueParam]]
}
/** A ''documentable'' class. */
-trait Class extends Trait {
+trait Class extends Trait with HigherKinded {
def primaryConstructor: Option[Constructor]
def constructors: List[Constructor]
def isCaseClass: Boolean
@@ -128,8 +130,7 @@ trait NonTemplateMemberEntity extends MemberEntity {
}
/** A method (`def`) of a ''documentable'' class, trait or object. */
-trait Def extends NonTemplateMemberEntity {
- def typeParams: List[TypeParam]
+trait Def extends NonTemplateMemberEntity with HigherKinded {
def valueParams : List[List[ValueParam]]
}
@@ -143,26 +144,23 @@ trait Constructor extends NonTemplateMemberEntity {
trait Val extends NonTemplateMemberEntity
/** An abstract type of a ''documentable'' class, trait or object. */
-trait AbstractType extends NonTemplateMemberEntity {
- // TODO: typeParams
+trait AbstractType extends NonTemplateMemberEntity with HigherKinded {
def lo: Option[TypeEntity]
def hi: Option[TypeEntity]
}
/** An abstract type of a ''documentable'' class, trait or object. */
-trait AliasType extends NonTemplateMemberEntity {
- // TODO: typeParams
+trait AliasType extends NonTemplateMemberEntity with HigherKinded {
def alias: TypeEntity
}
trait ParameterEntity extends Entity {
- def inTemplate: DocTemplateEntity
def isTypeParam: Boolean
def isValueParam: Boolean
}
/** A type parameter to a class or trait or to a method. */
-trait TypeParam extends ParameterEntity {
+trait TypeParam extends ParameterEntity with HigherKinded {
def variance: String
def lo: Option[TypeEntity]
def hi: Option[TypeEntity]
diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
index 72844201ba..218d3158f9 100644
--- a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
@@ -49,7 +49,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory
/** Provides a default implementation for instances of the `Entity` type. */
abstract class EntityImpl(val sym: Symbol, inTpl: => TemplateImpl) extends Entity {
val name = optimize(sym.nameString)
- def inTemplate = inTpl
+ def inTemplate: TemplateImpl = inTpl
def toRoot: List[EntityImpl] = this :: inTpl.toRoot
def qualifiedName = name
}
@@ -57,7 +57,8 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory
/** 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 optimize(inTemplate.qualifiedName + "." + name)
+ override def qualifiedName: String =
+ if (inTemplate.isRootPackage) name else optimize(inTemplate.qualifiedName + "." + name)
def isPackage = sym.isPackage
def isTrait = sym.isTrait
def isClass = sym.isClass && !sym.isTrait
@@ -141,7 +142,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory
* * 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 {
+ abstract class DocTemplateImpl(sym: Symbol, inTpl: => DocTemplateImpl) extends MemberImpl(sym, inTpl) with TemplateImpl with HigherKindedImpl with DocTemplateEntity {
//if (inTpl != null) println("mbr " + sym + " in " + (inTpl.toRoot map (_.sym)).mkString(" > "))
templatesCache += (sym -> this)
lazy val definitionName = optimize(inDefinitionTemplates.head.qualifiedName + "." + name)
@@ -159,11 +160,11 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory
}
else None
}
- def typeParams = if (sym.isClass) sym.typeParams map (makeTypeParam(_, this)) else Nil
def parentTemplates = sym.info.parents map { x: Type => makeTemplate(x.typeSymbol) }
- def parentType =
+ def parentType = {
if (sym.isPackage) None else
- Some(makeType(RefinedType(sym.tpe.parents filter (_ != ScalaObjectClass.tpe), EmptyScope), inTpl))
+ Some(makeType(RefinedType((sym.tpe.parents filter (_ != ScalaObjectClass.tpe)) map { _.asSeenFrom(sym.thisType, sym) }, EmptyScope), inTpl))
+ }
val linearization = {
val tpls = sym.ancestors filter { _ != ScalaObjectClass } map { makeTemplate(_) }
tpls map {
@@ -219,21 +220,28 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory
}}
}
- abstract class ParameterImpl(sym: Symbol, inTpl: => DocTemplateImpl) extends EntityImpl(sym, inTpl) with ParameterEntity {
+ abstract class ParameterImpl(sym: Symbol, inTpl: => TemplateImpl) extends EntityImpl(sym, inTpl) with ParameterEntity {
override def inTemplate = inTpl
}
private trait TypeBoundsImpl extends EntityImpl {
- def lo = sym.info.normalize match {
- case TypeBounds(lo, hi) if lo.typeSymbol != NothingClass => Some(makeType(lo, inTemplate, sym))
+ def lo = sym.info.bounds match {
+ case TypeBounds(lo, hi) if lo.typeSymbol != NothingClass =>
+ Some(makeType(appliedType(lo, sym.info.typeParams map {_.tpe}), inTemplate))
case _ => None
}
- def hi = sym.info.normalize match {
- case TypeBounds(lo, hi) if hi.typeSymbol != AnyClass => Some(makeType(hi, inTemplate, sym))
+ def hi = sym.info.bounds match {
+ case TypeBounds(lo, hi) if hi.typeSymbol != AnyClass =>
+ Some(makeType(appliedType(hi, sym.info.typeParams map {_.tpe}), inTemplate))
case _ => None
}
}
+ trait HigherKindedImpl extends EntityImpl with HigherKinded {
+ def typeParams =
+ sym.typeParams map (makeTypeParam(_, inTemplate))
+ }
+
/* ============== MAKER METHODS ============== */
/** */
@@ -348,10 +356,8 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory
override def isVar = true
})
else if (bSym.isMethod && !bSym.isGetterOrSetter && !bSym.isConstructor && !bSym.isModule)
- Some(new NonTemplateParamMemberImpl(bSym, inTpl) with Def {
+ Some(new NonTemplateParamMemberImpl(bSym, inTpl) with HigherKindedImpl with Def {
override def isDef = true
- def typeParams =
- sym.tpe.typeParams map (makeTypeParam(_, inTpl))
})
else if (bSym.isConstructor)
Some(new NonTemplateParamMemberImpl(bSym, inTpl) with Constructor {
@@ -363,13 +369,13 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory
override def isVal = true
})
else if (bSym.isAbstractType)
- Some(new NonTemplateMemberImpl(bSym, inTpl) with TypeBoundsImpl with AbstractType {
+ Some(new NonTemplateMemberImpl(bSym, inTpl) with TypeBoundsImpl with HigherKindedImpl with AbstractType {
override def isAbstractType = true
})
else if (bSym.isAliasType)
- Some(new NonTemplateMemberImpl(bSym, inTpl) with AliasType {
+ Some(new NonTemplateMemberImpl(bSym, inTpl) with HigherKindedImpl with AliasType {
override def isAliasType = true
- def alias = makeType(sym.tpe, inTpl, sym)
+ def alias = makeType(appliedType(sym.tpe, sym.info.typeParams map {_.tpe}).normalize, inTpl, sym)
})
else if (bSym.isPackage)
inTpl match { case inPkg: PackageImpl => makePackage(bSym, inPkg) }
@@ -391,8 +397,8 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory
}
/** */
- def makeTypeParam(aSym: Symbol, inTpl: => DocTemplateImpl): TypeParam = {
- new ParameterImpl(aSym, inTpl) with TypeBoundsImpl with 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 = {
@@ -401,7 +407,6 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory
else ""
}
}
- }
/** */
def makeValueParam(aSym: Symbol, inTpl: => DocTemplateImpl): ValueParam = {
@@ -452,9 +457,14 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory
nameBuffer append sep
appendTypes0(tps, sep)
}
- private def appendType0(tpe: Type): Unit = tpe.normalize match {
+ private def checkFunctionType(tpe: TypeRef): Boolean = {
+ val TypeRef(_, sym, args) = tpe
+ (args.length > 0) && (args.length - 1 <= definitions.MaxFunctionArity) &&
+ (sym == definitions.FunctionClass(args.length - 1))
+ }
+ private def appendType0(tpe: Type): Unit = tpe match {
/* Type refs */
- case tp: TypeRef if (definitions.isFunctionType(tp)) =>
+ case tp: TypeRef if (checkFunctionType(tp)) =>
nameBuffer append '('
appendTypes0(tp.args.init, ", ")
nameBuffer append ") ⇒ "
@@ -492,11 +502,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory
}
/* 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 */
+ throw new Error("Polymorphic type '" + tpe + "' cannot be printed as a type")
case PolyType(tparams, result) if (tparams.isEmpty) =>
nameBuffer append '⇒'
appendType0(result)