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
}
*/
}
|