summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/Global.scala
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@typesafe.com>2014-06-10 16:24:37 +0200
committerAdriaan Moors <adriaan.moors@typesafe.com>2014-07-04 15:49:05 +0200
commit98216be3f3e546fc320ab5182ac5c129707db1ce (patch)
tree1c20acf20ecfdfa37dd49ed53d82039af58c9e29 /src/compiler/scala/tools/nsc/Global.scala
parentf2b76e80094219db1f72a7a56d02f21bab1fc9eb (diff)
downloadscala-98216be3f3e546fc320ab5182ac5c129707db1ce.tar.gz
scala-98216be3f3e546fc320ab5182ac5c129707db1ce.tar.bz2
scala-98216be3f3e546fc320ab5182ac5c129707db1ce.zip
Move reporting logic into Reporting trait
Move code from Global/SymbolTable to separate Reporting traits to start carving out an interface in scala.reflect.internal.Reporting, with internals in scala.tools.nsc. Reporting is mixed into the cake. It contains a nested class PerRunReporting. Should do the same for debugging/logging. The idea is that CompilationUnit and Global forward all reporting to Reporter. The Reporting trait contains these forwarders, and PerRunReporting, which accumulates warning state during a run. In the process, I slightly changed the behavior of `globalError` in reflect.internal.SymbolTable: it used to abort, weirdly. I assume that was dummy behavior to avoid introducing an abstract method. It's immediately overridden in Global, and I couldn't find any other subclasses, so I don't think the behavior in SymbolTable was ever observed. Provide necessary hooks for scala.reflect.macros.Parsers#parse. See scala/reflect/macros/contexts/Parsers.scala's parse method, which overrides the reporter to detect when parsing goes wrong. This should be refactored, but that goes beyond the scope of this PR. Don't pop empty macro context stack. (Ran into this while reworking -Xfatal-warnings logic.) Fix -Xfatal-warnings behavior (and check files): it wasn't meant to influence warning reporting, except for emitting one final error; if necessary to fail the compile (when warnings but no errors were reported). Warnings should stay warnings. This was refactored in fbbbb22946, but we soon seem to have relapsed. An hour of gitfu did not lead to where it went wrong. Must've been a merge.
Diffstat (limited to 'src/compiler/scala/tools/nsc/Global.scala')
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala150
1 files changed, 45 insertions, 105 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 836203e80d..daf69ffc3f 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
@@ -1063,6 +1045,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
def currentUnit: CompilationUnit = if (currentRun eq null) NoCompilationUnit else currentRun.currentUnit
def currentSource: SourceFile = if (currentUnit.exists) currentUnit.source else lastSeenSourceFile
def currentFreshNameCreator = currentUnit.fresh
+ def currentReporting = currentRun.reporting
def isGlobalInitialized = (
definitions.isDefinitionsInitialized
@@ -1110,45 +1093,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"
+ 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
*/
@@ -1160,19 +1139,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)
@@ -1199,38 +1165,12 @@ 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
-
- def reportAdditionalErrors(): Unit = {
- if (!reporter.hasErrors) {
- if (reporter.hasWarnings && settings.fatalWarnings)
- globalError("No warnings can be incurred under -Xfatal-warnings.")
-
- 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
- }
- }
-
- var reportedFeature = Set[Symbol]()
-
- /** Has any macro expansion used a fallback during this run? */
- var seenMacroExpansionsFallingBack = false
+ val reporting = new PerRunReporting
- /** 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]
@@ -1590,7 +1530,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
def checkDeprecations() = {
checkDeprecatedSettings(newCompilationUnit(""))
- reportAdditionalErrors()
+ reporting.summarizeErrors()
}
val units = sources map scripted map (new CompilationUnit(_))
@@ -1660,7 +1600,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
advancePhase()
}
- reportAdditionalErrors()
+ reporting.summarizeErrors()
if (traceSymbolActivity)
units map (_.body) foreach (traceSymbols recordSymbolsInTree _)