diff options
author | Adriaan Moors <adriaan.moors@typesafe.com> | 2014-07-06 23:47:33 +0200 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@typesafe.com> | 2014-07-06 23:47:33 +0200 |
commit | 75ac2250156dc36f072d44b82b5b82dc155691d8 (patch) | |
tree | f511cd45fd3e7783c8b124df3863d1317a8b5af9 | |
parent | b38fc5eaac3eb938902fe56a69e44830d41c1f87 (diff) | |
parent | b384d5070f86e9003e8f1b57cc818520033242ab (diff) | |
download | scala-75ac2250156dc36f072d44b82b5b82dc155691d8.tar.gz scala-75ac2250156dc36f072d44b82b5b82dc155691d8.tar.bz2 scala-75ac2250156dc36f072d44b82b5b82dc155691d8.zip |
Merge pull request #3820 from adriaanm/report-filter
refactor error/warning reporting
86 files changed, 651 insertions, 469 deletions
diff --git a/bincompat-forward.whitelist.conf b/bincompat-forward.whitelist.conf index 3cd985aeae..30dac79974 100644 --- a/bincompat-forward.whitelist.conf +++ b/bincompat-forward.whitelist.conf @@ -234,6 +234,26 @@ filter { { matchName="scala.reflect.runtime.SynchronizedOps.newNestedScope" problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.runtime.JavaUniverse" + problemName=MissingTypesProblem + }, + { + matchName="scala.reflect.runtime.JavaUniverse.reporter" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.runtime.JavaUniverse$PerRunReporting" + problemName=MissingClassProblem + }, + { + matchName="scala.reflect.runtime.JavaUniverse.currentRun" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.runtime.JavaUniverse.PerRunReporting" + problemName=MissingMethodProblem } ] } diff --git a/src/compiler/scala/reflect/macros/contexts/Parsers.scala b/src/compiler/scala/reflect/macros/contexts/Parsers.scala index 88cfea8157..f4584f3627 100644 --- a/src/compiler/scala/reflect/macros/contexts/Parsers.scala +++ b/src/compiler/scala/reflect/macros/contexts/Parsers.scala @@ -9,12 +9,15 @@ trait Parsers { def parse(code: String) = { val sreporter = new StoreReporter() - val unit = new CompilationUnit(newSourceFile(code, "<macro>")) { override def reporter = sreporter } - val parser = newUnitParser(unit) - val tree = gen.mkTreeOrBlock(parser.parseStatsOrPackages()) - sreporter.infos.foreach { - case sreporter.Info(pos, msg, sreporter.ERROR) => throw ParseException(pos, msg) - } - tree + val oldReporter = global.reporter + try { + global.reporter = sreporter + val parser = newUnitParser(new CompilationUnit(newSourceFile(code, "<macro>"))) + val tree = gen.mkTreeOrBlock(parser.parseStatsOrPackages()) + sreporter.infos.foreach { + case sreporter.Info(pos, msg, sreporter.ERROR) => throw ParseException(pos, msg) + } + tree + } finally global.reporter = oldReporter } }
\ No newline at end of file diff --git a/src/compiler/scala/tools/nsc/CompilationUnits.scala b/src/compiler/scala/tools/nsc/CompilationUnits.scala index c2caed70a0..1ad206f519 100644 --- a/src/compiler/scala/tools/nsc/CompilationUnits.scala +++ b/src/compiler/scala/tools/nsc/CompilationUnits.scala @@ -123,31 +123,10 @@ trait CompilationUnits { global: Global => */ val icode: LinkedHashSet[icodes.IClass] = new LinkedHashSet - def reporter = global.reporter + // called by ScalaDocAnalyzer, overridden by the IDE (in Reporter) + // TODO: don't use reporter to communicate comments from parser to IDE! + final def comment(pos: Position, msg: String): Unit = reporter.comment(pos, msg) - def echo(pos: Position, msg: String) = - reporter.echo(pos, msg) - - def error(pos: Position, msg: String) = - reporter.error(pos, msg) - - def warning(pos: Position, msg: String) = - reporter.warning(pos, msg) - - def deprecationWarning(pos: Position, msg: String) = - currentRun.deprecationWarnings0.warn(pos, msg) - - def uncheckedWarning(pos: Position, msg: String) = - currentRun.uncheckedWarnings0.warn(pos, msg) - - def inlinerWarning(pos: Position, msg: String) = - currentRun.inlinerWarnings.warn(pos, msg) - - def incompleteInputError(pos: Position, msg:String) = - reporter.incompleteInputError(pos, msg) - - def comment(pos: Position, msg: String) = - reporter.comment(pos, msg) /** Is this about a .java source file? */ lazy val isJava = source.file.name.endsWith(".java") diff --git a/src/compiler/scala/tools/nsc/CompileServer.scala b/src/compiler/scala/tools/nsc/CompileServer.scala index 6f068e179c..1f3a4237eb 100644 --- a/src/compiler/scala/tools/nsc/CompileServer.scala +++ b/src/compiler/scala/tools/nsc/CompileServer.scala @@ -7,7 +7,7 @@ package scala.tools.nsc import java.io.PrintStream import scala.tools.nsc.reporters.{Reporter, ConsoleReporter} -import scala.reflect.internal.util.FakePos //Position +import scala.reflect.internal.util.{FakePos, Position} import scala.tools.util.SocketServer import settings.FscSettings @@ -37,7 +37,7 @@ class StandardCompileServer extends SocketServer { /** Create a new compiler instance */ def newGlobal(settings: Settings, reporter: Reporter) = new Global(settings, reporter) { - override def inform(msg: String) = out.println(msg) + override def inform(pos: Position, msg: String) = out.println(msg) } override def timeout() { diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index cb785de4b3..572e579aca 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -44,7 +44,8 @@ class Global(var currentSettings: Settings, var reporter: Reporter) with Trees with Printers with DocComments - with Positions { self => + with Positions + with Reporting { self => // the mirror -------------------------------------------------- @@ -227,20 +228,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) */ def registerTopLevelSym(sym: Symbol) {} -// ------------------ Reporting ------------------------------------- - - // not deprecated yet, but a method called "error" imported into - // nearly every trait really must go. For now using globalError. - def error(msg: String) = globalError(msg) - - override def inform(msg: String) = inform(NoPosition, msg) - override def globalError(msg: String) = globalError(NoPosition, msg) - override def warning(msg: String) = warning(NoPosition, msg) - override def deprecationWarning(pos: Position, msg: String) = currentUnit.deprecationWarning(pos, msg) - - def globalError(pos: Position, msg: String) = reporter.error(pos, msg) - def warning(pos: Position, msg: String) = if (settings.fatalWarnings) globalError(pos, msg) else reporter.warning(pos, msg) - def inform(pos: Position, msg: String) = reporter.echo(pos, msg) +// ------------------ Debugging ------------------------------------- // Getting in front of Predef's asserts to supplement with more info. // This has the happy side effect of masking the one argument forms @@ -263,12 +251,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) require(requirement, "") } - // Needs to call error to make sure the compile fails. - override def abort(msg: String): Nothing = { - error(msg) - super.abort(msg) - } - @inline final def ifDebug(body: => Unit) { if (settings.debug) body @@ -291,8 +273,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) log(s"!!!$pos_s $msg") // such warnings always at least logged } - def informComplete(msg: String): Unit = reporter.withoutTruncating(inform(msg)) - def logError(msg: String, t: Throwable): Unit = () override def shouldLogAtThisPhase = settings.log.isSetByUser && ( @@ -351,9 +331,9 @@ class Global(var currentSettings: Settings, var reporter: Reporter) } if (settings.verbose || settings.Ylogcp) { - // Uses the "do not truncate" inform - informComplete("[search path for source files: " + classPath.sourcepaths.mkString(",") + "]") - informComplete("[search path for class files: " + classPath.asClasspathString + "]") + reporter.echo( + s"[search path for source files: ${classPath.sourcepaths.mkString(",")}]\n"+ + s"[search path for class files: ${classPath.asClasspathString}") } // The current division between scala.reflect.* and scala.tools.nsc.* is pretty @@ -1112,45 +1092,41 @@ class Global(var currentSettings: Settings, var reporter: Reporter) /** Don't want to introduce new errors trying to report errors, * so swallow exceptions. */ - override def supplementErrorMessage(errorMessage: String): String = { - if (currentRun.supplementedError) errorMessage - else try { - currentRun.supplementedError = true - val tree = analyzer.lastTreeToTyper - val sym = tree.symbol - val tpe = tree.tpe - val site = lastSeenContext.enclClassOrMethod.owner - val pos_s = if (tree.pos.isDefined) s"line ${tree.pos.line} of ${tree.pos.source.file}" else "<unknown>" - val context_s = try { - // Taking 3 before, 3 after the fingered line. - val start = 0 max (tree.pos.line - 3) - val xs = scala.reflect.io.File(tree.pos.source.file.file).lines drop start take 7 - val strs = xs.zipWithIndex map { case (line, idx) => f"${start + idx}%6d $line" } - strs.mkString("== Source file context for tree position ==\n\n", "\n", "") - } - catch { case t: Exception => devWarning("" + t) ; "<Cannot read source file>" } - - val info1 = formatExplain( - "while compiling" -> currentSource.path, - "during phase" -> ( if (globalPhase eq phase) phase else "globalPhase=%s, enteringPhase=%s".format(globalPhase, phase) ), - "library version" -> scala.util.Properties.versionString, - "compiler version" -> Properties.versionString, - "reconstructed args" -> settings.recreateArgs.mkString(" ") - ) - val info2 = formatExplain( - "last tree to typer" -> tree.summaryString, - "tree position" -> pos_s, - "tree tpe" -> tpe, - "symbol" -> Option(sym).fold("null")(_.debugLocationString), - "symbol definition" -> Option(sym).fold("null")(s => s.defString + s" (a ${s.shortSymbolClass})"), - "symbol package" -> sym.enclosingPackage.fullName, - "symbol owners" -> ownerChainString(sym), - "call site" -> (site.fullLocationString + " in " + site.enclosingPackage) - ) - ("\n " + errorMessage + "\n" + info1) :: info2 :: context_s :: Nil mkString "\n\n" + override def supplementTyperState(errorMessage: String): String = try { + val tree = analyzer.lastTreeToTyper + val sym = tree.symbol + val tpe = tree.tpe + val site = lastSeenContext.enclClassOrMethod.owner + val pos_s = if (tree.pos.isDefined) s"line ${tree.pos.line} of ${tree.pos.source.file}" else "<unknown>" + val context_s = try { + // Taking 3 before, 3 after the fingered line. + val start = 0 max (tree.pos.line - 3) + val xs = scala.reflect.io.File(tree.pos.source.file.file).lines drop start take 7 + val strs = xs.zipWithIndex map { case (line, idx) => f"${start + idx}%6d $line" } + strs.mkString("== Source file context for tree position ==\n\n", "\n", "") } - catch { case _: Exception | _: TypeError => errorMessage } - } + catch { case t: Exception => devWarning("" + t) ; "<Cannot read source file>" } + + val info1 = formatExplain( + "while compiling" -> currentSource.path, + "during phase" -> ( if (globalPhase eq phase) phase else "globalPhase=%s, enteringPhase=%s".format(globalPhase, phase) ), + "library version" -> scala.util.Properties.versionString, + "compiler version" -> Properties.versionString, + "reconstructed args" -> settings.recreateArgs.mkString(" ") + ) + val info2 = formatExplain( + "last tree to typer" -> tree.summaryString, + "tree position" -> pos_s, + "tree tpe" -> tpe, + "symbol" -> Option(sym).fold("null")(_.debugLocationString), + "symbol definition" -> Option(sym).fold("null")(s => s.defString + s" (a ${s.shortSymbolClass})"), + "symbol package" -> sym.enclosingPackage.fullName, + "symbol owners" -> ownerChainString(sym), + "call site" -> (site.fullLocationString + " in " + site.enclosingPackage) + ) + ("\n " + errorMessage + "\n" + info1) :: info2 :: context_s :: Nil mkString "\n\n" + } catch { case _: Exception | _: TypeError => errorMessage } + /** The id of the currently active run */ @@ -1162,19 +1138,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) inform("[running phase " + ph.name + " on " + currentRun.size + " compilation units]") } - /** Collects for certain classes of warnings during this run. */ - class ConditionalWarning(what: String, option: Settings#BooleanSetting) { - val warnings = mutable.LinkedHashMap[Position, String]() - def warn(pos: Position, msg: String) = - if (option) reporter.warning(pos, msg) - else if (!(warnings contains pos)) warnings += ((pos, msg)) - def summarize() = - if (warnings.nonEmpty && (option.isDefault || settings.fatalWarnings)){ - val warningEvent = if (warnings.size > 1) s"were ${ warnings.size } $what warnings" else s"was one $what warning" - warning(s"there $warningEvent; re-run with ${ option.name } for details") - } - } - def newSourceFile(code: String, filename: String = "<console>") = new BatchSourceFile(filename, code) @@ -1192,7 +1155,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) /** A Run is a single execution of the compiler on a set of units. */ - class Run extends RunContextApi { + class Run extends RunContextApi with RunReporting { /** Have been running into too many init order issues with Run * during erroneous conditions. Moved all these vals up to the * top of the file so at least they're not trivially null. @@ -1201,24 +1164,10 @@ class Global(var currentSettings: Settings, var reporter: Reporter) /** The currently compiled unit; set from GlobalPhase */ var currentUnit: CompilationUnit = NoCompilationUnit - // This change broke sbt; I gave it the thrilling name of uncheckedWarnings0 so - // as to recover uncheckedWarnings for its ever-fragile compiler interface. - val deprecationWarnings0 = new ConditionalWarning("deprecation", settings.deprecation) - val uncheckedWarnings0 = new ConditionalWarning("unchecked", settings.unchecked) - val featureWarnings = new ConditionalWarning("feature", settings.feature) - val inlinerWarnings = new ConditionalWarning("inliner", settings.YinlinerWarnings) - val allConditionalWarnings = List(deprecationWarnings0, uncheckedWarnings0, featureWarnings, inlinerWarnings) - - def uncheckedWarnings: List[(Position, String)] = uncheckedWarnings0.warnings.toList // used in sbt - def deprecationWarnings: List[(Position, String)] = deprecationWarnings0.warnings.toList // used in sbt - - var reportedFeature = Set[Symbol]() - - /** Has any macro expansion used a fallback during this run? */ - var seenMacroExpansionsFallingBack = false - - /** Have we already supplemented the error message of a compiler crash? */ - private[nsc] final var supplementedError = false + // used in sbt + def uncheckedWarnings: List[(Position, String)] = reporting.uncheckedWarnings + // used in sbt + def deprecationWarnings: List[(Position, String)] = reporting.deprecationWarnings private class SyncedCompilationBuffer { self => private val underlying = new mutable.ArrayBuffer[CompilationUnit] @@ -1416,6 +1365,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) refreshProgress() } + // for sbt def cancel() { reporter.cancelled = true } private def currentProgress = (phasec * size) + unitc @@ -1481,10 +1431,10 @@ class Global(var currentSettings: Settings, var reporter: Reporter) private def checkDeprecatedSettings(unit: CompilationUnit) { // issue warnings for any usage of deprecated settings settings.userSetSettings filter (_.isDeprecated) foreach { s => - unit.deprecationWarning(NoPosition, s.name + " is deprecated: " + s.deprecationMessage.get) + currentRun.reporting.deprecationWarning(NoPosition, s.name + " is deprecated: " + s.deprecationMessage.get) } if (settings.target.value.contains("jvm-1.5")) - unit.deprecationWarning(NoPosition, settings.target.name + ":" + settings.target.value + " is deprecated: use target for Java 1.6 or above.") + currentRun.reporting.deprecationWarning(NoPosition, settings.target.name + ":" + settings.target.value + " is deprecated: use target for Java 1.6 or above.") } /* An iterator returning all the units being compiled in this run */ @@ -1565,26 +1515,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) } } - def reportCompileErrors() { - if (!reporter.hasErrors && reporter.hasWarnings && settings.fatalWarnings) - globalError("No warnings can be incurred under -Xfatal-warnings.") - - if (reporter.hasErrors) { - for ((sym, file) <- symSource.iterator) { - sym.reset(new loaders.SourcefileLoader(file)) - if (sym.isTerm) - sym.moduleClass reset loaders.moduleClassLoader - } - } - else { - allConditionalWarnings foreach (_.summarize()) - - if (seenMacroExpansionsFallingBack) - warning("some macros could not be expanded and code fell back to overridden methods;"+ - "\nrecompiling with generated classfiles on the classpath might help.") - // todo: migrationWarnings - } - } /** Caching member symbols that are def-s in Defintions because they might change from Run to Run. */ val runDefinitions: definitions.RunDefinitions = new definitions.RunDefinitions @@ -1597,7 +1527,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) def checkDeprecations() = { checkDeprecatedSettings(newCompilationUnit("")) - reportCompileErrors() + reporting.summarizeErrors() } val units = sources map scripted map (new CompilationUnit(_)) @@ -1621,7 +1551,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) checkDeprecatedSettings(unitbuf.head) globalPhase = fromPhase - while (globalPhase.hasNext && !reporter.hasErrors) { + while (globalPhase.hasNext && !reporter.hasErrors) { val startTime = currentTime phase = globalPhase globalPhase.run() @@ -1667,6 +1597,8 @@ class Global(var currentSettings: Settings, var reporter: Reporter) advancePhase() } + reporting.summarizeErrors() + if (traceSymbolActivity) units map (_.body) foreach (traceSymbols recordSymbolsInTree _) @@ -1674,8 +1606,15 @@ class Global(var currentSettings: Settings, var reporter: Reporter) if (settings.Yshow.isDefault) showMembers() - reportCompileErrors() + if (reporter.hasErrors) { + for ((sym, file) <- symSource.iterator) { + sym.reset(new loaders.SourcefileLoader(file)) + if (sym.isTerm) + sym.moduleClass reset loaders.moduleClassLoader + } + } symSource.keys foreach (x => resetPackageClass(x.owner)) + informTime("total", startTime) // Clear any sets or maps created via perRunCaches. diff --git a/src/compiler/scala/tools/nsc/Reporting.scala b/src/compiler/scala/tools/nsc/Reporting.scala new file mode 100644 index 0000000000..0263586418 --- /dev/null +++ b/src/compiler/scala/tools/nsc/Reporting.scala @@ -0,0 +1,123 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2014 LAMP/EPFL, Typesafe Inc. + * @author Adriaan Moors + */ + +package scala +package tools +package nsc + +import reporters.{ Reporter, ConsoleReporter } +import scala.collection.{ mutable, immutable } +import scala.reflect.internal.util.StringOps.countElementsAsString + +/** Provides delegates to the reporter doing the actual work. + * PerRunReporting implements per-Run stateful info tracking and reporting + * + * TODO: make reporting configurable + */ +trait Reporting extends scala.reflect.internal.Reporting { self: ast.Positions with CompilationUnits with scala.reflect.internal.Symbols => + def settings: Settings + + // not deprecated yet, but a method called "error" imported into + // nearly every trait really must go. For now using globalError. + def error(msg: String) = globalError(msg) + + // a new instance of this class is created for every Run (access the current instance via `currentRun.reporting`) + protected def PerRunReporting = new PerRunReporting + class PerRunReporting extends PerRunReportingBase { + /** Collects for certain classes of warnings during this run. */ + private class ConditionalWarning(what: String, option: Settings#BooleanSetting) { + val warnings = mutable.LinkedHashMap[Position, String]() + def warn(pos: Position, msg: String) = + if (option) reporter.warning(pos, msg) + else if (!(warnings contains pos)) warnings += ((pos, msg)) + def summarize() = + if (warnings.nonEmpty && (option.isDefault || settings.fatalWarnings)) { + val numWarnings = warnings.size + val warningVerb = if (numWarnings == 1) "was" else "were" + val warningCount = countElementsAsString(numWarnings, s"$what warning") + + reporter.warning(NoPosition, s"there $warningVerb $warningCount; re-run with ${option.name} for details") + } + } + + // This change broke sbt; I gave it the thrilling name of uncheckedWarnings0 so + // as to recover uncheckedWarnings for its ever-fragile compiler interface. + private val _deprecationWarnings = new ConditionalWarning("deprecation", settings.deprecation) + private val _uncheckedWarnings = new ConditionalWarning("unchecked", settings.unchecked) + private val _featureWarnings = new ConditionalWarning("feature", settings.feature) + private val _inlinerWarnings = new ConditionalWarning("inliner", settings.YinlinerWarnings) + private val _allConditionalWarnings = List(_deprecationWarnings, _uncheckedWarnings, _featureWarnings, _inlinerWarnings) + + // TODO: remove in favor of the overload that takes a Symbol, give that argument a default (NoSymbol) + def deprecationWarning(pos: Position, msg: String): Unit = _deprecationWarnings.warn(pos, msg) + def uncheckedWarning(pos: Position, msg: String): Unit = _uncheckedWarnings.warn(pos, msg) + def featureWarning(pos: Position, msg: String): Unit = _featureWarnings.warn(pos, msg) + def inlinerWarning(pos: Position, msg: String): Unit = _inlinerWarnings.warn(pos, msg) + + def deprecationWarnings = _deprecationWarnings.warnings.toList + def uncheckedWarnings = _uncheckedWarnings.warnings.toList + def featureWarnings = _featureWarnings.warnings.toList + def inlinerWarnings = _inlinerWarnings.warnings.toList + + def allConditionalWarnings = _allConditionalWarnings flatMap (_.warnings) + + // behold! the symbol that caused the deprecation warning (may not be deprecated itself) + def deprecationWarning(pos: Position, sym: Symbol, msg: String): Unit = _deprecationWarnings.warn(pos, msg) + def deprecationWarning(pos: Position, sym: Symbol): Unit = { + val suffix = sym.deprecationMessage match { case Some(msg) => ": "+ msg case _ => "" } + deprecationWarning(pos, sym, s"$sym${sym.locationString} is deprecated$suffix") + } + + private[this] var reportedFeature = Set[Symbol]() + def featureWarning(pos: Position, featureName: String, featureDesc: String, featureTrait: Symbol, construct: => String = "", required: Boolean): Unit = { + val req = if (required) "needs to" else "should" + val fqname = "scala.language." + featureName + val explain = ( + if (reportedFeature contains featureTrait) "" else + s"""| + |This can be achieved by adding the import clause 'import $fqname' + |or by setting the compiler option -language:$featureName. + |See the Scala docs for value $fqname for a discussion + |why the feature $req be explicitly enabled.""".stripMargin + ) + reportedFeature += featureTrait + + val msg = s"$featureDesc $req be enabled\nby making the implicit value $fqname visible.$explain" replace ("#", construct) + if (required) reporter.error(pos, msg) + else featureWarning(pos, msg) + } + + /** Has any macro expansion used a fallback during this run? */ + var seenMacroExpansionsFallingBack = false + + def summarizeErrors(): Unit = if (!reporter.hasErrors) { + _allConditionalWarnings foreach (_.summarize()) + + if (seenMacroExpansionsFallingBack) + reporter.warning(NoPosition, "some macros could not be expanded and code fell back to overridden methods;"+ + "\nrecompiling with generated classfiles on the classpath might help.") + + // todo: migrationWarnings + + if (settings.fatalWarnings && reporter.hasWarnings) + reporter.error(NoPosition, "No warnings can be incurred under -Xfatal-warnings.") + } + + // for repl + private[this] var incompleteHandler: (Position, String) => Unit = null + def withIncompleteHandler[T](handler: (Position, String) => Unit)(thunk: => T) = { + val saved = incompleteHandler + incompleteHandler = handler + try thunk + finally incompleteHandler = saved + } + + def incompleteHandled = incompleteHandler != null + def incompleteInputError(pos: Position, msg: String): Unit = + if (incompleteHandled) incompleteHandler(pos, msg) + else reporter.error(pos, msg) + + } +}
\ No newline at end of file diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index ffc45b21ea..883fd31dbc 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -205,11 +205,11 @@ self => override def newScanner() = new UnitScanner(unit, patches) override def warning(offset: Offset, msg: String) { - unit.warning(o2p(offset), msg) + reporter.warning(o2p(offset), msg) } override def deprecationWarning(offset: Offset, msg: String) { - unit.deprecationWarning(o2p(offset), msg) + currentRun.reporting.deprecationWarning(o2p(offset), msg) } private var smartParsing = false @@ -224,17 +224,17 @@ self => val syntaxErrors = new ListBuffer[(Int, String)] def showSyntaxErrors() = for ((offset, msg) <- syntaxErrors) - unit.error(o2p(offset), msg) + reporter.error(o2p(offset), msg) override def syntaxError(offset: Offset, msg: String) { if (smartParsing) syntaxErrors += ((offset, msg)) - else unit.error(o2p(offset), msg) + else reporter.error(o2p(offset), msg) } override def incompleteInputError(msg: String) { val offset = source.content.length - 1 if (smartParsing) syntaxErrors += ((offset, msg)) - else unit.incompleteInputError(o2p(offset), msg) + else currentRun.reporting.incompleteInputError(o2p(offset), msg) } /** parse unit. If there are inbalanced braces, diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala index e8d46704c3..572497ac90 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala @@ -1259,9 +1259,9 @@ trait Scanners extends ScannersCommon { class UnitScanner(val unit: CompilationUnit, patches: List[BracePatch]) extends SourceFileScanner(unit.source) { def this(unit: CompilationUnit) = this(unit, List()) - override def deprecationWarning(off: Offset, msg: String) = unit.deprecationWarning(unit.position(off), msg) - override def error (off: Offset, msg: String) = unit.error(unit.position(off), msg) - override def incompleteInputError(off: Offset, msg: String) = unit.incompleteInputError(unit.position(off), msg) + override def deprecationWarning(off: Offset, msg: String) = currentRun.reporting.deprecationWarning(unit.position(off), msg) + override def error (off: Offset, msg: String) = reporter.error(unit.position(off), msg) + override def incompleteInputError(off: Offset, msg: String) = currentRun.reporting.incompleteInputError(unit.position(off), msg) private var bracePatches: List[BracePatch] = patches diff --git a/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala b/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala index 3a695c6f59..64b762696e 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala @@ -83,7 +83,7 @@ abstract class SyntaxAnalyzer extends SubComponent with Parsers with MarkupParse private def initialUnitBody(unit: CompilationUnit): Tree = { if (unit.isJava) new JavaUnitParser(unit).parse() - else if (global.reporter.incompleteHandled) newUnitParser(unit).parse() + else if (currentRun.reporting.incompleteHandled) newUnitParser(unit).parse() else newUnitParser(unit).smartParse() } diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala index 0ad3c2c76b..d9f56b47fa 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala @@ -680,7 +680,7 @@ abstract class GenICode extends SubComponent { val dims = arr.dimensions var elemKind = arr.elementKind if (args.length > dims) - unit.error(tree.pos, "too many arguments for array constructor: found " + args.length + + reporter.error(tree.pos, "too many arguments for array constructor: found " + args.length + " but array has only " + dims + " dimension(s)") if (args.length != dims) for (i <- args.length until dims) elemKind = ARRAY(elemKind) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala index bffa4bc51d..4583462b71 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeBodyBuilder.scala @@ -504,7 +504,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { case nextCleanup :: rest => if (saveReturnValue) { if (insideCleanupBlock) { - cunit.warning(r.pos, "Return statement found in finally-clause, discarding its return-value in favor of that of a more deeply nested return.") + reporter.warning(r.pos, "Return statement found in finally-clause, discarding its return-value in favor of that of a more deeply nested return.") bc drop returnType } else { // regarding return value, the protocol is: in place of a `return-stmt`, a sequence of `adapt, store, jump` are inserted. @@ -602,7 +602,7 @@ abstract class BCodeBodyBuilder extends BCodeSkelBuilder { var elemKind = arr.elementType val argsSize = args.length if (argsSize > dims) { - cunit.error(app.pos, s"too many arguments for array constructor: found ${args.length} but array has only $dims dimension(s)") + reporter.error(app.pos, s"too many arguments for array constructor: found ${args.length} but array has only $dims dimension(s)") } if (argsSize < dims) { /* In one step: diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala index 51bfdf0027..31a392ed55 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeHelpers.scala @@ -38,7 +38,7 @@ abstract class BCodeHelpers extends BCodeTypes with BytecodeWriters { outputDirectory(csym) } catch { case ex: Throwable => - cunit.error(cunit.body.pos, s"Couldn't create file for class $cName\n${ex.getMessage}") + reporter.error(cunit.body.pos, s"Couldn't create file for class $cName\n${ex.getMessage}") null } } @@ -141,7 +141,7 @@ abstract class BCodeHelpers extends BCodeTypes with BytecodeWriters { */ def apply(sym: Symbol, csymCompUnit: CompilationUnit): Boolean = { def fail(msg: String, pos: Position = sym.pos) = { - csymCompUnit.warning(sym.pos, + reporter.warning(sym.pos, sym.name + s" has a main method with parameter type Array[String], but ${sym.fullName('.')} will not be a runnable program.\n Reason: $msg" // TODO: make this next claim true, if possible diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala index effc68c5e3..8845ffa0cd 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeSkelBuilder.scala @@ -570,7 +570,7 @@ abstract class BCodeSkelBuilder extends BCodeHelpers { if (params.size > MaximumJvmParameters) { // SI-7324 - cunit.error(methSymbol.pos, s"Platform restriction: a parameter list's length cannot exceed $MaximumJvmParameters.") + reporter.error(methSymbol.pos, s"Platform restriction: a parameter list's length cannot exceed $MaximumJvmParameters.") return } diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala index 988c04f514..b0fb3069c1 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala @@ -113,7 +113,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM { // Warn when classes will overwrite one another on case-insensitive systems. for ((_, v1 :: v2 :: _) <- sortedClasses groupBy (_.symbol.javaClassName.toString.toLowerCase)) { - v1.cunit.warning(v1.symbol.pos, + reporter.warning(v1.symbol.pos, s"Class ${v1.symbol.javaClassName} differs only in case from ${v2.symbol.javaClassName}. " + "Such classes will overwrite one another on case-insensitive filesystems.") } @@ -141,7 +141,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM { try emitFor(c) catch { case e: FileConflictException => - c.cunit.error(c.symbol.pos, s"error writing ${c.symbol}: ${e.getMessage}") + reporter.error(c.symbol.pos, s"error writing ${c.symbol}: ${e.getMessage}") } sortedClasses = sortedClasses.tail classes -= c.symbol // GC opportunity @@ -1363,7 +1363,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM { if (m.symbol.isStaticConstructor || definitions.isGetClass(m.symbol)) return if (m.params.size > MaximumJvmParameters) { - getCurrentCUnit().error(m.symbol.pos, s"Platform restriction: a parameter list's length cannot exceed $MaximumJvmParameters.") + reporter.error(m.symbol.pos, s"Platform restriction: a parameter list's length cannot exceed $MaximumJvmParameters.") return } @@ -3245,7 +3245,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM { } if(!isValidSignature) { - unit.warning(sym.pos, + reporter.warning(sym.pos, """|compiler bug: created invalid generic signature for %s in %s |signature: %s |if this is reproducible, please report bug at https://issues.scala-lang.org/ @@ -3258,7 +3258,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM { val normalizedTpe = enteringErasure(erasure.prepareSigMap(memberTpe)) val bytecodeTpe = owner.thisType.memberInfo(sym) if (!sym.isType && !sym.isConstructor && !(erasure.erasure(sym)(normalizedTpe) =:= bytecodeTpe)) { - unit.warning(sym.pos, + reporter.warning(sym.pos, """|compiler bug: created generic signature for %s in %s that does not conform to its erasure |signature: %s |original type: %s diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala index 9b292fee7f..a401de05e5 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenBCode.scala @@ -156,7 +156,7 @@ abstract class GenBCode extends BCodeSyncAndTry { case None => caseInsensitively.put(lowercaseJavaClassName, claszSymbol) case Some(dupClassSym) => - item.cunit.warning( + reporter.warning( claszSymbol.pos, s"Class ${claszSymbol.javaClassName} differs only in case from ${dupClassSym.javaClassName}. " + "Such classes will overwrite one another on case-insensitive filesystems." diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVMASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVMASM.scala index 01c4ff5a52..2bcde7f7b9 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVMASM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVMASM.scala @@ -27,7 +27,7 @@ trait GenJVMASM { protected def isJavaEntryPoint(icls: IClass) = { val sym = icls.symbol def fail(msg: String, pos: Position = sym.pos) = { - icls.cunit.warning(sym.pos, + reporter.warning(sym.pos, sym.name + " has a main method with parameter type Array[String], but " + sym.fullName('.') + " will not be a runnable program.\n" + " Reason: " + msg // TODO: make this next claim true, if possible diff --git a/src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala b/src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala index 235e954f88..425c10d153 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala @@ -182,7 +182,7 @@ abstract class InlineExceptionHandlers extends SubComponent { // in other words: what's on the stack MUST conform to what's in the THROW(..)! if (!canReplaceHandler) { - currentClass.cunit.warning(NoPosition, "Unable to inline the exception handler inside incorrect" + + reporter.warning(NoPosition, "Unable to inline the exception handler inside incorrect" + " block:\n" + bblock.iterator.mkString("\n") + "\nwith stack: " + typeInfo + " just " + "before instruction index " + index) } @@ -383,7 +383,7 @@ abstract class InlineExceptionHandlers extends SubComponent { Some((exceptionLocal, copy)) case _ => - currentClass.cunit.warning(NoPosition, "Unable to inline the exception handler due to incorrect format:\n" + + reporter.warning(NoPosition, "Unable to inline the exception handler due to incorrect format:\n" + handler.iterator.mkString("\n")) None } diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala index f6de522d09..8df3969c49 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala @@ -195,7 +195,7 @@ abstract class Inliners extends SubComponent { /** The current iclass */ private var currentIClazz: IClass = _ - private def warn(pos: Position, msg: String) = currentIClazz.cunit.inlinerWarning(pos, msg) + private def warn(pos: Position, msg: String) = currentRun.reporting.inlinerWarning(pos, msg) private def ownedName(sym: Symbol): String = exitingUncurry { val count = ( diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala index a61ad392ee..37b00aa9a3 100644 --- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala @@ -26,10 +26,10 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { def freshName(prefix: String): Name = freshTermName(prefix) def freshTermName(prefix: String): TermName = unit.freshTermName(prefix) def freshTypeName(prefix: String): TypeName = unit.freshTypeName(prefix) - def deprecationWarning(off: Int, msg: String) = unit.deprecationWarning(off, msg) + def deprecationWarning(off: Int, msg: String) = currentRun.reporting.deprecationWarning(off, msg) implicit def i2p(offset : Int) : Position = Position.offset(unit.source, offset) - def warning(pos : Int, msg : String) : Unit = unit.warning(pos, msg) - def syntaxError(pos: Int, msg: String) : Unit = unit.error(pos, msg) + def warning(pos : Int, msg : String) : Unit = reporter.warning(pos, msg) + def syntaxError(pos: Int, msg: String) : Unit = reporter.error(pos, msg) } abstract class JavaParser extends ParserCommon { diff --git a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala index c5401219dd..bddcf6567c 100644 --- a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala @@ -860,9 +860,9 @@ trait JavaScanners extends ast.parser.ScannersCommon { class JavaUnitScanner(unit: CompilationUnit) extends JavaScanner { in = new JavaCharArrayReader(unit.source.content, !settings.nouescape.value, syntaxError) init() - def error (pos: Int, msg: String) = unit. error(pos, msg) - def incompleteInputError(pos: Int, msg: String) = unit.incompleteInputError(pos, msg) - def deprecationWarning(pos: Int, msg: String) = unit.deprecationWarning(pos, msg) + def error (pos: Int, msg: String) = reporter.error(pos, msg) + def incompleteInputError(pos: Int, msg: String) = currentRun.reporting.incompleteInputError(pos, msg) + def deprecationWarning(pos: Int, msg: String) = currentRun.reporting.deprecationWarning(pos, msg) implicit def g2p(pos: Int): Position = Position.offset(unit.source, pos) } } diff --git a/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala b/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala index 16d432438a..6c592ead0d 100644 --- a/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala +++ b/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala @@ -62,12 +62,13 @@ abstract class AbstractReporter extends Reporter { */ private def testAndLog(pos: Position, severity: Severity, msg: String): Boolean = pos != null && pos.isDefined && { - val fpos = pos.focus + val fpos = pos.focus val suppress = positions(fpos) match { - case ERROR => true // already error at position - case highest if highest > severity => true // already message higher than present severity - case `severity` => messages(fpos) contains msg // already issued this exact message - case _ => false // good to go + case ERROR => true // already error at position + case highest + if highest.id > severity.id => true // already message higher than present severity + case `severity` => messages(fpos) contains msg // already issued this exact message + case _ => false // good to go } suppress || { diff --git a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala index 3f210a543c..0b218b711c 100644 --- a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala +++ b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala @@ -12,8 +12,7 @@ import scala.reflect.internal.util._ import StringOps._ /** - * This class implements a Reporter that displays messages on a text - * console. + * This class implements a Reporter that displays messages on a text console. */ class ConsoleReporter(val settings: Settings, reader: BufferedReader, writer: PrintWriter) extends AbstractReporter { def this(settings: Settings) = this(settings, Console.in, new PrintWriter(Console.err, true)) diff --git a/src/compiler/scala/tools/nsc/reporters/Reporter.scala b/src/compiler/scala/tools/nsc/reporters/Reporter.scala index 68362c066d..5b576a547d 100644 --- a/src/compiler/scala/tools/nsc/reporters/Reporter.scala +++ b/src/compiler/scala/tools/nsc/reporters/Reporter.scala @@ -8,76 +8,50 @@ package reporters import scala.reflect.internal.util._ -/** - * This interface provides methods to issue information, warning and - * error messages. +/** Report information, warnings and errors. + * + * This describes the internal interface for issuing information, warnings and errors. + * The only abstract method in this class must be info0. + * + * TODO: Move external clients (sbt/ide/partest) to reflect.internal.Reporter + * This interface should be considered private to the compiler. */ -abstract class Reporter { - protected def info0(pos: Position, msg: String, severity: Severity, force: Boolean): Unit - - object severity extends Enumeration - class Severity(val id: Int) extends severity.Value { - var count: Int = 0 - } - val INFO = new Severity(0) { - override def toString: String = "INFO" - } - val WARNING = new Severity(1) { - override def toString: String = "WARNING" - } - val ERROR = new Severity(2) { - override def toString: String = "ERROR" - } - - /** 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 - } - - private var incompleteHandler: (Position, String) => Unit = null - def incompleteHandled = incompleteHandler != null - def withIncompleteHandler[T](handler: (Position, String) => Unit)(thunk: => T) = { - val saved = incompleteHandler - incompleteHandler = handler - try thunk - finally incompleteHandler = saved - } - - var cancelled = false - def hasErrors = ERROR.count > 0 || cancelled - def hasWarnings = WARNING.count > 0 +abstract class Reporter extends scala.reflect.internal.Reporter { + /** Informational messages. If `!force`, they may be suppressed. */ + final def info(pos: Position, msg: String, force: Boolean): Unit = info0(pos, msg, INFO, force) /** 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): Unit = info(NoPosition, msg, force = true) - def echo(pos: Position, msg: String): Unit = info(pos, msg, force = true) + def echo(msg: String): Unit = info(NoPosition, msg, force = true) - /** Informational messages, suppressed unless -verbose or force=true. */ - def info(pos: Position, msg: String, force: Boolean): Unit = info0(pos, msg, INFO, force) + // overridden by sbt, IDE -- should not be in the reporting interface + // (IDE receives comments from ScaladocAnalyzer using this hook method) + // TODO: IDE should override a hook method in the parser instead + def comment(pos: Position, msg: String): Unit = {} - /** Warnings and errors. */ - def warning(pos: Position, msg: String): Unit = withoutTruncating(info0(pos, msg, WARNING, force = false)) - def error(pos: Position, msg: String): Unit = withoutTruncating(info0(pos, msg, ERROR, force = false)) - def incompleteInputError(pos: Position, msg: String): Unit = { - if (incompleteHandled) incompleteHandler(pos, msg) - else error(pos, msg) - } + // used by sbt (via unit.cancel) to cancel a compile (see hasErrors) + // TODO: figure out how sbt uses this, come up with a separate interface for controlling the build + var cancelled: Boolean = false - def comment(pos: Position, msg: String) { } - def flush() { } - def reset() { - INFO.count = 0 - ERROR.count = 0 - WARNING.count = 0 - cancelled = false + override def hasErrors: Boolean = super.hasErrors || cancelled + + override def reset(): Unit = { + super.reset() + cancelled = false } + + // the below is copy/pasted from ReporterImpl for now + // partest expects this inner class + // TODO: rework partest to use the scala.reflect.internal interface, + // remove duplication here, and consolidate reflect.internal.{ReporterImpl & ReporterImpl} + class Severity(val id: Int)(name: String) { var count: Int = 0 ; override def toString = name} + object INFO extends Severity(0)("INFO") + object WARNING extends Severity(1)("WARNING") + // reason for copy/paste: this is used by partest (must be a val, not an object) + // TODO: use count(ERROR) in scala.tools.partest.nest.DirectCompiler#errorCount, rather than ERROR.count + lazy val ERROR = new Severity(2)("ERROR") + + def count(severity: Severity): Int = severity.count + def resetCount(severity: Severity): Unit = severity.count = 0 } diff --git a/src/compiler/scala/tools/nsc/reporters/StoreReporter.scala b/src/compiler/scala/tools/nsc/reporters/StoreReporter.scala index 04c5bdf824..24a61cb171 100644 --- a/src/compiler/scala/tools/nsc/reporters/StoreReporter.scala +++ b/src/compiler/scala/tools/nsc/reporters/StoreReporter.scala @@ -10,8 +10,7 @@ import scala.collection.mutable import scala.reflect.internal.util.Position /** - * This class implements a Reporter that displays messages on a text - * console. + * This class implements a Reporter that stores its reports in the set `infos`. */ class StoreReporter extends Reporter { case class Info(pos: Position, msg: String, severity: Severity) { diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala index 592c5497b5..2fc00fe068 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala @@ -69,7 +69,7 @@ abstract class Pickler extends SubComponent { // OPT: do this only as a recovery after fatal error. Checking in advance was expensive. if (t.isErroneous) { if (settings.debug) e.printStackTrace() - unit.error(t.pos, "erroneous or inaccessible type") + reporter.error(t.pos, "erroneous or inaccessible type") return } } diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala index f14fce5de9..1664fe0e0d 100644 --- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala +++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala @@ -76,7 +76,7 @@ abstract class CleanUp extends Statics with Transform with ast.TreeDSL { val qual0 = ad.qual val params = ad.args if (settings.logReflectiveCalls) - unit.echo(ad.pos, "method invocation uses reflection") + reporter.echo(ad.pos, "method invocation uses reflection") val typedPos = typedWithPos(ad.pos) _ @@ -360,13 +360,13 @@ abstract class CleanUp extends Statics with Transform with ast.TreeDSL { assert(params.length == mparams.length, ((params, mparams))) (mparams, resType) case tpe @ OverloadedType(pre, alts) => - unit.warning(ad.pos, s"Overloaded type reached the backend! This is a bug in scalac.\n Symbol: ${ad.symbol}\n Overloads: $tpe\n Arguments: " + ad.args.map(_.tpe)) + reporter.warning(ad.pos, s"Overloaded type reached the backend! This is a bug in scalac.\n Symbol: ${ad.symbol}\n Overloads: $tpe\n Arguments: " + ad.args.map(_.tpe)) alts filter (_.paramss.flatten.size == params.length) map (_.tpe) match { case mt @ MethodType(mparams, resType) :: Nil => - unit.warning(NoPosition, "Only one overload has the right arity, proceeding with overload " + mt) + reporter.warning(NoPosition, "Only one overload has the right arity, proceeding with overload " + mt) (mparams, resType) case _ => - unit.error(ad.pos, "Cannot resolve overload.") + reporter.error(ad.pos, "Cannot resolve overload.") (Nil, NoType) } } diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala index 391bce5abb..f471440293 100644 --- a/src/compiler/scala/tools/nsc/transform/Constructors.scala +++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala @@ -54,7 +54,7 @@ abstract class Constructors extends Statics with Transform with ast.TreeDSL { def check(tree: Tree) = { for (t <- tree) t match { case t: RefTree if uninitializedVals(t.symbol.accessedOrSelf) && t.qualifier.symbol == clazz => - unit.warning(t.pos, s"Reference to uninitialized ${t.symbol.accessedOrSelf}") + reporter.warning(t.pos, s"Reference to uninitialized ${t.symbol.accessedOrSelf}") case _ => } } @@ -685,7 +685,7 @@ abstract class Constructors extends Statics with Transform with ast.TreeDSL { // mangling before we introduce more of it. val conflict = clazz.info.nonPrivateMember(acc.name) filter (s => s.isGetter && !s.isOuterField && s.enclClass.isTrait) if (conflict ne NoSymbol) - unit.error(acc.pos, "parameter '%s' requires field but conflicts with %s".format(acc.name, conflict.fullLocationString)) + reporter.error(acc.pos, "parameter '%s' requires field but conflicts with %s".format(acc.name, conflict.fullLocationString)) copyParam(acc, parameter(acc)) } diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 2f2142027f..ec4deb6be0 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -488,7 +488,7 @@ abstract class Erasure extends AddInterfaces || (checkBridgeOverrides(member, other, bridge) match { case Nil => true case es if member.owner.isAnonymousClass => resolveAnonymousBridgeClash(member, bridge); true - case es => for ((pos, msg) <- es) unit.error(pos, msg); false + case es => for ((pos, msg) <- es) reporter.error(pos, msg); false }) ) @@ -724,7 +724,7 @@ abstract class Erasure extends AddInterfaces ) val when = if (exitingRefchecks(lowType matches highType)) "" else " after erasure: " + exitingPostErasure(highType) - unit.error(pos, + reporter.error(pos, s"""|$what: |${exitingRefchecks(highString)} and |${exitingRefchecks(lowString)} @@ -865,7 +865,7 @@ abstract class Erasure extends AddInterfaces fn match { case TypeApply(sel @ Select(qual, name), List(targ)) => if (qual.tpe != null && isPrimitiveValueClass(qual.tpe.typeSymbol) && targ.tpe != null && targ.tpe <:< AnyRefTpe) - unit.error(sel.pos, "isInstanceOf cannot test if value types are references.") + reporter.error(sel.pos, "isInstanceOf cannot test if value types are references.") def mkIsInstanceOf(q: () => Tree)(tp: Type): Tree = Apply( @@ -952,7 +952,7 @@ abstract class Erasure extends AddInterfaces case nme.length => nme.array_length case nme.update => nme.array_update case nme.clone_ => nme.array_clone - case _ => unit.error(tree.pos, "Unexpected array member, no translation exists.") ; nme.NO_NAME + case _ => reporter.error(tree.pos, "Unexpected array member, no translation exists.") ; nme.NO_NAME } gen.mkRuntimeCall(arrayMethodName, qual :: args) } @@ -1055,7 +1055,7 @@ abstract class Erasure extends AddInterfaces qual match { case Super(_, _) => // Insert a cast here at your peril -- see SI-5162. - unit.error(tree.pos, s"Unable to access ${tree.symbol.fullLocationString} with a super reference.") + reporter.error(tree.pos, s"Unable to access ${tree.symbol.fullLocationString} with a super reference.") tree case _ => // Todo: Figure out how qual.tpe could be null in the check above (it does appear in build where SwingWorker.this diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala index 0447e23e9e..c291961447 100644 --- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala +++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala @@ -481,7 +481,7 @@ abstract class ExplicitOuter extends InfoTransform // since we can't fix SI-4440 properly (we must drop the outer accessors of final classes when there's no immediate reference to them in sight) // at least don't crash... this duplicates maybeOmittable from constructors (acc.owner.isEffectivelyFinal && !acc.isOverridingSymbol)) { - unit.uncheckedWarning(tree.pos, "The outer reference in this type test cannot be checked at run time.") + currentRun.reporting.uncheckedWarning(tree.pos, "The outer reference in this type test cannot be checked at run time.") transform(TRUE) // urgh... drop condition if there's no accessor (or if it may disappear after constructors) } else { // println("(base, acc)= "+(base, acc)) diff --git a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala index 2235a93ca4..228c9da624 100644 --- a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala +++ b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala @@ -127,7 +127,7 @@ abstract class ExtensionMethods extends Transform with TypingTransformers { def checkNonCyclic(pos: Position, seen: Set[Symbol], clazz: Symbol): Unit = if (seen contains clazz) - unit.error(pos, "value class may not unbox to itself") + reporter.error(pos, "value class may not unbox to itself") else { val unboxed = definitions.underlyingOfValueClass(clazz).typeSymbol if (unboxed.isDerivedValueClass) checkNonCyclic(pos, seen + clazz, unboxed) diff --git a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala index e38c034f4d..f85d8222f0 100644 --- a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala +++ b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala @@ -339,7 +339,7 @@ abstract class LambdaLift extends InfoTransform { if (clazz.isStaticOwner) clazz.fullLocationString else s"the unconstructed `this` of ${clazz.fullLocationString}" val msg = s"Implementation restriction: access of ${sym.fullLocationString} from ${currentClass.fullLocationString}, would require illegal premature access to $what" - currentUnit.error(curTree.pos, msg) + reporter.error(curTree.pos, msg) } val qual = if (clazz == currentClass) gen.mkAttributedThis(clazz) diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index 313d0a6e61..7927875583 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -336,7 +336,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { rebindSuper(clazz, mixinMember.alias, mixinClass) match { case NoSymbol => - unit.error(clazz.pos, "Member %s of mixin %s is missing a concrete super implementation.".format( + reporter.error(clazz.pos, "Member %s of mixin %s is missing a concrete super implementation.".format( mixinMember.alias, mixinClass)) case alias1 => superAccessor.asInstanceOf[TermSymbol] setAlias alias1 diff --git a/src/compiler/scala/tools/nsc/transform/TailCalls.scala b/src/compiler/scala/tools/nsc/transform/TailCalls.scala index d9d1192772..ef534f70fd 100644 --- a/src/compiler/scala/tools/nsc/transform/TailCalls.scala +++ b/src/compiler/scala/tools/nsc/transform/TailCalls.scala @@ -96,7 +96,7 @@ abstract class TailCalls extends Transform { val failReason = failReasons(ctx) val failPos = failPositions(ctx) - unit.error(failPos, s"could not optimize @tailrec annotated $method: $failReason") + reporter.error(failPos, s"could not optimize @tailrec annotated $method: $failReason") } /** Has the label been accessed? Then its symbol is in this set. */ @@ -268,14 +268,14 @@ abstract class TailCalls extends Transform { tree match { case ValDef(_, _, _, _) => if (tree.symbol.isLazy && tree.symbol.hasAnnotation(TailrecClass)) - unit.error(tree.pos, "lazy vals are not tailcall transformed") + reporter.error(tree.pos, "lazy vals are not tailcall transformed") super.transform(tree) case dd @ DefDef(_, name, _, vparamss0, _, rhs0) if isEligible(dd) => val newCtx = new DefDefTailContext(dd) if (newCtx.isMandatory && !(newCtx containsRecursiveCall rhs0)) - unit.error(tree.pos, "@tailrec annotated method contains no recursive calls") + reporter.error(tree.pos, "@tailrec annotated method contains no recursive calls") debuglog(s"Considering $name for tailcalls, with labels in tailpos: ${newCtx.tailLabels}") val newRHS = transform(rhs0, newCtx) diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index d77c6b54a9..2209aac00f 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -93,7 +93,7 @@ abstract class UnCurry extends InfoTransform override def transform(tree: Tree): Tree = ( try postTransform(mainTransform(tree)) catch { case ex: TypeError => - unit.error(ex.pos, ex.msg) + reporter.error(ex.pos, ex.msg) debugStack(ex) EmptyTree } @@ -174,7 +174,7 @@ abstract class UnCurry extends InfoTransform cdef <- catches if catchesThrowable(cdef) && !isSyntheticCase(cdef) } { - unit.warning(body.pos, "catch block may intercept non-local return from " + meth) + reporter.warning(body.pos, "catch block may intercept non-local return from " + meth) } Block(List(keyDef), tryCatch) @@ -706,10 +706,10 @@ abstract class UnCurry extends InfoTransform */ private def saveRepeatedParams(dd: DefDef): Unit = if (dd.symbol.isConstructor) - unit.error(dd.symbol.pos, "A constructor cannot be annotated with a `varargs` annotation.") + reporter.error(dd.symbol.pos, "A constructor cannot be annotated with a `varargs` annotation.") else treeInfo.repeatedParams(dd) match { case Nil => - unit.error(dd.symbol.pos, "A method without repeated parameters cannot be annotated with the `varargs` annotation.") + reporter.error(dd.symbol.pos, "A method without repeated parameters cannot be annotated with the `varargs` annotation.") case reps => repeatedParams(dd.symbol) = reps } @@ -782,7 +782,7 @@ abstract class UnCurry extends InfoTransform // check if the method with that name and those arguments already exists in the template currentClass.info.member(forwsym.name).alternatives.find(s => s != forwsym && s.tpe.matches(forwsym.tpe)) match { - case Some(s) => unit.error(dd.symbol.pos, + case Some(s) => reporter.error(dd.symbol.pos, "A method with a varargs annotation produces a forwarder method with the same signature " + s.tpe + " as an existing method.") case None => diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala index e1a663ea41..6f81cbe152 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala @@ -51,7 +51,7 @@ trait TreeAndTypeAnalysis extends Debugging { // This is a pretty poor approximation. def unsoundAssumptionUsed = binder.name != nme.WILDCARD && !(pt <:< pat.tpe) if (settings.lint && unsoundAssumptionUsed) - global.currentUnit.warning(pat.pos, + reporter.warning(pat.pos, sm"""The value matched by $pat is bound to ${binder.name}, which may be used under the |unsound assumption that it has type ${pat.tpe}, whereas we can only safely |count on it having type $pt, as the pattern is matched using `==` (see SI-1503).""") @@ -398,7 +398,7 @@ trait MatchAnalysis extends MatchApproximation { import global.definitions._ trait MatchAnalyzer extends MatchApproximator { - def uncheckedWarning(pos: Position, msg: String) = global.currentUnit.uncheckedWarning(pos, msg) + def uncheckedWarning(pos: Position, msg: String) = currentRun.reporting.uncheckedWarning(pos, msg) def warn(pos: Position, ex: AnalysisBudget.Exception, kind: String) = uncheckedWarning(pos, s"Cannot check match for $kind.\n${ex.advice}") // TODO: model dependencies between variables: if V1 corresponds to (x: List[_]) and V2 is (x.hd), V2 cannot be assigned when V1 = null or V1 = Nil diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala index 8ff7824159..e9c81f4728 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchOptimization.scala @@ -442,7 +442,7 @@ trait MatchOptimization extends MatchTreeMaking with MatchAnalysis { val distinctAlts = distinctBy(switchableAlts)(extractConst) if (distinctAlts.size < switchableAlts.size) { val duplicated = switchableAlts.groupBy(extractConst).flatMap(_._2.drop(1).take(1)) // report the first duplicated - global.currentUnit.warning(pos, s"Pattern contains duplicate alternatives: ${duplicated.mkString(", ")}") + reporter.warning(pos, s"Pattern contains duplicate alternatives: ${duplicated.mkString(", ")}") } CaseDef(Alternative(distinctAlts), guard, body) } diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala index 4cf8980689..0eaffe7cee 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala @@ -154,7 +154,7 @@ trait MatchTranslation { case SymbolBound(sym, expr) => bindingStep(sym, expr) case Literal(Constant(_)) | Ident(_) | Select(_, _) | This(_) => equalityTestStep() case Alternative(alts) => alternativesStep(alts) - case _ => context.unit.error(pos, unsupportedPatternMsg) ; noStep() + case _ => reporter.error(pos, unsupportedPatternMsg) ; noStep() } def translate(): List[TreeMaker] = nextStep() merge (_.translate()) diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala index 5d8a9fecef..1974befb45 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala @@ -558,7 +558,7 @@ trait MatchTreeMaking extends MatchCodeGen with Debugging { } emitSwitch(scrut, scrutSym, casesNoSubstOnly, pt, matchFailGenOverride, suppression.exhaustive).getOrElse{ - if (requireSwitch) typer.context.unit.warning(scrut.pos, "could not emit switch for @switch annotated match") + if (requireSwitch) reporter.warning(scrut.pos, "could not emit switch for @switch annotated match") if (casesNoSubstOnly nonEmpty) { // before optimizing, check casesNoSubstOnly for presence of a default case, diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchWarnings.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchWarnings.scala index a7d7680db1..9e9372f709 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchWarnings.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchWarnings.scala @@ -67,7 +67,7 @@ trait MatchWarnings { val cdef = it.next() // If a default case has been seen, then every succeeding case is unreachable. if (vpat != null) - context.unit./*error*/warning(cdef.body.pos, "unreachable code due to " + vpat + addendum(cdef.pat)) + reporter.warning(cdef.body.pos, "unreachable code due to " + vpat + addendum(cdef.pat)) // TODO: make configurable whether this is an error // If this is a default case and more cases follow, warn about this one so // we have a reason to mention its pattern variable name and any corresponding // symbol in scope. Errors will follow from the remaining cases, at least @@ -78,7 +78,7 @@ trait MatchWarnings { case _ => "" } vpat = s"variable pattern$vpatName on line ${cdef.pat.pos.line}" - context.unit.warning(cdef.pos, s"patterns after a variable pattern cannot match (SLS 8.1.1)" + addendum(cdef.pat)) + reporter.warning(cdef.pos, s"patterns after a variable pattern cannot match (SLS 8.1.1)" + addendum(cdef.pat)) } } } diff --git a/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala b/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala index f6c960d089..ef50e083a1 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/PatternMatching.scala @@ -65,7 +65,7 @@ trait PatternMatching extends Transform } catch { case x: (Types#TypeError) => // TODO: this should never happen; error should've been reported during type checking - unit.error(tree.pos, "error during expansion of this match (this is a scalac bug).\nThe underlying error was: "+ x.msg) + reporter.error(tree.pos, "error during expansion of this match (this is a scalac bug).\nThe underlying error was: "+ x.msg) translated } case Try(block, catches, finalizer) => @@ -175,13 +175,13 @@ trait Interface extends ast.TreeDSL { val matchOwner = typer.context.owner def pureType(tp: Type): Type = tp - def reportUnreachable(pos: Position) = typer.context.unit.warning(pos, "unreachable code") + def reportUnreachable(pos: Position) = reporter.warning(pos, "unreachable code") def reportMissingCases(pos: Position, counterExamples: List[String]) = { val ceString = if (counterExamples.tail.isEmpty) "input: " + counterExamples.head else "inputs: " + counterExamples.mkString(", ") - typer.context.unit.warning(pos, "match may not be exhaustive.\nIt would fail on the following "+ ceString) + reporter.warning(pos, "match may not be exhaustive.\nIt would fail on the following "+ ceString) } } diff --git a/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala b/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala index d10eff1d8d..8f21f4ecfc 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala @@ -103,8 +103,8 @@ trait ScalacPatternExpanders { def offerString = if (extractor.isErroneous) "" else s" offering $offering" def arityExpected = ( if (extractor.hasSeq) "at least " else "" ) + productArity - def err(msg: String) = currentUnit.error(tree.pos, msg) - def warn(msg: String) = currentUnit.warning(tree.pos, msg) + def err(msg: String) = reporter.error(tree.pos, msg) + def warn(msg: String) = reporter.warning(tree.pos, msg) def arityError(what: String) = err(s"$what patterns for $owner$offerString: expected $arityExpected, found $totalArity") if (isStar && !isSeq) @@ -139,8 +139,10 @@ trait ScalacPatternExpanders { def acceptMessage = if (extractor.isErroneous) "" else s" to hold ${extractor.offeringString}" val requiresTupling = isUnapply && patterns.totalArity == 1 && productArity > 1 - if (requiresTupling && effectivePatternArity(args) == 1) - currentUnit.deprecationWarning(sel.pos, s"${sel.symbol.owner} expects $productArity patterns$acceptMessage but crushing into $productArity-tuple to fit single pattern (SI-6675)") + if (requiresTupling && effectivePatternArity(args) == 1) { + val sym = sel.symbol.owner + currentRun.reporting.deprecationWarning(sel.pos, sym, s"${sym} expects $productArity patterns$acceptMessage but crushing into $productArity-tuple to fit single pattern (SI-6675)") + } val normalizedExtractor = if (requiresTupling) tupleExtractor(extractor) else extractor validateAligned(fn, Aligned(patterns, normalizedExtractor)) diff --git a/src/compiler/scala/tools/nsc/typechecker/Adaptations.scala b/src/compiler/scala/tools/nsc/typechecker/Adaptations.scala index 1e544e54f6..37c39c07be 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Adaptations.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Adaptations.scala @@ -77,7 +77,7 @@ trait Adaptations { val msg = "Adaptation of argument list by inserting () has been deprecated: " + ( if (isLeakyTarget) "leaky (Object-receiving) target makes this especially dangerous." else "this is unlikely to be what you want.") - context.unit.deprecationWarning(t.pos, adaptWarningMessage(msg)) + context.deprecationWarning(t.pos, t.symbol, adaptWarningMessage(msg)) } } else if (settings.warnAdaptedArgs) context.warning(t.pos, adaptWarningMessage(s"Adapting argument list by creating a ${args.size}-tuple: this may not be what you want.")) diff --git a/src/compiler/scala/tools/nsc/typechecker/Checkable.scala b/src/compiler/scala/tools/nsc/typechecker/Checkable.scala index 13884404b3..3a77cab919 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Checkable.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Checkable.scala @@ -275,7 +275,7 @@ trait Checkable { ; // Matching on types like case _: AnyRef { def bippy: Int } => doesn't work -- yet. case RefinedType(_, decls) if !decls.isEmpty => - getContext.unit.warning(tree.pos, s"a pattern match on a refinement type is unchecked") + reporter.warning(tree.pos, s"a pattern match on a refinement type is unchecked") case RefinedType(parents, _) => parents foreach (p => checkCheckable(tree, p, X, inPattern, canRemedy)) case _ => @@ -285,14 +285,14 @@ trait Checkable { if (checker.neverMatches) { val addendum = if (checker.neverSubClass) "" else " (but still might match its erasure)" - getContext.unit.warning(tree.pos, s"fruitless type test: a value of type $X cannot also be a $PString$addendum") + reporter.warning(tree.pos, s"fruitless type test: a value of type $X cannot also be a $PString$addendum") } else if (checker.isUncheckable) { val msg = ( if (checker.uncheckableType =:= P) s"abstract type $where$PString" else s"${checker.uncheckableMessage} in type $where$PString" ) - getContext.unit.warning(tree.pos, s"$msg is unchecked since it is eliminated by erasure") + reporter.warning(tree.pos, s"$msg is unchecked since it is eliminated by erasure") } } } diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index 8e1ceffecd..72ca9b879a 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -66,7 +66,7 @@ trait Contexts { self: Analyzer => def isMask(s: ImportSelector) = s.name != nme.WILDCARD && s.rename == nme.WILDCARD imp.tree.selectors filterNot (s => isMask(s) || used(s)) foreach { sel => - unit.warning(imp posOf sel, "Unused import") + reporter.warning(imp posOf sel, "Unused import") } } allUsedSelectors --= imps @@ -103,7 +103,7 @@ trait Contexts { self: Analyzer => // there must be a scala.xml package when xml literals were parsed in this unit if (unit.hasXml && ScalaXmlPackage == NoSymbol) - unit.error(unit.firstXmlPos, "To compile XML syntax, the scala.xml package must be on the classpath.\nPlease see http://docs.scala-lang.org/overviews/core/scala-2.11.html#scala-xml.") + reporter.error(unit.firstXmlPos, "To compile XML syntax, the scala.xml package must be on the classpath.\nPlease see http://docs.scala-lang.org/overviews/core/scala-2.11.html#scala-xml.") // scala-xml needs `scala.xml.TopScope` to be in scope globally as `$scope` // We detect `scala-xml` by looking for `scala.xml.TopScope` and @@ -359,7 +359,7 @@ trait Contexts { self: Analyzer => /** Issue and clear all warnings from the report buffer */ def flushAndIssueWarnings() { reportBuffer.warnings foreach { - case (pos, msg) => unit.warning(pos, msg) + case (pos, msg) => reporter.warning(pos, msg) } reportBuffer.clearAllWarnings() } @@ -541,7 +541,7 @@ trait Contexts { self: Analyzer => } private def unitError(pos: Position, msg: String): Unit = - if (checking) onTreeCheckerError(pos, msg) else unit.error(pos, msg) + if (checking) onTreeCheckerError(pos, msg) else reporter.error(pos, msg) @inline private def issueCommon(err: AbsTypeError)(pf: PartialFunction[AbsTypeError, Unit]) { // TODO: are errors allowed to have pos == NoPosition?? @@ -589,10 +589,20 @@ trait Contexts { self: Analyzer => /** Issue/throw the given error message according to the current mode for error reporting. */ def warning(pos: Position, msg: String, force: Boolean = false) { - if (reportErrors || force) unit.warning(pos, msg) + if (reportErrors || force) reporter.warning(pos, msg) else if (bufferErrors) reportBuffer += (pos -> msg) } + def deprecationWarning(pos: Position, sym: Symbol, msg: String): Unit = + currentRun.reporting.deprecationWarning(pos, sym, msg) + def deprecationWarning(pos: Position, sym: Symbol): Unit = + currentRun.reporting.deprecationWarning(pos, sym) // TODO: allow this to escalate to an error, and implicit search will ignore deprecated implicits + + def featureWarning(pos: Position, featureName: String, featureDesc: String, featureTrait: Symbol, construct: => String = "", required: Boolean): Unit = + currentRun.reporting.featureWarning(pos, featureName, featureDesc, featureTrait, construct, required) + + def echo(pos: Position, msg: String): Unit = reporter.echo(pos, msg) + // nextOuter determines which context is searched next for implicits // (after `this`, which contributes `newImplicits` below.) In // most cases, it is simply the outer context: if we're owned by diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index fc0e2c7c80..a3f1da60ce 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -558,7 +558,7 @@ trait Infer extends Checkable { foreachWithIndex(targs) ((targ, idx) => targ.typeSymbol match { case sym @ (AnyClass | AnyValClass) => - context.unit.warning(argumentPosition(idx), s"a type was inferred to be `${sym.name}`; this may indicate a programming error.") + reporter.warning(argumentPosition(idx), s"a type was inferred to be `${sym.name}`; this may indicate a programming error.") case _ => } ) diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index ef74beec62..9c22688581 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -714,7 +714,7 @@ trait Macros extends MacroRuntimes with Traces with Helpers { sealed abstract class MacroStatus(val result: Tree) case class Success(expanded: Tree) extends MacroStatus(expanded) - case class Fallback(fallback: Tree) extends MacroStatus(fallback) { currentRun.seenMacroExpansionsFallingBack = true } + case class Fallback(fallback: Tree) extends MacroStatus(fallback) { currentRun.reporting.seenMacroExpansionsFallingBack = true } case class Delayed(delayed: Tree) extends MacroStatus(delayed) case class Skipped(skipped: Tree) extends MacroStatus(skipped) case class Failure(failure: Tree) extends MacroStatus(failure) @@ -788,7 +788,7 @@ trait Macros extends MacroRuntimes with Traces with Helpers { } } catch { case ex: Throwable => - popMacroContext() + if (openMacros.nonEmpty) popMacroContext() // weirdly we started popping on an empty stack when refactoring fatalWarnings logic val realex = ReflectionUtils.unwrapThrowable(ex) realex match { case ex: AbortMacroException => MacroGeneratedAbort(expandee, ex) diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 099031d536..1328119aac 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -443,7 +443,7 @@ trait Namers extends MethodSynthesis { && clazz.exists ) if (fails) { - context.unit.error(tree.pos, ( + reporter.error(tree.pos, ( s"Companions '$clazz' and '$module' must be defined in same file:\n" + s" Found in ${clazz.sourceFile.canonicalPath} and ${module.sourceFile.canonicalPath}") ) @@ -718,7 +718,7 @@ trait Namers extends MethodSynthesis { } val owner = tree.symbol.owner if (settings.lint && owner.isPackageObjectClass && !mods.isImplicit) { - context.unit.warning(tree.pos, + reporter.warning(tree.pos, "it is not recommended to define classes/objects inside of package objects.\n" + "If possible, define " + tree.symbol + " in " + owner.skipPackageObject + " instead." ) @@ -730,7 +730,7 @@ trait Namers extends MethodSynthesis { log("enter implicit wrapper "+tree+", owner = "+owner) enterImplicitWrapper(tree) } - else context.unit.error(tree.pos, "implicit classes must accept exactly one primary constructor parameter") + else reporter.error(tree.pos, "implicit classes must accept exactly one primary constructor parameter") } validateCompanionDefs(tree) } diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala index 284ab2f6f9..43902d1c65 100644 --- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala +++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala @@ -536,8 +536,8 @@ trait NamesDefaults { self: Analyzer => def matchesName(param: Symbol) = !param.isSynthetic && ( (param.name == name) || (param.deprecatedParamName match { case Some(`name`) => - context0.unit.deprecationWarning(arg.pos, - "the parameter name "+ name +" has been deprecated. Use "+ param.name +" instead.") + context0.deprecationWarning(arg.pos, param, + s"the parameter name $name has been deprecated. Use ${param.name} instead.") true case _ => false }) diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 4540017b62..1b3da26bf2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -147,7 +147,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans val owners = haveDefaults map (_.owner) // constructors of different classes are allowed to have defaults if (haveDefaults.exists(x => !x.isConstructor) || owners.distinct.size < haveDefaults.size) { - unit.error(clazz.pos, + reporter.error(clazz.pos, "in "+ clazz + ", multiple overloaded alternatives of "+ haveDefaults.head + " define default arguments" + ( @@ -162,7 +162,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans // Check for doomed attempt to overload applyDynamic if (clazz isSubClass DynamicClass) { for ((_, m1 :: m2 :: _) <- (clazz.info member nme.applyDynamic).alternatives groupBy (_.typeParams.length)) { - unit.error(m1.pos, "implementation restriction: applyDynamic cannot be overloaded except by methods with different numbers of type parameters, e.g. applyDynamic[T1](method: String)(arg: T1) and applyDynamic[T1, T2](method: String)(arg1: T1, arg2: T2)") + reporter.error(m1.pos, "implementation restriction: applyDynamic cannot be overloaded except by methods with different numbers of type parameters, e.g. applyDynamic[T1](method: String)(arg: T1) and applyDynamic[T1, T2](method: String)(arg1: T1, arg2: T2)") } } @@ -172,7 +172,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans // implicit classes leave both a module symbol and a method symbol as residue val alts = clazz.info.decl(sym.name).alternatives filterNot (_.isModule) if (alts.size > 1) - alts foreach (x => unit.warning(x.pos, "parameterized overloaded implicit methods are not visible as view bounds")) + alts foreach (x => reporter.warning(x.pos, "parameterized overloaded implicit methods are not visible as view bounds")) } } } @@ -281,10 +281,10 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans mixinOverrideErrors.toList match { case List() => case List(MixinOverrideError(_, msg)) => - unit.error(clazz.pos, msg) + reporter.error(clazz.pos, msg) case MixinOverrideError(member, msg) :: others => val others1 = others.map(_.member.name.decode).filter(member.name.decode != _).distinct - unit.error( + reporter.error( clazz.pos, msg+(if (others1.isEmpty) "" else ";\n other members with override errors are: "+(others1 mkString ", "))) @@ -347,7 +347,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans ) } def emitOverrideError(fullmsg: String) { - if (member.owner == clazz) unit.error(member.pos, fullmsg) + if (member.owner == clazz) reporter.error(member.pos, fullmsg) else mixinOverrideErrors += new MixinOverrideError(member, fullmsg) } @@ -464,7 +464,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans checkOverrideDeprecated() if (settings.warnNullaryOverride) { if (other.paramss.isEmpty && !member.paramss.isEmpty) { - unit.warning(member.pos, "non-nullary method overrides nullary method") + reporter.warning(member.pos, "non-nullary method overrides nullary method") } } } @@ -496,7 +496,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans typer.infer.checkKindBounds(high :: Nil, lowType :: Nil, rootType, low.owner) match { // (1.7.2) case Nil => case kindErrors => - unit.error(member.pos, + reporter.error(member.pos, "The kind of "+member.keyString+" "+member.varianceString + member.nameString+ " does not conform to the expected kind of " + other.defString + other.locationString + "." + kindErrors.toList.mkString("\n", ", ", "")) @@ -507,7 +507,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans typer.infer.checkKindBounds(low :: Nil, lowType.normalize :: Nil, rootType, low.owner) match { case Nil => case kindErrors => - unit.error(member.pos, + reporter.error(member.pos, "The kind of the right-hand side "+lowType.normalize+" of "+low.keyString+" "+ low.varianceString + low.nameString+ " does not conform to its expected kind."+ kindErrors.toList.mkString("\n", ", ", "")) @@ -546,7 +546,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans if (other.hasDeprecatedOverridingAnnotation) { val suffix = other.deprecatedOverridingMessage map (": " + _) getOrElse "" val msg = s"overriding ${other.fullLocationString} is deprecated$suffix" - unit.deprecationWarning(member.pos, msg) + currentRun.reporting.deprecationWarning(member.pos, other, msg) } } } @@ -754,7 +754,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans checkNoAbstractDecls(clazz) if (abstractErrors.nonEmpty) - unit.error(clazz.pos, abstractErrorMessage) + reporter.error(clazz.pos, abstractErrorMessage) } else if (clazz.isTrait && !(clazz isSubClass AnyValClass)) { // For non-AnyVal classes, prevent abstract methods in interfaces that override @@ -765,7 +765,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans // override a concrete method in Object. The jvm, however, does not. val overridden = decl.matchingSymbol(ObjectClass, ObjectTpe) if (overridden.isFinal) - unit.error(decl.pos, "trait cannot redefine final method from class AnyRef") + reporter.error(decl.pos, "trait cannot redefine final method from class AnyRef") } } @@ -818,7 +818,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans // for (bc <- clazz.info.baseClasses.tail) Console.println("" + bc + " has " + bc.info.decl(member.name) + ":" + bc.info.decl(member.name).tpe);//DEBUG val nonMatching: List[Symbol] = clazz.info.member(member.name).alternatives.filterNot(_.owner == clazz).filterNot(_.isFinal) - def issueError(suffix: String) = unit.error(member.pos, member.toString() + " overrides nothing" + suffix) + def issueError(suffix: String) = reporter.error(member.pos, member.toString() + " overrides nothing" + suffix) nonMatching match { case Nil => issueError("") @@ -871,7 +871,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans case _ :: Nil => ;// OK case tp1 :: tp2 :: _ => - unit.error(clazz.pos, "illegal inheritance;\n " + clazz + + reporter.error(clazz.pos, "illegal inheritance;\n " + clazz + " inherits different type instances of " + baseClass + ":\n" + tp1 + " and " + tp2) explainTypes(tp1, tp2) @@ -888,7 +888,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans case _ => "type "+tp } override def issueVarianceError(base: Symbol, sym: Symbol, required: Variance) { - currentRun.currentUnit.error(base.pos, + reporter.error(base.pos, s"${sym.variance} $sym occurs in $required position in ${tpString(base.info)} of $base") } } @@ -956,7 +956,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans def checkImplicitViewOptionApply(pos: Position, fn: Tree, args: List[Tree]): Unit = if (settings.lint) (fn, args) match { case (tap@TypeApply(fun, targs), List(view: ApplyImplicitView)) if fun.symbol == currentRun.runDefinitions.Option_apply => - unit.warning(pos, s"Suspicious application of an implicit view (${view.fun}) in the argument to Option.apply.") // SI-6567 + reporter.warning(pos, s"Suspicious application of an implicit view (${view.fun}) in the argument to Option.apply.") // SI-6567 case _ => } @@ -1031,7 +1031,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans def nonSensibleWarning(what: String, alwaysEqual: Boolean) = { val msg = alwaysEqual == (name == nme.EQ || name == nme.eq) - unit.warning(pos, s"comparing $what using `${name.decode}' will always yield $msg") + reporter.warning(pos, s"comparing $what using `${name.decode}' will always yield $msg") isNonSensible = true } def nonSensible(pre: String, alwaysEqual: Boolean) = @@ -1046,7 +1046,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans } def unrelatedTypes() = if (!isNonSensible) { val weaselWord = if (isEitherValueClass) "" else " most likely" - unit.warning(pos, s"$typesString are unrelated: they will$weaselWord $unrelatedMsg") + reporter.warning(pos, s"$typesString are unrelated: they will$weaselWord $unrelatedMsg") } if (nullCount == 2) // null == null @@ -1141,7 +1141,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans && callsSelf ) if (trivialInifiniteLoop) - unit.warning(valOrDef.rhs.pos, s"${valOrDef.symbol.fullLocationString} does nothing other than call itself recursively") + reporter.warning(valOrDef.rhs.pos, s"${valOrDef.symbol.fullLocationString} does nothing other than call itself recursively") } // Transformation ------------------------------------------------------------ @@ -1231,7 +1231,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans finally if (currentLevel.maxindex > 0) { // An implementation restriction to avoid VerifyErrors and lazyvals mishaps; see SI-4717 debuglog("refsym = " + currentLevel.refsym) - unit.error(currentLevel.refpos, "forward reference not allowed from self constructor invocation") + reporter.error(currentLevel.refpos, "forward reference not allowed from self constructor invocation") } case ModuleDef(_, _, _) => eliminateModuleDefs(tree) case ValDef(_, _, _, _) => @@ -1241,7 +1241,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans val lazySym = tree.symbol.lazyAccessorOrSelf if (lazySym.isLocalToBlock && index <= currentLevel.maxindex) { debuglog("refsym = " + currentLevel.refsym) - unit.error(currentLevel.refpos, "forward reference extends over definition of " + lazySym) + reporter.error(currentLevel.refpos, "forward reference extends over definition of " + lazySym) } tree1 :: Nil } @@ -1255,7 +1255,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans try typer.infer.checkBounds(tree0, pre, owner, tparams, argtps, "") catch { case ex: TypeError => - unit.error(tree0.pos, ex.getMessage()) + reporter.error(tree0.pos, ex.getMessage()) if (settings.explaintypes) { val bounds = tparams map (tp => tp.info.instantiateTypeParams(tparams, argtps).bounds) (argtps, bounds).zipped map ((targ, bound) => explainTypes(bound.lo, targ)) @@ -1287,11 +1287,9 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans private def checkUndesiredProperties(sym: Symbol, pos: Position) { // If symbol is deprecated, and the point of reference is not enclosed // in either a deprecated member or a scala bridge method, issue a warning. - if (sym.isDeprecated && !currentOwner.ownerChain.exists(x => x.isDeprecated || x.hasBridgeAnnotation)) { - unit.deprecationWarning(pos, "%s%s is deprecated%s".format( - sym, sym.locationString, sym.deprecationMessage map (": " + _) getOrElse "") - ) - } + if (sym.isDeprecated && !currentOwner.ownerChain.exists(x => x.isDeprecated || x.hasBridgeAnnotation)) + currentRun.reporting.deprecationWarning(pos, sym) + // Similar to deprecation: check if the symbol is marked with @migration // indicating it has changed semantics between versions. if (sym.hasMigrationAnnotation && settings.Xmigration.value != NoScalaVersion) { @@ -1299,12 +1297,12 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans settings.Xmigration.value < ScalaVersion(sym.migrationVersion.get) catch { case e : NumberFormatException => - unit.warning(pos, s"${sym.fullLocationString} has an unparsable version number: ${e.getMessage()}") + reporter.warning(pos, s"${sym.fullLocationString} has an unparsable version number: ${e.getMessage()}") // if we can't parse the format on the migration annotation just conservatively assume it changed true } if (changed) - unit.warning(pos, s"${sym.fullLocationString} has changed semantics in version ${sym.migrationVersion.get}:\n${sym.migrationMessage.get}") + reporter.warning(pos, s"${sym.fullLocationString} has changed semantics in version ${sym.migrationVersion.get}:\n${sym.migrationMessage.get}") } // See an explanation of compileTimeOnly in its scaladoc at scala.annotation.compileTimeOnly. if (sym.isCompileTimeOnly) { @@ -1312,7 +1310,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans sm"""Reference to ${sym.fullLocationString} should not have survived past type checking, |it should have been processed and eliminated during expansion of an enclosing macro.""" // The getOrElse part should never happen, it's just here as a backstop. - unit.error(pos, sym.compileTimeOnlyMessage getOrElse defaultMsg) + reporter.error(pos, sym.compileTimeOnlyMessage getOrElse defaultMsg) } } @@ -1323,7 +1321,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans && sym.accessedOrSelf.isVal ) if (settings.lint.value && isLikelyUninitialized) - unit.warning(pos, s"Selecting ${sym} from ${sym.owner}, which extends scala.DelayedInit, is likely to yield an uninitialized value") + reporter.warning(pos, s"Selecting ${sym} from ${sym.owner}, which extends scala.DelayedInit, is likely to yield an uninitialized value") } private def lessAccessible(otherSym: Symbol, memberSym: Symbol): Boolean = ( @@ -1355,7 +1353,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans if (memberSym.isDeferred) "may be unable to provide a concrete implementation of" else "may be unable to override" - unit.warning(memberSym.pos, + reporter.warning(memberSym.pos, "%s%s references %s %s.".format( memberSym.fullLocationString, comparison, accessFlagsToString(otherSym), otherSym @@ -1390,7 +1388,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans tree match { case DefDef(_, name, _, params :: _, _, _) => if (settings.lint && !treeInfo.isLeftAssoc(name.decodedName) && params.exists(p => isByName(p.symbol))) - unit.warning(tree.pos, + reporter.warning(tree.pos, "by-name parameters will be evaluated eagerly when called as a right-associative infix operator. For more details, see SI-1980.") case _ => } @@ -1407,10 +1405,10 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans symbol.allOverriddenSymbols.filter(sym => !sym.isDeprecated && !sym.isDeferred) if(!concrOvers.isEmpty) - unit.deprecationWarning( + currentRun.reporting.deprecationWarning( tree.pos, - symbol.toString + " overrides concrete, non-deprecated symbol(s):" + - concrOvers.map(_.name.decode).mkString(" ", ", ", "")) + symbol, + s"${symbol.toString} overrides concrete, non-deprecated symbol(s): ${concrOvers.map(_.name.decode).mkString(", ")}") } } private def isRepeatedParamArg(tree: Tree) = currentApplication match { @@ -1471,7 +1469,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans applyChecks(sym.annotations) // validate implicitNotFoundMessage analyzer.ImplicitNotFoundMsg.check(sym) foreach { warn => - unit.warning(tree.pos, f"Invalid implicitNotFound message for ${sym}%s${sym.locationString}%s:%n$warn") + reporter.warning(tree.pos, f"Invalid implicitNotFound message for ${sym}%s${sym.locationString}%s:%n$warn") } case tpt@TypeTree() => @@ -1596,7 +1594,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans || sym.allOverriddenSymbols.exists(over => !(over.tpe.resultType =:= sym.tpe.resultType)) ) if (!isOk) - unit.warning(sym.pos, s"side-effecting nullary methods are discouraged: suggest defining as `def ${sym.name.decode}()` instead") + reporter.warning(sym.pos, s"side-effecting nullary methods are discouraged: suggest defining as `def ${sym.name.decode}()` instead") case _ => () } @@ -1604,15 +1602,15 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans private def checkAnyValSubclass(clazz: Symbol) = { if (clazz.isDerivedValueClass) { if (clazz.isTrait) - unit.error(clazz.pos, "Only classes (not traits) are allowed to extend AnyVal") + reporter.error(clazz.pos, "Only classes (not traits) are allowed to extend AnyVal") else if (clazz.hasAbstractFlag) - unit.error(clazz.pos, "`abstract' modifier cannot be used with value classes") + reporter.error(clazz.pos, "`abstract' modifier cannot be used with value classes") } } private def checkUnexpandedMacro(t: Tree) = if (!t.isDef && t.hasSymbolField && t.symbol.isTermMacro) - unit.error(t.pos, "macro has not been expanded") + reporter.error(t.pos, "macro has not been expanded") override def transform(tree: Tree): Tree = { val savedLocalTyper = localTyper @@ -1707,7 +1705,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans tree case treeInfo.WildcardStarArg(_) if !isRepeatedParamArg(tree) => - unit.error(tree.pos, "no `: _*' annotation allowed here\n"+ + reporter.error(tree.pos, "no `: _*' annotation allowed here\n"+ "(such annotations are only allowed in arguments to *-parameters)") tree @@ -1780,7 +1778,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans } catch { case ex: TypeError => if (settings.debug) ex.printStackTrace() - unit.error(tree.pos, ex.getMessage()) + reporter.error(tree.pos, ex.getMessage()) tree } finally { localTyper = savedLocalTyper diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala index b6d37ab9a7..d3a41b9570 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala @@ -124,7 +124,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT if (other == NoSymbol) other = linked.info.decl(sym.name.toTermName).filter(_.isModule) if (other != NoSymbol) - unit.error(sym.pos, "name clash: "+sym.owner+" defines "+sym+ + reporter.error(sym.pos, "name clash: "+sym.owner+" defines "+sym+ "\nand its companion "+sym.owner.companionModule+" also defines "+ other) } @@ -139,14 +139,14 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT val member = sym.overridingSymbol(clazz) if (mix != tpnme.EMPTY || member == NoSymbol || !(member.isAbstractOverride && member.isIncompleteIn(clazz))) - unit.error(sel.pos, ""+sym.fullLocationString+" is accessed from super. It may not be abstract "+ + reporter.error(sel.pos, ""+sym.fullLocationString+" is accessed from super. It may not be abstract "+ "unless it is overridden by a member declared `abstract' and `override'") } else if (mix == tpnme.EMPTY && !sym.owner.isTrait){ // SI-4989 Check if an intermediate class between `clazz` and `sym.owner` redeclares the method as abstract. val intermediateClasses = clazz.info.baseClasses.tail.takeWhile(_ != sym.owner) intermediateClasses.map(sym.overridingSymbol).find(s => s.isDeferred && !s.isAbstractOverride && !s.owner.isTrait).foreach { absSym => - unit.error(sel.pos, s"${sym.fullLocationString} cannot be directly accessed from ${clazz} because ${absSym.owner} redeclares it as abstract") + reporter.error(sel.pos, s"${sym.fullLocationString} cannot be directly accessed from ${clazz} because ${absSym.owner} redeclares it as abstract") } } @@ -252,7 +252,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT qual.symbol.ancestors foreach { parent => parent.info.decls filterNot (x => x.isPrivate || x.isLocalToThis) foreach { m2 => if (sym.name == m2.name && m2.isGetter && m2.accessed.isMutable) { - unit.warning(sel.pos, + reporter.warning(sel.pos, sym.accessString + " " + sym.fullLocationString + " shadows mutable " + m2.name + " inherited from " + m2.owner + ". Changes to " + m2.name + " will not be visible within " + sym.owner + " - you may want to give them distinct names.") @@ -310,9 +310,9 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT case Super(_, mix) => if (sym.isValue && !sym.isMethod || sym.hasAccessorFlag) { if (!settings.overrideVars) - unit.error(tree.pos, "super may be not be used on " + sym.accessedOrSelf) + reporter.error(tree.pos, "super may be not be used on " + sym.accessedOrSelf) } else if (isDisallowed(sym)) { - unit.error(tree.pos, "super not allowed here: use this." + name.decode + " instead") + reporter.error(tree.pos, "super not allowed here: use this." + name.decode + " instead") } transformSuperSelect(sel) diff --git a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala index a2f52e1905..399a4ca8d5 100644 --- a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala @@ -17,7 +17,7 @@ abstract class TreeCheckers extends Analyzer { override protected def onTreeCheckerError(pos: Position, msg: String) { if (settings.fatalWarnings) - currentUnit.warning(pos, "\n** Error during internal checking:\n" + msg) + reporter.warning(pos, "\n** Error during internal checking:\n" + msg) } case class DiffResult[T](lost: List[T], gained: List[T]) { @@ -170,7 +170,7 @@ abstract class TreeCheckers extends Analyzer { ) - def errorFn(pos: Position, msg: Any): Unit = currentUnit.warning(pos, "[check: %s] %s".format(phase.prev, msg)) + def errorFn(pos: Position, msg: Any): Unit = reporter.warning(pos, "[check: %s] %s".format(phase.prev, msg)) def errorFn(msg: Any): Unit = errorFn(NoPosition, msg) def informFn(msg: Any) { diff --git a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala index 60346e7be1..7440f69e93 100644 --- a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala +++ b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala @@ -41,9 +41,9 @@ trait TypeDiagnostics { * indicate that the restriction may be lifted in the future. */ def restrictionWarning(pos: Position, unit: CompilationUnit, msg: String): Unit = - unit.warning(pos, "Implementation restriction: " + msg) + reporter.warning(pos, "Implementation restriction: " + msg) def restrictionError(pos: Position, unit: CompilationUnit, msg: String): Unit = - unit.error(pos, "Implementation restriction: " + msg) + reporter.error(pos, "Implementation restriction: " + msg) /** A map of Positions to addendums - if an error involves a position in * the map, the addendum should also be printed. @@ -435,12 +435,8 @@ trait TypeDiagnostics { trait TyperDiagnostics { self: Typer => - private def contextError(context0: Analyzer#Context, pos: Position, msg: String) = context0.error(pos, msg) - private def contextError(context0: Analyzer#Context, pos: Position, err: Throwable) = context0.error(pos, err) - private def contextWarning(pos: Position, msg: String) = context.unit.warning(pos, msg) - def permanentlyHiddenWarning(pos: Position, hidden: Name, defn: Symbol) = - contextWarning(pos, "imported `%s' is permanently hidden by definition of %s".format(hidden, defn.fullLocationString)) + context.warning(pos, "imported `%s' is permanently hidden by definition of %s".format(hidden, defn.fullLocationString)) object checkUnused { val ignoreNames = Set[TermName]("readResolve", "readObject", "writeObject", "writeReplace") @@ -542,15 +538,15 @@ trait TypeDiagnostics { else if (sym.isModule) "object" else "term" ) - unit.warning(pos, s"$why $what in ${sym.owner} is never used") + reporter.warning(pos, s"$why $what in ${sym.owner} is never used") } p.unsetVars foreach { v => - unit.warning(v.pos, s"local var ${v.name} in ${v.owner} is never set - it could be a val") + reporter.warning(v.pos, s"local var ${v.name} in ${v.owner} is never set - it could be a val") } p.unusedTypes foreach { t => val sym = t.symbol val why = if (sym.isPrivate) "private" else "local" - unit.warning(t.pos, s"$why ${sym.fullLocationString} is never used") + reporter.warning(t.pos, s"$why ${sym.fullLocationString} is never used") } } } @@ -627,13 +623,13 @@ trait TypeDiagnostics { case Import(expr, _) => expr.pos case _ => ex.pos } - contextError(context0, pos, cyclicReferenceMessage(sym, info.tree) getOrElse ex.getMessage()) + context0.error(pos, cyclicReferenceMessage(sym, info.tree) getOrElse ex.getMessage()) if (sym == ObjectClass) throw new FatalError("cannot redefine root "+sym) } case _ => - contextError(context0, ex.pos, ex) + context0.error(ex.pos, ex) } } } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 9a4d5e3c06..2c31ef2e8e 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -746,21 +746,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper if (!OK) { val Some(AnnotationInfo(_, List(Literal(Constant(featureDesc: String)), Literal(Constant(required: Boolean))), _)) = featureTrait getAnnotation LanguageFeatureAnnot - val req = if (required) "needs to" else "should" - val fqname = "scala.language." + featureName - val explain = ( - if (currentRun.reportedFeature contains featureTrait) "" else - s"""| - |This can be achieved by adding the import clause 'import $fqname' - |or by setting the compiler option -language:$featureName. - |See the Scala docs for value $fqname for a discussion - |why the feature $req be explicitly enabled.""".stripMargin - ) - currentRun.reportedFeature += featureTrait - - val msg = s"$featureDesc $req be enabled\nby making the implicit value $fqname visible.$explain" replace ("#", construct) - if (required) unit.error(pos, msg) - else currentRun.featureWarnings.warn(pos, msg) + context.featureWarning(pos, featureName, featureDesc, featureTrait, construct, required) } OK } @@ -955,10 +941,9 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper } def adaptConstant(value: Constant): Tree = { val sym = tree.symbol - if (sym != null && sym.isDeprecated) { - val msg = sym.toString + sym.locationString + " is deprecated: " + sym.deprecationMessage.getOrElse("") - unit.deprecationWarning(tree.pos, msg) - } + if (sym != null && sym.isDeprecated) + context.deprecationWarning(tree.pos, sym) + treeCopy.Literal(tree, value) } @@ -1066,7 +1051,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper case coercion => def msg = "inferred view from " + tree.tpe + " to " + pt + " = " + coercion + ":" + coercion.tpe if (settings.logImplicitConv) - unit.echo(tree.pos, msg) + context.echo(tree.pos, msg) debuglog(msg) val silentContext = context.makeImplicit(context.ambiguousErrors) @@ -1226,7 +1211,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper case EmptyTree => qual case coercion => if (settings.logImplicitConv) - unit.echo(qual.pos, + context.echo(qual.pos, "applied implicit conversion from %s to %s = %s".format( qual.tpe, searchTemplate, coercion.symbol.defString)) @@ -1291,7 +1276,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper private def validateNoCaseAncestor(clazz: Symbol) = { if (!phase.erasedTypes) { for (ancestor <- clazz.ancestors find (_.isCase)) { - unit.error(clazz.pos, ( + context.error(clazz.pos, ( "case %s has case ancestor %s, but case-to-case inheritance is prohibited."+ " To overcome this limitation, use extractors to pattern match on non-leaf nodes." ).format(clazz, ancestor.fullName)) @@ -1308,7 +1293,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper val isValueClass = !clazz.isTrait def where = if (isValueClass) "value class" else "universal trait extending from class Any" def implRestriction(tree: Tree, what: String) = - unit.error(tree.pos, s"implementation restriction: $what is not allowed in $where" + + context.error(tree.pos, s"implementation restriction: $what is not allowed in $where" + "\nThis restriction is planned to be removed in subsequent releases.") /** * Deeply traverses the tree in search of constructs that are not allowed @@ -1337,7 +1322,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper } } for (stat <- body) { - def notAllowed(what: String) = unit.error(stat.pos, s"$what is not allowed in $where") + def notAllowed(what: String) = context.error(stat.pos, s"$what is not allowed in $where") stat match { // see https://issues.scala-lang.org/browse/SI-6444 // see https://issues.scala-lang.org/browse/SI-6463 @@ -1365,9 +1350,9 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper private def validateDerivedValueClass(clazz: Symbol, body: List[Tree]) = { if (clazz.isTrait) - unit.error(clazz.pos, "only classes (not traits) are allowed to extend AnyVal") + context.error(clazz.pos, "only classes (not traits) are allowed to extend AnyVal") if (!clazz.isStatic) - unit.error(clazz.pos, "value class may not be a "+ + context.error(clazz.pos, "value class may not be a "+ (if (clazz.owner.isTerm) "local class" else "member of another class")) if (!clazz.isPrimitiveValueClass) { clazz.primaryConstructor.paramss match { @@ -1375,26 +1360,26 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper val decls = clazz.info.decls val paramAccessor = clazz.constrParamAccessors.head if (paramAccessor.isMutable) - unit.error(paramAccessor.pos, "value class parameter must not be a var") + context.error(paramAccessor.pos, "value class parameter must not be a var") val accessor = decls.toList.find(x => x.isMethod && x.accessedOrSelf == paramAccessor) accessor match { case None => - unit.error(paramAccessor.pos, "value class parameter must be a val and not be private[this]") + context.error(paramAccessor.pos, "value class parameter must be a val and not be private[this]") case Some(acc) if acc.isProtectedLocal => - unit.error(paramAccessor.pos, "value class parameter must not be protected[this]") + context.error(paramAccessor.pos, "value class parameter must not be protected[this]") case Some(acc) => if (acc.tpe.typeSymbol.isDerivedValueClass) - unit.error(acc.pos, "value class may not wrap another user-defined value class") + context.error(acc.pos, "value class may not wrap another user-defined value class") checkEphemeral(clazz, body filterNot (stat => stat.symbol != null && stat.symbol.accessedOrSelf == paramAccessor)) } case _ => - unit.error(clazz.pos, "value class needs to have exactly one val parameter") + context.error(clazz.pos, "value class needs to have exactly one val parameter") } } for (tparam <- clazz.typeParams) if (tparam hasAnnotation definitions.SpecializedClass) - unit.error(tparam.pos, "type parameter of value class may not be specialized") + context.error(tparam.pos, "type parameter of value class may not be specialized") } /** Typechecks a parent type reference. @@ -1690,7 +1675,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper if (!isPastTyper && psym.hasDeprecatedInheritanceAnnotation && !sameSourceFile) { val suffix = psym.deprecatedInheritanceMessage map (": " + _) getOrElse "" val msg = s"inheritance from ${psym.fullLocationString} is deprecated$suffix" - unit.deprecationWarning(parent.pos, msg) + context.deprecationWarning(parent.pos, psym, msg) } if (psym.isSealed && !phase.erasedTypes) @@ -1757,7 +1742,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper if ((clazz isNonBottomSubClass ClassfileAnnotationClass) && (clazz != ClassfileAnnotationClass)) { if (!clazz.owner.isPackageClass) - unit.error(clazz.pos, "inner classes cannot be classfile annotations") + context.error(clazz.pos, "inner classes cannot be classfile annotations") else restrictionWarning(cdef.pos, unit, """|subclassing Classfile does not |make your annotation visible at runtime. If that is what @@ -1812,7 +1797,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper private def ensurePredefParentsAreInSameSourceFile(template: Template) = { val parentSyms = template.parents map (_.symbol) filterNot (_ == AnyRefClass) if (parentSyms exists (_.associatedFile != PredefModule.associatedFile)) - unit.error(template.pos, s"All parents of Predef must be defined in ${PredefModule.associatedFile}.") + context.error(template.pos, s"All parents of Predef must be defined in ${PredefModule.associatedFile}.") } /** In order to override this in the TreeCheckers Typer so synthetics aren't re-added * all the time, it is exposed here the module/class typing methods go through it. @@ -1883,7 +1868,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper ConstrArgsInParentOfTraitError(parents1.head, clazz) if ((clazz isSubClass ClassfileAnnotationClass) && !clazz.isTopLevel) - unit.error(clazz.pos, "inner classes cannot be classfile annotations") + context.error(clazz.pos, "inner classes cannot be classfile annotations") if (!phase.erasedTypes && !clazz.info.resultType.isError) // @S: prevent crash for duplicated type members checkFinitary(clazz.info.resultType.asInstanceOf[ClassInfoType]) @@ -1911,7 +1896,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper if (clazz.isTrait) { for (decl <- clazz.info.decls if decl.isTerm && decl.isEarlyInitialized) { - unit.warning(decl.pos, "Implementation restriction: early definitions in traits are not initialized before the super class is initialized.") + context.warning(decl.pos, "Implementation restriction: early definitions in traits are not initialized before the super class is initialized.") } } @@ -2099,7 +2084,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper case xs => xs.map(_.nameString).mkString(" (of ", " with ", ")") } def fail(pos: Position, msg: String): Boolean = { - unit.error(pos, msg) + context.error(pos, msg) false } /* Have to examine all parameters in all lists. @@ -3680,7 +3665,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper } if (annType.typeSymbol == DeprecatedAttr && argss.flatten.size < 2) - unit.deprecationWarning(ann.pos, "@deprecated now takes two arguments; see the scaladoc.") + context.deprecationWarning(ann.pos, DeprecatedAttr, "@deprecated now takes two arguments; see the scaladoc.") if ((typedAnn.tpe == null) || typedAnn.tpe.isErroneous) ErroneousAnnotation else annInfo(typedAnn) @@ -4254,7 +4239,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper // it is non-Unit) so we have to retype it. Fortunately it won't come up much // unless the warning is legitimate. if (typed(expr).tpe.typeSymbol != UnitClass) - unit.warning(tree.pos, "enclosing method " + name + " has result type Unit: return value discarded") + context.warning(tree.pos, "enclosing method " + name + " has result type Unit: return value discarded") } val res = treeCopy.Return(tree, checkDead(expr1)).setSymbol(enclMethod.owner) val tp = pluginsTypedReturn(NothingTpe, this, res, restpt.tpe) @@ -4712,10 +4697,10 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper // temporarily use `filter` as an alternative for `withFilter` def tryWithFilterAndFilter(tree: Select, qual: Tree): Tree = { - def warn() = unit.deprecationWarning(tree.pos, s"`withFilter' method does not yet exist on ${qual.tpe.widen}, using `filter' method instead") + def warn(sym: Symbol) = context.deprecationWarning(tree.pos, sym, s"`withFilter' method does not yet exist on ${qual.tpe.widen}, using `filter' method instead") silent(_ => typedSelect(tree, qual, nme.withFilter)) orElse { _ => silent(_ => typed1(Select(qual, nme.filter) setPos tree.pos, mode, pt)) match { - case SilentResultValue(res) => warn() ; res + case SilentResultValue(res) => warn(res.symbol) ; res case SilentTypeError(err) => WithFilterError(tree, err) } } @@ -5492,11 +5477,11 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper val commonMessage = "macro defs must have explicitly specified return types" def reportFailure() = { ddef.symbol.setFlag(IS_ERROR) - unit.error(ddef.pos, commonMessage) + context.error(ddef.pos, commonMessage) } def reportWarning(inferredType: Type) = { val explanation = s"inference of $inferredType from macro impl's c.Expr[$inferredType] is deprecated and is going to stop working in 2.12" - unit.deprecationWarning(ddef.pos, s"$commonMessage ($explanation)") + context.deprecationWarning(ddef.pos, ddef.symbol, s"$commonMessage ($explanation)") } computeMacroDefTypeFromMacroImplRef(ddef, rhs1) match { case ErrorType => ErrorType diff --git a/src/compiler/scala/tools/reflect/FormatInterpolator.scala b/src/compiler/scala/tools/reflect/FormatInterpolator.scala index e0f9bb6044..57be1afdfe 100644 --- a/src/compiler/scala/tools/reflect/FormatInterpolator.scala +++ b/src/compiler/scala/tools/reflect/FormatInterpolator.scala @@ -117,7 +117,7 @@ abstract class FormatInterpolator { c.error(errPoint, msg("unsupported")) s0 } else { - c.enclosingUnit.deprecationWarning(errPoint, msg("deprecated")) + currentRun.reporting.deprecationWarning(errPoint, msg("deprecated")) try StringContext.treatEscapes(s0) catch escapeHatch } } diff --git a/src/reflect/scala/reflect/internal/Positions.scala b/src/reflect/scala/reflect/internal/Positions.scala index 01fba1efc1..c16d8778d9 100644 --- a/src/reflect/scala/reflect/internal/Positions.scala +++ b/src/reflect/scala/reflect/internal/Positions.scala @@ -23,13 +23,10 @@ import scala.collection.mutable.ListBuffer * Otherwise, the singleton consisting of the node itself. */ trait Positions extends api.Positions { self: SymbolTable => - type Position = scala.reflect.internal.util.Position val NoPosition = scala.reflect.internal.util.NoPosition implicit val PositionTag = ClassTag[Position](classOf[Position]) - def inform(msg: String): Unit - def useOffsetPositions: Boolean = true /** A position that wraps a set of trees. @@ -100,7 +97,7 @@ trait Positions extends api.Positions { self: SymbolTable => inform("\nWhile validating #" + tree.id) inform(treeStatus(tree)) inform("\nChildren:") - tree.children map (t => " " + treeStatus(t, tree)) foreach inform + tree.children foreach (t => inform(" " + treeStatus(t, tree))) inform("=======") throw new ValidateException(msg) } @@ -109,7 +106,7 @@ trait Positions extends api.Positions { self: SymbolTable => if (!tree.isEmpty && tree.canHaveAttrs) { if (settings.Yposdebug && (settings.verbose || settings.Yrangepos)) - println("[%10s] %s".format("validate", treeStatus(tree, encltree))) + inform("[%10s] %s".format("validate", treeStatus(tree, encltree))) if (!tree.pos.isDefined) positionError("Unpositioned tree #"+tree.id) { @@ -176,7 +173,7 @@ trait Positions extends api.Positions { self: SymbolTable => case r :: rs1 => assert(!t.pos.isTransparent) if (r.isFree && (r.pos includes t.pos)) { -// println("subdividing "+r+"/"+t.pos) +// inform("subdividing "+r+"/"+t.pos) maybeFree(t.pos.end, r.pos.end) ::: List(Range(t.pos, t)) ::: maybeFree(r.pos.start, t.pos.start) ::: rs1 } else { if (!r.isFree && (r.pos overlaps t.pos)) conflicting += r.tree @@ -225,7 +222,7 @@ trait Positions extends api.Positions { self: SymbolTable => } } catch { case ex: Exception => - println("error while set children pos "+pos+" of "+trees) + inform("error while set children pos "+pos+" of "+trees) throw ex } diff --git a/src/reflect/scala/reflect/internal/Reporting.scala b/src/reflect/scala/reflect/internal/Reporting.scala new file mode 100644 index 0000000000..423127803e --- /dev/null +++ b/src/reflect/scala/reflect/internal/Reporting.scala @@ -0,0 +1,113 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2014 LAMP/EPFL, Typesafe Inc. + * @author Adriaan Moors + */ + +package scala +package reflect +package internal + +/** Provides delegates to the reporter doing the actual work. + * All forwarding methods should be marked final, + * but some subclasses out of our reach stil override them. + * + * Eventually, this interface should be reduced to one method: `reporter`, + * and clients should indirect themselves (reduce duplication of forwarders). + */ +trait Reporting { self : Positions => + def reporter: Reporter + def currentRun: RunReporting + + trait RunReporting { + val reporting: PerRunReporting = PerRunReporting + } + + type PerRunReporting <: PerRunReportingBase + protected def PerRunReporting: PerRunReporting + abstract class PerRunReportingBase { + def deprecationWarning(pos: Position, msg: String): Unit + + /** Have we already supplemented the error message of a compiler crash? */ + private[this] var supplementedError = false + def supplementErrorMessage(errorMessage: String): String = + if (supplementedError) errorMessage + else { + supplementedError = true + supplementTyperState(errorMessage) + } + + } + + // overridden in Global + def supplementTyperState(errorMessage: String): String = errorMessage + + def supplementErrorMessage(errorMessage: String) = currentRun.reporting.supplementErrorMessage(errorMessage) + + @deprecatedOverriding("This forwards to the corresponding method in reporter -- override reporter instead", "2.11.2") + def inform(msg: String): Unit = inform(NoPosition, msg) + @deprecatedOverriding("This forwards to the corresponding method in reporter -- override reporter instead", "2.11.2") + def warning(msg: String): Unit = warning(NoPosition, msg) + // globalError(msg: String) used to abort -- not sure that was a good idea, so I made it more regular + // (couldn't find any uses that relied on old behavior) + @deprecatedOverriding("This forwards to the corresponding method in reporter -- override reporter instead", "2.11.2") + def globalError(msg: String): Unit = globalError(NoPosition, msg) + + def abort(msg: String): Nothing = { + val augmented = supplementErrorMessage(msg) + // Needs to call error to make sure the compile fails. + globalError(augmented) + throw new FatalError(augmented) + } + + @deprecatedOverriding("This forwards to the corresponding method in reporter -- override reporter instead", "2.11.2") + def inform(pos: Position, msg: String) = reporter.echo(pos, msg) + @deprecatedOverriding("This forwards to the corresponding method in reporter -- override reporter instead", "2.11.2") + def warning(pos: Position, msg: String) = reporter.warning(pos, msg) + @deprecatedOverriding("This forwards to the corresponding method in reporter -- override reporter instead", "2.11.2") + def globalError(pos: Position, msg: String) = reporter.error(pos, msg) +} + +import util.Position + +/** Report information, warnings and errors. + * + * This describes the (future) external interface for issuing information, warnings and errors. + * Currently, scala.tools.nsc.Reporter is used by sbt/ide/partest. + */ +abstract class Reporter { + protected def info0(pos: Position, msg: String, severity: Severity, force: Boolean): Unit + + def echo(pos: Position, msg: String): Unit = info0(pos, msg, INFO, force = true) + def warning(pos: Position, msg: String): Unit = info0(pos, msg, WARNING, force = false) + def error(pos: Position, msg: String): Unit = info0(pos, msg, ERROR, force = false) + + type Severity + val INFO: Severity + val WARNING: Severity + val ERROR: Severity + + def count(severity: Severity): Int + def resetCount(severity: Severity): Unit + + def hasErrors: Boolean = count(ERROR) > 0 + def hasWarnings: Boolean = count(WARNING) > 0 + + def reset(): Unit = { + resetCount(INFO) + resetCount(WARNING) + resetCount(ERROR) + } + + def flush(): Unit = { } +} + +// TODO: move into superclass once partest cuts tie on Severity +abstract class ReporterImpl extends Reporter { + class Severity(val id: Int)(name: String) { var count: Int = 0 ; override def toString = name} + object INFO extends Severity(0)("INFO") + object WARNING extends Severity(1)("WARNING") + object ERROR extends Severity(2)("ERROR") + + def count(severity: Severity): Int = severity.count + def resetCount(severity: Severity): Unit = severity.count = 0 +} diff --git a/src/reflect/scala/reflect/internal/SymbolTable.scala b/src/reflect/scala/reflect/internal/SymbolTable.scala index c76dedbff4..ed5c68fe82 100644 --- a/src/reflect/scala/reflect/internal/SymbolTable.scala +++ b/src/reflect/scala/reflect/internal/SymbolTable.scala @@ -46,16 +46,12 @@ abstract class SymbolTable extends macros.Universe with pickling.Translations with FreshNames with Internals + with Reporting { val gen = new InternalTreeGen { val global: SymbolTable.this.type = SymbolTable.this } def log(msg: => AnyRef): Unit - def deprecationWarning(pos: Position, msg: String): Unit = warning(msg) - def warning(msg: String): Unit = Console.err.println(msg) - def inform(msg: String): Unit = Console.err.println(msg) - def globalError(msg: String): Unit = abort(msg) - def abort(msg: String): Nothing = throw new FatalError(supplementErrorMessage(msg)) protected def elapsedMessage(msg: String, start: Long) = msg + " in " + (TimeUnit.NANOSECONDS.toMillis(System.nanoTime()) - start) + "ms" @@ -82,9 +78,6 @@ abstract class SymbolTable extends macros.Universe /** Prints a stack trace if -Ydebug or equivalent was given, otherwise does nothing. */ def debugStack(t: Throwable): Unit = devWarning(throwableAsString(t)) - /** Overridden when we know more about what was happening during a failure. */ - def supplementErrorMessage(msg: String): String = msg - private[scala] def printCaller[T](msg: String)(result: T) = { Console.err.println("%s: %s\nCalled from: %s".format(msg, result, (new Throwable).getStackTrace.drop(2).take(50).mkString("\n"))) diff --git a/src/reflect/scala/reflect/internal/Variances.scala b/src/reflect/scala/reflect/internal/Variances.scala index cfe2ad8b87..12b765b7a6 100644 --- a/src/reflect/scala/reflect/internal/Variances.scala +++ b/src/reflect/scala/reflect/internal/Variances.scala @@ -79,7 +79,7 @@ trait Variances { // Unsound pre-2.11 behavior preserved under -Xsource:2.10 if (settings.isScala211 || sym.isOverridingSymbol) Invariant else { - deprecationWarning(sym.pos, s"Construct depends on unsound variance analysis and will not compile in scala 2.11 and beyond") + currentRun.reporting.deprecationWarning(sym.pos, s"Construct depends on unsound variance analysis and will not compile in scala 2.11 and beyond") Bivariant } ) diff --git a/src/reflect/scala/reflect/runtime/JavaUniverse.scala b/src/reflect/scala/reflect/runtime/JavaUniverse.scala index b5446694ed..fe39e1f245 100644 --- a/src/reflect/scala/reflect/runtime/JavaUniverse.scala +++ b/src/reflect/scala/reflect/runtime/JavaUniverse.scala @@ -14,15 +14,27 @@ import scala.reflect.api.{TreeCreator, TypeCreator, Universe} * @contentDiagram hideNodes "*Api" "*Extractor" */ class JavaUniverse extends InternalSymbolTable with JavaUniverseForce with ReflectSetup with RuntimeSymbolTable { self => - - override def inform(msg: String): Unit = log(msg) def picklerPhase = SomePhase def erasurePhase = SomePhase lazy val settings = new Settings - private val isLogging = sys.props contains "scala.debug.reflect" + private val isLogging = sys.props contains "scala.debug.reflect" def log(msg: => AnyRef): Unit = if (isLogging) Console.err.println("[reflect] " + msg) + // TODO: why put output under isLogging? Calls to inform are already conditional on debug/verbose/... + import scala.reflect.internal.{Reporter, ReporterImpl} + override def reporter: Reporter = new ReporterImpl { + protected def info0(pos: Position, msg: String, severity: Severity, force: Boolean): Unit = log(msg) + } + + // minimal Run to get Reporting wired + def currentRun = new RunReporting {} + class PerRunReporting extends PerRunReportingBase { + def deprecationWarning(pos: Position, msg: String): Unit = reporter.warning(pos, msg) + } + protected def PerRunReporting = new PerRunReporting + + type TreeCopier = InternalTreeCopierOps implicit val TreeCopierTag: ClassTag[TreeCopier] = ClassTag[TreeCopier](classOf[TreeCopier]) def newStrictTreeCopier: TreeCopier = new StrictTreeCopier diff --git a/src/repl/scala/tools/nsc/interpreter/IMain.scala b/src/repl/scala/tools/nsc/interpreter/IMain.scala index 47d97dd4dd..8ea8759ee5 100644 --- a/src/repl/scala/tools/nsc/interpreter/IMain.scala +++ b/src/repl/scala/tools/nsc/interpreter/IMain.scala @@ -110,7 +110,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set lazy val reporter: ReplReporter = new ReplReporter(this) import formatting._ - import reporter.{ printMessage, withoutTruncating } + import reporter.{ printMessage, printUntruncatedMessage } // This exists mostly because using the reporter too early leads to deadlock. private def echo(msg: String) { Console println msg } @@ -609,7 +609,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set } else { // don't truncate stack traces - withoutTruncating(printMessage(result)) + printUntruncatedMessage(result) IR.Error } } @@ -793,7 +793,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set } ((pos, msg)) :: loop(filtered) } - val warnings = loop(run.allConditionalWarnings flatMap (_.warnings)) + val warnings = loop(run.reporting.allConditionalWarnings) if (warnings.nonEmpty) mostRecentWarnings = warnings } @@ -1121,7 +1121,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set def apply(line: String): Result = debugging(s"""parse("$line")""") { var isIncomplete = false - reporter.withIncompleteHandler((_, _) => isIncomplete = true) { + currentRun.reporting.withIncompleteHandler((_, _) => isIncomplete = true) { reporter.reset() val trees = newUnitParser(line).parseStats() if (reporter.hasErrors) Error diff --git a/src/repl/scala/tools/nsc/interpreter/ReplReporter.scala b/src/repl/scala/tools/nsc/interpreter/ReplReporter.scala index b20166d070..88372334d6 100644 --- a/src/repl/scala/tools/nsc/interpreter/ReplReporter.scala +++ b/src/repl/scala/tools/nsc/interpreter/ReplReporter.scala @@ -9,11 +9,29 @@ package interpreter import reporters._ import IMain._ +import scala.reflect.internal.util.Position + /** Like ReplGlobal, a layer for ensuring extra functionality. */ class ReplReporter(intp: IMain) extends ConsoleReporter(intp.settings, Console.in, new ReplStrippingWriter(intp)) { def printUntruncatedMessage(msg: String) = withoutTruncating(printMessage(msg)) + /** 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 = !intp.settings.verbose + def truncationOK = _truncationOK + def withoutTruncating[T](body: => T): T = { + val saved = _truncationOK + _truncationOK = false + try body + finally _truncationOK = saved + } + + override def warning(pos: Position, msg: String): Unit = withoutTruncating(super.warning(pos, msg)) + override def error(pos: Position, msg: String): Unit = withoutTruncating(super.error(pos, msg)) + override def printMessage(msg: String) { // Avoiding deadlock if the compiler starts logging before // the lazy val is complete. @@ -31,4 +49,5 @@ class ReplReporter(intp: IMain) extends ConsoleReporter(intp.settings, Console.i if (intp.totalSilence) () else super.displayPrompt() } + } diff --git a/src/scaladoc/scala/tools/nsc/doc/ScaladocAnalyzer.scala b/src/scaladoc/scala/tools/nsc/doc/ScaladocAnalyzer.scala index e5c64c6f45..10c382e169 100644 --- a/src/scaladoc/scala/tools/nsc/doc/ScaladocAnalyzer.scala +++ b/src/scaladoc/scala/tools/nsc/doc/ScaladocAnalyzer.scala @@ -39,12 +39,12 @@ trait ScaladocAnalyzer extends Analyzer { for (useCase <- comment.useCases) { typer1.silent(_.asInstanceOf[ScaladocTyper].defineUseCases(useCase)) match { case SilentTypeError(err) => - unit.warning(useCase.pos, err.errMsg) + reporter.warning(useCase.pos, err.errMsg) case _ => } for (useCaseSym <- useCase.defined) { if (sym.name != useCaseSym.name) - unit.warning(useCase.pos, "@usecase " + useCaseSym.name.decode + " does not match commented symbol: " + sym.name.decode) + reporter.warning(useCase.pos, "@usecase " + useCaseSym.name.decode + " does not match commented symbol: " + sym.name.decode) } } } @@ -191,7 +191,7 @@ abstract class ScaladocSyntaxAnalyzer[G <: Global](val global: G) extends Syntax } def isDirty = unclean(unmooredParser parseComment doc) if ((doc ne null) && (settings.lint || isDirty)) - unit.warning(doc.pos, "discarding unmoored doc comment") + reporter.warning(doc.pos, "discarding unmoored doc comment") } override def flushDoc(): DocComment = (try lastDoc finally lastDoc = null) diff --git a/test/files/jvm/deprecation.check b/test/files/jvm/deprecation.check index 3c27d4d082..d57b6b55a5 100644 --- a/test/files/jvm/deprecation.check +++ b/test/files/jvm/deprecation.check @@ -1,3 +1,3 @@ -warning: there were 4 deprecation warnings; re-run with -deprecation for details +warning: there were four deprecation warnings; re-run with -deprecation for details Note: deprecation/Use_2.java uses or overrides a deprecated API. Note: Recompile with -Xlint:deprecation for details. diff --git a/test/files/jvm/serialization-new.check b/test/files/jvm/serialization-new.check index 8ec5754ea2..1555135926 100644 --- a/test/files/jvm/serialization-new.check +++ b/test/files/jvm/serialization-new.check @@ -1,4 +1,4 @@ -warning: there were 2 deprecation warnings; re-run with -deprecation for details +warning: there were two deprecation warnings; re-run with -deprecation for details a1 = Array[1,2,3] _a1 = Array[1,2,3] arrayEquals(a1, _a1): true diff --git a/test/files/jvm/serialization.check b/test/files/jvm/serialization.check index 8ec5754ea2..1555135926 100644 --- a/test/files/jvm/serialization.check +++ b/test/files/jvm/serialization.check @@ -1,4 +1,4 @@ -warning: there were 2 deprecation warnings; re-run with -deprecation for details +warning: there were two deprecation warnings; re-run with -deprecation for details a1 = Array[1,2,3] _a1 = Array[1,2,3] arrayEquals(a1, _a1): true diff --git a/test/files/neg/checksensible.check b/test/files/neg/checksensible.check index e5f1a38d96..7de22fef54 100644 --- a/test/files/neg/checksensible.check +++ b/test/files/neg/checksensible.check @@ -97,6 +97,7 @@ checksensible.scala:84: warning: comparing values of types EqEqRefTest.this.C3 a checksensible.scala:95: warning: comparing values of types Unit and Int using `!=' will always yield true while ((c = in.read) != -1) ^ +warning: there were three deprecation warnings; re-run with -deprecation for details error: No warnings can be incurred under -Xfatal-warnings. -33 warnings found +34 warnings found one error found diff --git a/test/files/neg/overloaded-implicit.check b/test/files/neg/overloaded-implicit.check index ca0870705d..0e6617d904 100644 --- a/test/files/neg/overloaded-implicit.check +++ b/test/files/neg/overloaded-implicit.check @@ -4,6 +4,7 @@ overloaded-implicit.scala:2: warning: parameterized overloaded implicit methods overloaded-implicit.scala:3: warning: parameterized overloaded implicit methods are not visible as view bounds implicit def imp1[T](x: Set[T]): Map[T, T] = Map() ^ +warning: there were four feature warnings; re-run with -feature for details error: No warnings can be incurred under -Xfatal-warnings. -two warnings found +three warnings found one error found diff --git a/test/files/neg/t1909-object.check b/test/files/neg/t1909-object.check index 401c1f7ebf..7141c84d4b 100644 --- a/test/files/neg/t1909-object.check +++ b/test/files/neg/t1909-object.check @@ -1,4 +1,6 @@ -t1909-object.scala:4: error: !!! SI-1909 Unable to STATICally lift object InnerTrouble$1, which is defined in the self- or super-constructor call of class Kaboom. A VerifyError is likely. +t1909-object.scala:4: warning: !!! SI-1909 Unable to STATICally lift object InnerTrouble$1, which is defined in the self- or super-constructor call of class Kaboom. A VerifyError is likely. object InnerTrouble ^ +error: No warnings can be incurred under -Xfatal-warnings. +one warning found one error found diff --git a/test/files/neg/t5675.check b/test/files/neg/t5675.check index 13226935dc..3b3b2fa04c 100644 --- a/test/files/neg/t5675.check +++ b/test/files/neg/t5675.check @@ -1,2 +1,4 @@ -error: there was one feature warning; re-run with -feature for details +warning: there was one feature warning; re-run with -feature for details +error: No warnings can be incurred under -Xfatal-warnings. +one warning found one error found diff --git a/test/files/neg/t6567.check b/test/files/neg/t6567.check index a733d75354..f42f157371 100644 --- a/test/files/neg/t6567.check +++ b/test/files/neg/t6567.check @@ -4,6 +4,7 @@ t6567.scala:8: warning: Suspicious application of an implicit view (Test.this.a2 t6567.scala:10: warning: Suspicious application of an implicit view (Test.this.a2b) in the argument to Option.apply. val b: Option[B] = Option(a) ^ +warning: there was one feature warning; re-run with -feature for details error: No warnings can be incurred under -Xfatal-warnings. -two warnings found +three warnings found one error found diff --git a/test/files/neg/unchecked-refinement.check b/test/files/neg/unchecked-refinement.check index e85a51f44d..0bb944621b 100644 --- a/test/files/neg/unchecked-refinement.check +++ b/test/files/neg/unchecked-refinement.check @@ -10,6 +10,7 @@ unchecked-refinement.scala:23: warning: a pattern match on a refinement type is unchecked-refinement.scala:24: warning: a pattern match on a refinement type is unchecked /* nowarn - todo */ case x: AnyRef { def size: Int } if b => x.size // this could/should do a static conformance test and not warn ^ +warning: there was one feature warning; re-run with -feature for details error: No warnings can be incurred under -Xfatal-warnings. -four warnings found +5 warnings found one error found diff --git a/test/files/run/colltest.check b/test/files/run/colltest.check index 46e4017eb6..9579d781aa 100644 --- a/test/files/run/colltest.check +++ b/test/files/run/colltest.check @@ -1,4 +1,4 @@ -warning: there were 2 deprecation warnings; re-run with -deprecation for details +warning: there were two deprecation warnings; re-run with -deprecation for details true false true diff --git a/test/files/run/inferred-type-constructors.check b/test/files/run/inferred-type-constructors.check index 67075a59a9..4a63853bd9 100644 --- a/test/files/run/inferred-type-constructors.check +++ b/test/files/run/inferred-type-constructors.check @@ -1,4 +1,4 @@ -warning: there were 2 feature warnings; re-run with -feature for details +warning: there were two feature warnings; re-run with -feature for details p.Iterable[Int] p.Set[Int] p.Seq[Int] diff --git a/test/files/run/names-defaults.check b/test/files/run/names-defaults.check index 97cfa4e520..25999c488a 100644 --- a/test/files/run/names-defaults.check +++ b/test/files/run/names-defaults.check @@ -1,7 +1,7 @@ names-defaults.scala:269: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses spawn(b = { val ttt = 1; ttt }, a = 0) ^ -warning: there were 4 deprecation warnings; re-run with -deprecation for details +warning: there were four deprecation warnings; re-run with -deprecation for details 1: @ get: $ get: 2 diff --git a/test/files/run/richs.check b/test/files/run/richs.check index bcaf8bdb8d..cf265ae007 100644 --- a/test/files/run/richs.check +++ b/test/files/run/richs.check @@ -1,4 +1,4 @@ -warning: there were 2 deprecation warnings; re-run with -deprecation for details +warning: there were two deprecation warnings; re-run with -deprecation for details RichCharTest1: true diff --git a/test/files/run/t2212.check b/test/files/run/t2212.check index f7e80439c7..1465f1341a 100644 --- a/test/files/run/t2212.check +++ b/test/files/run/t2212.check @@ -1,4 +1,4 @@ -warning: there were 2 deprecation warnings; re-run with -deprecation for details +warning: there were two deprecation warnings; re-run with -deprecation for details LinkedList(1) LinkedList(1) true diff --git a/test/files/run/t3996.check b/test/files/run/t3996.check index 2e8e558f88..a9ecc29fea 100644 --- a/test/files/run/t3996.check +++ b/test/files/run/t3996.check @@ -1 +1 @@ -warning: there were 2 deprecation warnings; re-run with -deprecation for details +warning: there were two deprecation warnings; re-run with -deprecation for details diff --git a/test/files/run/t4080.check b/test/files/run/t4080.check index c642cc67da..462e925b76 100644 --- a/test/files/run/t4080.check +++ b/test/files/run/t4080.check @@ -1,2 +1,2 @@ -warning: there were 3 deprecation warnings; re-run with -deprecation for details +warning: there were three deprecation warnings; re-run with -deprecation for details LinkedList(1, 0, 2, 3) diff --git a/test/files/run/t4461.check b/test/files/run/t4461.check index c44b0fc077..346993af6f 100644 --- a/test/files/run/t4461.check +++ b/test/files/run/t4461.check @@ -1,4 +1,4 @@ -warning: there were 4 deprecation warnings; re-run with -deprecation for details +warning: there were four deprecation warnings; re-run with -deprecation for details Include(End,1) Include(End,2) Include(End,3) diff --git a/test/files/run/t4813.check b/test/files/run/t4813.check index 2e8e558f88..a9ecc29fea 100644 --- a/test/files/run/t4813.check +++ b/test/files/run/t4813.check @@ -1 +1 @@ -warning: there were 2 deprecation warnings; re-run with -deprecation for details +warning: there were two deprecation warnings; re-run with -deprecation for details diff --git a/test/files/run/t6111.check b/test/files/run/t6111.check index 21a5b19ea0..5880658001 100644 --- a/test/files/run/t6111.check +++ b/test/files/run/t6111.check @@ -1,3 +1,3 @@ -warning: there were 2 deprecation warnings; re-run with -deprecation for details +warning: there were two deprecation warnings; re-run with -deprecation for details (8,8) (x,x) diff --git a/test/files/run/t6690.check b/test/files/run/t6690.check index 2e8e558f88..a9ecc29fea 100644 --- a/test/files/run/t6690.check +++ b/test/files/run/t6690.check @@ -1 +1 @@ -warning: there were 2 deprecation warnings; re-run with -deprecation for details +warning: there were two deprecation warnings; re-run with -deprecation for details diff --git a/test/files/run/t6863.check b/test/files/run/t6863.check index 37de2e6e51..d4df5f7a74 100644 --- a/test/files/run/t6863.check +++ b/test/files/run/t6863.check @@ -10,4 +10,4 @@ t6863.scala:46: warning: comparing values of types Unit and Unit using `==' will t6863.scala:59: warning: comparing values of types Unit and Unit using `==' will always yield true assert({ () => x }.apply == ()) ^ -warning: there were 4 deprecation warnings; re-run with -deprecation for details +warning: there were four deprecation warnings; re-run with -deprecation for details diff --git a/test/files/run/t8196.check b/test/files/run/t8196.check index f021a3619f..d11dc27e68 100644 --- a/test/files/run/t8196.check +++ b/test/files/run/t8196.check @@ -1,7 +1,7 @@ t8196.scala:26: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses form2.g1 // comment this line in order to make the test pass ^ -warning: there were 2 feature warnings; re-run with -feature for details +warning: there were two feature warnings; re-run with -feature for details Scope{ final private val f1: Int } diff --git a/test/files/run/t8549.check b/test/files/run/t8549.check index 2e8e558f88..a9ecc29fea 100644 --- a/test/files/run/t8549.check +++ b/test/files/run/t8549.check @@ -1 +1 @@ -warning: there were 2 deprecation warnings; re-run with -deprecation for details +warning: there were two deprecation warnings; re-run with -deprecation for details diff --git a/test/junit/scala/tools/nsc/symtab/SymbolTableForUnitTesting.scala b/test/junit/scala/tools/nsc/symtab/SymbolTableForUnitTesting.scala index 25d8c4667f..91868a5683 100644 --- a/test/junit/scala/tools/nsc/symtab/SymbolTableForUnitTesting.scala +++ b/test/junit/scala/tools/nsc/symtab/SymbolTableForUnitTesting.scala @@ -72,6 +72,18 @@ class SymbolTableForUnitTesting extends SymbolTable { def picklerPhase: scala.reflect.internal.Phase = SomePhase def erasurePhase: scala.reflect.internal.Phase = SomePhase + // Members declared in scala.reflect.internal.Reporting + def reporter = new scala.reflect.internal.ReporterImpl { + protected def info0(pos: Position, msg: String, severity: Severity, force: Boolean): Unit = println(msg) + } + + // minimal Run to get Reporting wired + def currentRun = new RunReporting {} + class PerRunReporting extends PerRunReportingBase { + def deprecationWarning(pos: Position, msg: String): Unit = reporter.warning(pos, msg) + } + protected def PerRunReporting = new PerRunReporting + // Members declared in scala.reflect.internal.SymbolTable def currentRunId: Int = 1 def log(msg: => AnyRef): Unit = println(msg) |