aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc
diff options
context:
space:
mode:
authorFelix Mulder <felix.mulder@gmail.com>2016-09-21 15:02:30 +0200
committerFelix Mulder <felix.mulder@gmail.com>2016-10-06 17:45:39 +0200
commit92536168e9fda4005a8eff54e5ca72cc70fb32e4 (patch)
tree285d92137cc5c33a0dba3b352b6fa252ed57ce13 /src/dotty/tools/dotc
parent208232aba52903ae090711589e9c572dc5347651 (diff)
downloaddotty-92536168e9fda4005a8eff54e5ca72cc70fb32e4.tar.gz
dotty-92536168e9fda4005a8eff54e5ca72cc70fb32e4.tar.bz2
dotty-92536168e9fda4005a8eff54e5ca72cc70fb32e4.zip
Separate `ContextDocstrings` from `Context` and make it pluggable
Diffstat (limited to 'src/dotty/tools/dotc')
-rw-r--r--src/dotty/tools/dotc/core/Comments.scala47
-rw-r--r--src/dotty/tools/dotc/core/Contexts.scala34
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala4
-rw-r--r--src/dotty/tools/dotc/typer/Docstrings.scala56
-rw-r--r--src/dotty/tools/dotc/typer/Namer.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Typer.scala45
-rw-r--r--src/dotty/tools/dotc/util/CommentParsing.scala7
7 files changed, 104 insertions, 91 deletions
diff --git a/src/dotty/tools/dotc/core/Comments.scala b/src/dotty/tools/dotc/core/Comments.scala
index 4f36b3b6b..8c2443c9d 100644
--- a/src/dotty/tools/dotc/core/Comments.scala
+++ b/src/dotty/tools/dotc/core/Comments.scala
@@ -2,17 +2,40 @@ package dotty.tools
package dotc
package core
-import dotc.ast.{ untpd, tpd }
-import Decorators._
-import Symbols._
-import Contexts.Context
-import Flags.EmptyFlags
-import dotc.util.SourceFile
-import dotc.util.Positions._
-import dotc.util.CommentParsing._
-import dotc.parsing.Parsers.Parser
+import ast.{ untpd, tpd }
+import Decorators._, Symbols._, Contexts._, Flags.EmptyFlags
+import util.SourceFile
+import util.Positions._
+import util.CommentParsing._
+import util.Property.Key
+import parsing.Parsers.Parser
object Comments {
+ val ContextDoc = new Key[ContextDocstrings]
+
+ /** Decorator for getting docbase out of context */
+ implicit class CommentsContext(val ctx: Context) extends AnyVal {
+ def docCtx: Option[ContextDocstrings] = ctx.property(ContextDoc)
+ }
+
+ /** Context for Docstrings, contains basic functionality for getting
+ * docstrings via `Symbol` and expanding templates
+ */
+ class ContextDocstrings {
+ import scala.collection.mutable
+
+ private[this] val _docstrings: mutable.Map[Symbol, Comment] =
+ mutable.Map.empty
+
+ val templateExpander = new CommentExpander
+
+ def docstrings: Map[Symbol, Comment] = _docstrings.toMap
+
+ def docstring(sym: Symbol): Option[Comment] = _docstrings.get(sym)
+
+ def addDocstring(sym: Symbol, doc: Option[Comment]): Unit =
+ doc.map(d => _docstrings += (sym -> d))
+ }
abstract case class Comment(pos: Position, raw: String)(implicit ctx: Context) { self =>
def isExpanded: Boolean
@@ -155,7 +178,7 @@ object Comments {
*/
def cookedDocComment(sym: Symbol, docStr: String = "")(implicit ctx: Context): String = cookedDocComments.getOrElseUpdate(sym, {
var ownComment =
- if (docStr.length == 0) ctx.getDocbase.flatMap(_.docstring(sym).map(c => template(c.raw))).getOrElse("")
+ if (docStr.length == 0) ctx.docCtx.flatMap(_.docstring(sym).map(c => template(c.raw))).getOrElse("")
else template(docStr)
ownComment = replaceInheritDocToInheritdoc(ownComment)
@@ -365,7 +388,7 @@ object Comments {
def defineVariables(sym: Symbol)(implicit ctx: Context) = {
val Trim = "(?s)^[\\s&&[^\n\r]]*(.*?)\\s*$".r
- val raw = ctx.getDocbase.flatMap(_.docstring(sym).map(_.raw)).getOrElse("")
+ val raw = ctx.docCtx.flatMap(_.docstring(sym).map(_.raw)).getOrElse("")
defs(sym) ++= defines(raw).map {
str => {
val start = skipWhitespace(str, "@define".length)
@@ -406,7 +429,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.getDocbase.flatMap(_.docstring(sym).map(_.pos)).getOrElse(NoPosition)
+ ctx.docCtx.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 bf171bf60..5c9fdaf88 100644
--- a/src/dotty/tools/dotc/core/Contexts.scala
+++ b/src/dotty/tools/dotc/core/Contexts.scala
@@ -69,9 +69,6 @@ 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
@@ -578,37 +575,6 @@ object Contexts {
}
}
- val DocContext = new Key[DocBase]
- class DocBase {
- private[this] val _docstrings: mutable.Map[Symbol, Comment] =
- mutable.Map.empty
-
- val templateExpander = new CommentExpander
-
- def docstrings: Map[Symbol, Comment] = _docstrings.toMap
-
- def docstring(sym: Symbol): Option[Comment] = _docstrings.get(sym)
-
- def addDocstring(sym: Symbol, doc: Option[Comment]): Unit =
- doc.map(d => _docstrings += (sym -> d))
-
- /*
- * Dottydoc places instances of `Package` in this map - but we do not want
- * to depend on `dottydoc` for the compiler, as such this is defined as a
- * map of `String -> AnyRef`
- */
- private[this] val _packages: mutable.Map[String, AnyRef] = mutable.Map.empty
- 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
- def defs(sym: Symbol): Set[Symbol] = _defs.get(sym).getOrElse(Set.empty)
-
- def addDef(s: Symbol, d: Symbol): Unit = _defs = (_defs + {
- s -> _defs.get(s).map(xs => xs + d).getOrElse(Set(d))
- })
- }
-
/** The essential mutable state of a context base, collected into a common class */
class ContextState {
// Symbols state
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala
index e2cb378b5..5a5eacd18 100644
--- a/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -3,7 +3,7 @@ package dotc
package core
import Periods._, Contexts._, Symbols._, Denotations._, Names._, NameOps._, Annotations._
-import Types._, Flags._, Decorators._, DenotTransformers._, StdNames._, Scopes._
+import Types._, Flags._, Decorators._, DenotTransformers._, StdNames._, Scopes._, Comments._
import NameOps._
import Scopes.Scope
import collection.mutable
@@ -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 = ctx.property(DocContext).isDefined && sym.name.show.takeRight(4) == "$doc"
+ def isUsecase = ctx.docCtx.isDefined && sym.name.show.takeRight(4) == "$doc"
require(
(sym.denot.flagsUNSAFE is Private) ||
!(this is Frozen) ||
diff --git a/src/dotty/tools/dotc/typer/Docstrings.scala b/src/dotty/tools/dotc/typer/Docstrings.scala
new file mode 100644
index 000000000..370844e65
--- /dev/null
+++ b/src/dotty/tools/dotc/typer/Docstrings.scala
@@ -0,0 +1,56 @@
+package dotty.tools
+package dotc
+package typer
+
+import core._
+import Contexts._, Symbols._, Decorators._, Comments._
+import util.Positions._
+import ast.tpd
+
+trait Docstrings { self: Typer =>
+
+ /** The Docstrings typer will handle the expansion of `@define` and
+ * `@inheritdoc` if there is a `DocContext` present as a property in the
+ * supplied `ctx`.
+ *
+ * It will also type any `@usecase` available in function definitions.
+ */
+ def cookComments(syms: List[Symbol], owner: Symbol)(implicit ctx: Context): Unit =
+ ctx.docCtx.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))
+
+ 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.docCtx.foreach { docCtx =>
+ docCtx.docstring(sym).foreach { cmt =>
+ def expandDoc(owner: Symbol): Unit = if (!cmt.isExpanded) {
+ val tplExp = docCtx.templateExpander
+ tplExp.defineVariables(sym)
+
+ val newCmt = cmt
+ .expand(tplExp.expandedDocComment(sym, owner, _))
+ .withUsecases
+
+ docCtx.addDocstring(sym, Some(newCmt))
+ }
+
+ if (sym ne NoSymbol) {
+ expandParentDocs(sym.owner)
+ expandDoc(sym.owner)
+ }
+ }
+ }
+}
diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala
index 938b280d1..4f4278468 100644
--- a/src/dotty/tools/dotc/typer/Namer.scala
+++ b/src/dotty/tools/dotc/typer/Namer.scala
@@ -457,7 +457,7 @@ class Namer { typer: Typer =>
def setDocstring(sym: Symbol, tree: Tree)(implicit ctx: Context) = tree match {
case t: MemberDef if t.rawComment.isDefined =>
- ctx.getDocbase.foreach(_.addDocstring(sym, t.rawComment))
+ ctx.docCtx.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 3ed6c9228..3e3bb32f5 100644
--- a/src/dotty/tools/dotc/typer/Typer.scala
+++ b/src/dotty/tools/dotc/typer/Typer.scala
@@ -58,7 +58,7 @@ object Typer {
assert(tree.pos.exists, s"position not set for $tree # ${tree.uniqueId}")
}
-class Typer extends Namer with TypeAssigner with Applications with Implicits with Dynamic with Checking {
+class Typer extends Namer with TypeAssigner with Applications with Implicits with Dynamic with Checking with Docstrings {
import Typer._
import tpd.{cpy => _, _}
@@ -1247,8 +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))
- if (ctx.property(DocContext).isDefined)
- typedUsecases(body1.map(_.symbol), self1.symbol)(localContext(cdef, cls).setNewScope)
+ // Expand comments and type usecases
+ cookComments(body1.map(_.symbol), self1.symbol)(localContext(cdef, cls).setNewScope)
checkNoDoubleDefs(cls)
val impl1 = cpy.Template(impl)(constr1, parents1, self1, body1)
@@ -1538,45 +1538,6 @@ 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 =
- 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))
-
- 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.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
-
- docbase.addDocstring(sym, Some(newCmt))
- }
-
- if (sym ne NoSymbol) {
- expandParentDocs(sym.owner)
- expandDoc(sym.owner)
- }
- }
- }
-
def typedExpr(tree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): Tree =
typed(tree, pt)(ctx retractMode Mode.PatternOrType)
def typedType(tree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): Tree = // todo: retract mode between Type and Pattern?
diff --git a/src/dotty/tools/dotc/util/CommentParsing.scala b/src/dotty/tools/dotc/util/CommentParsing.scala
index 077776b5d..cc790d683 100644
--- a/src/dotty/tools/dotc/util/CommentParsing.scala
+++ b/src/dotty/tools/dotc/util/CommentParsing.scala
@@ -5,6 +5,13 @@
*/
package dotty.tools.dotc.util
+/** The comment parsing in `dotc` is used by both the comment cooking and the
+ * dottydoc tool.
+ *
+ * The comment cooking is used to expand comments with `@inheritdoc` and
+ * `@define` annotations. The rest of the comment is untouched and later
+ * handled by dottydoc.
+ */
object CommentParsing {
import scala.reflect.internal.Chars._