|
| 1 | +/** Adapted from https://github.com/sbt/sbt/blob/0.13/compile/interface/src/test/scala/xsbt/DependencySpecification.scala */ |
| 2 | +package xsbt |
| 3 | + |
| 4 | +import org.junit.runner.RunWith |
| 5 | +import xsbti.api.ClassLike |
| 6 | +import xsbti.api.Def |
| 7 | +import xsbt.api.SameAPI |
| 8 | +import org.specs2.mutable.Specification |
| 9 | +import org.specs2.runner.JUnitRunner |
| 10 | + |
| 11 | +import ScalaCompilerForUnitTesting.ExtractedSourceDependencies |
| 12 | + |
| 13 | +@RunWith(classOf[JUnitRunner]) |
| 14 | +class DependencySpecification extends Specification { |
| 15 | + |
| 16 | + "Extracted source dependencies from public members" in { |
| 17 | + val sourceDependencies = extractSourceDependenciesPublic |
| 18 | + val memberRef = sourceDependencies.memberRef |
| 19 | + val inheritance = sourceDependencies.inheritance |
| 20 | + memberRef('A) === Set.empty |
| 21 | + inheritance('A) === Set.empty |
| 22 | + memberRef('B) === Set('A, 'D) |
| 23 | + inheritance('B) === Set('D) |
| 24 | + memberRef('C) === Set('A) |
| 25 | + inheritance('C) === Set.empty |
| 26 | + memberRef('D) === Set.empty |
| 27 | + inheritance('D) === Set.empty |
| 28 | + memberRef('E) === Set.empty |
| 29 | + inheritance('E) === Set.empty |
| 30 | + memberRef('F) === Set('A, 'B, 'C, 'D, 'E, 'G) |
| 31 | + inheritance('F) === Set('A, 'E) |
| 32 | + memberRef('H) === Set('B, 'E, 'G) |
| 33 | + // aliases and applied type constructors are expanded so we have inheritance dependency on B |
| 34 | + inheritance('H) === Set('B, 'E) |
| 35 | + } |
| 36 | + |
| 37 | + "Extracted source dependencies from private members" in { |
| 38 | + val sourceDependencies = extractSourceDependenciesPrivate |
| 39 | + val memberRef = sourceDependencies.memberRef |
| 40 | + val inheritance = sourceDependencies.inheritance |
| 41 | + memberRef('A) === Set.empty |
| 42 | + inheritance('A) === Set.empty |
| 43 | + memberRef('B) === Set.empty |
| 44 | + inheritance('B) === Set.empty |
| 45 | + memberRef('C) === Set('A) |
| 46 | + inheritance('C) === Set('A) |
| 47 | + memberRef('D) === Set('B) |
| 48 | + inheritance('D) === Set('B) |
| 49 | + } |
| 50 | + |
| 51 | + "Extracted source dependencies with trait as first parent" in { |
| 52 | + val sourceDependencies = extractSourceDependenciesTraitAsFirstPatent |
| 53 | + val memberRef = sourceDependencies.memberRef |
| 54 | + val inheritance = sourceDependencies.inheritance |
| 55 | + memberRef('A) === Set.empty |
| 56 | + inheritance('A) === Set.empty |
| 57 | + memberRef('B) === Set('A) |
| 58 | + inheritance('B) === Set('A) |
| 59 | + // verify that memberRef captures the oddity described in documentation of `Relations.inheritance` |
| 60 | + // we are mainly interested whether dependency on A is captured in `memberRef` relation so |
| 61 | + // the invariant that says that memberRef is superset of inheritance relation is preserved |
| 62 | + memberRef('C) === Set('A, 'B) |
| 63 | + inheritance('C) === Set('A, 'B) |
| 64 | + // same as above but indirect (C -> B -> A), note that only A is visible here |
| 65 | + memberRef('D) === Set('A, 'C) |
| 66 | + inheritance('D) === Set('A, 'C) |
| 67 | + } |
| 68 | + |
| 69 | + /* |
| 70 | + "Extracted source dependencies from macro arguments" in { |
| 71 | + val sourceDependencies = extractSourceDependenciesFromMacroArgument |
| 72 | + val memberRef = sourceDependencies.memberRef |
| 73 | + val inheritance = sourceDependencies.inheritance |
| 74 | +
|
| 75 | + memberRef('A) === Set('B, 'C) |
| 76 | + inheritance('A) === Set.empty |
| 77 | + memberRef('B) === Set.empty |
| 78 | + inheritance('B) === Set.empty |
| 79 | + memberRef('C) === Set.empty |
| 80 | + inheritance('C) === Set.empty |
| 81 | + } |
| 82 | + */ |
| 83 | + |
| 84 | + private def extractSourceDependenciesPublic: ExtractedSourceDependencies = { |
| 85 | + val srcA = "class A" |
| 86 | + val srcB = "class B extends D[A]" |
| 87 | + val srcC = """|class C { |
| 88 | + | def a: A = null |
| 89 | + |}""".stripMargin |
| 90 | + val srcD = "class D[T]" |
| 91 | + val srcE = "trait E[T]" |
| 92 | + val srcF = "trait F extends A with E[D[B]] { self: G.MyC => }" |
| 93 | + val srcG = "object G { type T[x] = B ; type MyC = C }" |
| 94 | + // T is a type constructor [x]B |
| 95 | + // B extends D |
| 96 | + // E verifies the core type gets pulled out |
| 97 | + val srcH = "trait H extends G.T[Int] with (E[Int] @unchecked)" |
| 98 | + |
| 99 | + val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true) |
| 100 | + val sourceDependencies = compilerForTesting.extractDependenciesFromSrcs('A -> srcA, 'B -> srcB, 'C -> srcC, |
| 101 | + 'D -> srcD, 'E -> srcE, 'F -> srcF, 'G -> srcG, 'H -> srcH) |
| 102 | + sourceDependencies |
| 103 | + } |
| 104 | + |
| 105 | + private def extractSourceDependenciesPrivate: ExtractedSourceDependencies = { |
| 106 | + val srcA = "class A" |
| 107 | + val srcB = "class B" |
| 108 | + val srcC = "class C { private class Inner1 extends A }" |
| 109 | + val srcD = "class D { def foo: Unit = { class Inner2 extends B } }" |
| 110 | + |
| 111 | + val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true) |
| 112 | + val sourceDependencies = |
| 113 | + compilerForTesting.extractDependenciesFromSrcs('A -> srcA, 'B -> srcB, 'C -> srcC, 'D -> srcD) |
| 114 | + sourceDependencies |
| 115 | + } |
| 116 | + |
| 117 | + private def extractSourceDependenciesTraitAsFirstPatent: ExtractedSourceDependencies = { |
| 118 | + val srcA = "class A" |
| 119 | + val srcB = "trait B extends A" |
| 120 | + val srcC = "trait C extends B" |
| 121 | + val srcD = "class D extends C" |
| 122 | + |
| 123 | + val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true) |
| 124 | + val sourceDependencies = |
| 125 | + compilerForTesting.extractDependenciesFromSrcs('A -> srcA, 'B -> srcB, 'C -> srcC, 'D -> srcD) |
| 126 | + sourceDependencies |
| 127 | + } |
| 128 | + |
| 129 | + /* |
| 130 | + private def extractSourceDependenciesFromMacroArgument: ExtractedSourceDependencies = { |
| 131 | + val srcA = "class A { println(B.printTree(C.foo)) }" |
| 132 | + val srcB = """ |
| 133 | + |import scala.language.experimental.macros |
| 134 | + |import scala.reflect.macros._ |
| 135 | + |object B { |
| 136 | + | def printTree(arg: Any) = macro printTreeImpl |
| 137 | + | def printTreeImpl(c: Context)(arg: c.Expr[Any]): c.Expr[String] = { |
| 138 | + | val argStr = arg.tree.toString |
| 139 | + | val literalStr = c.universe.Literal(c.universe.Constant(argStr)) |
| 140 | + | c.Expr[String](literalStr) |
| 141 | + | } |
| 142 | + |}""".stripMargin |
| 143 | + val srcC = "object C { val foo = 1 }" |
| 144 | +
|
| 145 | + val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true) |
| 146 | + val sourceDependencies = |
| 147 | + compilerForTesting.extractDependenciesFromSrcs(List(Map('B -> srcB, 'C -> srcC), Map('A -> srcA))) |
| 148 | + sourceDependencies |
| 149 | + } |
| 150 | + */ |
| 151 | +} |
0 commit comments