diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/dotty/tools/dotc/config/ScalaSettings.scala | 1 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Comments.scala | 10 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Contexts.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/SymDenotations.scala | 6 | ||||
-rw-r--r-- | src/dotty/tools/dotc/parsing/Scanners.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Namer.scala | 11 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Typer.scala | 45 |
7 files changed, 48 insertions, 29 deletions
diff --git a/src/dotty/tools/dotc/config/ScalaSettings.scala b/src/dotty/tools/dotc/config/ScalaSettings.scala index ff17a9939..9304daf98 100644 --- a/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -171,6 +171,7 @@ class ScalaSettings extends Settings.SettingGroup { val Ybuildmanagerdebug = BooleanSetting("-Ybuild-manager-debug", "Generate debug information for the Refined Build Manager compiler.") val Ycompletion = BooleanSetting("-Ycompletion-debug", "Trace all tab completion activity.") val Ydocdebug = BooleanSetting("-Ydoc-debug", "Trace all scaladoc activity.") + val Ydocrun = BooleanSetting("-Ydoc-run", "Current run should be treated as a docrun, enables `@usecase` annotations in comments") val Yidedebug = BooleanSetting("-Yide-debug", "Generate, validate and output trees using the interactive compiler.") val Yinferdebug = BooleanSetting("-Yinfer-debug", "Trace type inference and implicit search.") val Yissuedebug = BooleanSetting("-Yissue-debug", "Print stack traces when a context issues an error.") diff --git a/src/dotty/tools/dotc/core/Comments.scala b/src/dotty/tools/dotc/core/Comments.scala index 1d9d53bac..ea5726fa0 100644 --- a/src/dotty/tools/dotc/core/Comments.scala +++ b/src/dotty/tools/dotc/core/Comments.scala @@ -15,6 +15,7 @@ import dotty.tools.dottydoc.model.comment.CommentUtils._ object Comments { case class Comment(pos: Position, raw: String)(implicit ctx: Context) { + val isDocComment = raw.startsWith("/**") private[this] lazy val sections = tagIndex(raw) @@ -41,10 +42,10 @@ object Comments { val code = raw.substring(codeStart, codeEnd) + " = ???" val codePos = subPos(codeStart, codeEnd) val commentStart = skipLineLead(raw, codeEnd + 1) min end - val comment = "/** " + raw.substring(commentStart, end) + "*/" + val commentStr = "/** " + raw.substring(commentStart, end) + "*/" val commentPos = subPos(commentStart, end) - UseCase(Comment(commentPos, comment), code, codePos) + UseCase(Comment(commentPos, commentStr), code, codePos) } private def subPos(start: Int, end: Int) = @@ -57,9 +58,6 @@ object Comments { } case class UseCase(comment: Comment, code: String, codePos: Position)(implicit ctx: Context) { - /** Entered by Namer */ - var symbol: Symbol = _ - /** Set by typer */ var tpdCode: tpd.DefDef = _ @@ -68,7 +66,7 @@ object Comments { tree match { case tree: untpd.DefDef => - val newName = (tree.name.show + "$" + codePos.start).toTermName + val newName = (tree.name.show + "$" + codePos + "$doc").toTermName untpd.DefDef(newName, tree.tparams, tree.vparamss, tree.tpt, tree.rhs) case _ => ctx.error("proper definition was not found in `@usecase`", codePos) diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala index 429b95c1e..a37e367fa 100644 --- a/src/dotty/tools/dotc/core/Contexts.scala +++ b/src/dotty/tools/dotc/core/Contexts.scala @@ -582,6 +582,8 @@ object Contexts { private[this] val _docstrings: mutable.Map[Symbol, Comment] = mutable.Map.empty + def docstrings: Map[Symbol, Comment] = _docstrings.toMap + def docstring(sym: Symbol): Option[Comment] = _docstrings.get(sym) def addDocstring(sym: Symbol, doc: Option[Comment]): Unit = diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index 969d09c3e..34612e83d 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -1541,13 +1541,15 @@ object SymDenotations { /** Enter a symbol in given `scope` without potentially replacing the old copy. */ def enterNoReplace(sym: Symbol, scope: MutableScope)(implicit ctx: Context): Unit = { - + lazy val isUsecase = ctx.settings.Ydocrun.value && sym.name.show.takeRight(4) == "$doc" require( (sym.denot.flagsUNSAFE is Private) || !(this is Frozen) || (scope ne this.unforcedDecls) || sym.hasAnnotation(defn.ScalaStaticAnnot) || - sym.name.isInlineAccessor) + sym.name.isInlineAccessor || + isUsecase) + scope.enter(sym) if (myMemberFingerPrint != FingerPrint.unknown) diff --git a/src/dotty/tools/dotc/parsing/Scanners.scala b/src/dotty/tools/dotc/parsing/Scanners.scala index 60003d098..8aee757ce 100644 --- a/src/dotty/tools/dotc/parsing/Scanners.scala +++ b/src/dotty/tools/dotc/parsing/Scanners.scala @@ -172,7 +172,7 @@ object Scanners { } class Scanner(source: SourceFile, override val startFrom: Offset = 0)(implicit ctx: Context) extends ScannerCommon(source)(ctx) { - val keepComments = ctx.settings.YkeepComments.value + val keepComments = ctx.settings.YkeepComments.value || ctx.settings.Ydocrun.value /** All doc comments as encountered, each list contains doc comments from * the same block level. Starting with the deepest level and going upward diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index b34eaa605..1d2d59208 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -4,7 +4,7 @@ package typer import core._ import ast._ -import Trees._, Constants._, StdNames._, Scopes._, Denotations._ +import Trees._, Constants._, StdNames._, Scopes._, Denotations._, Comments._ import Contexts._, Symbols._, Types._, SymDenotations._, Names._, NameOps._, Flags._, Decorators._ import ast.desugar, ast.desugar._ import ProtoTypes._ @@ -456,14 +456,7 @@ class Namer { typer: Typer => def setDocstring(sym: Symbol, tree: Tree)(implicit ctx: Context) = tree match { - case t: MemberDef if t.rawComment.isDefined => - val cmt = t.rawComment - ctx.docbase.addDocstring(sym, cmt) - - cmt.get.usecases.foreach { usecase => - usecase.symbol = enterSymbol(createSymbol(usecase.untpdCode)) - } - + case t: MemberDef if t.rawComment.isDefined => ctx.docbase.addDocstring(sym, t.rawComment) case _ => () } diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 181f5bd7c..2a8e7da9a 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -11,6 +11,7 @@ import Scopes._ import Denotations._ import ProtoTypes._ import Contexts._ +import Comments._ import Symbols._ import Types._ import SymDenotations._ @@ -1246,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) + if (ctx.settings.Ydocrun.value) + typedUsecases(body1.map(_.symbol), self1.symbol) checkNoDoubleDefs(cls) val impl1 = cpy.Template(impl)(constr1, parents1, self1, body1) @@ -1536,16 +1538,37 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit tpd.cpy.DefDef(mdef)(rhs = Inliner.bodyToInline(mdef.symbol)) :: Inliner.removeInlineAccessors(mdef.symbol) - def typedUsecases(syms: List[Symbol], owner: Symbol)(implicit ctx: Context): Unit = - for { - sym <- syms - usecase <- ctx.docbase.docstring(sym).map(_.usecases).getOrElse(Nil) - List(tpdTree) = typedStats(usecase.untpdCode :: Nil, owner) - } yield { - if (tpdTree.isInstanceOf[tpd.DefDef]) - usecase.tpdCode = tpdTree.asInstanceOf[tpd.DefDef] - else - ctx.error("Couldn't compile `@usecase`", usecase.codePos) + 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) + + 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) + } + } + } + } + + import dotty.tools.dottydoc.model.comment.CommentExpander + val expander = new CommentExpander {} + def expandParentDocs(sym: Symbol)(implicit ctx: Context): Unit = + ctx.docbase.docstring(sym).foreach { cmt => + def expandDoc(owner: Symbol): Unit = { + expander.defineVariables(sym) + val newCmt = Comment(cmt.pos, expander.expandedDocComment(sym, owner, cmt.raw)) + ctx.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 = |