From 208232aba52903ae090711589e9c572dc5347651 Mon Sep 17 00:00:00 2001 From: Felix Mulder Date: Thu, 8 Sep 2016 20:25:51 +0200 Subject: Implement docbase as property --- dottydoc/src/dotty/tools/dottydoc/DottyDoc.scala | 4 +- .../dotty/tools/dottydoc/core/DocASTPhase.scala | 5 ++- .../tools/dottydoc/core/DocImplicitsPhase.scala | 1 + .../dotty/tools/dottydoc/core/DocstringPhase.scala | 3 +- .../tools/dottydoc/core/MiniPhaseTransform.scala | 9 ++-- .../tools/dottydoc/core/TypeLinkingPhases.scala | 13 +++--- .../dotty/tools/dottydoc/core/UsecasePhase.scala | 1 + .../src/dotty/tools/dottydoc/util/syntax.scala | 21 +++++++++ dottydoc/test/BaseTest.scala | 6 ++- dottydoc/test/UsecaseTest.scala | 1 + src/dotty/tools/dotc/core/Comments.scala | 6 +-- src/dotty/tools/dotc/core/Contexts.scala | 9 ++-- src/dotty/tools/dotc/core/SymDenotations.scala | 2 +- src/dotty/tools/dotc/typer/Namer.scala | 3 +- src/dotty/tools/dotc/typer/Typer.scala | 52 ++++++++++++---------- 15 files changed, 87 insertions(+), 49 deletions(-) create mode 100644 dottydoc/src/dotty/tools/dottydoc/util/syntax.scala diff --git a/dottydoc/src/dotty/tools/dottydoc/DottyDoc.scala b/dottydoc/src/dotty/tools/dottydoc/DottyDoc.scala index 77ceb179d..a80efb165 100644 --- a/dottydoc/src/dotty/tools/dottydoc/DottyDoc.scala +++ b/dottydoc/src/dotty/tools/dottydoc/DottyDoc.scala @@ -1,6 +1,7 @@ package dotty.tools package dottydoc +import dotty.tools.dottydoc.util.syntax._ import core._ import core.transform._ import dotc.config.CompilerCommand @@ -56,6 +57,7 @@ abstract class DocDriver extends Driver { ctx.setSettings(summary.sstate) ctx.setSetting(ctx.settings.YkeepComments, true) + ctx.setProperty(DocContext, new DocBase) val fileNames = CompilerCommand.checkUsage(summary, sourcesRequired)(ctx) (fileNames, ctx) @@ -67,7 +69,7 @@ abstract class DocDriver extends Driver { val (fileNames, ctx) = setup(args, initCtx.fresh) doCompile(newCompiler(ctx), fileNames)(ctx) - ctx.docbase.packages[Package] + ctx.docbase.packages } def compiledDocsJava(args: Array[String]): JMap[String, Package] = diff --git a/dottydoc/src/dotty/tools/dottydoc/core/DocASTPhase.scala b/dottydoc/src/dotty/tools/dottydoc/core/DocASTPhase.scala index 617afec51..c6e9d6190 100644 --- a/dottydoc/src/dotty/tools/dottydoc/core/DocASTPhase.scala +++ b/dottydoc/src/dotty/tools/dottydoc/core/DocASTPhase.scala @@ -6,7 +6,7 @@ package core import dotc.ast.Trees._ import dotc.CompilationUnit import dotc.config.Printers.dottydoc -import dotc.core.Contexts.Context +import dotc.core.Contexts.{ Context, DocBase } import dotc.core.Phases.Phase import dotc.core.Symbols.{ Symbol, NoSymbol } @@ -17,6 +17,7 @@ class DocASTPhase extends Phase { import model.comment.Comment import dotty.tools.dotc.core.Flags import dotty.tools.dotc.ast.tpd._ + import dotty.tools.dottydoc.util.syntax._ import util.traversing._ import util.internal.setters._ @@ -161,7 +162,7 @@ class DocASTPhase extends Phase { } setParent(child, to = parent) // (3) Update Doc AST in ctx.base - for (kv <- packages) ctx.docbase.packages += kv + for (kv <- packages) ctx.docbase.packagesMutable += kv // Return super's result compUnits diff --git a/dottydoc/src/dotty/tools/dottydoc/core/DocImplicitsPhase.scala b/dottydoc/src/dotty/tools/dottydoc/core/DocImplicitsPhase.scala index f322d7a5a..6577f0cb7 100644 --- a/dottydoc/src/dotty/tools/dottydoc/core/DocImplicitsPhase.scala +++ b/dottydoc/src/dotty/tools/dottydoc/core/DocImplicitsPhase.scala @@ -5,6 +5,7 @@ package core import dotty.tools.dotc.transform.TreeTransforms.{ MiniPhaseTransform, TransformerInfo } import dotty.tools.dotc.core.Flags import dotc.core.Contexts.Context +import util.syntax._ class DocImplicitsPhase extends MiniPhaseTransform { thisTransformer => import dotty.tools.dotc.ast.tpd._ diff --git a/dottydoc/src/dotty/tools/dottydoc/core/DocstringPhase.scala b/dottydoc/src/dotty/tools/dottydoc/core/DocstringPhase.scala index 93d51503f..cff614528 100644 --- a/dottydoc/src/dotty/tools/dottydoc/core/DocstringPhase.scala +++ b/dottydoc/src/dotty/tools/dottydoc/core/DocstringPhase.scala @@ -8,11 +8,12 @@ import model._ import model.internal._ import model.comment._ import BodyParsers._ +import util.syntax._ class DocstringPhase extends DocMiniPhase with CommentParser with CommentCleaner { private def parsedComment[E <: Entity](ent: E)(implicit ctx: Context): Option[Comment] = ctx.docbase.docstring(ent.symbol).map { cmt => - parse(ent, ctx.docbase.packages[Package].toMap, clean(cmt.raw), cmt.raw, cmt.pos) + parse(ent, ctx.docbase.packages, clean(cmt.raw), cmt.raw, cmt.pos) .toComment(_.toHtml(ent)) } diff --git a/dottydoc/src/dotty/tools/dottydoc/core/MiniPhaseTransform.scala b/dottydoc/src/dotty/tools/dottydoc/core/MiniPhaseTransform.scala index fc0b40955..201640e4a 100644 --- a/dottydoc/src/dotty/tools/dottydoc/core/MiniPhaseTransform.scala +++ b/dottydoc/src/dotty/tools/dottydoc/core/MiniPhaseTransform.scala @@ -3,10 +3,11 @@ package dottydoc package core import dotc.CompilationUnit -import dotc.core.Contexts.Context +import dotc.core.Contexts.{ Context, DocBase } import dotc.core.Phases.Phase import model._ import model.internal._ +import util.syntax._ object transform { /** @@ -43,9 +44,9 @@ object transform { override def runOn(units: List[CompilationUnit])(implicit ctx: Context): List[CompilationUnit] = { for { rootName <- rootPackages - pack = ctx.docbase.packages[Package](rootName) + pack = ctx.docbase.packages(rootName) transformed = performPackageTransform(pack) - } yield ctx.docbase.packages(rootName) = transformed + } yield ctx.docbase.packagesMutable(rootName) = transformed super.runOn(units) } @@ -85,7 +86,7 @@ object transform { ) // Update reference in context to newPackage - ctx.docbase.packages[Package] += (newPackage.path.mkString(".") -> newPackage) + ctx.docbase.packagesMutable += (newPackage.path.mkString(".") -> newPackage) newPackage } diff --git a/dottydoc/src/dotty/tools/dottydoc/core/TypeLinkingPhases.scala b/dottydoc/src/dotty/tools/dottydoc/core/TypeLinkingPhases.scala index ae07effa9..1aecca9e1 100644 --- a/dottydoc/src/dotty/tools/dottydoc/core/TypeLinkingPhases.scala +++ b/dottydoc/src/dotty/tools/dottydoc/core/TypeLinkingPhases.scala @@ -14,15 +14,16 @@ import BodyParsers._ import util.MemberLookup import util.traversing._ import util.internal.setters._ +import util.syntax._ class LinkReturnTypes extends DocMiniPhase with TypeLinker { override def transformDef(implicit ctx: Context) = { case df: DefImpl => - val returnValue = linkReference(df, df.returnValue, ctx.docbase.packages[Package].toMap) + val returnValue = linkReference(df, df.returnValue, ctx.docbase.packages) df.copy(returnValue = returnValue) } override def transformVal(implicit ctx: Context) = { case vl: ValImpl => - val returnValue = linkReference(vl, vl.returnValue, ctx.docbase.packages[Package].toMap) + val returnValue = linkReference(vl, vl.returnValue, ctx.docbase.packages) vl.copy(returnValue = returnValue) } } @@ -31,7 +32,7 @@ class LinkParamListTypes extends DocMiniPhase with TypeLinker { override def transformDef(implicit ctx: Context) = { case df: DefImpl => val newParamLists = for { ParamListImpl(list, isImplicit) <- df.paramLists - newList = list.map(linkReference(df, _, ctx.docbase.packages[Package].toMap)) + newList = list.map(linkReference(df, _, ctx.docbase.packages)) } yield ParamListImpl(newList.asInstanceOf[List[NamedReference]], isImplicit) df.copy(paramLists = newParamLists) @@ -42,7 +43,7 @@ class LinkSuperTypes extends DocMiniPhase with TypeLinker { def linkSuperTypes(ent: Entity with SuperTypes)(implicit ctx: Context): List[MaterializableLink] = ent.superTypes.collect { case UnsetLink(title, query) => - val packages = ctx.docbase.packages[Package].toMap + val packages = ctx.docbase.packages val entityLink = makeEntityLink(ent, packages, Text(title), NoPosition, query).link handleEntityLink(title, entityLink, ent) } @@ -67,13 +68,13 @@ class LinkSuperTypes extends DocMiniPhase with TypeLinker { class LinkImplicitlyAddedTypes extends DocMiniPhase with TypeLinker { override def transformDef(implicit ctx: Context) = { case df: DefImpl if df.implicitlyAddedFrom.isDefined => - val implicitlyAddedFrom = linkReference(df, df.implicitlyAddedFrom.get, ctx.docbase.packages[Package].toMap) + val implicitlyAddedFrom = linkReference(df, df.implicitlyAddedFrom.get, ctx.docbase.packages) df.copy(implicitlyAddedFrom = Some(implicitlyAddedFrom)) } override def transformVal(implicit ctx: Context) = { case vl: ValImpl if vl.implicitlyAddedFrom.isDefined => - val implicitlyAddedFrom = linkReference(vl, vl.implicitlyAddedFrom.get, ctx.docbase.packages[Package].toMap) + val implicitlyAddedFrom = linkReference(vl, vl.implicitlyAddedFrom.get, ctx.docbase.packages) vl.copy(implicitlyAddedFrom = Some(implicitlyAddedFrom)) } } diff --git a/dottydoc/src/dotty/tools/dottydoc/core/UsecasePhase.scala b/dottydoc/src/dotty/tools/dottydoc/core/UsecasePhase.scala index 8e9e1fd57..47376eb26 100644 --- a/dottydoc/src/dotty/tools/dottydoc/core/UsecasePhase.scala +++ b/dottydoc/src/dotty/tools/dottydoc/core/UsecasePhase.scala @@ -9,6 +9,7 @@ import transform.DocMiniPhase import model.internal._ import model.factories._ import dotty.tools.dotc.core.Symbols.Symbol +import util.syntax._ class UsecasePhase extends DocMiniPhase { private def defdefToDef(d: tpd.DefDef, sym: Symbol)(implicit ctx: Context) = { diff --git a/dottydoc/src/dotty/tools/dottydoc/util/syntax.scala b/dottydoc/src/dotty/tools/dottydoc/util/syntax.scala new file mode 100644 index 000000000..140b3e761 --- /dev/null +++ b/dottydoc/src/dotty/tools/dottydoc/util/syntax.scala @@ -0,0 +1,21 @@ +package dotty.tools +package dottydoc +package util + +import dotc.core.Contexts.{ Context, DocBase } +import model.Package + +object syntax { + implicit class RichDocContext(val ctx: Context) extends AnyVal { + def docbase: DocBase = ctx.getDocbase getOrElse { + throw new IllegalStateException("DocBase must be set before running dottydoc phases") + } + } + + implicit class RichDocBase(val db: DocBase) { + def packages: Map[String, Package] = db.packagesAs[Package].toMap + + def packagesMutable: collection.mutable.Map[String, Package] = + db.packagesAs[Package] + } +} diff --git a/dottydoc/test/BaseTest.scala b/dottydoc/test/BaseTest.scala index 1aa426886..4dff1d4d1 100644 --- a/dottydoc/test/BaseTest.scala +++ b/dottydoc/test/BaseTest.scala @@ -2,12 +2,13 @@ package dotty.tools package dottydoc import dotc.core.Contexts -import Contexts.{ Context, ContextBase, FreshContext } +import Contexts.{ Context, ContextBase, FreshContext, DocContext, DocBase } import dotc.util.SourceFile import dotc.core.Phases.Phase import dotc.typer.FrontEnd import dottydoc.core.DocASTPhase import model.Package +import dotty.tools.dottydoc.util.syntax._ trait DottyTest { dotty.tools.dotc.parsing.Scanners // initialize keywords @@ -19,6 +20,7 @@ trait DottyTest { ctx.setSetting(ctx.settings.language, List("Scala2")) ctx.setSetting(ctx.settings.YnoInline, true) ctx.setSetting(ctx.settings.YkeepComments, true) + ctx.setProperty(DocContext, new DocBase) base.initialize()(ctx) ctx } @@ -28,7 +30,7 @@ trait DottyTest { List(new Phase { def phaseName = "assertionPhase" override def run(implicit ctx: Context): Unit = - assertion(ctx.docbase.packages[Package].toMap) + assertion(ctx.docbase.packages) }) :: Nil override def phases = diff --git a/dottydoc/test/UsecaseTest.scala b/dottydoc/test/UsecaseTest.scala index c7b398d1f..b5d47e4b6 100644 --- a/dottydoc/test/UsecaseTest.scala +++ b/dottydoc/test/UsecaseTest.scala @@ -8,6 +8,7 @@ import dotc.util.SourceFile import model._ import model.internal._ import model.references._ +import util.syntax._ class UsecaseTest extends DottyTest { @Test def simpleUsecase = { diff --git a/src/dotty/tools/dotc/core/Comments.scala b/src/dotty/tools/dotc/core/Comments.scala index 3e562baff..4f36b3b6b 100644 --- a/src/dotty/tools/dotc/core/Comments.scala +++ b/src/dotty/tools/dotc/core/Comments.scala @@ -155,7 +155,7 @@ object Comments { */ def cookedDocComment(sym: Symbol, docStr: String = "")(implicit ctx: Context): String = cookedDocComments.getOrElseUpdate(sym, { var ownComment = - if (docStr.length == 0) ctx.docbase.docstring(sym).map(c => template(c.raw)).getOrElse("") + if (docStr.length == 0) ctx.getDocbase.flatMap(_.docstring(sym).map(c => template(c.raw))).getOrElse("") else template(docStr) ownComment = replaceInheritDocToInheritdoc(ownComment) @@ -365,7 +365,7 @@ object Comments { def defineVariables(sym: Symbol)(implicit ctx: Context) = { val Trim = "(?s)^[\\s&&[^\n\r]]*(.*?)\\s*$".r - val raw = ctx.docbase.docstring(sym).map(_.raw).getOrElse("") + val raw = ctx.getDocbase.flatMap(_.docstring(sym).map(_.raw)).getOrElse("") defs(sym) ++= defines(raw).map { str => { val start = skipWhitespace(str, "@define".length) @@ -406,7 +406,7 @@ object Comments { * the position of the doc comment of the overridden version is returned instead. */ def docCommentPos(sym: Symbol)(implicit ctx: Context): Position = - ctx.docbase.docstring(sym).map(_.pos).getOrElse(NoPosition) + ctx.getDocbase.flatMap(_.docstring(sym).map(_.pos)).getOrElse(NoPosition) /** A version which doesn't consider self types, as a temporary measure: * an infinite loop has broken out between superComment and cookedDocComment diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala index 3378f0790..bf171bf60 100644 --- a/src/dotty/tools/dotc/core/Contexts.scala +++ b/src/dotty/tools/dotc/core/Contexts.scala @@ -69,6 +69,9 @@ object Contexts { /** The context base at the root */ val base: ContextBase + /** Documentation base */ + def getDocbase = property(DocContext) + /** All outer contexts, ending in `base.initialCtx` and then `NoContext` */ def outersIterator = new Iterator[Context] { var current = thiscontext @@ -537,9 +540,6 @@ object Contexts { /** The symbol loaders */ val loaders = new SymbolLoaders - /** Documentation base */ - val docbase = new DocBase - /** The platform, initialized by `initPlatform()`. */ private var _platform: Platform = _ @@ -578,6 +578,7 @@ object Contexts { } } + val DocContext = new Key[DocBase] class DocBase { private[this] val _docstrings: mutable.Map[Symbol, Comment] = mutable.Map.empty @@ -597,7 +598,7 @@ object Contexts { * map of `String -> AnyRef` */ private[this] val _packages: mutable.Map[String, AnyRef] = mutable.Map.empty - def packages[A]: mutable.Map[String, A] = _packages.asInstanceOf[mutable.Map[String, A]] + def packagesAs[A]: mutable.Map[String, A] = _packages.asInstanceOf[mutable.Map[String, A]] /** Should perhaps factorize this into caches that get flushed */ private var _defs: Map[Symbol, Set[Symbol]] = Map.empty diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index 018b050ff..e2cb378b5 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -1541,7 +1541,7 @@ object SymDenotations { /** Enter a symbol in given `scope` without potentially replacing the old copy. */ def enterNoReplace(sym: Symbol, scope: MutableScope)(implicit ctx: Context): Unit = { - def isUsecase = sym.name.show.takeRight(4) == "$doc" + def isUsecase = ctx.property(DocContext).isDefined && sym.name.show.takeRight(4) == "$doc" require( (sym.denot.flagsUNSAFE is Private) || !(this is Frozen) || diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index 1d2d59208..938b280d1 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -456,7 +456,8 @@ class Namer { typer: Typer => def setDocstring(sym: Symbol, tree: Tree)(implicit ctx: Context) = tree match { - case t: MemberDef if t.rawComment.isDefined => ctx.docbase.addDocstring(sym, t.rawComment) + case t: MemberDef if t.rawComment.isDefined => + ctx.getDocbase.foreach(_.addDocstring(sym, t.rawComment)) case _ => () } diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 3291cb9d0..3ed6c9228 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -1247,7 +1247,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit val dummy = localDummy(cls, impl) val body1 = typedStats(impl.body, dummy)(inClassContext(self1.symbol)) - typedUsecases(body1.map(_.symbol), self1.symbol)(localContext(cdef, cls).setNewScope) + if (ctx.property(DocContext).isDefined) + typedUsecases(body1.map(_.symbol), self1.symbol)(localContext(cdef, cls).setNewScope) checkNoDoubleDefs(cls) val impl1 = cpy.Template(impl)(constr1, parents1, self1, body1) @@ -1537,39 +1538,42 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit tpd.cpy.DefDef(mdef)(rhs = Inliner.bodyToInline(mdef.symbol)) :: Inliner.removeInlineAccessors(mdef.symbol) - private def typedUsecases(syms: List[Symbol], owner: Symbol)(implicit ctx: Context): Unit = { - val relevantSyms = syms.filter(ctx.docbase.docstring(_).isDefined) - relevantSyms.foreach { sym => - expandParentDocs(sym) - val usecases = ctx.docbase.docstring(sym).map(_.usecases).getOrElse(Nil) + private def typedUsecases(syms: List[Symbol], owner: Symbol)(implicit ctx: Context): Unit = + ctx.getDocbase.foreach { docbase => + val relevantSyms = syms.filter(docbase.docstring(_).isDefined) + relevantSyms.foreach { sym => + expandParentDocs(sym) + val usecases = docbase.docstring(sym).map(_.usecases).getOrElse(Nil) - usecases.foreach { usecase => - enterSymbol(createSymbol(usecase.untpdCode)) + usecases.foreach { usecase => + enterSymbol(createSymbol(usecase.untpdCode)) - typedStats(usecase.untpdCode :: Nil, owner) match { - case List(df: tpd.DefDef) => usecase.tpdCode = df - case _ => ctx.error("`@usecase` was not a valid definition", usecase.codePos) + typedStats(usecase.untpdCode :: Nil, owner) match { + case List(df: tpd.DefDef) => usecase.tpdCode = df + case _ => ctx.error("`@usecase` was not a valid definition", usecase.codePos) + } } } } - } private def expandParentDocs(sym: Symbol)(implicit ctx: Context): Unit = - ctx.docbase.docstring(sym).foreach { cmt => - def expandDoc(owner: Symbol): Unit = if (!cmt.isExpanded) { - val tplExp = ctx.docbase.templateExpander - tplExp.defineVariables(sym) + ctx.getDocbase.foreach { docbase => + docbase.docstring(sym).foreach { cmt => + def expandDoc(owner: Symbol): Unit = if (!cmt.isExpanded) { + val tplExp = docbase.templateExpander + tplExp.defineVariables(sym) - val newCmt = cmt - .expand(tplExp.expandedDocComment(sym, owner, _)) - .withUsecases + val newCmt = cmt + .expand(tplExp.expandedDocComment(sym, owner, _)) + .withUsecases - ctx.docbase.addDocstring(sym, Some(newCmt)) - } + docbase.addDocstring(sym, Some(newCmt)) + } - if (sym ne NoSymbol) { - expandParentDocs(sym.owner) - expandDoc(sym.owner) + if (sym ne NoSymbol) { + expandParentDocs(sym.owner) + expandDoc(sym.owner) + } } } -- cgit v1.2.3