diff options
Diffstat (limited to 'src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala | 325 |
1 files changed, 167 insertions, 158 deletions
diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala index f935dd4478..3968d3483c 100644 --- a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala @@ -9,51 +9,37 @@ import comment._ import scala.collection._ import symtab.Flags -import util.Position + +import model.{ RootPackage => RootPackageEntity } /** This trait extracts all required information for documentation from compilation units */ -class ModelFactory(val global: Global, val settings: doc.Settings) { extractor => +class ModelFactory(val global: Global, val settings: doc.Settings) extends CommentFactory { thisFactory => import global._ - import definitions.{ ObjectClass, ScalaObjectClass, RootPackage, EmptyPackage } + import definitions.{ ObjectClass, ScalaObjectClass, RootPackage, EmptyPackage, NothingClass, AnyClass, AnyRefClass } private var droppedPackages = 0 def templatesCount = templatesCache.size - droppedPackages - /** */ - def makeModel: Package = - makePackage(RootPackage, null) getOrElse { throw new Error("no documentable class found in compilation units") } - - object commentator { - - private val factory = new CommentFactory(reporter) - - private val commentCache = mutable.HashMap.empty[(Symbol, TemplateImpl), Comment] - - def registeredUseCase(sym: Symbol, inTpl: => TemplateImpl, docStr: String, docPos: Position): Symbol = { - commentCache += (sym, inTpl) -> factory.parse(docStr, docPos) - sym - } - - def comment(sym: Symbol, inTpl: => DocTemplateImpl): Option[Comment] = { - val key = (sym, inTpl) - if (commentCache isDefinedAt key) - Some(commentCache(key)) - else { // not reached for use-case comments - val rawComment = expandedDocComment(sym, inTpl.sym) - if (rawComment == "") None else { - val c = factory.parse(rawComment, docCommentPos(sym)) - commentCache += (sym, inTpl) -> c - Some(c) - } - } - } + private var modelFinished = false + /** */ + def makeModel: Universe = { + val rootPackage = + makeRootPackage getOrElse { throw new Error("no documentable class found in compilation units") } + val universe = new Universe(settings, rootPackage) + modelFinished = true + universe } /** */ 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") + templatesCache.values find { tpl => tpl.qualifiedName == query && !tpl.isObject } + } def optimize(str: String): String = if (str.length < 16) str.intern else str @@ -88,44 +74,47 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { extractor = /** Provides a default implementation for instances of the `MemberEntity` type. It must be instantiated as a * `SymbolicEntity` to access the compiler symbol that underlies the entity. */ abstract class MemberImpl(sym: Symbol, inTpl: => DocTemplateImpl) extends EntityImpl(sym, inTpl) with MemberEntity { - val comment = - if (inTpl == null) None else commentator.comment(sym, inTpl) + lazy val comment = + if (inTpl == null) None else thisFactory.comment(sym, inTpl) override def inTemplate = inTpl override def toRoot: List[MemberImpl] = this :: inTpl.toRoot def inDefinitionTemplates = if (inTpl == null) - makePackage(RootPackage, null).toList - else if (sym.owner == inTpl.sym) - inTpl :: Nil + makeRootPackage.toList 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.isPrivateLocal) PrivateInInstance() + else if (sym.isProtectedLocal) 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.isPrivate) PrivateInTemplate(inTpl) + else if (sym.isProtected) 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] - if (sym hasFlag Flags.IMPLICIT) fgs += Paragraph(Text("implicit")) + if (sym.isImplicit) fgs += Paragraph(Text("implicit")) if (sym hasFlag Flags.SEALED) fgs += Paragraph(Text("sealed")) if (!sym.isTrait && (sym hasFlag Flags.ABSTRACT)) fgs += Paragraph(Text("abstract")) if (!sym.isTrait && (sym hasFlag Flags.DEFERRED)) fgs += Paragraph(Text("abstract")) if (!sym.isModule && (sym hasFlag Flags.FINAL)) fgs += Paragraph(Text("final")) fgs.toList } + def deprecation = + if (sym.isDeprecated) + Some(sym.deprecationMessage map (x => parseWiki(x, NoPosition)) getOrElse Body(Nil)) + else + comment flatMap (_.deprecated) + def inheritedFrom = if (inTemplate.sym == this.sym.owner || inTemplate.sym.isPackage) Nil else makeTemplate(this.sym.owner) :: (sym.allOverriddenSymbols map { os => makeTemplate(os.owner) }) - def isDeprecated = sym.isDeprecated def resultType = makeType(sym.tpe.finalResultType, inTemplate, sym) def isDef = false def isVal = false @@ -146,10 +135,22 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { extractor = * * 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 = { + def fixPath(s: String) = s.replaceAll("\\" + java.io.File.separator, "/") + val assumedSourceRoot: String = { + val fixed = fixPath(settings.sourcepath.value) + if (fixed endsWith "/") fixed.dropRight(1) else fixed + } + if (!settings.docsourceurl.isDefault) + inSource map { case (file, _) => + new java.net.URL(settings.docsourceurl.value + "/" + fixPath(file.path).replaceFirst("^" + assumedSourceRoot, "")) + } + else None + } def typeParams = if (sym.isClass) sym.typeParams map (makeTypeParam(_, this)) else Nil def parentType = if (sym.isPackage) None else @@ -161,7 +162,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { extractor = case _ => } } - sym.ancestors filter (_ != ScalaObjectClass) map (makeTemplate(_)) + sym.ancestors filter (_ != ScalaObjectClass) map makeTemplate } private lazy val subClassesCache = mutable.Buffer.empty[DocTemplateEntity] def registerSubClass(sc: DocTemplateEntity) = { @@ -169,16 +170,18 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { extractor = subClassesCache += sc } def subClasses = subClassesCache.toList - protected def memberSyms = sym.info.nonPrivateMembers - val members: List[MemberEntity] = memberSyms flatMap (makeMember(_, this)) - val templates = members partialMap { case c: DocTemplateEntity => c } - val methods = members partialMap { case d: Def => d } - val values = members partialMap { case v: Val => v } - val abstractTypes = members partialMap { case t: AbstractType => t } - val aliasTypes = members partialMap { case t: AliasType => t } + protected 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)) + val members = memberSyms flatMap (makeMember(_, this)) + 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 def isDocTemplate = true - def companion = sym.linkedSym match { + def companion = sym.companionSymbol match { case NoSymbol => None case comSym => Some(makeDocTemplate(comSym, inTpl)) } @@ -187,49 +190,61 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { extractor = abstract class PackageImpl(sym: Symbol, inTpl: => PackageImpl) extends DocTemplateImpl(sym, inTpl) with Package { override def inTemplate = inTpl override def toRoot: List[PackageImpl] = this :: inTpl.toRoot - val packages = members partialMap { case p: Package => p } + val packages = members collect { case p: Package => p } } + abstract class RootPackageImpl(sym: Symbol) extends PackageImpl(sym, null) with RootPackageEntity + 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 { override def inTemplate = inTpl } + private trait StdTypeBounds extends EntityImpl { + def lo = sym.info.normalize match { + case TypeBounds(lo, hi) if lo.typeSymbol != NothingClass => Some(makeType(lo, inTemplate, sym)) + case _ => None + } + def hi = sym.info.normalize match { + case TypeBounds(lo, hi) if hi.typeSymbol != AnyClass => Some(makeType(hi, inTemplate, sym)) + case _ => None + } + } + /* ============== MAKER METHODS ============== */ /** */ - def normalizeTemplate(aSym: Symbol): Symbol = { - if (aSym == null || aSym == EmptyPackage || aSym == NoSymbol) - normalizeTemplate(RootPackage) - else if (aSym == ScalaObjectClass || aSym == ObjectClass) - normalizeTemplate(definitions.AnyRefClass) - else if (aSym.isModuleClass || aSym.isPackageObject) - normalizeTemplate(aSym.sourceModule) - else - aSym + def normalizeTemplate(aSym: Symbol): Symbol = aSym match { + case null | EmptyPackage | NoSymbol => normalizeTemplate(RootPackage) + case ScalaObjectClass | ObjectClass => normalizeTemplate(AnyRefClass) + case _ if aSym.isModuleClass || aSym.isPackageObject => normalizeTemplate(aSym.sourceModule) + case _ => aSym } + def makeRootPackage: Option[PackageImpl] = + makePackage(RootPackage, null) + /** Creates a package entity for the given symbol or returns `None` if the symbol does not denote a package that * contains at least one ''documentable'' class, trait or object. Creating a package entity */ def makePackage(aSym: Symbol, inTpl: => PackageImpl): Option[PackageImpl] = { val bSym = normalizeTemplate(aSym) - if (templatesCache isDefinedAt (bSym, inTpl)) - Some(templatesCache(bSym, inTpl) match {case p: PackageImpl => p}) + if (templatesCache isDefinedAt (bSym)) + Some(templatesCache(bSym) match {case p: PackageImpl => p}) else { val pack = if (bSym == RootPackage) - new PackageImpl(bSym, null) { + new RootPackageImpl(bSym) { 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 protected def memberSyms = + override protected lazy val memberSyms = (bSym.info.members ++ EmptyPackage.info.members) filter { s => s != EmptyPackage && s != RootPackage } @@ -249,52 +264,48 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { extractor = 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 = - members partialMap { case d: Constructor => d } - def primaryConstructor = (constructors find (_.isPrimary)) + members collect { case d: Constructor => d } + def primaryConstructor = constructors find (_.isPrimary) def isCaseClass = sym.isClass && sym.hasFlag(Flags.CASE) } else @@ -303,78 +314,69 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { extractor = /** */ def makeMember(aSym: Symbol, inTpl: => DocTemplateImpl): List[MemberImpl] = { + def makeMember0(bSym: Symbol): Option[MemberImpl] = { - if (bSym.isGetter && (bSym.accessed hasFlag Flags.MUTABLE)) - Some(new NonTemplateMemberImpl(bSym, inTpl) with Val { + abstract class MakeMemberTemplateImpl extends NonTemplateMemberImpl(bSym, inTpl) { + def isUseCase = bSym.isSynthetic + } + trait MethodParams extends MakeMemberTemplateImpl { + def valueParams = + sym.paramss map { ps => + ps.zipWithIndex map { case (p, i) => + if (p.nameString contains "$") makeValueParam(p, inTemplate, optimize("arg" + i)) + else makeValueParam(p, inTemplate) + } + } + } + + if (bSym.isGetter && bSym.accessed.isMutable) + Some(new MakeMemberTemplateImpl with Val { override def isVar = true - def isUseCase = bSym hasFlag Flags.SYNTHETIC }) - else if (bSym.isMethod && !(bSym hasFlag Flags.ACCESSOR) && !bSym.isConstructor && !(bSym hasFlag Flags.FINAL)) - Some(new NonTemplateMemberImpl(bSym, inTpl) with Def { + else if (bSym.isMethod && !bSym.isGetterOrSetter && !bSym.isConstructor) + Some(new MakeMemberTemplateImpl with Def with MethodParams { override def isDef = true - def isUseCase = bSym hasFlag Flags.SYNTHETIC def typeParams = sym.tpe.typeParams map (makeTypeParam(_, inTpl)) - def valueParams = - sym.paramss map { ps => (ps.zipWithIndex) map { case (p, i) => - if (p.nameString contains "$") makeValueParam(p, inTpl, optimize("arg" + i)) else makeValueParam(p, inTpl) - }} }) else if (bSym.isConstructor) - Some(new NonTemplateMemberImpl(bSym, inTpl) with Constructor { + Some(new MakeMemberTemplateImpl with Constructor with MethodParams { override def isConstructor = true - def isUseCase = bSym hasFlag Flags.SYNTHETIC def isPrimary = sym.isPrimaryConstructor - def valueParams = - sym.paramss map { ps => (ps.zipWithIndex) map { case (p, i) => - if (p.nameString contains "$") makeValueParam(p, inTpl, optimize("arg" + i)) else makeValueParam(p, inTpl) - }} }) else if (bSym.isGetter) // Scala field accessor or Java field - Some(new NonTemplateMemberImpl(bSym, inTpl) with Val { + Some(new MakeMemberTemplateImpl with Val { override def isVal = true - def isUseCase = bSym hasFlag Flags.SYNTHETIC }) else if (bSym.isAbstractType) - Some(new NonTemplateMemberImpl(bSym, inTpl) with AbstractType { + Some(new MakeMemberTemplateImpl with AbstractType with StdTypeBounds { override def isAbstractType = true - def isUseCase = bSym hasFlag Flags.SYNTHETIC - def lo = sym.info.normalize match { - case TypeBounds(lo, hi) if lo.typeSymbol != definitions.NothingClass => Some(makeType(lo, inTpl, sym)) - case _ => None - } - def hi = sym.info.normalize match { - case TypeBounds(lo, hi) if hi.typeSymbol != definitions.AnyClass => Some(makeType(hi, inTpl, sym)) - case _ => None - } }) else if (bSym.isAliasType) - Some(new NonTemplateMemberImpl(bSym, inTpl) with AliasType { + Some(new MakeMemberTemplateImpl with AliasType { override def isAliasType = true - def isUseCase = bSym hasFlag Flags.SYNTHETIC def alias = makeType(sym.tpe, inTpl, sym) }) else if (bSym.isPackage) inTpl match { case inPkg: PackageImpl => makePackage(bSym, inPkg) } - else if ((bSym.isClass || bSym.isModule) && (bSym.sourceFile != null) && 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.isPublic || (aSym hasFlag Flags.SYNTHETIC) || (aSym hasFlag Flags.BRIDGE) || 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) => - commentator.registeredUseCase(bSym, inTpl, bComment, bPos) + addCommentBody(bSym, inTpl, bComment, bPos) } - (allSyms ::: List(aSym)) flatMap (makeMember0(_)) + (allSyms :+ aSym) flatMap makeMember0 } } /** */ def makeTypeParam(aSym: Symbol, inTpl: => DocTemplateImpl): TypeParam = { - new ParameterImpl(aSym, inTpl) with TypeParam { + new ParameterImpl(aSym, inTpl) with TypeParam with StdTypeBounds { def isTypeParam = true def isValueParam = false def variance: String = { @@ -382,16 +384,6 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { extractor = else if (sym hasFlag Flags.CONTRAVARIANT) "-" else "" } - def lo = sym.info.normalize match { - case TypeBounds(lo, hi) if lo.typeSymbol != definitions.NothingClass => - Some(makeType(lo, inTpl, sym)) - case _ => None - } - def hi = sym.info.normalize match { - case TypeBounds(lo, hi) if hi.typeSymbol != definitions.AnyClass => - Some(makeType(hi, inTpl, sym)) - case _ => None - } } } @@ -401,16 +393,27 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { extractor = } /** */ - 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 resultType = { + def defaultValue = + if (aSym.hasDefault) + // units.filter should return only one element + (currentRun.units filter (_.source.file == aSym.sourceFile)).toList match { + case List(unit) => + (unit.body find (_.symbol == aSym)) match { + case Some(ValDef(_,_,_,rhs)) => Some(rhs.toString) + case _ => None + } + case _ => None + } + else None + def resultType = makeType(sym.tpe, inTpl, sym) - } + def isImplicit = aSym.isImplicit } - } /** */ def makeType(aType: Type, seeInTpl: => TemplateImpl, dclSym: Symbol): TypeEntity = { @@ -452,7 +455,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { extractor = nameBuffer append ')' case TypeRef(pre, aSym, targs) => val bSym = normalizeTemplate(aSym) - if (bSym.isTypeMember) + if (bSym.isNonClassType) nameBuffer append bSym.name else { val tpl = makeTemplate(bSym) @@ -489,4 +492,10 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { extractor = 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.isPrivate && (aSym.isProtected || aSym.privateWithin == NoSymbol) && !aSym.isSynthetic } |