From 7e85b595502974bebf2f2625c6bc3645f0d3ab27 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 17 Dec 2013 17:47:15 +0100 Subject: SI-8085 Fix BrowserTraverser for package objects A source file like: import foo.bar package object baz Is parsed into: package { import foo.bar package baz { object `package` } } A special case in Namers compensates by adjusting the owner of `baz` to be ``, rather than ``. This wasn't being accounted for in `BrowserTraverser`, which underpins `-sourcepath`, and allows the presentation compiler to load top level symbols from sources outside those passes as the list of sources to compile. This bug did not appear in sources like: package p1 package object p2 { ... } ... because the parser does not wrap this in the `package {}` This goes some way to explaining why it has gone unnoticed for so long. --- test/files/presentation/t8085.check | 4 ++-- test/files/presentation/t8085/Test.scala | 1 - .../t8085/src/nodescala/NodeScalaSuite.scala | 6 ++--- .../presentation/t8085/src/nodescala/package.scala | 7 +++--- test/files/presentation/t8085b.check | 3 +++ test/files/presentation/t8085b.flags | 1 + test/files/presentation/t8085b/Test.scala | 27 ++++++++++++++++++++++ .../presentation/t8085b/src/p1/nodescala/Foo.scala | 4 ++++ .../t8085b/src/p1/nodescala/NodeScalaSuite.scala | 11 +++++++++ .../t8085b/src/p1/nodescala/package.scala | 9 ++++++++ 10 files changed, 62 insertions(+), 11 deletions(-) create mode 100644 test/files/presentation/t8085b.check create mode 100644 test/files/presentation/t8085b.flags create mode 100644 test/files/presentation/t8085b/Test.scala create mode 100644 test/files/presentation/t8085b/src/p1/nodescala/Foo.scala create mode 100644 test/files/presentation/t8085b/src/p1/nodescala/NodeScalaSuite.scala create mode 100644 test/files/presentation/t8085b/src/p1/nodescala/package.scala (limited to 'test/files/presentation') diff --git a/test/files/presentation/t8085.check b/test/files/presentation/t8085.check index 46aac791f5..79c1b2aa17 100644 --- a/test/files/presentation/t8085.check +++ b/test/files/presentation/t8085.check @@ -1,3 +1,3 @@ reload: NodeScalaSuite.scala -prefixes differ: .nodescala,nodescala -value always is not a member of object scala.concurrent.Future +open package module: package nodescala +Test OK diff --git a/test/files/presentation/t8085/Test.scala b/test/files/presentation/t8085/Test.scala index 5d11009818..e46b7ab8c8 100644 --- a/test/files/presentation/t8085/Test.scala +++ b/test/files/presentation/t8085/Test.scala @@ -5,7 +5,6 @@ import scala.tools.nsc.interactive.Response object Test extends InteractiveTest { override def execute(): Unit = { - // loadSourceAndWaitUntilTypechecked("package.scala") // <-- uncomment this line and the test succeed val src = loadSourceAndWaitUntilTypechecked("NodeScalaSuite.scala") checkErrors(src) } diff --git a/test/files/presentation/t8085/src/nodescala/NodeScalaSuite.scala b/test/files/presentation/t8085/src/nodescala/NodeScalaSuite.scala index a8803ff86d..45e43c7afb 100644 --- a/test/files/presentation/t8085/src/nodescala/NodeScalaSuite.scala +++ b/test/files/presentation/t8085/src/nodescala/NodeScalaSuite.scala @@ -1,12 +1,10 @@ package nodescala -import scala.concurrent.Future - class NodeScalaSuite { - Future.always(517) + "".rich // This is here only to prove that the presentation compiler is instantiated with the // correct `sourcepath` value (if it wasn't, you would see a `not found: type Foo` in // the test's output println(new Foo()) -} \ No newline at end of file +} diff --git a/test/files/presentation/t8085/src/nodescala/package.scala b/test/files/presentation/t8085/src/nodescala/package.scala index 6e9d4b729a..26fb9f08e4 100644 --- a/test/files/presentation/t8085/src/nodescala/package.scala +++ b/test/files/presentation/t8085/src/nodescala/package.scala @@ -1,8 +1,7 @@ -import scala.concurrent.Future // <-- if you move the import *inside* the package object, then it all works fine!! +import scala.Some // <-- if you move the import *inside* the package object, then it all works fine!! package object nodescala { - implicit class FutureCompanionOps[T](val f: Future.type) extends AnyVal { - def always[T](value: T): Future[T] = Promise[T].success(value).future + implicit class StringOps(val f: String) { + def rich = 0 } } - diff --git a/test/files/presentation/t8085b.check b/test/files/presentation/t8085b.check new file mode 100644 index 0000000000..79c1b2aa17 --- /dev/null +++ b/test/files/presentation/t8085b.check @@ -0,0 +1,3 @@ +reload: NodeScalaSuite.scala +open package module: package nodescala +Test OK diff --git a/test/files/presentation/t8085b.flags b/test/files/presentation/t8085b.flags new file mode 100644 index 0000000000..ec35b223d8 --- /dev/null +++ b/test/files/presentation/t8085b.flags @@ -0,0 +1 @@ +-sourcepath src diff --git a/test/files/presentation/t8085b/Test.scala b/test/files/presentation/t8085b/Test.scala new file mode 100644 index 0000000000..e46b7ab8c8 --- /dev/null +++ b/test/files/presentation/t8085b/Test.scala @@ -0,0 +1,27 @@ +import scala.tools.nsc.interactive.tests.InteractiveTest +import scala.reflect.internal.util.SourceFile +import scala.tools.nsc.interactive.Response + +object Test extends InteractiveTest { + + override def execute(): Unit = { + val src = loadSourceAndWaitUntilTypechecked("NodeScalaSuite.scala") + checkErrors(src) + } + + private def loadSourceAndWaitUntilTypechecked(sourceName: String): SourceFile = { + val sourceFile = sourceFiles.find(_.file.name == sourceName).head + askReload(List(sourceFile)).get + askLoadedTyped(sourceFile).get + sourceFile + } + + private def checkErrors(source: SourceFile): Unit = compiler.getUnitOf(source) match { + case Some(unit) => + val problems = unit.problems.toList + if(problems.isEmpty) reporter.println("Test OK") + else problems.foreach(problem => reporter.println(problem.msg)) + + case None => reporter.println("No compilation unit found for " + source.file.name) + } +} diff --git a/test/files/presentation/t8085b/src/p1/nodescala/Foo.scala b/test/files/presentation/t8085b/src/p1/nodescala/Foo.scala new file mode 100644 index 0000000000..8ed1ada6b6 --- /dev/null +++ b/test/files/presentation/t8085b/src/p1/nodescala/Foo.scala @@ -0,0 +1,4 @@ +package p1 +package nodescala + +class Foo diff --git a/test/files/presentation/t8085b/src/p1/nodescala/NodeScalaSuite.scala b/test/files/presentation/t8085b/src/p1/nodescala/NodeScalaSuite.scala new file mode 100644 index 0000000000..f6da67bdc7 --- /dev/null +++ b/test/files/presentation/t8085b/src/p1/nodescala/NodeScalaSuite.scala @@ -0,0 +1,11 @@ +package p1 +package nodescala + +class NodeScalaSuite { + "".rich + + // This is here only to prove that the presentation compiler is instantiated with the + // correct `sourcepath` value (if it wasn't, you would see a `not found: type Foo` in + // the test's output + println(new Foo()) +} diff --git a/test/files/presentation/t8085b/src/p1/nodescala/package.scala b/test/files/presentation/t8085b/src/p1/nodescala/package.scala new file mode 100644 index 0000000000..cc383f1bab --- /dev/null +++ b/test/files/presentation/t8085b/src/p1/nodescala/package.scala @@ -0,0 +1,9 @@ +import scala.Some // <-- if you move the import *inside* the package object, then it all works fine!! + +package p1 { + package object nodescala { + implicit class StringOps(val f: String) { + def rich = 0 + } + } +} -- cgit v1.2.3