aboutsummaryrefslogtreecommitdiff
path: root/doc-tool/src/dotty/tools/dottydoc/core/StatisticsPhase.scala
diff options
context:
space:
mode:
Diffstat (limited to 'doc-tool/src/dotty/tools/dottydoc/core/StatisticsPhase.scala')
-rw-r--r--doc-tool/src/dotty/tools/dottydoc/core/StatisticsPhase.scala156
1 files changed, 156 insertions, 0 deletions
diff --git a/doc-tool/src/dotty/tools/dottydoc/core/StatisticsPhase.scala b/doc-tool/src/dotty/tools/dottydoc/core/StatisticsPhase.scala
new file mode 100644
index 000000000..e7f9a9ec7
--- /dev/null
+++ b/doc-tool/src/dotty/tools/dottydoc/core/StatisticsPhase.scala
@@ -0,0 +1,156 @@
+package dotty.tools
+package dottydoc
+package core
+
+import dotc.core.Phases.Phase
+import dotc.core.Contexts.Context
+import dotc.core.Symbols.Symbol
+import dotc.core.Decorators._
+import dotc.core.Flags._
+import dotc.CompilationUnit
+import dottydoc.util.syntax._
+import dottydoc.util.traversing._
+
+import model._
+
+object Statistics {
+ implicit class MapTotals(val map: Map[String, Statistics]) extends AnyVal {
+ def totalEntities =
+ map.values.foldLeft(0)(_ + _.totalEntities)
+ }
+}
+
+case class Statistics(pkgName: String, api: Counters, internalApi: Counters) {
+ def totalEntities =
+ api.totalEntities + internalApi.totalEntities
+
+ def totalDocstrings =
+ api.totalDocstrings + internalApi.totalDocstrings
+}
+
+case class Counters(
+ publicEntities: Int,
+ privateEntities: Int,
+ protectedEntities: Int,
+
+ publicDocstrings: Int,
+ privateDocstrings: Int,
+ protectedDocstrings: Int
+) {
+ def totalEntities =
+ publicEntities + privateEntities + protectedEntities
+
+ def totalDocstrings =
+ publicDocstrings + privateDocstrings + protectedDocstrings
+
+ def merge(o: Counters): Counters = Counters(
+ publicEntities + o.publicEntities,
+ privateEntities + o.privateEntities,
+ protectedEntities + o.protectedEntities,
+ publicDocstrings + o.publicDocstrings,
+ privateDocstrings + o.privateDocstrings,
+ protectedDocstrings + o.protectedDocstrings
+ )
+}
+
+class StatisticsPhase extends Phase {
+
+ def phaseName = "StatisticsPhase"
+
+ override def run(implicit ctx: Context): Unit = ()
+
+ override def runOn(units: List[CompilationUnit])(implicit ctx: Context): List[CompilationUnit] = {
+ for {
+ (pkgName, pack) <- ctx.docbase.packages
+ externalApi = collectPublicStats(pack)
+ internalApi = collectInternalStats(pack)
+ stats = Statistics(pkgName, externalApi, internalApi)
+ } ctx.docbase.registerStatistics(pkgName, stats)
+
+ units
+ }
+
+ def collectPublicStats(pack: Package)(implicit ctx: Context): Counters = {
+ var publicEntities: Int = 0
+ var protectedEntities: Int = 0
+ var publicDocstrings: Int = 0
+ var protectedDocstrings: Int = 0
+
+ if (pack.comment.isDefined) {
+ publicEntities += 1
+ publicDocstrings += 1
+ }
+
+ def doCount(sym: Symbol, comment: Int): Unit =
+ if (!sym.is(Protected)) {
+ publicEntities += 1
+ publicDocstrings += comment
+ }
+ else {
+ protectedEntities += 1
+ protectedDocstrings += comment
+ }
+
+
+ def recur(e: Entity, reachable: Boolean): Unit = {
+ val isVisible = !e.symbol.is(Private) && !e.symbol.privateWithin.exists
+ val shouldCount = isVisible && reachable
+ e match {
+ case e: Package => ()
+ case e: Entity with Members => if (shouldCount) {
+ doCount(e.symbol, if (e.comment.isDefined) 1 else 0)
+ e.members.foreach { c =>
+ if (!(e.symbol.is(Final) && c.symbol.is(Protected))) recur(c, true)
+ }
+ }
+ case e =>
+ if (shouldCount) doCount(e.symbol, if (e.comment.isDefined) 1 else 0)
+ }
+ }
+
+ pack.members.foreach(recur(_, true))
+ Counters(publicEntities, 0, protectedEntities, publicDocstrings, 0, protectedDocstrings)
+ }
+
+ def collectInternalStats(pack: Package)(implicit ctx: Context): Counters = {
+ var publicEntities: Int = 0
+ var privateEntities: Int = 0
+ var protectedEntities: Int = 0
+ var publicDocstrings: Int = 0
+ var privateDocstrings: Int = 0
+ var protectedDocstrings: Int = 0
+
+ def doCount(sym: Symbol, comment: Int): Unit =
+ if (sym.is(Private)) {
+ privateEntities += 1
+ privateDocstrings += comment
+ }
+ else if (!sym.is(Protected)) {
+ publicEntities += 1
+ publicDocstrings += comment
+ }
+ else {
+ protectedEntities += 1
+ protectedDocstrings += comment
+ }
+
+
+ def recur(e: Entity, reachable: Boolean): Unit = {
+ val internal = !reachable || e.symbol.is(Private) || e.symbol.privateWithin.exists
+ e match {
+ case _: Package => ()
+ case e: Entity with Members =>
+ e.members.foreach { c =>
+ val childIsInternal = !internal || (e.symbol.is(Final) && c.symbol.is(Protected))
+ recur(c, childIsInternal)
+ }
+ if (internal) doCount(e.symbol, if (e.comment.isDefined) 1 else 0)
+ case _ =>
+ if (internal) doCount(e.symbol, if (e.comment.isDefined) 1 else 0)
+ }
+ }
+
+ pack.members.foreach(recur(_, true))
+ Counters(publicEntities, privateEntities, protectedEntities, publicDocstrings, privateDocstrings, protectedDocstrings)
+ }
+}