Add a pending test for self variable bug (#2504)

Add a pending test that shows a problem with instability of representing
self variables. This test covers the bug described in #2504.

In order to test API representation of a class declared either in source
file or unpickled from a class file, ScalaCompilerForUnitTesting has been
extended to extract APIs from multiple compiler instances sharing a
classpath.
This commit is contained in:
Grzegorz Kossakowski 2016-03-08 20:42:11 +01:00
parent abc525a23d
commit d7eee101d0
3 changed files with 44 additions and 3 deletions

View File

@ -46,7 +46,7 @@ object SameAPI {
def apply(a: Source, b: Source): Boolean =
a.apiHash == b.apiHash && (a.hash.nonEmpty && b.hash.nonEmpty) && apply(a.api, b.api)
def apply(a: Def, b: Def): Boolean =
def apply(a: Definition, b: Definition): Boolean =
(new SameAPI(false, true)).sameDefinitions(List(a), List(b), true)
def apply(a: SourceAPI, b: SourceAPI): Boolean =

View File

@ -1,8 +1,7 @@
package xsbt
import org.junit.runner.RunWith
import xsbti.api.ClassLike
import xsbti.api.Def
import xsbti.api.{ Definition, SourceAPI, ClassLike, Def }
import xsbt.api.SameAPI
import org.specs2.mutable.Specification
import org.specs2.runner.JUnitRunner
@ -39,4 +38,37 @@ class ExtractAPISpecification extends Specification {
val fooMethodApi2 = compileAndGetFooMethodApi(src2)
SameAPI.apply(fooMethodApi1, fooMethodApi2)
}
/**
* Checks if representation of the inherited Namer class (with a declared self variable) in Global.Foo
* is stable between compiling from source and unpickling. We compare extracted APIs of Global when Global
* is compiled together with Namers or Namers is compiled first and then Global refers
* to Namers by unpickling types from class files.
*/
"Self variable and no self type" in {
def selectNamer(api: SourceAPI): ClassLike = {
def selectClass(defs: Iterable[Definition], name: String): ClassLike = defs.collectFirst {
case cls: ClassLike if cls.name == name => cls
}.get
val global = selectClass(api.definitions, "Global")
val foo = selectClass(global.structure.declared, "Global.Foo")
selectClass(foo.structure.inherited, "Namers.Namer")
}
val src1 =
"""|class Namers {
| class Namer { thisNamer => }
|}
|""".stripMargin
val src2 =
"""|class Global {
| class Foo extends Namers
|}
|""".stripMargin
val compilerForTesting = new ScalaCompilerForUnitTesting
val apis = compilerForTesting.extractApisFromSrcs(reuseCompilerInstance = false)(List(src1, src2), List(src2))
val _ :: src2Api1 :: src2Api2 :: Nil = apis.toList
val namerApi1 = selectNamer(src2Api1)
val namerApi2 = selectNamer(src2Api2)
SameAPI(namerApi1, namerApi2)
}.pendingUntilFixed("have unstable representation (#2504)")
}

View File

@ -31,6 +31,15 @@ class ScalaCompilerForUnitTesting(nameHashing: Boolean = false) {
analysisCallback.apis(tempSrcFile)
}
/**
* Compiles given source code using Scala compiler and returns API representation
* extracted by ExtractAPI class.
*/
def extractApisFromSrcs(reuseCompilerInstance: Boolean)(srcs: List[String]*): Seq[SourceAPI] = {
val (tempSrcFiles, analysisCallback) = compileSrcs(srcs.toList, reuseCompilerInstance)
tempSrcFiles.map(analysisCallback.apis)
}
def extractUsedNamesFromSrc(src: String): Set[String] = {
val (Seq(tempSrcFile), analysisCallback) = compileSrcs(src)
analysisCallback.usedNames(tempSrcFile)