Skip to content

Commit

Permalink
Add a pending test for self variable bug (#2504)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
gkossakowski committed Mar 30, 2016
1 parent a184722 commit 3f26571
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package xsbt

import xsbti.api.{ DefinitionType, ClassLike, Def }
import xsbti.api._
import xsbt.api.SameAPI
import sbt.internal.util.UnitSpec

Expand Down Expand Up @@ -115,4 +115,38 @@ class ExtractAPISpecification extends UnitSpec {
val fooMethodApi2 = compileAndGetFooMethodApi(src2)
assert(SameAPI.apply(fooMethodApi1, fooMethodApi2), "APIs are not the same.")
}

/**
* 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.
*/
it should "make a stable representation of a self variable that has no self type" in pendingUntilFixed {
def selectNamer(apis: Set[ClassLike]): ClassLike = {
def selectClass(defs: Iterable[Definition], name: String): ClassLike = defs.collectFirst {
case cls: ClassLike if cls.name == name => cls
}.get
val global = apis.find(_.name == "Global").get
//val foo = selectClass(global.structure.declared, "Global.Foo")
val foo = apis.find(_.name == "Global.Foo").get
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)
assert(SameAPI(namerApi1, namerApi2))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ class ScalaCompilerForUnitTesting(nameHashing: Boolean = true) {
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[Set[ClassLike]] = {
val (tempSrcFiles, analysisCallback) = compileSrcs(srcs.toList, reuseCompilerInstance)
tempSrcFiles.map(analysisCallback.apis)
}

def extractUsedNamesFromSrc(src: String): Map[String, Set[String]] = {
val (_, analysisCallback) = compileSrcs(src)
analysisCallback.usedNames.toMap
Expand Down Expand Up @@ -63,7 +72,7 @@ class ScalaCompilerForUnitTesting(nameHashing: Boolean = true) {
* file system-independent way of testing dependencies between source code "files".
*/
def extractDependenciesFromSrcs(srcs: List[List[String]]): ExtractedClassDependencies = {
val (_, testCallback) = compileSrcs(srcs)
val (_, testCallback) = compileSrcs(srcs, reuseCompilerInstance = true)

val memberRefDeps = testCallback.classDependencies collect {
case (target, src, DependencyByMemberRef) => (src, target)
Expand Down Expand Up @@ -97,8 +106,10 @@ class ScalaCompilerForUnitTesting(nameHashing: Boolean = true) {
* The sequence of temporary files corresponding to passed snippets and analysis
* callback is returned as a result.
*/
private def compileSrcs(groupedSrcs: List[List[String]],
reuseCompilerInstance: Boolean): (Seq[File], TestCallback) = {
private def compileSrcs(
groupedSrcs: List[List[String]],
reuseCompilerInstance: Boolean
): (Seq[File], TestCallback) = {
withTemporaryDirectory { temp =>
val analysisCallback = new TestCallback(nameHashing)
val classesDir = new File(temp, "classes")
Expand Down

0 comments on commit 3f26571

Please sign in to comment.