diff options
author | Felix Mulder <felix.mulder@gmail.com> | 2016-05-13 15:35:42 +0200 |
---|---|---|
committer | Lukas Rytz <lukas.rytz@typesafe.com> | 2016-05-13 15:35:42 +0200 |
commit | 9e30bee0c9363f6cf36a7b65ddbaaa225b57d6a9 (patch) | |
tree | 49c6ec5a251514c114d92639bca03e0feea355c2 | |
parent | 554af4da73f812bf275d58589da4374fbbfa92a8 (diff) | |
download | scala-9e30bee0c9363f6cf36a7b65ddbaaa225b57d6a9.tar.gz scala-9e30bee0c9363f6cf36a7b65ddbaaa225b57d6a9.tar.bz2 scala-9e30bee0c9363f6cf36a7b65ddbaaa225b57d6a9.zip |
Add summary reporting to Scaladoc (#5063)
-rw-r--r-- | src/scaladoc/scala/tools/ant/Scaladoc.scala | 4 | ||||
-rw-r--r-- | src/scaladoc/scala/tools/nsc/ScalaDoc.scala | 51 | ||||
-rw-r--r-- | src/scaladoc/scala/tools/nsc/doc/DocFactory.scala | 16 | ||||
-rw-r--r-- | src/scaladoc/scala/tools/nsc/doc/html/Doclet.scala | 13 | ||||
-rw-r--r-- | src/scaladoc/scala/tools/nsc/doc/html/HtmlFactory.scala | 5 | ||||
-rw-r--r-- | src/scaladoc/scala/tools/nsc/doc/html/HtmlPage.scala | 3 | ||||
-rw-r--r-- | src/scaladoc/scala/tools/nsc/doc/html/page/Entity.scala | 12 |
7 files changed, 81 insertions, 23 deletions
diff --git a/src/scaladoc/scala/tools/ant/Scaladoc.scala b/src/scaladoc/scala/tools/ant/Scaladoc.scala index b38aadd328..63d3b4ce27 100644 --- a/src/scaladoc/scala/tools/ant/Scaladoc.scala +++ b/src/scaladoc/scala/tools/ant/Scaladoc.scala @@ -14,8 +14,8 @@ import org.apache.tools.ant.Project import org.apache.tools.ant.types.{Path, Reference} import org.apache.tools.ant.util.{FileUtils, GlobPatternMapper} +import scala.tools.nsc.ScalaDocReporter import scala.tools.nsc.doc.Settings -import scala.tools.nsc.reporters.ConsoleReporter /** An Ant task to document Scala code. * @@ -666,7 +666,7 @@ class Scaladoc extends ScalaMatchingTask { /** Performs the compilation. */ override def execute() = { val (docSettings, sourceFiles) = initialize - val reporter = new ConsoleReporter(docSettings) + val reporter = new ScalaDocReporter(docSettings) try { val docProcessor = new scala.tools.nsc.doc.DocFactory(reporter, docSettings) docProcessor.document(sourceFiles.map (_.toString)) diff --git a/src/scaladoc/scala/tools/nsc/ScalaDoc.scala b/src/scaladoc/scala/tools/nsc/ScalaDoc.scala index bd00c27f7b..e266f7beea 100644 --- a/src/scaladoc/scala/tools/nsc/ScalaDoc.scala +++ b/src/scaladoc/scala/tools/nsc/ScalaDoc.scala @@ -8,7 +8,8 @@ package scala.tools.nsc import scala.tools.nsc.doc.DocFactory import scala.tools.nsc.reporters.ConsoleReporter -import scala.reflect.internal.util.FakePos +import scala.reflect.internal.Reporter +import scala.reflect.internal.util.{ FakePos, NoPosition, Position } /** The main class for scaladoc, a front-end for the Scala compiler * that generates documentation from source files. @@ -38,23 +39,43 @@ class ScalaDoc { reporter.echo(command.usageMsg) else try { new DocFactory(reporter, docSettings) document command.files } - catch { - case ex @ FatalError(msg) => - if (docSettings.debug.value) ex.printStackTrace() - reporter.error(null, "fatal error: " + msg) - } - finally reporter.printSummary() + catch { + case ex @ FatalError(msg) => + if (docSettings.debug.value) ex.printStackTrace() + reporter.error(null, "fatal error: " + msg) + } + finally reporter.printSummary() !reporter.reallyHasErrors } } +/** The Scaladoc reporter adds summary messages to the `ConsoleReporter` + * + * Use the `summaryX` methods to add unique summarizing message to the end of + * the run. + */ class ScalaDocReporter(settings: Settings) extends ConsoleReporter(settings) { + import scala.collection.mutable.LinkedHashMap // need to do sometimes lie so that the Global instance doesn't // trash all the symbols just because there was an error override def hasErrors = false def reallyHasErrors = super.hasErrors + + private[this] val delayedMessages: LinkedHashMap[(Position, String), () => Unit] = + LinkedHashMap.empty + + /** Eliminates messages if both `pos` and `msg` are equal to existing element */ + def addDelayedMessage(pos: Position, msg: String, print: () => Unit): Unit = + delayedMessages += ((pos, msg) -> print) + + def printDelayedMessages(): Unit = delayedMessages.values.foreach(_.apply()) + + override def printSummary(): Unit = { + printDelayedMessages() + super.printSummary() + } } object ScalaDoc extends ScalaDoc { @@ -70,4 +91,20 @@ object ScalaDoc extends ScalaDoc { def main(args: Array[String]): Unit = sys exit { if (process(args)) 0 else 1 } + + implicit class SummaryReporter(val rep: Reporter) extends AnyVal { + /** Adds print lambda to ScalaDocReporter, executes it on other reporter */ + private[this] def summaryMessage(pos: Position, msg: String, print: () => Unit): Unit = rep match { + case r: ScalaDocReporter => r.addDelayedMessage(pos, msg, print) + case _ => print() + } + + def summaryEcho(pos: Position, msg: String): Unit = summaryMessage(pos, msg, () => rep.echo(pos, msg)) + def summaryError(pos: Position, msg: String): Unit = summaryMessage(pos, msg, () => rep.error(pos, msg)) + def summaryWarning(pos: Position, msg: String): Unit = summaryMessage(pos, msg, () => rep.warning(pos, msg)) + + def summaryEcho(msg: String): Unit = summaryEcho(NoPosition, msg) + def summaryError(msg: String): Unit = summaryError(NoPosition, msg) + def summaryWarning(msg: String): Unit = summaryWarning(NoPosition, msg) + } } diff --git a/src/scaladoc/scala/tools/nsc/doc/DocFactory.scala b/src/scaladoc/scala/tools/nsc/doc/DocFactory.scala index fb6c39d7e3..8c646be9c6 100644 --- a/src/scaladoc/scala/tools/nsc/doc/DocFactory.scala +++ b/src/scaladoc/scala/tools/nsc/doc/DocFactory.scala @@ -6,8 +6,8 @@ package scala.tools.nsc package doc -import scala.util.control.ControlThrowable import reporters.Reporter +import scala.util.control.ControlThrowable import scala.reflect.internal.util.BatchSourceFile /** A documentation processor controls the process of generating Scala @@ -105,7 +105,19 @@ class DocFactory(val reporter: Reporter, val settings: doc.Settings) { processor def generate() = { import doclet._ val docletClass = Class.forName(settings.docgenerator.value) // default is html.Doclet - val docletInstance = docletClass.newInstance().asInstanceOf[Generator] + val docletInstance = + docletClass + .getConstructors + .find { constr => + constr.getParameterTypes.length == 1 && + constr.getParameterTypes.apply(0) == classOf[scala.reflect.internal.Reporter] + } + .map(_.newInstance(reporter)) + .getOrElse{ + reporter.warning(null, "Doclets should be created with the Reporter constructor, otherwise logging reporters will not be shared by the creating parent") + docletClass.newInstance() + } + .asInstanceOf[Generator] docletInstance match { case universer: Universer => diff --git a/src/scaladoc/scala/tools/nsc/doc/html/Doclet.scala b/src/scaladoc/scala/tools/nsc/doc/html/Doclet.scala index 541266e4cc..73a854e995 100644 --- a/src/scaladoc/scala/tools/nsc/doc/html/Doclet.scala +++ b/src/scaladoc/scala/tools/nsc/doc/html/Doclet.scala @@ -7,14 +7,19 @@ package scala.tools.nsc package doc package html +import scala.reflect.internal.Reporter import doclet._ /** The default doclet used by the scaladoc command line tool * when no user-provided doclet is provided. */ -class Doclet extends Generator with Universer { +class Doclet(reporter: Reporter) extends Generator with Universer { - def generateImpl() { - new html.HtmlFactory(universe, new ScalaDocReporter(universe.settings)).generate() - } + @deprecated("Doclets should be created with the Reporter constructor. Otherwise logging reporters will not be shared by the creating parent", "2.12.0") + def this() = this(null) + def generateImpl() = + new html.HtmlFactory( + universe, + if (reporter != null) reporter else new ScalaDocReporter(universe.settings) + ).generate() } diff --git a/src/scaladoc/scala/tools/nsc/doc/html/HtmlFactory.scala b/src/scaladoc/scala/tools/nsc/doc/html/HtmlFactory.scala index 88b84be65e..62620057cb 100644 --- a/src/scaladoc/scala/tools/nsc/doc/html/HtmlFactory.scala +++ b/src/scaladoc/scala/tools/nsc/doc/html/HtmlFactory.scala @@ -12,12 +12,13 @@ import java.io.{ File => JFile } import io.{ Streamable, Directory } import scala.collection._ import page.diagram._ +import scala.reflect.internal.Reporter /** A class that can generate Scaladoc sites to some fixed root folder. * @author David Bernard * @author Gilles Dubochet */ -class HtmlFactory(val universe: doc.Universe, val reporter: ScalaDocReporter) { - import page.IndexScript +class HtmlFactory(val universe: doc.Universe, val reporter: Reporter) { + import page.{IndexScript, EntityPage} /** The character encoding to be used for generated Scaladoc sites. * This value is currently always UTF-8. */ diff --git a/src/scaladoc/scala/tools/nsc/doc/html/HtmlPage.scala b/src/scaladoc/scala/tools/nsc/doc/html/HtmlPage.scala index 0f37f86b3e..6ad51f4f7e 100644 --- a/src/scaladoc/scala/tools/nsc/doc/html/HtmlPage.scala +++ b/src/scaladoc/scala/tools/nsc/doc/html/HtmlPage.scala @@ -13,6 +13,7 @@ import base._ import base.comment._ import model._ +import scala.reflect.internal.Reporter import scala.xml.NodeSeq import scala.xml.Elem import scala.xml.dtd.DocType @@ -27,7 +28,7 @@ abstract class HtmlPage extends Page { thisPage => protected def title: String /** ScalaDoc reporter for error handling */ - protected def reporter: ScalaDocReporter + protected def docletReporter: Reporter /** The page description */ protected def description: String = diff --git a/src/scaladoc/scala/tools/nsc/doc/html/page/Entity.scala b/src/scaladoc/scala/tools/nsc/doc/html/page/Entity.scala index 836d1b4b7d..9dd2c2184d 100644 --- a/src/scaladoc/scala/tools/nsc/doc/html/page/Entity.scala +++ b/src/scaladoc/scala/tools/nsc/doc/html/page/Entity.scala @@ -13,6 +13,7 @@ package page import base._ import base.comment._ +import scala.reflect.internal.Reporter import scala.collection.mutable import scala.xml.{NodeSeq, Text, UnprefixedAttribute} import scala.language.postfixOps @@ -22,10 +23,12 @@ import model.diagram._ import diagram._ trait EntityPage extends HtmlPage { + import ScalaDoc.SummaryReporter + def universe: doc.Universe def generator: DiagramGenerator def tpl: DocTemplateEntity - def reporter: ScalaDocReporter + def docletReporter: Reporter override val path = templateToPath(tpl) @@ -158,8 +161,7 @@ trait EntityPage extends HtmlPage { val version = universe.settings.docversion.value if (version.length > "XX.XX.XX-XXX".length) { - reporter.warning(null, - s"doc-version ($version) is too long to be displayed in the webview") + docletReporter.summaryWarning(s"doc-version ($version) was too long to be displayed in the webview, and will be left out. The max length is: XX.XX.XX-XXX") "" } else version } @@ -1124,12 +1126,12 @@ object EntityPage { uni: doc.Universe, gen: DiagramGenerator, docTpl: DocTemplateEntity, - rep: ScalaDocReporter + rep: Reporter ): EntityPage = new EntityPage { def universe = uni def generator = gen def tpl = docTpl - def reporter = rep + def docletReporter = rep } /* Vlad: Lesson learned the hard way: don't put any stateful code that references the model here, |