scala.tools.nsc.Reporting.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of scala-compiler Show documentation
Show all versions of scala-compiler Show documentation
Compiler for the SubScript extension of the Scala Programming Language
The newest version!
/* NSC -- new Scala compiler
* Copyright 2005-2014 LAMP/EPFL, Typesafe Inc.
* @author Adriaan Moors
*/
package scala
package tools
package nsc
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 || option)) {
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.")
}
}
}