-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathVariable.qll
More file actions
229 lines (192 loc) · 7.45 KB
/
Variable.qll
File metadata and controls
229 lines (192 loc) · 7.45 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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
/** Provides classes for modeling program variables. */
overlay[local]
module;
private import codeql.ruby.AST
private import internal.AST
private import internal.TreeSitter
private import internal.Variable
private import internal.Parameter
/** A variable declared in a scope. */
class Variable instanceof VariableImpl {
/** Gets the name of this variable. */
final string getName() { result = super.getNameImpl() }
/** Holds if the name of this variable is `name`. */
final predicate hasName(string name) { this.getName() = name }
/** Gets a textual representation of this variable. */
final string toString() { result = this.getName() }
/** Gets the location of this variable. */
final Location getLocation() { result = super.getLocationImpl() }
/** Gets the scope this variable is declared in. */
final Scope getDeclaringScope() {
toGenerated(result) = this.(VariableReal).getDeclaringScopeImpl()
}
/** Gets an access to this variable. */
VariableAccess getAnAccess() { result.getVariable() = this }
}
/** A local variable. */
class LocalVariable extends Variable, TLocalVariable {
override LocalVariableAccess getAnAccess() { result.getVariable() = this }
/** Gets the access where this local variable is first introduced. */
VariableAccess getDefiningAccess() {
result = this.(LocalVariableReal).getDefiningAccessImpl() or
synthChild(any(NamedParameter p | this = p.getVariable()), 0, result)
}
/**
* Holds if this variable is captured. For example in
*
* ```rb
* def m x
* x.times do |y|
* puts x
* end
* puts x
* end
* ```
*
* `x` is a captured variable, whereas `y` is not.
*/
final predicate isCaptured() { this.getAnAccess().isCapturedAccess() }
}
/** A global variable. */
class GlobalVariable extends Variable instanceof GlobalVariableImpl {
final override GlobalVariableAccess getAnAccess() { result.getVariable() = this }
}
/** An instance variable. */
class InstanceVariable extends Variable instanceof InstanceVariableImpl {
/** Holds if this variable is a class instance variable. */
final predicate isClassInstanceVariable() { super.isClassInstanceVariable() }
final override InstanceVariableAccess getAnAccess() { result.getVariable() = this }
}
/** A class variable. */
class ClassVariable extends Variable instanceof ClassVariableImpl {
final override ClassVariableAccess getAnAccess() { result.getVariable() = this }
}
/** A `self` variable. */
class SelfVariable extends LocalVariable instanceof SelfVariableImpl { }
/** An access to a variable. */
class VariableAccess extends Expr instanceof VariableAccessImpl {
/** Gets the variable this identifier refers to. */
final Variable getVariable() { result = super.getVariableImpl() }
/**
* Holds if this access is a write access belonging to the explicit
* assignment `assignment`. For example, in
*
* ```rb
* a, b = foo
* ```
*
* both `a` and `b` are write accesses belonging to the same assignment.
*/
predicate isExplicitWrite(AstNode assignment) {
explicitWriteAccess(toGenerated(this), toGenerated(assignment))
or
this = assignment.(AssignExpr).getLeftOperand()
}
/**
* Holds if this access is a write access belonging to an implicit assignment.
* For example, in
*
* ```rb
* def m elements
* for e in elements do
* puts e
* end
* end
* ```
*
* the access to `elements` in the parameter list is an implicit assignment,
* as is the first access to `e`.
*/
predicate isImplicitWrite() {
implicitWriteAccess(toGenerated(this))
or
this = any(SimpleParameterSynthImpl p).getDefiningAccess()
or
this = any(HashPattern p).getValue(_)
or
synthChild(any(NamedParameter p), 0, this)
}
}
/** An access to a variable where the value is updated. */
class VariableWriteAccess extends VariableAccess {
VariableWriteAccess() {
this.isExplicitWrite(_) or
this.isImplicitWrite()
}
}
/** An access to a variable where the value is read. */
class VariableReadAccess extends VariableAccess {
VariableReadAccess() { not this instanceof VariableWriteAccess }
}
/** An access to a local variable. */
class LocalVariableAccess extends VariableAccess instanceof LocalVariableAccessImpl {
override string getAPrimaryQlClass() { result = "LocalVariableAccess" }
/**
* Holds if this access is a captured variable access. For example in
*
* ```rb
* def m x
* x.times do |y|
* puts x
* end
* puts x
* end
* ```
*
* the access to `x` in the first `puts x` is a captured access, while
* the access to `x` in the second `puts x` is not.
*/
final predicate isCapturedAccess() { isCapturedAccess(this) }
}
/** An access to a local variable where the value is updated. */
class LocalVariableWriteAccess extends LocalVariableAccess, VariableWriteAccess { }
/** An access to a local variable where the value is read. */
class LocalVariableReadAccess extends LocalVariableAccess, VariableReadAccess { }
/** An access to a global variable. */
class GlobalVariableAccess extends VariableAccess instanceof GlobalVariableAccessImpl {
final override string getAPrimaryQlClass() { result = "GlobalVariableAccess" }
}
/** An access to a global variable where the value is updated. */
class GlobalVariableWriteAccess extends GlobalVariableAccess, VariableWriteAccess { }
/** An access to a global variable where the value is read. */
class GlobalVariableReadAccess extends GlobalVariableAccess, VariableReadAccess { }
/** An access to an instance variable. */
class InstanceVariableAccess extends VariableAccess instanceof InstanceVariableAccessImpl {
final override string getAPrimaryQlClass() { result = "InstanceVariableAccess" }
/**
* Gets the synthetic receiver (`self`) of this instance variable access.
*/
final SelfVariableAccess getReceiver() { synthChild(this, 0, result) }
final override AstNode getAChild(string pred) {
result = VariableAccess.super.getAChild(pred)
or
pred = "getReceiver" and result = this.getReceiver()
}
}
/** An access to an instance variable where the value is updated. */
class InstanceVariableWriteAccess extends InstanceVariableAccess, VariableWriteAccess { }
/** An access to an instance variable where the value is read. */
class InstanceVariableReadAccess extends InstanceVariableAccess, VariableReadAccess { }
/** An access to a class variable. */
class ClassVariableAccess extends VariableAccess instanceof ClassVariableAccessRealImpl {
final override string getAPrimaryQlClass() { result = "ClassVariableAccess" }
}
/** An access to a class variable where the value is updated. */
class ClassVariableWriteAccess extends ClassVariableAccess, VariableWriteAccess { }
/** An access to a class variable where the value is read. */
class ClassVariableReadAccess extends ClassVariableAccess, VariableReadAccess { }
/**
* An access to the `self` variable. For example:
* - `self == other`
* - `self.method_name`
* - `def self.method_name ... end`
*
* This also includes implicit references to the current object in method
* calls. For example, the method call `foo(123)` has an implicit `self`
* receiver, and is equivalent to the explicit `self.foo(123)`.
*/
class SelfVariableAccess extends LocalVariableAccess instanceof SelfVariableAccessImpl {
final override string getAPrimaryQlClass() { result = "SelfVariableAccess" }
}
/** An access to the `self` variable where the value is read. */
class SelfVariableReadAccess extends SelfVariableAccess, VariableReadAccess { }