aboutsummaryrefslogtreecommitdiff
path: root/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala
diff options
context:
space:
mode:
Diffstat (limited to 'doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala')
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala102
1 files changed, 81 insertions, 21 deletions
diff --git a/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala b/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala
index 411818614..72953b5a8 100644
--- a/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala
+++ b/doc-tool/src/dotty/tools/dottydoc/core/DocASTPhase.scala
@@ -23,7 +23,7 @@ class DocASTPhase extends Phase {
import util.traversing._
import util.internal.setters._
- def phaseName = "docphase"
+ def phaseName = "docASTPhase"
/** Build documentation hierarchy from existing tree */
def collect(tree: Tree, prev: List[String] = Nil)(implicit ctx: Context): Entity = {
@@ -64,7 +64,6 @@ class DocASTPhase extends Phase {
// don't add privates, synthetics or class parameters (i.e. value class constructor val)
val vals = sym.info.fields.filterNot(_.symbol.is(Flags.ParamAccessor | Flags.Private | Flags.Synthetic)).map { value =>
- println(value + " " + value.symbol.flags)
val kind = if (value.symbol.is(Flags.Mutable)) "var" else "val"
ValImpl(
value.symbol,
@@ -87,7 +86,7 @@ class DocASTPhase extends Phase {
/** package */
case pd @ PackageDef(pid, st) =>
val pkgPath = path(pd.symbol)
- addEntity(PackageImpl(pd.symbol, annotations(pd.symbol), pd.symbol.showFullName, collectEntityMembers(st, pkgPath), pkgPath))
+ addPackage(PackageImpl(pd.symbol, annotations(pd.symbol), pd.symbol.showFullName, collectEntityMembers(st, pkgPath), pkgPath))
/** type alias */
case t: TypeDef if !t.isClassDef =>
@@ -111,7 +110,7 @@ class DocASTPhase extends Phase {
/** class / case class */
case c @ TypeDef(n, rhs) if c.symbol.isClass =>
//TODO: should not `collectMember` from `rhs` - instead: get from symbol, will get inherited members as well
- (c.symbol, annotations(c.symbol), n.show, collectMembers(rhs), flags(c), path(c.symbol), typeParams(c.symbol), constructors(c.symbol), superTypes(c), None, Nil) match {
+ (c.symbol, annotations(c.symbol), n.show, collectMembers(rhs), flags(c), path(c.symbol), typeParams(c.symbol), constructors(c.symbol), superTypes(c), None, Nil, NonEntity) match {
case x if c.symbol.is(Flags.CaseClass) => CaseClassImpl.tupled(x)
case x => ClassImpl.tupled(x)
}
@@ -132,29 +131,90 @@ class DocASTPhase extends Phase {
}
}
- var packages: Map[String, Package] = Map.empty
+ var packages: Map[String, PackageImpl] = 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")
+ def addPackage(newPkg: PackageImpl): Package = {
+ def mergeMembers(newPkg: PackageImpl, oldPkg: PackageImpl): Unit = {
+ val othersNew = newPkg.members.filterNot(_.kind == "package")
+ val (oldPacks, othersOld) = oldPkg.members.partition(_.kind == "package")
- val others = others1 ::: others2
- val packs = (packs1 ::: packs2).groupBy(_.path).map(_._2.head)
+ val others = othersNew ::: othersOld
+ // here we can just choose the old packs, since we're recursively (bottom up)
+ // discovering the tree, we should have met the child packages first, as
+ // such - they were already inserted into the tree
+ val newMembers = (others ++ oldPacks)
- (others ++ packs).sortBy(_.name)
+ oldPkg.members = newMembers
}
- 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)
+ // This function mutates packages in place as not to create any orphaned references
+ def mergedPackages(old: PackageImpl, newPkg: PackageImpl): PackageImpl = {
+ if (old.symbol eq NoSymbol) old.symbol = newPkg.symbol
+ if (old.annotations.isEmpty) old.annotations = newPkg.annotations
+ mergeMembers(newPkg, old)
+ if (old.superTypes.isEmpty) old.superTypes = newPkg.superTypes
+ if (!old.comment.isDefined) old.comment = newPkg.comment
+ old
+ }
+
+ def insertOrModifyRoot(): PackageImpl = {
+ val modifiedPkg =
+ packages
+ .get(newPkg.name)
+ .map(mergedPackages(_, newPkg))
+ .getOrElse(newPkg)
+
+ packages = packages + (modifiedPkg.name -> modifiedPkg)
+ modifiedPkg
+ }
- packages = packages + (path -> newPack)
- newPack
+ // This function inserts a package by creating empty packages to the point
+ // where it can insert the supplied package `newPkg`.
+ def createAndInsert(currentPkg: PackageImpl, path: List[String]): PackageImpl = {
+ (path: @unchecked) match {
+ case x :: Nil => {
+ val existingPkg = currentPkg.members.collect {
+ case p: PackageImpl if p.name == newPkg.name => p
+ }.headOption
+
+ if (existingPkg.isDefined) mergedPackages(existingPkg.get, newPkg)
+ else {
+ currentPkg.members = newPkg :: currentPkg.members
+ newPkg
+ }
+ }
+ case x :: xs => {
+ val subPkg = s"${currentPkg.name}.$x"
+ val existingPkg = currentPkg.members.collect {
+ case p: PackageImpl if p.name == subPkg => p
+ }.headOption
+
+ if (existingPkg.isDefined) createAndInsert(existingPkg.get, xs)
+ else {
+ val newEmpty = EmptyPackage(currentPkg.path :+ x, subPkg)
+ packages = packages + (subPkg -> newEmpty)
+ currentPkg.members = newEmpty :: currentPkg.members
+ createAndInsert(newEmpty, xs)
+ }
+ }
+ }
+ }
+
+ val path = newPkg.path
+ if (path.length == 1)
+ insertOrModifyRoot()
+ else if (packages.contains(newPkg.name))
+ mergedPackages(packages(newPkg.name), newPkg)
+ else {
+ val root = packages.get(path.head)
+
+ if (root.isDefined) createAndInsert(root.get, newPkg.path.drop(1))
+ else {
+ val newEmpty = EmptyPackage(List(path.head), path.head)
+ packages = packages + (path.head -> newEmpty)
+ createAndInsert(newEmpty, newPkg.path.drop(1))
+ }
+ }
}
private[this] var totalRuns = 0