diff options
author | Martin Odersky <odersky@gmail.com> | 2013-07-19 19:08:42 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2013-07-19 19:08:42 +0200 |
commit | 919310a29daebabe3335d428f5f5e52ed6295cbd (patch) | |
tree | 8f8e898afb10b3735cd1aa6101f19b19fbf18682 /src/dotty/tools/dotc/reporting/Reporter.scala | |
parent | 702c4fc89f3ff2abbc7457fd72ab19b5bbdbb782 (diff) | |
download | dotty-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.scala | 190 |
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 - } } |