diff options
Diffstat (limited to 'src/dotty/tools/dotc/reporting/Reporter.scala')
-rw-r--r-- | src/dotty/tools/dotc/reporting/Reporter.scala | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/src/dotty/tools/dotc/reporting/Reporter.scala b/src/dotty/tools/dotc/reporting/Reporter.scala new file mode 100644 index 000000000..862e665ae --- /dev/null +++ b/src/dotty/tools/dotc/reporting/Reporter.scala @@ -0,0 +1,133 @@ +package dotty.tools +package dotc +package reporting + +import core.Contexts._ +import core.Positions._ +import core.Decorators.PhaseListDecorator +import collection.mutable +import io.{SourceFile, NoSource} +import java.lang.System.currentTimeMillis + +trait Reporting { this: Context => + def error(msg: String, pos: Position = NoPosition): Unit = reporter.error(msg, pos) + def warning(msg: String, pos: Position = NoPosition): Unit = reporter.warning(msg, pos) + def inform(msg: String, pos: Position = NoPosition): Unit = reporter.info(msg, pos) + + def log(msg: => String)(implicit ctx: Context): Unit = + if (this.settings.log.value.containsPhase(phase)) + inform(s"[log ${ctx.phasesStack.reverse.mkString(" -> ")}] $msg") + + def debuglog(msg: => String)(implicit ctx: Context): Unit = + if (ctx.settings.debug.value) log(msg) + + def informTime(msg: => String, start: Long)(implicit ctx: Context): Unit = + informProgress(msg + elapsed(start)) + + private def elapsed(start: Long) = + " in " + (currentTimeMillis - start) + "ms" + + def informProgress(msg: => String)(implicit ctx: Context) = + if (ctx.settings.verbose.value) inform("[" + msg + "]") +} + +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 { + + import Reporter.Severity.{Value => Severity, _} + + protected def report(msg: String, severity: Severity, pos: Position)(implicit ctx: Context): Unit + + protected def isHidden(severity: Severity, pos: Position)(implicit ctx: Context) = false + + val count = new mutable.HashMap[Severity, Int]() { + override def default(key: Severity) = 0 + } + + /** Whether very long lines can be truncated. This exists so important + * debugging information (like printing the classpath) is not rendered + * invisible due to the max message length. + */ + private var _truncationOK: Boolean = true + def truncationOK = _truncationOK + def withoutTruncating[T](body: => T): T = { + val saved = _truncationOK + _truncationOK = false + try body + finally _truncationOK = saved + } + + type ErrorHandler = (String, Position, Context) => Unit + private var incompleteHandler: ErrorHandler = error(_, _)(_) + def withIncompleteHandler[T](handler: ErrorHandler)(op: => T): T = { + val saved = incompleteHandler + incompleteHandler = handler + try op + finally incompleteHandler = saved + } + + def hasErrors = count(ERROR) > 0 + def hasWarnings = count(WARNING) > 0 + + /** For sending messages that are printed only if -verbose is set */ + def info(msg: String, pos: Position = NoPosition)(implicit ctx: Context): Unit = + if (ctx.settings.verbose.value) info0(msg, INFO, pos) + + /** 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: Position = NoPosition)(implicit ctx: Context): Unit = + info0(msg, INFO, pos) + + def warning(msg: String, pos: Position = NoPosition)(implicit ctx: Context): Unit = + if (!ctx.settings.nowarn.value) + withoutTruncating(info0(msg, WARNING, pos)) + + def error(msg: String, pos: Position = NoPosition)(implicit ctx: Context): Unit = + withoutTruncating(info0(msg, ERROR, pos)) + + def incompleteInputError(msg: String, pos: Position = NoPosition)(implicit ctx: Context): Unit = + incompleteHandler(msg, pos, ctx) + + private def info0(msg: String, severity: Severity, pos: Position)(implicit ctx: Context): Unit = { + if (!isHidden(severity, pos)) { + count(severity) += 1 + report(msg, severity, pos) + } + } + + /** Returns a string meaning "n elements". */ + private def countElementsAsString(n: Int, elements: String): String = + n match { + case 0 => "no " + elements + "s" + case 1 => "one " + elements + case 2 => "two " + elements + "s" + case 3 => "three " + elements + "s" + case 4 => "four " + elements + "s" + case _ => n + " " + elements + "s" + } + + protected def label(severity: Severity): String = severity match { + case INFO => "" + case ERROR => "error: " + case WARNING => "warning: " + } + + protected def countString(severity: Severity) = { + assert(severity != INFO) + countElementsAsString(count(severity), label(severity).dropRight(2)) + } + + def flush(): Unit = {} + + def reset(): Unit = count.clear() +} |