Skip to content

Commit c2f026d

Browse files
committed
Overlay.qll: Streamline discardable entities into one Discardable superclass
1 parent 2ed8dc7 commit c2f026d

File tree

1 file changed

+64
-77
lines changed

1 file changed

+64
-77
lines changed

python/ql/lib/semmle/python/Overlay.qll

Lines changed: 64 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,71 @@ overlay[local]
1414
predicate isOverlay() { databaseMetadata("isOverlay", "true") }
1515

1616
overlay[local]
17-
private string getRawPathForLocation(@location loc) {
17+
private string getPathForLocation(@location loc) {
1818
exists(@file file | locations_default(loc, file, _, _, _, _) | files(file, result))
1919
or
20-
exists(@py_Module mod | locations_ast(loc, mod, _, _, _, _) | result = getRawPathForModule(mod))
20+
exists(@py_Module mod | locations_ast(loc, mod, _, _, _, _) | result = getPathForModule(mod))
2121
}
2222

2323
overlay[local]
24-
private string getRawPathForModule(@py_Module mod) {
24+
private string getPathForModule(@py_Module mod) {
2525
exists(@container fileOrFolder | py_module_path(mod, fileOrFolder) |
26-
result = getRawPathForContainer(fileOrFolder)
26+
result = getPathForContainer(fileOrFolder)
2727
)
2828
}
2929

3030
overlay[local]
31-
private string getRawPathForContainer(@container fileOrFolder) {
31+
private string getPathForContainer(@container fileOrFolder) {
3232
files(fileOrFolder, result) or folders(fileOrFolder, result)
3333
}
3434

35-
/*- Source elements -*/
35+
/*- Discardable entities and their discard predicates -*/
36+
overlay[local]
37+
private class Discardable_ = @py_source_element or @py_flow_node or @py_base_var or @location;
38+
39+
overlay[discard_entity]
40+
private predicate discardEntity(@py_source_element el) {
41+
// Within `@py_source_element`, only `@py_Module` and `@container`
42+
// use named IDs; the rest use *-ids.
43+
exists(Discardable d | d = el |
44+
overlayChangedFiles(d.getPath()) and
45+
d.existsInBase() and
46+
not d.existsInOverlay()
47+
)
48+
}
49+
50+
overlay[discard_entity]
51+
private predicate discardCfgNode(@py_flow_node n) {
52+
// `@py_flow_node`s use *-ids, so cannot exist both in base and overlay.
53+
exists(Discardable d | d = n |
54+
overlayChangedFiles(d.getPath()) and
55+
d.existsInBase()
56+
)
57+
}
58+
59+
overlay[discard_entity]
60+
private predicate discardVar(@py_base_var n) {
61+
// `@py_base_var`s use *-ids, so cannot exist both in base and overlay.
62+
exists(Discardable d | d = n |
63+
overlayChangedFiles(d.getPath()) and
64+
d.existsInBase()
65+
)
66+
}
67+
68+
overlay[discard_entity]
69+
private predicate discardLocation(@location loc) {
70+
// Locations use *-ids, so cannot exist both in base and overlay.
71+
exists(Discardable d | d = loc |
72+
overlayChangedFiles(d.getPath()) and
73+
d.existsInBase()
74+
)
75+
}
76+
3677
/**
3778
* An abstract base class for all elements that can be discarded from the base.
3879
*/
3980
overlay[local]
40-
abstract private class Discardable extends @py_source_element {
81+
abstract private class Discardable extends Discardable_ {
4182
/** Gets the path to the file in which this element occurs. */
4283
abstract string getPath();
4384

@@ -51,98 +92,51 @@ abstract private class Discardable extends @py_source_element {
5192
string toString() { none() }
5293
}
5394

54-
overlay[discard_entity]
55-
private predicate discardEntity(@py_source_element el) {
56-
exists(Discardable d | d = el |
57-
overlayChangedFiles(d.getPath()) and
58-
d.existsInBase() and
59-
not d.existsInOverlay()
60-
)
61-
}
62-
6395
/**
64-
* Discard all locatable AST nodes (`@py_location_parent`) in modified files
65-
* since they use *-ids and hence cannot be referenced across TRAP files.
96+
* Discardable locatable AST nodes (`@py_location_parent`).
6697
*/
6798
overlay[local]
6899
final private class DiscardableLocatable extends Discardable instanceof @py_location_parent {
69100
override string getPath() {
70-
exists(@location loc | py_locations(loc, this) | result = getRawPathForLocation(loc))
101+
exists(@location loc | py_locations(loc, this) | result = getPathForLocation(loc))
71102
}
72103
}
73104

74105
/**
75-
* Discard scopes (classes, functions, modules) that were deleted in the overlay.
106+
* Discardable scopes (classes, functions, modules).
76107
*/
77108
overlay[local]
78109
final private class DiscardableScope extends Discardable instanceof @py_scope {
79110
override string getPath() {
80-
exists(@location loc | py_scope_location(loc, this) | result = getRawPathForLocation(loc))
111+
exists(@location loc | py_scope_location(loc, this) | result = getPathForLocation(loc))
81112
or
82-
result = getRawPathForModule(this)
113+
result = getPathForModule(this)
83114
}
84115
}
85116

86117
/**
87-
* Discard files and folders that were deleted in the overlay.
118+
* Discardable files and folders.
88119
*/
89120
overlay[local]
90121
final private class DiscardableContainer extends Discardable instanceof @container {
91-
override string getPath() { result = getRawPathForContainer(this) }
122+
override string getPath() { result = getPathForContainer(this) }
92123
}
93124

94-
/*- CFG Nodes -*/
95125
/** Discardable control flow nodes */
96126
overlay[local]
97-
final private class DiscardableCfgNode instanceof @py_flow_node {
98-
string getPath() {
127+
final private class DiscardableCfgNode extends Discardable instanceof @py_flow_node {
128+
override string getPath() {
99129
exists(Discardable d | result = d.getPath() |
100130
py_flow_bb_node(this, d.(@py_ast_node), _, _)
101131
or
102132
py_scope_flow(this, d.(@py_scope), _)
103133
)
104134
}
105-
106-
predicate existsInBase() { not isOverlay() and exists(this) }
107-
108-
predicate existsInOverlay() { isOverlay() and exists(this) }
109-
110-
string toString() { none() }
111-
}
112-
113-
overlay[discard_entity]
114-
private predicate discardCfgNode(@py_flow_node n) {
115-
exists(DiscardableCfgNode d | d = n |
116-
overlayChangedFiles(d.getPath()) and
117-
d.existsInBase() and
118-
not d.existsInOverlay()
119-
)
120-
}
121-
122-
/*- Variables -*/
123-
/** Discardable (normal and SSA) variables */
124-
overlay[local]
125-
abstract private class DiscardableBaseVar instanceof @py_base_var {
126-
abstract string getPath();
127-
128-
predicate existsInBase() { not isOverlay() and exists(this) }
129-
130-
predicate existsInOverlay() { isOverlay() and exists(this) }
131-
132-
string toString() { none() }
133-
}
134-
135-
overlay[discard_entity]
136-
private predicate discardVar(@py_base_var n) {
137-
exists(DiscardableVar d | d = n |
138-
overlayChangedFiles(d.getPath()) and
139-
d.existsInBase() and
140-
not d.existsInOverlay()
141-
)
142135
}
143136

137+
/** Discardable Python variables. */
144138
overlay[local]
145-
final private class DiscardableVar extends DiscardableBaseVar instanceof @py_variable {
139+
final private class DiscardableVar extends Discardable instanceof @py_variable {
146140
override string getPath() {
147141
exists(Discardable parent | result = parent.getPath() |
148142
variable(this, parent.(@py_scope), _)
@@ -152,8 +146,9 @@ final private class DiscardableVar extends DiscardableBaseVar instanceof @py_var
152146
}
153147
}
154148

149+
/** Discardable SSA variables. */
155150
overlay[local]
156-
final private class DiscardableSsaVar extends DiscardableBaseVar instanceof @py_ssa_var {
151+
final private class DiscardableSsaVar extends Discardable instanceof @py_ssa_var {
157152
override string getPath() {
158153
exists(DiscardableSsaVar other | result = other.getPath() |
159154
py_ssa_phi(this, other.(@py_ssa_var))
@@ -169,18 +164,10 @@ final private class DiscardableSsaVar extends DiscardableBaseVar instanceof @py_
169164
}
170165
}
171166

172-
/*- Locations -*/
167+
/** Discardable locations. */
173168
overlay[local]
174-
private predicate locationExistsInBase(@location loc) { not isOverlay() and exists(loc) }
175-
176-
overlay[local]
177-
private predicate locationExistsInOverlay(@location loc) { isOverlay() and exists(loc) }
178-
179-
overlay[discard_entity]
180-
private predicate discardLocation(@location loc) {
181-
overlayChangedFiles(getRawPathForLocation(loc)) and
182-
locationExistsInBase(loc) and
183-
not locationExistsInOverlay(loc)
169+
final private class DiscardableLocation extends Discardable instanceof @location {
170+
override string getPath() { result = getPathForLocation(this) }
184171
}
185172

186173
/*- XML -*/

0 commit comments

Comments
 (0)