From c88f7338882c8ae81f1004407bc8c21b1cbe7b36 Mon Sep 17 00:00:00 2001 From: Eugene Vigdorchik Date: Fri, 26 Apr 2013 16:39:20 +0400 Subject: Improve code style in the Scaladoc implementation. It fixes the following inefficiences or code style violations: - Explicit asInstanceOf calls. - Boxing symbols instead of using plain NoSymbol. - Matching `this` instead of late-binding. --- .../tools/nsc/doc/base/CommentFactoryBase.scala | 14 ++--- .../tools/nsc/doc/base/MemberLookupBase.scala | 14 ++--- .../scala/tools/nsc/doc/model/CommentFactory.scala | 40 +++++-------- .../scala/tools/nsc/doc/model/ModelFactory.scala | 70 ++++++++++------------ .../doc/model/ModelFactoryImplicitSupport.scala | 11 ++-- 5 files changed, 64 insertions(+), 85 deletions(-) (limited to 'src/scaladoc') diff --git a/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala b/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala index ef0a013ff2..cd1d604843 100755 --- a/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala +++ b/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala @@ -22,7 +22,7 @@ import scala.language.postfixOps trait CommentFactoryBase { this: MemberLookupBase => val global: Global - import global.{ reporter, Symbol } + import global.{ reporter, Symbol, NoSymbol } /* Creates comments with necessary arguments */ def createComment ( @@ -186,7 +186,7 @@ trait CommentFactoryBase { this: MemberLookupBase => * @param comment The expanded comment string (including start and end markers) to be parsed. * @param src The raw comment source string. * @param pos The position of the comment in source. */ - protected def parseAtSymbol(comment: String, src: String, pos: Position, siteOpt: Option[Symbol] = None): Comment = { + protected def parseAtSymbol(comment: String, src: String, pos: Position, site: Symbol = NoSymbol): Comment = { /** The cleaned raw comment as a list of lines. Cleaning removes comment * start and end markers, line start markers and unnecessary whitespace. */ def clean(comment: String): List[String] = { @@ -312,7 +312,7 @@ trait CommentFactoryBase { this: MemberLookupBase => val tagsWithoutDiagram = tags.filterNot(pair => stripTags.contains(pair._1)) val bodyTags: mutable.Map[TagKey, List[Body]] = - mutable.Map(tagsWithoutDiagram mapValues {tag => tag map (parseWikiAtSymbol(_, pos, siteOpt))} toSeq: _*) + mutable.Map(tagsWithoutDiagram mapValues {tag => tag map (parseWikiAtSymbol(_, pos, site))} toSeq: _*) def oneTag(key: SimpleTagKey): Option[Body] = ((bodyTags remove key): @unchecked) match { @@ -345,7 +345,7 @@ trait CommentFactoryBase { this: MemberLookupBase => } val com = createComment ( - body0 = Some(parseWikiAtSymbol(docBody.toString, pos, siteOpt)), + body0 = Some(parseWikiAtSymbol(docBody.toString, pos, site)), authors0 = allTags(SimpleTagKey("author")), see0 = allTags(SimpleTagKey("see")), result0 = oneTag(SimpleTagKey("return")), @@ -385,14 +385,14 @@ trait CommentFactoryBase { this: MemberLookupBase => * - Removed start-of-line star and one whitespace afterwards (if present). * - Removed all end-of-line whitespace. * - Only `endOfLine` is used to mark line endings. */ - def parseWikiAtSymbol(string: String, pos: Position, siteOpt: Option[Symbol]): Body = new WikiParser(string, pos, siteOpt).document() + def parseWikiAtSymbol(string: String, pos: Position, site: Symbol): Body = new WikiParser(string, pos, site).document() /** TODO * * @author Ingo Maier * @author Manohar Jonnalagedda * @author Gilles Dubochet */ - protected final class WikiParser(val buffer: String, pos: Position, siteOpt: Option[Symbol]) extends CharReader(buffer) { wiki => + protected final class WikiParser(val buffer: String, pos: Position, site: Symbol) extends CharReader(buffer) { wiki => var summaryParsed = false def document(): Body = { @@ -694,7 +694,7 @@ trait CommentFactoryBase { this: MemberLookupBase => case (SchemeUri(uri), optTitle) => Link(uri, optTitle getOrElse Text(uri)) case (qualName, optTitle) => - makeEntityLink(optTitle getOrElse Text(target), pos, target, siteOpt) + makeEntityLink(optTitle getOrElse Text(target), pos, target, site) } } diff --git a/src/scaladoc/scala/tools/nsc/doc/base/MemberLookupBase.scala b/src/scaladoc/scala/tools/nsc/doc/base/MemberLookupBase.scala index 671518fbc6..cc217d2f80 100755 --- a/src/scaladoc/scala/tools/nsc/doc/base/MemberLookupBase.scala +++ b/src/scaladoc/scala/tools/nsc/doc/base/MemberLookupBase.scala @@ -21,10 +21,10 @@ trait MemberLookupBase { import global._ import rootMirror.{RootPackage, EmptyPackage} - private def isRoot(s: Symbol) = s.isRootSymbol || s.isEmptyPackage || s.isEmptyPackageClass + private def isRoot(s: Symbol) = (s eq NoSymbol) || s.isRootSymbol || s.isEmptyPackage || s.isEmptyPackageClass - def makeEntityLink(title: Inline, pos: Position, query: String, siteOpt: Option[Symbol]) = - new EntityLink(title) { lazy val link = memberLookup(pos, query, siteOpt) } + def makeEntityLink(title: Inline, pos: Position, query: String, site: Symbol) = + new EntityLink(title) { lazy val link = memberLookup(pos, query, site) } private var showExplanation = true private def explanation: String = @@ -45,18 +45,14 @@ trait MemberLookupBase { | - you can use \\# to escape hashes, otherwise they will be considered as delimiters, like dots.""".stripMargin } else "" - def memberLookup(pos: Position, query: String, siteOpt: Option[Symbol]): LinkTo = { + def memberLookup(pos: Position, query: String, site: Symbol): LinkTo = { val members = breakMembers(query) // (1) First look in the root package, as most of the links are qualified val fromRoot = lookupInRootPackage(pos, members) // (2) Or recursively go into each containing template. - val fromParents = siteOpt.fold(Stream.empty[Symbol]) { s => - Stream.iterate(s)(_.owner) - }.takeWhile (!isRoot(_)).map { - lookupInTemplate(pos, members, _) - } + val fromParents = Stream.iterate(site)(_.owner) takeWhile (!isRoot(_)) map (lookupInTemplate(pos, members, _)) val syms = (fromRoot +: fromParents) find (!_.isEmpty) getOrElse Nil diff --git a/src/scaladoc/scala/tools/nsc/doc/model/CommentFactory.scala b/src/scaladoc/scala/tools/nsc/doc/model/CommentFactory.scala index 574d6b04f8..4e06e5bd16 100644 --- a/src/scaladoc/scala/tools/nsc/doc/model/CommentFactory.scala +++ b/src/scaladoc/scala/tools/nsc/doc/model/CommentFactory.scala @@ -24,31 +24,20 @@ trait CommentFactory extends base.CommentFactoryBase { thisFactory: ModelFactory with CommentFactory with MemberLookup => val global: Global - import global.{ reporter, definitions, Symbol } + import global.{ reporter, definitions, Symbol, NoSymbol } - protected val commentCache = mutable.HashMap.empty[(Symbol, TemplateImpl), Comment] + protected val commentCache = mutable.HashMap.empty[(Symbol, DocTemplateImpl), Option[Comment]] - def addCommentBody(sym: Symbol, inTpl: TemplateImpl, docStr: String, docPos: global.Position): Symbol = { - commentCache += (sym, inTpl) -> parse(docStr, docStr, docPos, None) - sym - } - - def comment(sym: Symbol, currentTpl: Option[DocTemplateImpl], inTpl: DocTemplateImpl): Option[Comment] = { - val key = (sym, inTpl) - if (commentCache isDefinedAt key) - Some(commentCache(key)) - else { - val c = defineComment(sym, currentTpl, inTpl) - if (c isDefined) commentCache += (sym, inTpl) -> c.get - c - } - } + def comment(sym: Symbol, linkTarget: DocTemplateImpl, inTpl: DocTemplateImpl): Option[Comment] = + commentCache.getOrElseUpdate((sym, inTpl), { + defineComment(sym, linkTarget, inTpl) + }) /** A comment is usualy created by the parser, however for some special * cases we have to give some `inTpl` comments (parent class for example) * to the comment of the symbol. * This function manages some of those cases : Param accessor and Primary constructor */ - def defineComment(sym: Symbol, currentTpl: Option[DocTemplateImpl], inTpl: DocTemplateImpl):Option[Comment] = { + def defineComment(sym: Symbol, linkTarget: DocTemplateImpl, inTpl: DocTemplateImpl):Option[Comment] = { //param accessor case // We just need the @param argument, we put it into the body @@ -85,8 +74,7 @@ trait CommentFactory extends base.CommentFactoryBase { else { val rawComment = global.expandedDocComment(sym, inTpl.sym).trim if (rawComment != "") { - val tplOpt = if (currentTpl.isDefined) currentTpl else Some(inTpl) - val c = parse(rawComment, global.rawDocComment(sym), global.docCommentPos(sym), tplOpt) + val c = parse(rawComment, global.rawDocComment(sym), global.docCommentPos(sym), linkTarget) Some(c) } else None @@ -94,9 +82,9 @@ trait CommentFactory extends base.CommentFactoryBase { } - protected def parse(comment: String, src: String, pos: Position, inTplOpt: Option[DocTemplateImpl] = None): Comment = { - assert(!inTplOpt.isDefined || inTplOpt.get != null) - parseAtSymbol(comment, src, pos, inTplOpt map (_.sym)) + protected def parse(comment: String, src: String, pos: Position, linkTarget: DocTemplateImpl): Comment = { + val sym = if (linkTarget eq null) NoSymbol else linkTarget.sym + parseAtSymbol(comment, src, pos, sym) } /** Parses a string containing wiki syntax into a `Comment` object. @@ -105,8 +93,8 @@ trait CommentFactory extends base.CommentFactoryBase { * - Removed start-of-line star and one whitespace afterwards (if present). * - Removed all end-of-line whitespace. * - Only `endOfLine` is used to mark line endings. */ - def parseWiki(string: String, pos: Position, inTplOpt: Option[DocTemplateImpl]): Body = { - assert(!inTplOpt.isDefined || inTplOpt.get != null) - parseWikiAtSymbol(string,pos, inTplOpt map (_.sym)) + def parseWiki(string: String, pos: Position, inTpl: DocTemplateImpl): Body = { + val sym = if (inTpl eq null) NoSymbol else inTpl.sym + parseWikiAtSymbol(string,pos, sym) } } diff --git a/src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala b/src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala index cc228082c1..60406f4401 100644 --- a/src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala +++ b/src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala @@ -99,22 +99,21 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { } abstract class MemberImpl(sym: Symbol, inTpl: DocTemplateImpl) extends EntityImpl(sym, inTpl) with MemberEntity { + // If the current tpl is a DocTemplate, we consider itself as the root for resolving link targets (instead of the + // package the class is in) -- so people can refer to methods directly [[foo]], instead of using [[MyClass.foo]] + // in the doc comment of MyClass + def linkTarget: DocTemplateImpl = inTpl + lazy val comment = { - // If the current tpl is a DocTemplate, we consider itself as the root for resolving link targets (instead of the - // package the class is in) -- so people can refer to methods directly [[foo]], instead of using [[MyClass.foo]] - // in the doc comment of MyClass - val thisTpl = this match { - case d: DocTemplateImpl => Some(d) - case _ => None - } - if (inTpl != null) thisFactory.comment(sym, thisTpl, inTpl) else None + val documented = if (sym.hasAccessorFlag) sym.accessed else sym + thisFactory.comment(documented, linkTarget, inTpl) } def group = comment flatMap (_.group) getOrElse defaultGroup override def inTemplate = inTpl override def toRoot: List[MemberImpl] = this :: inTpl.toRoot def inDefinitionTemplates = if (inTpl == null) - List(makeRootPackage) + docTemplatesCache(RootPackage) :: Nil else makeTemplate(sym.owner)::(sym.allOverriddenSymbols map { inhSym => makeTemplate(inhSym.owner) }) def visibility = { @@ -152,9 +151,9 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { def deprecation = if (sym.isDeprecated) Some((sym.deprecationMessage, sym.deprecationVersion) match { - case (Some(msg), Some(ver)) => parseWiki("''(Since version " + ver + ")'' " + msg, NoPosition, Some(inTpl)) - case (Some(msg), None) => parseWiki(msg, NoPosition, Some(inTpl)) - case (None, Some(ver)) => parseWiki("''(Since version " + ver + ")''", NoPosition, Some(inTpl)) + case (Some(msg), Some(ver)) => parseWiki("''(Since version " + ver + ")'' " + msg, NoPosition, inTpl) + case (Some(msg), None) => parseWiki(msg, NoPosition, inTpl) + case (None, Some(ver)) => parseWiki("''(Since version " + ver + ")''", NoPosition, inTpl) case (None, None) => Body(Nil) }) else @@ -162,9 +161,9 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { def migration = if(sym.hasMigrationAnnotation) Some((sym.migrationMessage, sym.migrationVersion) match { - case (Some(msg), Some(ver)) => parseWiki("''(Changed in version " + ver + ")'' " + msg, NoPosition, Some(inTpl)) - case (Some(msg), None) => parseWiki(msg, NoPosition, Some(inTpl)) - case (None, Some(ver)) => parseWiki("''(Changed in version " + ver + ")''", NoPosition, Some(inTpl)) + case (Some(msg), Some(ver)) => parseWiki("''(Changed in version " + ver + ")'' " + msg, NoPosition, inTpl) + case (Some(msg), None) => parseWiki(msg, NoPosition, inTpl) + case (None, Some(ver)) => parseWiki("''(Changed in version " + ver + ")''", NoPosition, inTpl) case (None, None) => Body(Nil) }) else @@ -220,7 +219,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { (name + tParams(this) + defParams(this) +":"+ resultType.name).replaceAll("\\s","") // no spaces allowed, they break links } // these only apply for NonTemplateMemberEntities - def useCaseOf: Option[MemberEntity] = None + def useCaseOf: Option[MemberImpl] = None def byConversion: Option[ImplicitConversionImpl] = None def isImplicitlyInherited = false def isShadowedImplicit = false @@ -275,6 +274,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { if (settings.verbose) inform("Creating doc template for " + sym) + override def linkTarget: DocTemplateImpl = this override def toRoot: List[DocTemplateImpl] = this :: inTpl.toRoot protected def inSourceFromSymbol(symbol: Symbol) = @@ -392,7 +392,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { outgoingImplicitlyConvertedClasses // the members generated by the symbols in memberSymsEager PLUS the members from the usecases - val allMembers = ownMembers ::: ownMembers.flatMap(_.useCaseOf.map(_.asInstanceOf[MemberImpl])).distinct + val allMembers = ownMembers ::: ownMembers.flatMap(_.useCaseOf).distinct implicitsShadowing = makeShadowingTable(allMembers, conversions, this) // finally, add the members generated by implicit conversions members :::= conversions.flatMap(_.memberImpls) @@ -484,21 +484,22 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { abstract class RootPackageImpl(sym: Symbol) extends PackageImpl(sym, null) with RootPackageEntity abstract class NonTemplateMemberImpl(sym: Symbol, conversion: Option[ImplicitConversionImpl], - override val useCaseOf: Option[MemberEntity], inTpl: DocTemplateImpl) + override val useCaseOf: Option[MemberImpl], inTpl: DocTemplateImpl) extends MemberImpl(sym, inTpl) with NonTemplateMemberEntity { override lazy val comment = { - val inRealTpl = - conversion.fold(Option(inTpl)) { conv => - /* Variable precendence order for implicitly added members: Take the variable defifinitions from ... - * 1. the target of the implicit conversion - * 2. the definition template (owner) - * 3. the current template - */ - findTemplateMaybe(conv.toType.typeSymbol) filterNot (_ == makeRootPackage) orElse ( - findTemplateMaybe(sym.owner) filterNot (_ == makeRootPackage) orElse Option(inTpl) - ) - } - inRealTpl flatMap (thisFactory.comment(sym, None, _)) + def nonRootTemplate(sym: Symbol): Option[DocTemplateImpl] = + if (sym eq RootPackage) None else findTemplateMaybe(sym) + /* Variable precendence order for implicitly added members: Take the variable defifinitions from ... + * 1. the target of the implicit conversion + * 2. the definition template (owner) + * 3. the current template + */ + val inRealTpl = conversion.flatMap { conv => + nonRootTemplate(conv.toType.typeSymbol) + } orElse nonRootTemplate(sym.owner) orElse Option(inTpl) + inRealTpl flatMap { tpl => + thisFactory.comment(sym, tpl, tpl) + } } override def inDefinitionTemplates = useCaseOf.fold(super.inDefinitionTemplates)(_.inDefinitionTemplates) @@ -517,7 +518,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { } abstract class NonTemplateParamMemberImpl(sym: Symbol, conversion: Option[ImplicitConversionImpl], - useCaseOf: Option[MemberEntity], inTpl: DocTemplateImpl) + useCaseOf: Option[MemberImpl], inTpl: DocTemplateImpl) extends NonTemplateMemberImpl(sym, conversion, useCaseOf, inTpl) { def valueParams = { val info = conversion.fold(sym.info)(_.toType memberInfo sym) @@ -630,7 +631,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { import Streamable._ Path(settings.docRootContent.value) match { case f : File => { - val rootComment = closing(f.inputStream())(is => parse(slurp(is), "", NoPosition, Option(inTpl))) + val rootComment = closing(f.inputStream())(is => parse(slurp(is), "", NoPosition, inTpl)) Some(rootComment) } case _ => None @@ -738,16 +739,12 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { } } - def makeRootPackage: PackageImpl = docTemplatesCache(RootPackage).asInstanceOf[PackageImpl] - // TODO: Should be able to override the type def makeMember(aSym: Symbol, conversion: Option[ImplicitConversionImpl], inTpl: DocTemplateImpl): List[MemberImpl] = { def makeMember0(bSym: Symbol, useCaseOf: Option[MemberImpl]): Option[MemberImpl] = { if (bSym.isGetter && bSym.isLazy) Some(new NonTemplateMemberImpl(bSym, conversion, useCaseOf, 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, None, inTpl.asInstanceOf[DocTemplateImpl]) // This hack should be removed after analyser is fixed. override def isLazyVal = true }) else if (bSym.isGetter && bSym.accessed.isMutable) @@ -1041,4 +1038,3 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { { val rawComment = global.expandedDocComment(bSym, inTpl.sym) rawComment.contains("@template") || rawComment.contains("@documentable") } } - diff --git a/src/scaladoc/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala b/src/scaladoc/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala index 6cefe34887..4fd8fd4270 100644 --- a/src/scaladoc/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala +++ b/src/scaladoc/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala @@ -332,13 +332,12 @@ trait ModelFactoryImplicitSupport { def targetType: TypeEntity = makeType(toType, inTpl) - def convertorOwner: TemplateEntity = - if (convSym != NoSymbol) - makeTemplate(convSym.owner) - else { + def convertorOwner: TemplateEntity = { + if (convSym eq NoSymbol) error("Scaladoc implicits: " + toString + " = NoSymbol!") - makeRootPackage - } + + makeTemplate(convSym.owner) + } def targetTypeComponents: List[(TemplateEntity, TypeEntity)] = makeParentTypes(toType, None, inTpl) -- cgit v1.2.3 From 005a08d38a344c506ef2715bacac61bd56624402 Mon Sep 17 00:00:00 2001 From: Eugene Vigdorchik Date: Fri, 26 Apr 2013 20:18:09 +0400 Subject: Remove self types check suppression usage from scaladoc. Also remove private setting not used anymore. --- src/compiler/scala/tools/nsc/settings/ScalaSettings.scala | 1 - src/compiler/scala/tools/nsc/typechecker/Typers.scala | 1 - src/scaladoc/scala/tools/nsc/doc/Settings.scala | 5 ----- 3 files changed, 7 deletions(-) (limited to 'src/scaladoc') diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index ee9a3aed2a..e679fa6365 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -171,7 +171,6 @@ trait ScalaSettings extends AbsScalaSettings val etaExpandKeepsStar = BooleanSetting ("-Yeta-expand-keeps-star", "Eta-expand varargs methods to T* rather than Seq[T]. This is a temporary option to ease transition."). withDeprecationMessage("This flag is scheduled for removal in 2.12. If you have a case where you need this flag then please report a bug.") val Yinvalidate = StringSetting ("-Yinvalidate", "classpath-entry", "Invalidate classpath entry before run", "") - val noSelfCheck = BooleanSetting ("-Yno-self-type-checks", "Suppress check for self-type conformance among inherited members.") val YvirtClasses = false // too embryonic to even expose as a -Y //BooleanSetting ("-Yvirtual-classes", "Support virtual classes") val YdisableUnreachablePrevention = BooleanSetting("-Ydisable-unreachable-prevention", "Disable the prevention of unreachable blocks in code generation.") diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 6e26b12226..20b19b55cc 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1749,7 +1749,6 @@ trait Typers extends Adaptations with Tags { if (!(selfType <:< parent.tpe.typeOfThis) && !phase.erasedTypes && !context.owner.isSynthetic && // don't check synthetic concrete classes for virtuals (part of DEVIRTUALIZE) - !settings.noSelfCheck && // setting to suppress this very check !selfType.isErroneous && !parent.tpe.isErroneous) { diff --git a/src/scaladoc/scala/tools/nsc/doc/Settings.scala b/src/scaladoc/scala/tools/nsc/doc/Settings.scala index afffca12d1..e16b6be853 100644 --- a/src/scaladoc/scala/tools/nsc/doc/Settings.scala +++ b/src/scaladoc/scala/tools/nsc/doc/Settings.scala @@ -204,11 +204,6 @@ class Settings(error: String => Unit, val printMsg: String => Unit = println(_)) "Group similar functions together (based on the @group annotation)" ) - // Somewhere slightly before r18708 scaladoc stopped building unless the - // self-type check was suppressed. I hijacked the slotted-for-removal-anyway - // suppress-vt-warnings option and renamed it for this purpose. - noSelfCheck.value = true - // For improved help output. def scaladocSpecific = Set[Settings#Setting]( docformat, doctitle, docfooter, docversion, docUncompilable, docsourceurl, docgenerator, docRootContent, useStupidTypes, -- cgit v1.2.3 From add19e6839c8238d4ce173006287b399b7958f22 Mon Sep 17 00:00:00 2001 From: Eugene Vigdorchik Date: Sun, 28 Apr 2013 18:58:24 +0400 Subject: No longer cache all subclass templates. Instead only cache direct subclasses and compute all known subclasses as a transitive closure. --- .../scala/tools/nsc/doc/html/page/Template.scala | 25 +++++++++---- .../scala/tools/nsc/doc/model/Entity.scala | 4 -- .../scala/tools/nsc/doc/model/ModelFactory.scala | 43 +++++++--------------- 3 files changed, 32 insertions(+), 40 deletions(-) (limited to 'src/scaladoc') diff --git a/src/scaladoc/scala/tools/nsc/doc/html/page/Template.scala b/src/scaladoc/scala/tools/nsc/doc/html/page/Template.scala index 63509de4b5..c5ccc06cf9 100644 --- a/src/scaladoc/scala/tools/nsc/doc/html/page/Template.scala +++ b/src/scaladoc/scala/tools/nsc/doc/html/page/Template.scala @@ -15,6 +15,7 @@ import model._ import model.diagram._ import scala.xml.{ NodeSeq, Text, UnprefixedAttribute } import scala.language.postfixOps +import scala.collection.mutable. { Set, HashSet } import model._ import model.diagram._ @@ -636,13 +637,23 @@ class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemp } val subclasses = mbr match { - case dtpl: DocTemplateEntity if isSelf && !isReduced && dtpl.allSubClasses.nonEmpty => -
- Known Subclasses -
{ - templatesToHtml(dtpl.allSubClasses.sortBy(_.name), scala.xml.Text(", ")) - }
-
+ case dtpl: DocTemplateEntity if isSelf && !isReduced => + val subs: Set[DocTemplateEntity] = HashSet.empty + def transitive(dtpl: DocTemplateEntity) { + for (sub <- dtpl.directSubClasses if !(subs contains sub)) { + subs add sub + transitive(sub) + } + } + transitive(dtpl) + if (subs.nonEmpty) +
+ Known Subclasses +
{ + templatesToHtml(subs.toList.sortBy(_.name), scala.xml.Text(", ")) + }
+
+ else NodeSeq.Empty case _ => NodeSeq.Empty } diff --git a/src/scaladoc/scala/tools/nsc/doc/model/Entity.scala b/src/scaladoc/scala/tools/nsc/doc/model/Entity.scala index 924f203a59..6932f01e9a 100644 --- a/src/scaladoc/scala/tools/nsc/doc/model/Entity.scala +++ b/src/scaladoc/scala/tools/nsc/doc/model/Entity.scala @@ -258,10 +258,6 @@ trait DocTemplateEntity extends MemberTemplateEntity { * This template's linearization contains all of its direct and indirect super-types. */ def linearizationTypes: List[TypeEntity] - /** All class, trait and object templates for which this template is a direct or indirect super-class or super-trait. - * Only templates for which documentation is available in the universe (`DocTemplateEntity`) are listed. */ - def allSubClasses: List[DocTemplateEntity] - /** All class, trait and object templates for which this template is a *direct* super-class or super-trait. * Only templates for which documentation is available in the universe (`DocTemplateEntity`) are listed. */ def directSubClasses: List[DocTemplateEntity] diff --git a/src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala b/src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala index 60406f4401..5b91ef2ba5 100644 --- a/src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala +++ b/src/scaladoc/scala/tools/nsc/doc/model/ModelFactory.scala @@ -277,14 +277,14 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { override def linkTarget: DocTemplateImpl = this override def toRoot: List[DocTemplateImpl] = this :: inTpl.toRoot - protected def inSourceFromSymbol(symbol: Symbol) = - if (symbol.sourceFile != null && ! symbol.isSynthetic) - Some((symbol.sourceFile, symbol.pos.line)) + protected def reprSymbol: Symbol = sym + + def inSource = + if (reprSymbol.sourceFile != null && ! reprSymbol.isSynthetic) + Some((reprSymbol.sourceFile, reprSymbol.pos.line)) else None - def inSource = inSourceFromSymbol(sym) - def sourceUrl = { def fixPath(s: String) = s.replaceAll("\\" + java.io.File.separator, "/") val assumedSourceRoot = fixPath(settings.sourcepath.value) stripSuffix "/" @@ -306,20 +306,10 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { else None } - protected def linearizationFromSymbol(symbol: Symbol): List[(TemplateEntity, TypeEntity)] = { - symbol.ancestors map { ancestor => - val typeEntity = makeType(symbol.info.baseType(ancestor), this) - val tmplEntity = makeTemplate(ancestor) match { - case tmpl: DocTemplateImpl => tmpl registerSubClass this ; tmpl - case tmpl => tmpl - } - (tmplEntity, typeEntity) - } - } - - lazy val linearization = linearizationFromSymbol(sym) - def linearizationTemplates = linearization map { _._1 } - def linearizationTypes = linearization map { _._2 } + lazy val (linearizationTemplates, linearizationTypes) = + reprSymbol.ancestors map { ancestor => + (makeTemplate(ancestor), makeType(reprSymbol.info.baseType(ancestor), this)) + } unzip /* Subclass cache */ private lazy val subClassesCache = ( @@ -330,8 +320,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { if (subClassesCache != null) subClassesCache += sc } - def allSubClasses = if (subClassesCache == null) Nil else subClassesCache.toList - def directSubClasses = allSubClasses.filter(_.parentTypes.map(_._1).contains(this)) + def directSubClasses = if (subClassesCache == null) Nil else subClassesCache.toList /* Implcitly convertible class cache */ private var implicitlyConvertibleClassesCache: mutable.ListBuffer[(DocTemplateImpl, ImplicitConversionImpl)] = null @@ -387,10 +376,10 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { members :::= memberSymsLazy.map(modelCreation.createLazyTemplateMember(_, this)) - // compute linearization to register subclasses - linearization outgoingImplicitlyConvertedClasses + for (pt <- sym.info.parents; parentTemplate <- findTemplateMaybe(pt.typeSymbol)) parentTemplate registerSubClass this + // the members generated by the symbols in memberSymsEager PLUS the members from the usecases val allMembers = ownMembers ::: ownMembers.flatMap(_.useCaseOf).distinct implicitsShadowing = makeShadowingTable(allMembers, conversions, this) @@ -472,12 +461,8 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { 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 lazy val (inSource, linearization) = { - val representive = sym.info.members.find { - s => s.isPackageObject - } getOrElse sym - (inSourceFromSymbol(representive), linearizationFromSymbol(representive)) - } + override def reprSymbol = sym.info.members.find (_.isPackageObject) getOrElse sym + def packages = members collect { case p: PackageImpl if !(droppedPackages contains p) => p } } -- cgit v1.2.3