Skip to content
4 changes: 3 additions & 1 deletion dottydoc/src/dotty/tools/dottydoc/DottyDoc.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ class DocCompiler extends Compiler {
List(new DocFrontEnd),
List(new DocImplicitsPhase),
List(new DocASTPhase),
List(DocMiniTransformations(new LinkReturnTypes,
List(DocMiniTransformations(new UsecasePhase,
new DocstringPhase,
new LinkReturnTypes,
new LinkParamListTypes,
new LinkImplicitlyAddedTypes,
new LinkSuperTypes,
Expand Down
72 changes: 25 additions & 47 deletions dottydoc/src/dotty/tools/dottydoc/core/DocASTPhase.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ class DocASTPhase extends Phase {
import model._
import model.factories._
import model.internal._
import model.parsers.WikiParser
import model.comment.Comment
import dotty.tools.dotc.core.Flags
import dotty.tools.dotc.ast.tpd._
Expand All @@ -23,20 +22,8 @@ class DocASTPhase extends Phase {

def phaseName = "docphase"

private[this] val commentParser = new WikiParser

/** Saves the commentParser function for later evaluation, for when the AST has been filled */
def track(symbol: Symbol, ctx: Context, parent: Symbol = NoSymbol)(op: => Entity) = {
val entity = op

if (entity != NonEntity)
commentParser += (entity, symbol, parent, ctx)

entity
}

/** Build documentation hierarchy from existing tree */
def collect(tree: Tree, prev: List[String] = Nil)(implicit ctx: Context): Entity = track(tree.symbol, ctx) {
def collect(tree: Tree, prev: List[String] = Nil)(implicit ctx: Context): Entity = {
val implicitConversions = ctx.docbase.defs(tree.symbol)

def collectList(xs: List[Tree], ps: List[String]): List[Entity] =
Expand All @@ -58,28 +45,26 @@ class DocASTPhase extends Phase {
val defs = sym.info.bounds.hi.membersBasedOnFlags(Flags.Method, Flags.Synthetic | Flags.Private)
.filterNot(_.symbol.owner.name.show == "Any")
.map { meth =>
track(meth.symbol, ctx, tree.symbol) {
DefImpl(
meth.symbol.name.show,
Nil,
path(meth.symbol),
returnType(meth.info),
typeParams(meth.symbol),
paramLists(meth.info),
implicitlyAddedFrom = Some(returnType(meth.symbol.owner.info))
)
}
DefImpl(
meth.symbol,
meth.symbol.name.show,
Nil,
path(meth.symbol),
returnType(meth.info),
typeParams(meth.symbol),
paramLists(meth.info),
implicitlyAddedFrom = Some(returnType(meth.symbol.owner.info))
)
}.toList

val vals = sym.info.fields.filterNot(_.symbol.is(Flags.Private | Flags.Synthetic)).map { value =>
track(value.symbol, ctx, tree.symbol) {
ValImpl(
value.symbol.name.show,
Nil, path(value.symbol),
returnType(value.info),
implicitlyAddedFrom = Some(returnType(value.symbol.owner.info))
)
}
ValImpl(
value.symbol,
value.symbol.name.show,
Nil, path(value.symbol),
returnType(value.info),
implicitlyAddedFrom = Some(returnType(value.symbol.owner.info))
)
}

defs ++ vals
Expand All @@ -90,38 +75,38 @@ class DocASTPhase extends Phase {
/** package */
case pd @ PackageDef(pid, st) =>
val newPath = prev :+ pid.name.toString
addEntity(PackageImpl(newPath.mkString("."), collectEntityMembers(st, newPath), newPath))
addEntity(PackageImpl(pd.symbol, newPath.mkString("."), collectEntityMembers(st, newPath), newPath))

/** trait */
case t @ TypeDef(n, rhs) if t.symbol.is(Flags.Trait) =>
val name = n.decode.toString
val newPath = prev :+ name
//TODO: should not `collectMember` from `rhs` - instead: get from symbol, will get inherited members as well
TraitImpl(name, collectMembers(rhs), flags(t), newPath, typeParams(t.symbol), traitParameters(t.symbol), superTypes(t))
TraitImpl(t.symbol, name, collectMembers(rhs), flags(t), newPath, typeParams(t.symbol), traitParameters(t.symbol), superTypes(t))

/** objects, on the format "Object$" so drop the last letter */
case o @ TypeDef(n, rhs) if o.symbol.is(Flags.Module) =>
val name = n.decode.toString.dropRight(1)
//TODO: should not `collectMember` from `rhs` - instead: get from symbol, will get inherited members as well
ObjectImpl(name, collectMembers(rhs, prev :+ name), flags(o), prev :+ (name + "$"), superTypes(o))
ObjectImpl(o.symbol, name, collectMembers(rhs, prev :+ name), flags(o), prev :+ (name + "$"), superTypes(o))

/** class / case class */
case c @ TypeDef(n, rhs) if c.symbol.isClass =>
val name = n.decode.toString
val newPath = prev :+ name
//TODO: should not `collectMember` from `rhs` - instead: get from symbol, will get inherited members as well
(name, collectMembers(rhs), flags(c), newPath, typeParams(c.symbol), constructors(c.symbol), superTypes(c), None) match {
(c.symbol, name, collectMembers(rhs), flags(c), newPath, typeParams(c.symbol), constructors(c.symbol), superTypes(c), None) match {
case x if c.symbol.is(Flags.CaseClass) => CaseClassImpl.tupled(x)
case x => ClassImpl.tupled(x)
}

/** def */
case d: DefDef =>
DefImpl(d.name.decode.toString, flags(d), path(d.symbol), returnType(d.tpt.tpe), typeParams(d.symbol), paramLists(d.symbol.info))
DefImpl(d.symbol, d.name.decode.toString, flags(d), path(d.symbol), returnType(d.tpt.tpe), typeParams(d.symbol), paramLists(d.symbol.info))

/** val */
case v: ValDef if !v.symbol.is(Flags.ModuleVal) =>
ValImpl(v.name.decode.toString, flags(v), path(v.symbol), returnType(v.tpt.tpe))
ValImpl(v.symbol, v.name.decode.toString, flags(v), path(v.symbol), returnType(v.tpt.tpe))

case x => {
//dottydoc.println(s"Found unwanted entity: $x (${x.pos},\n${x.show}")
Expand Down Expand Up @@ -175,14 +160,7 @@ class DocASTPhase extends Phase {
child <- parent.children
} setParent(child, to = parent)

// (3) Create documentation template from docstrings, with internal links
println("Generating documentation, this might take a while...")
commentParser.parse(packages)

// (4) Clear caches
commentParser.clear()

// (5) Update Doc AST in ctx.base
// (3) Update Doc AST in ctx.base
for (kv <- packages) ctx.docbase.packages += kv

// Return super's result
Expand Down
46 changes: 46 additions & 0 deletions dottydoc/src/dotty/tools/dottydoc/core/DocstringPhase.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package dotty.tools
package dottydoc
package core

import dotc.core.Contexts.Context
import transform.DocMiniPhase
import model._
import model.internal._
import model.comment._
import BodyParsers._

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)
.toComment(_.toHtml(ent))
}

override def transformPackage(implicit ctx: Context) = { case ent: PackageImpl =>
ent.copy(comment = parsedComment(ent))
}

override def transformClass(implicit ctx: Context) = { case ent: ClassImpl =>
ent.copy(comment = parsedComment(ent))
}

override def transformCaseClass(implicit ctx: Context) = { case ent: CaseClassImpl =>
ent.copy(comment = parsedComment(ent))
}

override def transformTrait(implicit ctx: Context) = { case ent: TraitImpl =>
ent.copy(comment = parsedComment(ent))
}

override def transformObject(implicit ctx: Context) = { case ent: ObjectImpl =>
ent.copy(comment = parsedComment(ent))
}

override def transformDef(implicit ctx: Context) = { case ent: DefImpl =>
ent.copy(comment = parsedComment(ent))
}

override def transformVal(implicit ctx: Context) = { case ent: ValImpl =>
ent.copy(comment = parsedComment(ent))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ object transform {
def traverse(ent: Entity): Entity = ent match {
case p: Package => transformEntity(p, _.packageTransformation) { p =>
val newPackage = PackageImpl(
p.symbol,
p.name,
p.members.map(traverse),
p.path,
Expand All @@ -90,6 +91,7 @@ object transform {
}
case c: Class => transformEntity(c, _.classTransformation) { cls =>
ClassImpl(
cls.symbol,
cls.name,
cls.members.map(traverse),
cls.modifiers,
Expand All @@ -102,6 +104,7 @@ object transform {
}
case cc: CaseClass => transformEntity(cc, _.caseClassTransformation) { cc =>
CaseClassImpl(
cc.symbol,
cc.name,
cc.members.map(traverse),
cc.modifiers,
Expand All @@ -114,6 +117,7 @@ object transform {
}
case trt: Trait => transformEntity(trt, _.traitTransformation) { trt =>
TraitImpl(
trt.symbol,
trt.name,
trt.members.map(traverse),
trt.modifiers,
Expand All @@ -126,6 +130,7 @@ object transform {
}
case obj: Object => transformEntity(obj, _.objectTransformation) { obj =>
ObjectImpl(
obj.symbol,
obj.name,
obj.members.map(traverse),
obj.modifiers,
Expand All @@ -136,6 +141,7 @@ object transform {
}
case df: Def => transformEntity(df, _.defTransformation) { df =>
DefImpl(
df.symbol,
df.name,
df.modifiers,
df.path,
Expand All @@ -148,6 +154,7 @@ object transform {
}
case vl: Val => transformEntity(vl, _.valTransformation) { vl =>
ValImpl(
vl.symbol,
vl.name,
vl.modifiers,
vl.path,
Expand Down
30 changes: 30 additions & 0 deletions dottydoc/src/dotty/tools/dottydoc/core/UsecasePhase.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package dotty.tools
package dottydoc
package core

import dotc.core.Contexts.Context
import dotc.ast.tpd

import transform.DocMiniPhase
import model.internal._
import model.factories._
import dotty.tools.dotc.core.Symbols.Symbol

class UsecasePhase extends DocMiniPhase {
private def defdefToDef(d: tpd.DefDef, sym: Symbol)(implicit ctx: Context) = {
val name = d.name.show.split("\\$").head // UseCase defs get $pos appended to their names
DefImpl(
sym,
name,
flags(d),
path(d.symbol).init :+ name,
returnType(d.tpt.tpe),
typeParams(d.symbol),
paramLists(d.symbol.info)
)
}

override def transformDef(implicit ctx: Context) = { case df: DefImpl =>
ctx.docbase.docstring(df.symbol).flatMap(_.usecases.headOption.map(_.tpdCode)).map(defdefToDef(_, df.symbol)).getOrElse(df)
}
}
Loading