aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/reporting/Reporter.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-07-19 19:08:42 +0200
committerMartin Odersky <odersky@gmail.com>2013-07-19 19:08:42 +0200
commit919310a29daebabe3335d428f5f5e52ed6295cbd (patch)
tree8f8e898afb10b3735cd1aa6101f19b19fbf18682 /src/dotty/tools/dotc/reporting/Reporter.scala
parent702c4fc89f3ff2abbc7457fd72ab19b5bbdbb782 (diff)
downloaddotty-919310a29daebabe3335d428f5f5e52ed6295cbd.tar.gz
dotty-919310a29daebabe3335d428f5f5e52ed6295cbd.tar.bz2
dotty-919310a29daebabe3335d428f5f5e52ed6295cbd.zip
Made reporting framework more lightweight and uniform in preparation of future integration of reporters in typerstate.
Diffstat (limited to 'src/dotty/tools/dotc/reporting/Reporter.scala')
-rw-r--r--src/dotty/tools/dotc/reporting/Reporter.scala190
1 files changed, 104 insertions, 86 deletions
diff --git a/src/dotty/tools/dotc/reporting/Reporter.scala b/src/dotty/tools/dotc/reporting/Reporter.scala
index 851aa084d..2f580c2f9 100644
--- a/src/dotty/tools/dotc/reporting/Reporter.scala
+++ b/src/dotty/tools/dotc/reporting/Reporter.scala
@@ -10,37 +10,88 @@ import collection.mutable
import config.Settings.Setting
import java.lang.System.currentTimeMillis
+object Reporter {
+ class Diagnostic(msgFn: => String, val pos: SourcePosition, val severity: Severity) {
+ lazy val msg: String = msgFn
+ override def toString = s"$severity at $pos: $msg"
+ }
+
+ class Severity(val level: Int) extends AnyVal {
+ override def toString = this match {
+ case VerboseINFO => "VerboseINFO"
+ case INFO => "INFO"
+ case DeprecationWARNING => "DeprecationWARNING"
+ case UncheckedWARNING => "UncheckedWARNING"
+ case FeatureWARNING => "FeatureWARNING"
+ case WARNING => "WARNING"
+ case ERROR => "ERROR"
+ }
+ }
+
+ final val VerboseINFO = new Severity(0)
+ final val INFO = new Severity(1)
+ final val DeprecationWARNING = new Severity(2)
+ final val UncheckedWARNING = new Severity(3)
+ final val FeatureWARNING = new Severity(4)
+ final val WARNING = new Severity(5)
+ final val ERROR = new Severity(6)
+
+ def isConditionalWarning(s: Severity) =
+ DeprecationWARNING.level <= s.level && s.level <= FeatureWARNING.level
+
+ val conditionalWarnings = List(DeprecationWARNING, UncheckedWARNING, FeatureWARNING)
+}
+
+import Reporter._
+
trait Reporting { this: Context =>
- def error(msg: String, pos: SourcePosition = NoSourcePosition): Unit = reporter.error(msg, pos)
- def warning(msg: String, pos: SourcePosition = NoSourcePosition): Unit = reporter.warning(msg, pos)
- def inform(msg: String, pos: SourcePosition = NoSourcePosition): Unit = reporter.info(msg, pos)
+
+ /** For sending messages that are printed only if -verbose is set */
+ def inform(msg: => String, pos: SourcePosition = NoSourcePosition): Unit =
+ reporter.report(new Diagnostic(msg, pos, VerboseINFO))
+
+ def echo(msg: => String, pos: SourcePosition = NoSourcePosition): Unit =
+ reporter.report(new Diagnostic(msg, pos, INFO))
+
+ def deprecationWarning(msg: => String, pos: SourcePosition = NoSourcePosition): Unit =
+ reporter.report(new Diagnostic(msg, pos, DeprecationWARNING))
+
+ def uncheckedWarning(msg: => String, pos: SourcePosition = NoSourcePosition): Unit =
+ reporter.report(new Diagnostic(msg, pos, UncheckedWARNING))
+
+ def featureWarning(msg: => String, pos: SourcePosition = NoSourcePosition): Unit =
+ reporter.report(new Diagnostic(msg, pos, FeatureWARNING))
+
+ def warning(msg: => String, pos: SourcePosition = NoSourcePosition): Unit =
+ reporter.report(new Diagnostic(msg, pos, WARNING))
+
+ def error(msg: => String, pos: SourcePosition = NoSourcePosition): Unit =
+ reporter.report(new Diagnostic(msg, pos, ERROR))
+
+ def incompleteInputError(msg: String, pos: SourcePosition = NoSourcePosition)(implicit ctx: Context): Unit =
+ reporter.incomplete(new Diagnostic(msg, pos, ERROR))(ctx)
def log(msg: => String): Unit =
if (this.settings.log.value.containsPhase(phase))
- inform(s"[log ${ctx.phasesStack.reverse.mkString(" -> ")}] $msg")
+ echo(s"[log ${ctx.phasesStack.reverse.mkString(" -> ")}] $msg")
def debuglog(msg: => String): Unit =
if (ctx.debug) log(msg)
- def informTime(msg: => String, start: Long): Unit =
- informProgress(msg + elapsed(start))
-
- def deprecation = reporter.deprecation
- def unchecked = reporter.unchecked
- def feature = reporter.feature
-
- private def elapsed(start: Long) =
- " in " + (currentTimeMillis - start) + "ms"
+ def informTime(msg: => String, start: Long): Unit = {
+ def elapsed = s" in ${currentTimeMillis - start}ms"
+ informProgress(msg + elapsed)
+ }
def informProgress(msg: => String) =
- if (this.settings.verbose.value) inform("[" + msg + "]")
+ inform("[" + msg + "]")
def trace[T](msg: => String)(value: T) = {
log(msg + " " + value)
value
}
- def debugwarn(msg: String, pos: SourcePosition = NoSourcePosition): Unit =
+ def debugwarn(msg: => String, pos: SourcePosition = NoSourcePosition): Unit =
if (this.settings.debug.value) warning(msg, pos)
def debugTraceIndented[T](question: => String)(op: => T): T =
@@ -72,27 +123,14 @@ trait Reporting { this: Context =>
}
}
-object Reporter {
- object Severity extends Enumeration {
- val INFO, WARNING, ERROR = Value
- }
-}
-
/**
* This interface provides methods to issue information, warning and
* error messages.
*/
abstract class Reporter(ctx: Context) {
- import Reporter.Severity.{Value => Severity, _}
-
- protected def report(msg: String, severity: Severity, pos: SourcePosition)(implicit ctx: Context): Unit
-
- protected def isHidden(severity: Severity, pos: SourcePosition)(implicit ctx: Context) = false
-
- val count = new mutable.HashMap[Severity, Int]() {
- override def default(key: Severity) = 0
- }
+ /** Report a diagnostic */
+ protected def doReport(d: Diagnostic)(implicit ctx: Context): Unit
/** Whether very long lines can be truncated. This exists so important
* debugging information (like printing the classpath) is not rendered
@@ -107,8 +145,8 @@ abstract class Reporter(ctx: Context) {
finally _truncationOK = saved
}
- type ErrorHandler = (String, SourcePosition, Context) => Unit
- private var incompleteHandler: ErrorHandler = error(_, _)(_)
+ type ErrorHandler = Diagnostic => Context => Unit
+ private var incompleteHandler: ErrorHandler = d => c => report(d)(c)
def withIncompleteHandler[T](handler: ErrorHandler)(op: => T): T = {
val saved = incompleteHandler
incompleteHandler = handler
@@ -116,35 +154,34 @@ abstract class Reporter(ctx: Context) {
finally incompleteHandler = saved
}
- def hasErrors = count(ERROR) > 0
- def hasWarnings = count(WARNING) > 0
+ protected def isHidden(s: Severity, pos: SourcePosition)(implicit ctx: Context) = s match {
+ case VerboseINFO => !ctx.settings.verbose.value
+ case DeprecationWARNING | UncheckedWARNING | FeatureWARNING => true
+ case _ => false
+ }
- /** For sending messages that are printed only if -verbose is set */
- def info(msg: String, pos: SourcePosition = NoSourcePosition)(implicit ctx: Context): Unit =
- if (ctx.settings.verbose.value) info0(msg, INFO, pos)
+ private def enablingOption(warning: Severity)(implicit ctx: Context) = warning match {
+ case DeprecationWARNING => ctx.settings.deprecation
+ case UncheckedWARNING => ctx.settings.unchecked
+ case FeatureWARNING => ctx.settings.feature
+ }
- /** For sending a message which should not be labeled as a warning/error,
- * but also shouldn't require -verbose to be visible.
- */
- def echo(msg: String, pos: SourcePosition = NoSourcePosition)(implicit ctx: Context): Unit =
- info0(msg, INFO, pos)
+ private def promoteSeverity(s: Severity)(implicit ctx: Context): Severity =
+ if (isConditionalWarning(s) && enablingOption(s).value) WARNING else s
- def warning(msg: String, pos: SourcePosition = NoSourcePosition)(implicit ctx: Context): Unit =
- if (!ctx.settings.nowarn.value)
- withoutTruncating(info0(msg, WARNING, pos))
+ val count = new Array[Int](ERROR.level + 1)
- def error(msg: String, pos: SourcePosition = NoSourcePosition)(implicit ctx: Context): Unit =
- withoutTruncating(info0(msg, ERROR, pos))
+ def report(d: Diagnostic)(implicit ctx: Context): Unit = {
+ val severity = promoteSeverity(d.severity)
+ if (!isHidden(severity, d.pos)) doReport(d)
+ count(severity.level) += 1
+ }
- def incompleteInputError(msg: String, pos: SourcePosition = NoSourcePosition)(implicit ctx: Context): Unit =
- incompleteHandler(msg, pos, ctx)
+ def incomplete(d: Diagnostic)(implicit ctx: Context): Unit =
+ incompleteHandler(d)(ctx)
- private def info0(msg: String, severity: Severity, pos: SourcePosition)(implicit ctx: Context): Unit = {
- if (!isHidden(severity, pos)) {
- count(severity) += 1
- report(msg, severity, pos)
- }
- }
+ def hasErrors = count(ERROR.level) > 0
+ def hasWarnings = count(WARNING.level) > 0
/** Returns a string meaning "n elements". */
private def countElementsAsString(n: Int, elements: String): String =
@@ -158,46 +195,27 @@ abstract class Reporter(ctx: Context) {
}
protected def label(severity: Severity): String = severity match {
- case INFO => ""
case ERROR => "error: "
case WARNING => "warning: "
+ case _ => ""
}
protected def countString(severity: Severity) = {
- assert(severity != INFO)
- countElementsAsString(count(severity), label(severity).dropRight(2))
+ assert(severity.level >= WARNING.level)
+ countElementsAsString(count(severity.level), label(severity).dropRight(2))
}
def printSummary(implicit ctx: Context) {
- if (count(WARNING) > 0) info(countString(WARNING) + " found")
- if ( count(ERROR) > 0) info(countString(ERROR ) + " found")
- allConditionalWarnings foreach (_.summarize)
+ if (count(WARNING.level) > 0) ctx.echo(countString(WARNING) + " found")
+ if ( count(ERROR.level) > 0) ctx.echo(countString(ERROR ) + " found")
+ for (cwarning <- conditionalWarnings) {
+ val unreported = count(cwarning.level)
+ if (unreported > 0) {
+ val what = enablingOption(cwarning).name.tail
+ ctx.warning(s"there were $unreported $what warning(s); re-run with -$what for details")
+ }
+ }
}
def flush(): Unit = {}
-
- def reset(): Unit = {
- count.clear()
- allConditionalWarnings foreach (_.clear())
- }
-
- protected val allConditionalWarnings = new mutable.ListBuffer[ConditionalWarning]
-
- val deprecation = new ConditionalWarning("deprecation", ctx.settings.deprecation)
- val unchecked = new ConditionalWarning("unchecked", ctx.settings.unchecked)
- val feature = new ConditionalWarning("feature", ctx.settings.feature)
-
- /** Collects for certain classes of warnings during this run. */
- class ConditionalWarning(what: String, option: Setting[Boolean]) {
- private var unreported: Int = 0
- def clear() =
- unreported = 0
- def warning(msg: String, pos: SourcePosition = NoSourcePosition)(implicit ctx: Context) =
- if (option.value) Reporter.this.warning(msg, pos)
- else unreported += 1
- def summarize(implicit ctx: Context) =
- if (unreported > 0)
- Reporter.this.warning(s"there were $unreported $what warning(s); re-run with ${option.name} for details")
- allConditionalWarnings += this
- }
}