Changed the way use cases are handled in scaladoc.

If use cases are present, the original member disappears from the list. References SI-5054, but needs more work on the html part.
If use cases are present along with links, scaladoc doesn't crash anymore. Closes SI-4898.
    
Review by kzys.


git-svn-id: http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk@26048 5e8d7ff9-d8ef-0310-90f0-a4852d11357a
This commit is contained in:
ureche 2011-11-22 19:09:28 +00:00
parent 4659eb0fa1
commit a64ac8eb39
5 changed files with 55 additions and 3 deletions

View File

@ -301,6 +301,10 @@ trait NonTemplateMemberEntity extends MemberEntity {
* It corresponds to a real member, and provides a simplified, yet compatible signature for that member. */ * It corresponds to a real member, and provides a simplified, yet compatible signature for that member. */
def isUseCase: Boolean def isUseCase: Boolean
/** If this symbol is a use case, the useCaseOf will contain the member it was derived from, containing the full
* signature and the complete parameter descriptions. */
def useCaseOf: Option[MemberEntity]
/** Whether this member is a bridge member. A bridge member does only exist for binary compatibility reasons /** Whether this member is a bridge member. A bridge member does only exist for binary compatibility reasons
* and should not appear in ScalaDoc. */ * and should not appear in ScalaDoc. */
def isBridge: Boolean def isBridge: Boolean

View File

@ -453,16 +453,18 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
/** */ /** */
def makeMember(aSym: Symbol, inTpl: => DocTemplateImpl): List[MemberImpl] = { def makeMember(aSym: Symbol, inTpl: => DocTemplateImpl): List[MemberImpl] = {
def makeMember0(bSym: Symbol): Option[MemberImpl] = { def makeMember0(bSym: Symbol, _useCaseOf: Option[MemberImpl]): Option[MemberImpl] = {
if (bSym.isGetter && bSym.isLazy) if (bSym.isGetter && bSym.isLazy)
Some(new NonTemplateMemberImpl(bSym, inTpl) with Val { Some(new NonTemplateMemberImpl(bSym, inTpl) with Val {
override lazy val comment = // The analyser does not duplicate the lazy val's DocDef when it introduces its accessor. 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) // This hack should be removed after analyser is fixed.
override def isLazyVal = true override def isLazyVal = true
override def useCaseOf = _useCaseOf
}) })
else if (bSym.isGetter && bSym.accessed.isMutable) else if (bSym.isGetter && bSym.accessed.isMutable)
Some(new NonTemplateMemberImpl(bSym, inTpl) with Val { Some(new NonTemplateMemberImpl(bSym, inTpl) with Val {
override def isVar = true override def isVar = true
override def useCaseOf = _useCaseOf
}) })
else if (bSym.isMethod && !bSym.hasAccessorFlag && !bSym.isConstructor && !bSym.isModule) { else if (bSym.isMethod && !bSym.hasAccessorFlag && !bSym.isConstructor && !bSym.isModule) {
val cSym = { // This unsightly hack closes issue #4086. val cSym = { // This unsightly hack closes issue #4086.
@ -478,25 +480,30 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
} }
Some(new NonTemplateParamMemberImpl(cSym, inTpl) with HigherKindedImpl with Def { Some(new NonTemplateParamMemberImpl(cSym, inTpl) with HigherKindedImpl with Def {
override def isDef = true override def isDef = true
override def useCaseOf = _useCaseOf
}) })
} }
else if (bSym.isConstructor) else if (bSym.isConstructor)
Some(new NonTemplateParamMemberImpl(bSym, inTpl) with Constructor { Some(new NonTemplateParamMemberImpl(bSym, inTpl) with Constructor {
override def isConstructor = true override def isConstructor = true
def isPrimary = sym.isPrimaryConstructor def isPrimary = sym.isPrimaryConstructor
override def useCaseOf = _useCaseOf
}) })
else if (bSym.isGetter) // Scala field accessor or Java field else if (bSym.isGetter) // Scala field accessor or Java field
Some(new NonTemplateMemberImpl(bSym, inTpl) with Val { Some(new NonTemplateMemberImpl(bSym, inTpl) with Val {
override def isVal = true override def isVal = true
override def useCaseOf = _useCaseOf
}) })
else if (bSym.isAbstractType) else if (bSym.isAbstractType)
Some(new NonTemplateMemberImpl(bSym, inTpl) with TypeBoundsImpl with HigherKindedImpl with AbstractType { Some(new NonTemplateMemberImpl(bSym, inTpl) with TypeBoundsImpl with HigherKindedImpl with AbstractType {
override def isAbstractType = true override def isAbstractType = true
override def useCaseOf = _useCaseOf
}) })
else if (bSym.isAliasType) else if (bSym.isAliasType)
Some(new NonTemplateMemberImpl(bSym, inTpl) with HigherKindedImpl with AliasType { Some(new NonTemplateMemberImpl(bSym, inTpl) with HigherKindedImpl with AliasType {
override def isAliasType = true override def isAliasType = true
def alias = makeTypeInTemplateContext(sym.tpe.dealias, inTpl, sym) def alias = makeTypeInTemplateContext(sym.tpe.dealias, inTpl, sym)
override def useCaseOf = _useCaseOf
}) })
else if (bSym.isPackage) else if (bSym.isPackage)
inTpl match { case inPkg: PackageImpl => makePackage(bSym, inPkg) } inTpl match { case inPkg: PackageImpl => makePackage(bSym, inPkg) }
@ -510,9 +517,16 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
Nil Nil
else { else {
val allSyms = useCases(aSym, inTpl.sym) map { case (bSym, bComment, bPos) => val allSyms = useCases(aSym, inTpl.sym) map { case (bSym, bComment, bPos) =>
addCommentBody(bSym, inTpl, bComment, bPos) docComments.put(bSym, DocComment(bComment, bPos)) // put the comment in the list, don't parse it yet, closes SI-4898
bSym
} }
(allSyms :+ aSym) flatMap { makeMember0(_) }
val member = makeMember0(aSym, None)
if (allSyms.isEmpty)
member.toList
else
// Use cases replace the original definitions - SI-5054
allSyms flatMap { makeMember0(_, member) }
} }
} }

View File

@ -0,0 +1,9 @@
class SI_4898 {
/**
* A link to [[__root__
*
* @usecase def test(): Int
*/
def test(implicit param: Int): Int = param
}

View File

@ -0,0 +1,10 @@
class SI_5054 {
/**
* A simple comment
*
* @param lost a lost parameter
* @usecase def test(): Int
*/
def test(implicit lost: Int): Int = lost
}

View File

@ -373,6 +373,21 @@ object Test extends Properties("HtmlFactory") {
} }
} }
property("Use cases and links should not crash scaladoc") = {
createTemplate("SI_4898.scala")
true
}
property("Use cases should override their original members - valid until signature is added to html") = {
createTemplate("SI_5054.scala") match {
case node: scala.xml.Node =>
node.toString.contains("A simple comment") &&
! node.toString.contains("a lost parameter")
case _ => false
}
}
{ {
val files = createTemplates("basic.scala") val files = createTemplates("basic.scala")
println(files) println(files)