aboutsummaryrefslogtreecommitdiff
path: root/doc-tool/src/dotty/tools/dottydoc/core/ContextDottydoc.scala
blob: 8f463833d3734bbd7da1f5d248aec581e187e366 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package dotty.tools
package dottydoc
package core

import dotc.core.Symbols._
import dotc.core.Flags._
import dotc.core.Decorators._
import dotc.core.Comments.ContextDocstrings
import model.{ Package, Entity }
import model.comment.Comment

import dotc.core.Contexts.Context
import dotc.printing.Highlighting._
import dotc.util.{ SourcePosition, NoSourcePosition }

class ContextDottydoc extends ContextDocstrings {
  import scala.collection.mutable

  private[this] val _packages: mutable.Map[String, Package] = mutable.Map.empty
  def packages: Map[String, Package] = _packages.toMap
  def packagesMutable: mutable.Map[String, Package] = _packages

  private[this]  var _statistics: Map[String, Statistics] = Map.empty
  def registerStatistics(pkgName: String, stat: Statistics): Unit =
    _statistics = _statistics + (pkgName -> stat)

  def statistics: Map[String, Statistics] = _statistics

  /** Should perhaps factorize this into caches that get flushed */
  private var _defs: Map[Symbol, Set[Symbol]] = Map.empty
  def defs(sym: Symbol): Set[Symbol] = _defs.get(sym).getOrElse(Set.empty)

  def addDef(s: Symbol, d: Symbol): Unit = _defs = (_defs + {
    s -> _defs.get(s).map(xs => xs + d).getOrElse(Set(d))
  })

  def error(msg: String, pos: SourcePosition)(implicit ctx: Context): Unit = ctx.error({
    NoColor("[") + Red("doc error") + "] " + msg
  }.toString, pos)

  def error(msg: String)(implicit ctx: Context): Unit = error(msg, NoSourcePosition)

  def warn(msg: String, pos: SourcePosition)(implicit ctx: Context): Unit = ctx.warning({
    NoColor("[") + Yellow("doc warn") + "] " + msg
  }.toString, pos)

  def warn(msg: String)(implicit ctx: Context): Unit = warn(msg, NoSourcePosition)

  def echo(msg: String, pos: SourcePosition)(implicit ctx: Context): Unit = ctx.echo({
    "[doc info] " + msg
  }.toString, pos)

  def echo(msg: String)(implicit ctx: Context): Unit = echo(msg, NoSourcePosition)

  def debug(msg: String, pos: SourcePosition)(implicit ctx: Context): Unit =
    if (ctx.settings.debug.value) ctx.inform({
      "[doc debug] " + msg
    }.toString, pos)

  def debug(msg: String)(implicit ctx: Context): Unit = debug(msg, NoSourcePosition)

  def printSummary()(implicit ctx: Context): Unit = {
    def colored(part: Int, total: Int) =
      if (total == 0) "0"
      else {
        val percentage = (part * 100.0 / total).toInt
        val str = s"$part/$total ($percentage%)"

        if (percentage > 75) Green(str)
        else if (percentage > 50) Yellow(str)
        else Red(str)
      }

    val totalEntities = statistics.totalEntities

    val projectName = ctx.settings.projectName.value
    val warningsText =
      if (ctx.reporter.hasWarnings)
        s"total warnings with regards to compilation and documentation: ${ctx.reporter.warningCount}"
      else ""

    val api = statistics.values.iterator.map(_.api).foldLeft(Counters(0,0,0,0,0,0))(_ merge _)
    val internalApi = statistics.values.iterator.map(_.internalApi).foldLeft(Counters(0,0,0,0,0,0))(_ merge _)

    val apiSummary = (for {
      (pkgName, stat) <- statistics.toList.sortBy(_._1)
    } yield {
      val pub = colored(stat.api.publicDocstrings, stat.api.publicEntities)
      val pro = colored(stat.api.protectedDocstrings, stat.api.protectedEntities)
      s"""|package $pkgName
          |${Blue("-" * ctx.settings.pageWidth.value)}
          |public: $pub \t protected: $pro
          |""".stripMargin
    }).mkString("\n")

    val internalSummary = (for {
      (pkgName, stat) <- statistics.toList.sortBy(_._1)
    } yield {
      val pub = colored(stat.internalApi.publicDocstrings, stat.internalApi.publicEntities)
      val pro = colored(stat.internalApi.protectedDocstrings, stat.internalApi.protectedEntities)
      val pri = colored(stat.internalApi.privateDocstrings, stat.internalApi.privateEntities)
      s"""|package $pkgName
          |${Blue("-" * ctx.settings.pageWidth.value)}
          |public: $pub \t protected: $pro \t private: $pri
          |""".stripMargin
    }).mkString("\n")

    ctx.echo {
      s"""|${Blue("=" * ctx.settings.pageWidth.value)}
          |Dottydoc summary report for project `$projectName`
          |${Blue("=" * ctx.settings.pageWidth.value)}
          |Documented members in public API:
          |
          |$apiSummary
          |
          |Summary:
          |
          |public members with docstrings:    ${colored(api.publicDocstrings, api.publicEntities)}
          |${hl"${"protected"}"} members with docstrings: ${colored(api.protectedDocstrings, api.protectedEntities)}
          |${Blue("=" * ctx.settings.pageWidth.value)}
          |
          |Documented members in internal API:
          |
          |$internalSummary
          |
          |Summary internal API:
          |
          |public members with docstrings:    ${colored(internalApi.publicDocstrings, internalApi.publicEntities)}
          |${hl"${"protected"}"} members with docstrings: ${colored(internalApi.protectedDocstrings, internalApi.protectedEntities)}
          |${hl"${"private"}"} members with docstrings:   ${colored(internalApi.privateDocstrings, internalApi.privateEntities)}
          |$warningsText""".stripMargin
    }
  }
}