aboutsummaryrefslogtreecommitdiff
path: root/sbt-bridge/test/xsbt/DependencySpecification.scala
blob: 60545091b666c013354f8acd38192f9d4de58089 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/** Adapted from https://github.com/sbt/sbt/blob/0.13/compile/interface/src/test/scala/xsbt/DependencySpecification.scala */
package xsbt

import org.junit.runner.RunWith
import xsbti.api.ClassLike
import xsbti.api.Def
import xsbt.api.SameAPI
import org.specs2.mutable.Specification
import org.specs2.runner.JUnitRunner

import ScalaCompilerForUnitTesting.ExtractedSourceDependencies

@RunWith(classOf[JUnitRunner])
class DependencySpecification extends Specification {

  "Extracted source dependencies from public members" in {
    val sourceDependencies = extractSourceDependenciesPublic
    val memberRef = sourceDependencies.memberRef
    val inheritance = sourceDependencies.inheritance
    memberRef('A) === Set.empty
    inheritance('A) === Set.empty
    memberRef('B) === Set('A, 'D)
    inheritance('B) === Set('D)
    memberRef('C) === Set('A)
    inheritance('C) === Set.empty
    memberRef('D) === Set.empty
    inheritance('D) === Set.empty
    memberRef('E) === Set.empty
    inheritance('E) === Set.empty
    memberRef('F) === Set('A, 'B, 'C, 'D, 'E, 'G)
    inheritance('F) === Set('A, 'E)
    memberRef('H) === Set('B, 'E, 'G)
    // aliases and applied type constructors are expanded so we have inheritance dependency on B
    inheritance('H) === Set('B, 'E)
  }

  "Extracted source dependencies from private members" in {
    val sourceDependencies = extractSourceDependenciesPrivate
    val memberRef = sourceDependencies.memberRef
    val inheritance = sourceDependencies.inheritance
    memberRef('A) === Set.empty
    inheritance('A) === Set.empty
    memberRef('B) === Set.empty
    inheritance('B) === Set.empty
    memberRef('C) === Set('A)
    inheritance('C) === Set('A)
    memberRef('D) === Set('B)
    inheritance('D) === Set('B)
  }

  "Extracted source dependencies with trait as first parent" in {
    val sourceDependencies = extractSourceDependenciesTraitAsFirstPatent
    val memberRef = sourceDependencies.memberRef
    val inheritance = sourceDependencies.inheritance
    memberRef('A) === Set.empty
    inheritance('A) === Set.empty
    memberRef('B) === Set('A)
    inheritance('B) === Set('A)
    // verify that memberRef captures the oddity described in documentation of `Relations.inheritance`
    // we are mainly interested whether dependency on A is captured in `memberRef` relation so
    // the invariant that says that memberRef is superset of inheritance relation is preserved
    memberRef('C) === Set('A, 'B)
    inheritance('C) === Set('A, 'B)
    // same as above but indirect (C -> B -> A), note that only A is visible here
    memberRef('D) === Set('A, 'C)
    inheritance('D) === Set('A, 'C)
  }

  /*
  "Extracted source dependencies from macro arguments" in {
    val sourceDependencies = extractSourceDependenciesFromMacroArgument
    val memberRef = sourceDependencies.memberRef
    val inheritance = sourceDependencies.inheritance

    memberRef('A) === Set('B, 'C)
    inheritance('A) === Set.empty
    memberRef('B) === Set.empty
    inheritance('B) === Set.empty
    memberRef('C) === Set.empty
    inheritance('C) === Set.empty
  }
  */

  private def extractSourceDependenciesPublic: ExtractedSourceDependencies = {
    val srcA = "class A"
    val srcB = "class B extends D[A]"
    val srcC = """|class C {
		  |  def a: A = null
		  |}""".stripMargin
    val srcD = "class D[T]"
    val srcE = "trait E[T]"
    val srcF = "trait F extends A with E[D[B]] { self: G.MyC => }"
    val srcG = "object G { type T[x] = B ; type MyC = C }"
    // T is a type constructor [x]B
    // B extends D
    // E verifies the core type gets pulled out
    val srcH = "trait H extends G.T[Int] with (E[Int] @unchecked)"

    val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true)
    val sourceDependencies = compilerForTesting.extractDependenciesFromSrcs('A -> srcA, 'B -> srcB, 'C -> srcC,
      'D -> srcD, 'E -> srcE, 'F -> srcF, 'G -> srcG, 'H -> srcH)
    sourceDependencies
  }

  private def extractSourceDependenciesPrivate: ExtractedSourceDependencies = {
    val srcA = "class A"
    val srcB = "class B"
    val srcC = "class C { private class Inner1 extends A }"
    val srcD = "class D { def foo: Unit = { class Inner2 extends B } }"

    val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true)
    val sourceDependencies =
      compilerForTesting.extractDependenciesFromSrcs('A -> srcA, 'B -> srcB, 'C -> srcC, 'D -> srcD)
    sourceDependencies
  }

  private def extractSourceDependenciesTraitAsFirstPatent: ExtractedSourceDependencies = {
    val srcA = "class A"
    val srcB = "trait B extends A"
    val srcC = "trait C extends B"
    val srcD = "class D extends C"

    val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true)
    val sourceDependencies =
      compilerForTesting.extractDependenciesFromSrcs('A -> srcA, 'B -> srcB, 'C -> srcC, 'D -> srcD)
    sourceDependencies
  }

  /*
  private def extractSourceDependenciesFromMacroArgument: ExtractedSourceDependencies = {
    val srcA = "class A { println(B.printTree(C.foo)) }"
    val srcB = """
			|import scala.language.experimental.macros
			|import scala.reflect.macros._
			|object B {
			|  def printTree(arg: Any) = macro printTreeImpl
			|  def printTreeImpl(c: Context)(arg: c.Expr[Any]): c.Expr[String] = {
			|    val argStr = arg.tree.toString
			|    val literalStr = c.universe.Literal(c.universe.Constant(argStr))
			|    c.Expr[String](literalStr)
			|  }
			|}""".stripMargin
    val srcC = "object C { val foo = 1 }"

    val compilerForTesting = new ScalaCompilerForUnitTesting(nameHashing = true)
    val sourceDependencies =
      compilerForTesting.extractDependenciesFromSrcs(List(Map('B -> srcB, 'C -> srcC), Map('A -> srcA)))
    sourceDependencies
  }
  */
}