diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2012-11-13 11:02:30 +0100 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2012-11-13 11:02:30 +0100 |
commit | 079296632d8ef5ecc40aafa83757231599c78783 (patch) | |
tree | ae523bd1269c22b460890298c34dc6c922e1aafa /src | |
parent | 86e045e2863b04bf4af4abb5c2ce345bcdae2b80 (diff) | |
download | scala-079296632d8ef5ecc40aafa83757231599c78783.tar.gz scala-079296632d8ef5ecc40aafa83757231599c78783.tar.bz2 scala-079296632d8ef5ecc40aafa83757231599c78783.zip |
SI-6440 Address regressions around MissingRequirementError
Go back to using globalError to report when a stub's info is referenced,
and only throw the MissingRequirementError when compilation really
must abort due to having a StubTermSymbol in a place where a
StubClassSymbol would have been a better choice.
This situation arises when an entire package is missing from the
classpath, as was the case in the reported bug.
Adds `StoreReporterDirectTest`, which buffers messages issued
during compilation for more structured interrogation. Use this
in two test for manifests -- these tests were using a crude means
of grepping compiler console output to focus on the relevant output,
but this approach was insufficient with the new multi-line error
message emitted as part of this change.
Also used that base test class to add two new tests: one for
the reported error (package missing), and another for a simpler
error (class missing). The latter test shows how stub symbols
allow code to compile if it doesn't the subset of signatures
in some type that refer to a missing class.
Gave the INFO/WARNING/ERROR members of Reporter sensible
toString implementations; they inherit from Enumeration#Value
in an unusual manner (why?) that means the built in toString of
Enumeration printed `Severity@0`.
Diffstat (limited to 'src')
6 files changed, 47 insertions, 15 deletions
diff --git a/src/compiler/scala/tools/nsc/reporters/Reporter.scala b/src/compiler/scala/tools/nsc/reporters/Reporter.scala index c5321dd728..8871ae6555 100644 --- a/src/compiler/scala/tools/nsc/reporters/Reporter.scala +++ b/src/compiler/scala/tools/nsc/reporters/Reporter.scala @@ -20,9 +20,15 @@ abstract class Reporter { class Severity(val id: Int) extends severity.Value { var count: Int = 0 } - val INFO = new Severity(0) - val WARNING = new Severity(1) - val ERROR = new Severity(2) + 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 diff --git a/src/partest/scala/tools/partest/DirectTest.scala b/src/partest/scala/tools/partest/DirectTest.scala index 554e7848c7..8c18809ad6 100644 --- a/src/partest/scala/tools/partest/DirectTest.scala +++ b/src/partest/scala/tools/partest/DirectTest.scala @@ -8,6 +8,7 @@ package scala.tools.partest import scala.tools.nsc._ import io.Directory import util.{BatchSourceFile, CommandLineParser} +import reporters.{Reporter, ConsoleReporter} /** A class for testing code which is embedded as a string. * It allows for more complete control over settings, compiler @@ -38,9 +39,12 @@ abstract class DirectTest extends App { // new compiler def newCompiler(args: String*): Global = { val settings = newSettings((CommandLineParser tokenize ("-d \"" + testOutput.path + "\" " + extraSettings)) ++ args.toList) - if (settings.Yrangepos.value) new Global(settings) with interactive.RangePositions - else new Global(settings) + if (settings.Yrangepos.value) new Global(settings, reporter(settings)) with interactive.RangePositions + else new Global(settings, reporter(settings)) } + + def reporter(settings: Settings): Reporter = new ConsoleReporter(settings) + def newSources(sourceCodes: String*) = sourceCodes.toList.zipWithIndex map { case (src, idx) => new BatchSourceFile("newSource" + (idx + 1), src) } diff --git a/src/partest/scala/tools/partest/StoreReporterDirectTest.scala b/src/partest/scala/tools/partest/StoreReporterDirectTest.scala new file mode 100644 index 0000000000..7f3604c86c --- /dev/null +++ b/src/partest/scala/tools/partest/StoreReporterDirectTest.scala @@ -0,0 +1,15 @@ +package scala.tools.partest + +import scala.tools.nsc.Settings +import scala.tools.nsc.reporters.StoreReporter +import scala.collection.mutable + +trait StoreReporterDirectTest extends DirectTest { + lazy val storeReporter: StoreReporter = new scala.tools.nsc.reporters.StoreReporter() + + /** Discards all but the first message issued at a given position. */ + def filteredInfos: Seq[storeReporter.Info] = storeReporter.infos.groupBy(_.pos).map(_._2.head).toList + + /** Hook into [[scala.tools.partest.DirectTest]] to install the custom reporter */ + override def reporter(settings: Settings) = storeReporter +} diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 67b2d05224..06bf54c1f8 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -3103,12 +3103,18 @@ trait Symbols extends api.Symbols { self: SymbolTable => ) } trait StubSymbol extends Symbol { - override final def failIfStub() = fail(()) protected def missingMessage: String + + /** Fail the stub by throwing a [[scala.reflect.internal.MissingRequirementError]]. */ + override final def failIfStub() = {MissingRequirementError.signal(missingMessage)} // + + /** Fail the stub by reporting an error to the reporter, setting the IS_ERROR flag + * on this symbol, and returning the dummy value `alt`. + */ private def fail[T](alt: T): T = { // Avoid issuing lots of redundant errors if (!hasFlag(IS_ERROR)) { - MissingRequirementError.signal(missingMessage) + globalError(missingMessage) if (settings.debug.value) (new Throwable).printStackTrace diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 57212bab55..d5347705a6 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -1385,10 +1385,11 @@ trait Types extends api.Types { self: SymbolTable => /** A class for this-types of the form <sym>.this.type */ abstract case class ThisType(sym: Symbol) extends SingletonType with ThisTypeApi { - // SI-6640 allow StubSymbols to reveal what's missing from the classpath - // before we trip the assertion. - sym.failIfStub() - assert(sym.isClass, sym) + if (!sym.isClass) { + // SI-6640 allow StubSymbols to reveal what's missing from the classpath before we trip the assertion. + sym.failIfStub() + assert(false, sym) + } //assert(sym.isClass && !sym.isModuleClass || sym.isRoot, sym) override def isTrivial: Boolean = sym.isPackageClass diff --git a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala index 5464a68205..f3a5053a91 100644 --- a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala +++ b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala @@ -234,10 +234,10 @@ abstract class UnPickler { adjust(mirrorThatLoaded(owner).missingHook(owner, name)) orElse { // (5) Create a stub symbol to defer hard failure a little longer. val missingMessage = - s"""|A signature in $filename refers to ${name.longString} in ${owner.fullLocationString} - |which is not available. It may be completely missing from the current classpath, - |or the version on the classpath might be incompatible with the version used when - |compiling $filename.""".stripMargin + s"""|bad symbolic reference. A signature in $filename refers to ${name.longString} + |in ${owner.kindString} ${owner.fullName} which is not available. + |It may be completely missing from the current classpath, or the version on + |the classpath might be incompatible with the version used when compiling $filename.""".stripMargin owner.newStubSymbol(name, missingMessage) } } |