-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Expand file tree
/
Copy pathDependency.qll
More file actions
117 lines (113 loc) · 4.13 KB
/
Dependency.qll
File metadata and controls
117 lines (113 loc) · 4.13 KB
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
/**
* Provides utility predicates for representing dependencies between types.
*/
overlay[local?]
module;
import Type
import Generics
import Expr
/**
* Holds if type `t` depends on type `dep`.
*
* Dependencies are restricted to generic and non-generic reference types.
*
* Dependencies on parameterized or raw types are decomposed into
* a dependency on the corresponding generic type and separate
* dependencies on (source declarations of) any type arguments.
*
* For example, a dependency on type `List<Set<String>>` is represented by
* dependencies on the generic types `List` and `Set` as well as a dependency
* on the type `String` but not on the parameterized types `List<Set<String>>`
* or `Set<String>`.
*/
predicate depends(RefType t, RefType dep) {
// Type `t` is neither a parameterized nor a raw type and is distinct from `dep`.
not isParameterized(t) and
not isRaw(t) and
not t = dep and
// Type `t` depends on:
(
// its supertypes,
usesType(t.getASupertype(), dep)
or
// its enclosing type,
usesType(t.(NestedType).getEnclosingType(), dep)
or
// the type of any field declared in `t`,
exists(Field f | f.getDeclaringType() = t | usesType(f.getType(), dep))
or
// the return type of any method declared in `t`,
exists(Method m | m.getDeclaringType() = t | usesType(m.getReturnType(), dep))
or
// the type of any parameter of a callable in `t`,
exists(Callable c | c.getDeclaringType() = t | usesType(c.getAParamType(), dep))
or
// the type of any exception in the `throws` clause of a callable declared in `t`,
exists(Exception e | e.getCallable().getDeclaringType() = t | usesType(e.getType(), dep))
or
// the declaring type of a callable accessed in `t`,
exists(Callable c | c.getAReference().getEnclosingCallable().getDeclaringType() = t |
usesType(c.getSourceDeclaration().getDeclaringType(), dep)
)
or
// the declaring type of a field accessed in `t`,
exists(Field f | f.getAnAccess().getEnclosingCallable().getDeclaringType() = t |
usesType(f.getDeclaringType(), dep)
)
or
// the type of a local variable declared in `t`,
exists(LocalVariableDeclExpr decl | decl.getEnclosingCallable().getDeclaringType() = t |
usesType(decl.getType(), dep)
)
or
// the type of a type literal accessed in `t`,
exists(TypeLiteral l | l.getEnclosingCallable().getDeclaringType() = t |
usesType(l.getReferencedType(), dep)
)
or
// the type of an annotation (or one of its element values) that annotates `t` or one of its members,
exists(Annotation a |
a.getAnnotatedElement() = t or
a.getAnnotatedElement().(Member).getDeclaringType() = t
|
usesType(a.getType(), dep) or
usesType(a.getValue(_).getType(), dep) or
usesType(a.getAnArrayValue(_).getType(), dep)
)
or
// the type accessed in an `instanceof` expression in `t`.
exists(InstanceOfExpr ioe | t = ioe.getEnclosingCallable().getDeclaringType() |
usesType(ioe.getCheckedType(), dep)
or
usesType(ioe.getPattern().getAChildExpr*().getType(), dep)
)
or
// A type accessed in a pattern-switch case statement in `t`.
exists(PatternCase pc | t = pc.getEnclosingCallable().getDeclaringType() |
usesType(pc.getAPattern().getAChildExpr*().getType(), dep)
)
)
}
/**
* Bind the reference type `dep` to the source declaration of any types used to construct `t`,
* including (possibly nested) type parameters of parameterized types, element types of array types,
* and bounds of type variables or wildcards.
*/
cached
predicate usesType(Type t, RefType dep) {
dep = inside*(t).getSourceDeclaration() and
not dep instanceof TypeVariable and
not dep instanceof Wildcard and
not dep instanceof Array
}
/**
* Gets a type argument of a parameterized type,
* the element type of an array type, or
* a bound of a type variable or wildcard.
*/
private RefType inside(Type t) {
result = t.(TypeVariable).getATypeBound().getType() or
result = t.(Wildcard).getATypeBound().getType() or
result = t.(ParameterizedType).getATypeArgument() or
result = t.(Array).getElementType()
}