diff options
author | Felix Mulder <felix.mulder@gmail.com> | 2016-11-03 16:20:28 +0100 |
---|---|---|
committer | Guillaume Martres <smarter@ubuntu.com> | 2016-11-22 01:35:07 +0100 |
commit | 94a8177f208418682b86934eb3f0b8edab99b1f0 (patch) | |
tree | ef2018006aee9af3f3afb9a92037ec605d835cd1 /doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala | |
parent | fcdb1c984c4b32c0c1b13337d9bd50a3883cb3b3 (diff) | |
download | dotty-94a8177f208418682b86934eb3f0b8edab99b1f0.tar.gz dotty-94a8177f208418682b86934eb3f0b8edab99b1f0.tar.bz2 dotty-94a8177f208418682b86934eb3f0b8edab99b1f0.zip |
Move `dottydoc` -> `doc-tool`
Diffstat (limited to 'doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala')
-rw-r--r-- | doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala b/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala new file mode 100644 index 000000000..806d9d0ae --- /dev/null +++ b/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala @@ -0,0 +1,171 @@ +package dotty.tools +package dottydoc +package core + +/** Dotty and Dottydoc imports */ +import dotc.ast.Trees._ +import dotc.CompilationUnit +import dotc.config.Printers.dottydoc +import dotc.core.Contexts.Context +import dotc.core.Comments.ContextDocstrings +import dotc.core.Phases.Phase +import dotc.core.Symbols.{ Symbol, NoSymbol } + +class DocASTPhase extends Phase { + import model._ + import model.factories._ + import model.internal._ + 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._ + + def phaseName = "docphase" + + /** Build documentation hierarchy from existing tree */ + 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] = + xs.map(collect(_, ps)).filter(_ != NonEntity) + + def collectEntityMembers(xs: List[Tree], ps: List[String]) = + collectList(xs, ps).asInstanceOf[List[Entity with Members]] + + def collectMembers(tree: Tree, ps: List[String] = prev)(implicit ctx: Context): List[Entity] = { + val defs = (tree match { + case t: Template => collectList(t.body, ps) + case _ => Nil + }) + + defs ++ implicitConversions.flatMap(membersFromSymbol) + } + + def membersFromSymbol(sym: Symbol): List[Entity] = { + val defs = sym.info.bounds.hi.membersBasedOnFlags(Flags.Method, Flags.Synthetic | Flags.Private) + .filterNot(_.symbol.owner.name.show == "Any") + .map { meth => + 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 => + ValImpl( + value.symbol, + value.symbol.name.show, + Nil, path(value.symbol), + returnType(value.info), + implicitlyAddedFrom = Some(returnType(value.symbol.owner.info)) + ) + } + + defs ++ vals + } + + + tree match { + /** package */ + case pd @ PackageDef(pid, st) => + val newPath = prev :+ pid.name.toString + 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(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(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 + (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.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.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}") + NonEntity + } + } + } + + var packages: Map[String, Package] = Map.empty + + def addEntity(p: Package): Package = { + def mergedChildren(x1s: List[Entity], x2s: List[Entity]): List[Entity] = { + val (packs1, others1) = x1s.partition(_.kind == "package") + val (packs2, others2) = x2s.partition(_.kind == "package") + + val others = others1 ::: others2 + val packs = (packs1 ::: packs2).groupBy(_.path).map(_._2.head) + + (others ++ packs).sortBy(_.name) + } + + val path = p.path.mkString(".") + val newPack = packages.get(path).map { + case ex: PackageImpl => + if (!ex.comment.isDefined) ex.comment = p.comment + ex.members = mergedChildren(ex.members, p.members) + ex + }.getOrElse(p) + + packages = packages + (path -> newPack) + newPack + } + + private[this] var totalRuns = 0 + private[this] var currentRun = 0 + + override def run(implicit ctx: Context): Unit = { + currentRun += 1 + println(s"Compiling ($currentRun/$totalRuns): ${ctx.compilationUnit.source.file.name}") + collect(ctx.compilationUnit.tpdTree) // Will put packages in `packages` var + } + + override def runOn(units: List[CompilationUnit])(implicit ctx: Context): List[CompilationUnit] = { + // (1) Create package structure for all `units`, this will give us a complete structure + totalRuns = units.length + val compUnits = super.runOn(units) + + // (2) Set parents of entities, needed for linking + for { + parent <- packages.values + child <- parent.children + } setParent(child, to = parent) + + // (3) Update Doc AST in ctx.base + for (kv <- packages) ctx.docbase.packagesMutable += kv + + // Return super's result + compUnits + } +} |