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
predicateisOverlay(){databaseMetadata("isOverlay","true")}
1515

1616
overlay[local]
17-
privatestringgetRawPathForLocation(@location loc){
17+
privatestringgetPathForLocation(@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-
privatestringgetRawPathForModule(@py_Module mod){
24+
privatestringgetPathForModule(@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-
privatestringgetRawPathForContainer(@container fileOrFolder){
31+
privatestringgetPathForContainer(@container fileOrFolder){
3232
files(fileOrFolder,result)orfolders(fileOrFolder,result)
3333
}
3434

35-
/*- Source elements -*/
35+
/*- Discardable entities and their discard predicates -*/
36+
overlay[local]
37+
privateclassDiscardable_= @py_source_element or @py_flow_node or @py_base_var or @location;
38+
39+
overlay[discard_entity]
40+
privatepredicatediscardEntity(@py_source_element el){
41+
// Within `@py_source_element`, only `@py_Module` and `@container`
42+
// use named IDs; the rest use *-ids.
43+
exists(Discardabled|d=el|
44+
overlayChangedFiles(d.getPath())and
45+
d.existsInBase()and
46+
notd.existsInOverlay()
47+
)
48+
}
49+
50+
overlay[discard_entity]
51+
privatepredicatediscardCfgNode(@py_flow_node n){
52+
// `@py_flow_node`s use *-ids, so cannot exist both in base and overlay.
53+
exists(Discardabled|d=n|
54+
overlayChangedFiles(d.getPath())and
55+
d.existsInBase()
56+
)
57+
}
58+
59+
overlay[discard_entity]
60+
privatepredicatediscardVar(@py_base_var n){
61+
// `@py_base_var`s use *-ids, so cannot exist both in base and overlay.
62+
exists(Discardabled|d=n|
63+
overlayChangedFiles(d.getPath())and
64+
d.existsInBase()
65+
)
66+
}
67+
68+
overlay[discard_entity]
69+
privatepredicatediscardLocation(@location loc){
70+
// Locations use *-ids, so cannot exist both in base and overlay.
71+
exists(Discardabled|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-
abstractprivateclassDiscardableextends@py_source_element{
81+
abstractprivateclassDiscardableextendsDiscardable_{
4182
/** Gets the path to the file in which this element occurs. */
4283
abstractstringgetPath();
4384

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

54-
overlay[discard_entity]
55-
privatepredicatediscardEntity(@py_source_element el){
56-
exists(Discardabled|d=el|
57-
overlayChangedFiles(d.getPath())and
58-
d.existsInBase()and
59-
notd.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
finalprivateclassDiscardableLocatableextendsDiscardableinstanceof @py_location_parent {
69100
overridestringgetPath(){
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
finalprivateclassDiscardableScopeextendsDiscardableinstanceof @py_scope {
79110
overridestringgetPath(){
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
finalprivateclassDiscardableContainerextendsDiscardableinstanceof @container {
91-
overridestringgetPath(){result=getRawPathForContainer(this)}
122+
overridestringgetPath(){result=getPathForContainer(this)}
92123
}
93124

94-
/*- CFG Nodes -*/
95125
/** Discardable control flow nodes */
96126
overlay[local]
97-
finalprivateclassDiscardableCfgNodeinstanceof @py_flow_node {
98-
stringgetPath(){
127+
finalprivateclassDiscardableCfgNodeextendsDiscardableinstanceof @py_flow_node {
128+
overridestringgetPath(){
99129
exists(Discardabled|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-
predicateexistsInBase(){notisOverlay()andexists(this)}
107-
108-
predicateexistsInOverlay(){isOverlay()andexists(this)}
109-
110-
stringtoString(){none()}
111-
}
112-
113-
overlay[discard_entity]
114-
privatepredicatediscardCfgNode(@py_flow_node n){
115-
exists(DiscardableCfgNoded|d=n|
116-
overlayChangedFiles(d.getPath())and
117-
d.existsInBase()and
118-
notd.existsInOverlay()
119-
)
120-
}
121-
122-
/*- Variables -*/
123-
/** Discardable (normal and SSA) variables */
124-
overlay[local]
125-
abstractprivateclassDiscardableBaseVarinstanceof @py_base_var {
126-
abstractstringgetPath();
127-
128-
predicateexistsInBase(){notisOverlay()andexists(this)}
129-
130-
predicateexistsInOverlay(){isOverlay()andexists(this)}
131-
132-
stringtoString(){none()}
133-
}
134-
135-
overlay[discard_entity]
136-
privatepredicatediscardVar(@py_base_var n){
137-
exists(DiscardableVard|d=n|
138-
overlayChangedFiles(d.getPath())and
139-
d.existsInBase()and
140-
notd.existsInOverlay()
141-
)
142135
}
143136

137+
/** Discardable Python variables. */
144138
overlay[local]
145-
finalprivateclassDiscardableVarextendsDiscardableBaseVarinstanceof @py_variable {
139+
finalprivateclassDiscardableVarextendsDiscardableinstanceof @py_variable {
146140
overridestringgetPath(){
147141
exists(Discardableparent|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-
finalprivateclassDiscardableSsaVarextendsDiscardableBaseVarinstanceof @py_ssa_var {
151+
finalprivateclassDiscardableSsaVarextendsDiscardableinstanceof @py_ssa_var {
157152
overridestringgetPath(){
158153
exists(DiscardableSsaVarother|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-
privatepredicatelocationExistsInBase(@location loc){notisOverlay()andexists(loc)}
175-
176-
overlay[local]
177-
privatepredicatelocationExistsInOverlay(@location loc){isOverlay()andexists(loc)}
178-
179-
overlay[discard_entity]
180-
privatepredicatediscardLocation(@location loc){
181-
overlayChangedFiles(getRawPathForLocation(loc))and
182-
locationExistsInBase(loc)and
183-
notlocationExistsInOverlay(loc)
169+
finalprivateclassDiscardableLocationextendsDiscardableinstanceof @location {
170+
overridestringgetPath(){result=getPathForLocation(this)}
184171
}
185172

186173
/*- XML -*/

0 commit comments

Comments
(0)