-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Expand file tree
/
Copy pathVariable.qll
More file actions
139 lines (107 loc) · 5.04 KB
/
Variable.qll
File metadata and controls
139 lines (107 loc) · 5.04 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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/**
* Provides classes and predicates for working with Java variables and their declarations.
*/
overlay[local?]
module;
import Element
private import semmle.code.java.Overlay
/** A variable is a field, a local variable or a parameter. */
class Variable extends @variable, Annotatable, Element, Modifiable {
/** Gets the type of this variable. */
/*abstract*/ Type getType() { none() }
/** Gets the Kotlin type of this variable. */
/*abstract*/ KotlinType getKotlinType() { none() }
/** Gets an access to this variable. */
VarAccess getAnAccess() { variableBinding(result, this) }
/**
* Gets an expression assigned to this variable, either appearing on the right-hand side of an
* assignment or bound to it via a binding `instanceof` expression or `switch` block.
*/
Expr getAnAssignedValue() {
exists(LocalVariableDeclExpr e | e.getVariable() = this and result = e.getInitOrPatternSource())
or
exists(AssignExpr e | e.getDest() = this.getAnAccess() and result = e.getSource())
}
/** Gets the initializer expression of this variable. */
Expr getInitializer() { none() }
/** Gets a printable representation of this variable together with its type. */
string pp() { result = this.getType().getName() + " " + this.getName() }
}
/** A locally scoped variable, that is, either a local variable or a parameter. */
class LocalScopeVariable extends Variable, @localscopevariable {
/** Gets the callable in which this variable is declared. */
abstract Callable getCallable();
}
/** A local variable declaration */
class LocalVariableDecl extends @localvar, LocalScopeVariable {
/** Gets the type of this local variable. */
override Type getType() { localvars(this, _, result, _) }
/** Gets the Kotlin type of this local variable. */
override KotlinType getKotlinType() { localvarsKotlinType(this, result) }
/** Gets the expression declaring this variable. */
LocalVariableDeclExpr getDeclExpr() { localvars(this, _, _, result) }
/** Gets the parent of this declaration. */
Expr getParent() { localvars(this, _, _, result) }
/** Gets the callable in which this declaration occurs. */
override Callable getCallable() { result = this.getParent().getEnclosingCallable() }
/** Gets the callable in which this declaration occurs. */
Callable getEnclosingCallable() { result = this.getCallable() }
override string toString() {
exists(string sourceName |
if this.getName() = "" then sourceName = "_" else sourceName = this.getName()
|
result = this.getType().getName() + " " + sourceName
)
}
/** Gets the initializer expression of this local variable declaration. */
override Expr getInitializer() { result = this.getDeclExpr().getInit() }
override string getAPrimaryQlClass() { result = "LocalVariableDecl" }
}
/** A formal parameter of a callable. */
class Parameter extends Element, @param, LocalScopeVariable {
/** Gets the type of this formal parameter. */
override Type getType() { params(this, result, _, _, _) }
/** Gets the Kotlin type of this formal parameter. */
override KotlinType getKotlinType() { paramsKotlinType(this, result) }
/** Holds if the parameter is never assigned a value in the body of the callable. */
predicate isEffectivelyFinal() { not exists(this.getAnAssignedValue()) }
/** Gets the (zero-based) index of this formal parameter. */
int getPosition() { params(this, _, result, _, _) }
/** Gets the callable that declares this formal parameter. */
override Callable getCallable() { params(this, _, _, result, _) }
/** Gets the source declaration of this formal parameter. */
Parameter getSourceDeclaration() { params(this, _, _, _, result) }
/** Holds if this formal parameter is the same as its source declaration. */
predicate isSourceDeclaration() { this.getSourceDeclaration() = this }
/** Holds if this formal parameter is a variable arity parameter. */
predicate isVarargs() { isVarargsParam(this) }
/** Holds if this formal parameter is a parameter representing the dispatch receiver in an extension method. */
predicate isExtensionParameter() {
this.getPosition() = this.getCallable().(ExtensionMethod).getExtensionReceiverParameterIndex()
}
/**
* Gets an argument for this parameter in any call to the callable that declares this formal
* parameter.
*
* Varargs parameters will have no results for this method.
*/
Expr getAnArgument() {
not this.isVarargs() and
result = this.getACallArgument(this.getPosition())
}
pragma[noinline]
private Expr getACallArgument(int i) {
exists(Call call |
result = call.getArgument(i) and
call.getCallee().getSourceDeclaration().getAParameter() = this
)
}
override string getAPrimaryQlClass() { result = "Parameter" }
override string toString() {
if this.getName() = "" then result = "<anonymous parameter>" else result = super.toString()
}
/** Holds if this is an anonymous parameter, `_` */
predicate isAnonymous() { this.getName() = "" }
}
overlay[local]
private class DiscardableLocalScopeVariable extends DiscardableLocatable, @localscopevariable { }