aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/reporting/ConsoleReporter.scala8
-rw-r--r--src/dotty/tools/dotc/reporting/Reporter.scala72
-rw-r--r--src/dotty/tools/dotc/reporting/UniqueMessagePositions.scala14
-rw-r--r--src/dotty/tools/dotc/typer/ErrorReporting.scala59
4 files changed, 104 insertions, 49 deletions
diff --git a/src/dotty/tools/dotc/reporting/ConsoleReporter.scala b/src/dotty/tools/dotc/reporting/ConsoleReporter.scala
index ae677ecdc..6b3f08cf0 100644
--- a/src/dotty/tools/dotc/reporting/ConsoleReporter.scala
+++ b/src/dotty/tools/dotc/reporting/ConsoleReporter.scala
@@ -40,11 +40,11 @@ class ConsoleReporter(
}
}
- override def doReport(d: Diagnostic)(implicit ctx: Context) {
- if (d.severity != ERROR || count(d.severity.level) <= ErrorLimit)
+ override def doReport(d: Diagnostic)(implicit ctx: Context): Unit =
+ if (d.severity != ERROR || count(d.severity.level) <= ErrorLimit && !d.isSuppressed) {
printMessageAndPos(label(d.severity) + d.msg, d.pos)
- if (d.severity.level > INFO.level && ctx.settings.prompt.value) displayPrompt()
- }
+ if (d.severity.level > INFO.level && ctx.settings.prompt.value) displayPrompt()
+ }
def displayPrompt(): Unit = {
writer.print("\na)bort, s)tack, r)esume: ")
diff --git a/src/dotty/tools/dotc/reporting/Reporter.scala b/src/dotty/tools/dotc/reporting/Reporter.scala
index 5ebc5934f..be2136655 100644
--- a/src/dotty/tools/dotc/reporting/Reporter.scala
+++ b/src/dotty/tools/dotc/reporting/Reporter.scala
@@ -12,12 +12,33 @@ import java.lang.System.currentTimeMillis
object Reporter {
- class Diagnostic(msgFn: => String, val pos: SourcePosition, val severity: Severity) extends Exception {
- lazy val msg: String = msgFn
+ class Diagnostic(msgFn: => String, val pos: SourcePosition, val severity: Severity, base: ContextBase) extends Exception {
+ private var myMsg: String = null
+ private var myIsSuppressed: Boolean = false
+ def msg: String = {
+ if (myMsg == null)
+ try myMsg = msgFn
+ catch {
+ case ex: SuppressedMessage =>
+ val saved = base.suppressNonSensicalErrors
+ base.suppressNonSensicalErrors = false
+ try myMsg = msgFn
+ finally base.suppressNonSensicalErrors = saved
+ }
+ myMsg
+ }
+ def isSuppressed = { msg; myIsSuppressed }
override def toString = s"$severity at $pos: $msg"
override def getMessage() = msg
+
+ def promotedSeverity(implicit ctx: Context): Severity =
+ if (isConditionalWarning(severity) && enablingOption(severity).value) WARNING
+ else severity
}
+ def Diagnostic(msgFn: => String, pos: SourcePosition, severity: Severity)(implicit ctx: Context) =
+ new Diagnostic(msgFn, pos, severity, ctx.base)
+
class Severity(val level: Int) extends AnyVal {
override def toString = this match {
case VerboseINFO => "VerboseINFO"
@@ -42,6 +63,14 @@ object Reporter {
DeprecationWARNING.level <= s.level && s.level <= FeatureWARNING.level
val conditionalWarnings = List(DeprecationWARNING, UncheckedWARNING, FeatureWARNING)
+
+ 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
+ }
+
+ class SuppressedMessage extends Exception
}
import Reporter._
@@ -50,28 +79,28 @@ trait Reporting { this: Context =>
/** 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))
+ reporter.report(Diagnostic(msg, pos, VerboseINFO))
def echo(msg: => String, pos: SourcePosition = NoSourcePosition): Unit =
- reporter.report(new Diagnostic(msg, pos, INFO))
+ reporter.report(Diagnostic(msg, pos, INFO))
def deprecationWarning(msg: => String, pos: SourcePosition = NoSourcePosition): Unit =
- reporter.report(new Diagnostic(msg, pos, DeprecationWARNING))
+ reporter.report(Diagnostic(msg, pos, DeprecationWARNING))
def uncheckedWarning(msg: => String, pos: SourcePosition = NoSourcePosition): Unit =
- reporter.report(new Diagnostic(msg, pos, UncheckedWARNING))
+ reporter.report(Diagnostic(msg, pos, UncheckedWARNING))
def featureWarning(msg: => String, pos: SourcePosition = NoSourcePosition): Unit =
- reporter.report(new Diagnostic(msg, pos, FeatureWARNING))
+ reporter.report(Diagnostic(msg, pos, FeatureWARNING))
def warning(msg: => String, pos: SourcePosition = NoSourcePosition): Unit =
- reporter.report(new Diagnostic(msg, pos, WARNING))
+ reporter.report(Diagnostic(msg, pos, WARNING))
def error(msg: => String, pos: SourcePosition = NoSourcePosition): Unit =
- reporter.report(new Diagnostic(msg, pos, ERROR))
+ reporter.report(Diagnostic(msg, pos, ERROR))
def incompleteInputError(msg: String, pos: SourcePosition = NoSourcePosition)(implicit ctx: Context): Unit =
- reporter.incomplete(new Diagnostic(msg, pos, ERROR))(ctx)
+ reporter.incomplete(Diagnostic(msg, pos, ERROR))(ctx)
def log(msg: => String): Unit =
if (this.settings.log.value.containsPhase(phase))
@@ -134,7 +163,7 @@ abstract class Reporter {
/** Report a diagnostic */
protected def doReport(d: Diagnostic)(implicit ctx: Context): Unit
- /** Whether very long lines can be truncated. This exists so important
+ /** 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.
*/
@@ -156,28 +185,19 @@ abstract class Reporter {
finally incompleteHandler = saved
}
- protected def isHidden(s: Severity, pos: SourcePosition)(implicit ctx: Context) = s match {
+ protected def isHidden(d: Diagnostic)(implicit ctx: Context) = d.promotedSeverity match {
case VerboseINFO => !ctx.settings.verbose.value
case DeprecationWARNING | UncheckedWARNING | FeatureWARNING => true
case _ => false
}
- 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
- }
-
- private def promoteSeverity(s: Severity)(implicit ctx: Context): Severity =
- if (isConditionalWarning(s) && enablingOption(s).value) WARNING else s
-
val count = new Array[Int](ERROR.level + 1)
- 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 report(d: Diagnostic)(implicit ctx: Context): Unit =
+ if (!isHidden(d)) {
+ doReport(d)
+ count(d.promotedSeverity.level) += 1
+ }
def incomplete(d: Diagnostic)(implicit ctx: Context): Unit =
incompleteHandler(d)(ctx)
diff --git a/src/dotty/tools/dotc/reporting/UniqueMessagePositions.scala b/src/dotty/tools/dotc/reporting/UniqueMessagePositions.scala
index b14b842d0..93e24b27f 100644
--- a/src/dotty/tools/dotc/reporting/UniqueMessagePositions.scala
+++ b/src/dotty/tools/dotc/reporting/UniqueMessagePositions.scala
@@ -4,7 +4,7 @@ package reporting
import scala.collection.mutable
import util.{SourcePosition, SourceFile}
-import Reporter.Severity
+import Reporter.{Severity, Diagnostic}
import core.Contexts.Context
/**
@@ -18,12 +18,12 @@ trait UniqueMessagePositions extends Reporter {
/** Logs a position and returns true if it was already logged.
* @note Two positions are considered identical for logging if they have the same point.
*/
- override def isHidden(severity: Severity, pos: SourcePosition)(implicit ctx: Context): Boolean =
- super.isHidden(severity, pos) || {
- pos.exists && {
- positions get (ctx.source, pos.point) match {
- case Some(s) if s.level >= severity.level => true
- case _ => positions((ctx.source, pos.point)) = severity; false
+ override def isHidden(d: Diagnostic)(implicit ctx: Context): Boolean =
+ super.isHidden(d) || {
+ d.pos.exists && {
+ positions get (ctx.source, d.pos.point) match {
+ case Some(s) if s.level >= d.severity.level => true
+ case _ => positions((ctx.source, d.pos.point)) = d.severity; false
}
}
}
diff --git a/src/dotty/tools/dotc/typer/ErrorReporting.scala b/src/dotty/tools/dotc/typer/ErrorReporting.scala
index 7a91adde6..bf2d19e85 100644
--- a/src/dotty/tools/dotc/typer/ErrorReporting.scala
+++ b/src/dotty/tools/dotc/typer/ErrorReporting.scala
@@ -5,9 +5,11 @@ package typer
import ast._
import core._
import Trees._
-import Types._, Contexts._, Decorators._, Denotations._
+import Types._, Contexts._, Decorators._, Denotations._, Symbols._
import Applications._
import util.Positions._
+import printing.Showable
+import reporting.Reporter.SuppressedMessage
object ErrorReporting {
@@ -27,11 +29,11 @@ object ErrorReporting {
case tp: FunProtoType =>
val result = tp.resultType match {
case tp: WildcardType => ""
- case tp => s"and expected result type $tp"
+ case tp => i"and expected result type $tp"
}
- s"arguments (${tp.typedArgs map (_.tpe.show) mkString ", "})$result"
+ i"arguments (${tp.typedArgs.tpes}%, %)$result"
case _ =>
- s"expected type ${tp.show}"
+ i"expected type $tp"
}
def anonymousTypeMemberStr(tpe: Type) = {
@@ -40,12 +42,12 @@ object ErrorReporting {
case _: PolyType | _: MethodType => "method"
case _ => "value of type"
}
- s"$kind $tpe"
+ i"$kind $tpe"
}
def overloadedAltsStr(alts: List[SingleDenotation]) =
- s"overloaded alternatives of ${denotStr(alts.head)} with types\n" +
- s" ${alts map (_.info) mkString "\n "}"
+ i"overloaded alternatives of ${denotStr(alts.head)} with types\n" +
+ i" ${alts map (_.info)}%\n %"
def denotStr(denot: Denotation): String =
if (denot.isOverloaded) overloadedAltsStr(denot.alternatives)
@@ -61,13 +63,46 @@ object ErrorReporting {
def patternConstrStr(tree: Tree): String = ???
- def typeMismatch(tree: Tree, pt: Type): Tree =
- errorTree(tree,
- s"""type mismatch:
- | found : ${tree.tpe.show}
- | required: ${pt.show}""".stripMargin)
+ def typeMismatch(tree: Tree, pt: Type): Tree = {
+ val result = errorTree(tree,
+ i"""type mismatch:
+ | found : ${tree.tpe}
+ | required: $pt""".stripMargin)
+ if (ctx.settings.explaintypes.value)
+ new ExplainingTypeComparer().isSubType(tree.tpe, pt)
+ result
+ }
}
def err(implicit ctx: Context): Errors = new Errors
+
+ def isSensical(arg: Any)(implicit ctx: Context): Boolean = arg match {
+ case tpe: Type if tpe.isErroneous => false
+ case NoSymbol => false
+ case _ => true
+ }
+
+ def treatArg(arg: Any, suffix: String)(implicit ctx: Context): (Any, String) = arg match {
+ case arg: Showable =>
+ (arg.show, suffix)
+ case arg: List[_] if suffix.head == '%' =>
+ val (sep, rest) = suffix.tail.span(_ != '%')
+ if (rest.nonEmpty) (arg mkString sep, rest.tail)
+ else (arg, suffix)
+ case _ =>
+ (arg, suffix)
+ }
+
+ /** Implementation of i"..." string interpolator */
+ implicit class InfoString(val sc: StringContext) extends AnyVal {
+
+ def i(args: Any*)(implicit ctx: Context): String = {
+ if (ctx.reporter.hasErrors && ctx.suppressNonSensicalErrors && !args.forall(isSensical(_)))
+ throw new SuppressedMessage
+ val prefix :: suffixes = sc.parts.toList
+ val (args1, suffixes1) = (args, suffixes).zipped.map(treatArg(_, _)).unzip
+ new StringContext(prefix :: suffixes1.toList: _*).s(args1: _*)
+ }
+ }
} \ No newline at end of file