1
+ /** Provides classes for working with files and folders. */
2
+
1
3
import python
4
+ private import codeql.util.FileSystem
5
+
6
+ private module Input implements InputSig {
7
+ abstract class ContainerBase extends @container {
8
+ abstract string getAbsolutePath ( ) ;
9
+
10
+ ContainerBase getParentContainer ( ) { containerparent ( result , this ) }
11
+
12
+ string toString ( ) { result = this .getAbsolutePath ( ) }
13
+ }
14
+
15
+ class FolderBase extends ContainerBase , @folder {
16
+ override string getAbsolutePath ( ) { folders ( this , result ) }
17
+ }
18
+
19
+ class FileBase extends ContainerBase , @file {
20
+ override string getAbsolutePath ( ) { files ( this , result ) }
21
+ }
22
+
23
+ predicate hasSourceLocationPrefix = sourceLocationPrefix / 1 ;
24
+ }
25
+
26
+ private module Impl = Make< Input > ;
2
27
3
28
/** A file */
4
- class File extends Container , @file {
29
+ class File extends Container , Impl :: File {
5
30
/**
6
31
* Holds if this element is at the specified location.
7
32
* The location spans column `startcolumn` of line `startline` to
@@ -45,11 +70,6 @@ class File extends Container, @file {
45
70
)
46
71
}
47
72
48
- override string getAbsolutePath ( ) { files ( this , result ) }
49
-
50
- /** Gets the URL of this file. */
51
- override string getURL ( ) { result = "file://" + this .getAbsolutePath ( ) + ":0:0:0:0" }
52
-
53
73
override Container getImportRoot ( int n ) {
54
74
/* File stem must be a legal Python identifier */
55
75
this .getStem ( ) .regexpMatch ( "[^\\d\\W]\\w*" ) and
@@ -108,7 +128,7 @@ private predicate occupied_line(File f, int n) {
108
128
}
109
129
110
130
/** A folder (directory) */
111
- class Folder extends Container , @folder {
131
+ class Folder extends Container , Impl :: Folder {
112
132
/**
113
133
* Holds if this element is at the specified location.
114
134
* The location spans column `startcolumn` of line `startline` to
@@ -126,11 +146,6 @@ class Folder extends Container, @folder {
126
146
endcolumn = 0
127
147
}
128
148
129
- override string getAbsolutePath ( ) { folders ( this , result ) }
130
-
131
- /** Gets the URL of this folder. */
132
- override string getURL ( ) { result = "folder://" + this .getAbsolutePath ( ) }
133
-
134
149
override Container getImportRoot ( int n ) {
135
150
this .isImportRoot ( n ) and result = this
136
151
or
@@ -144,34 +159,8 @@ class Folder extends Container, @folder {
144
159
* A container is an abstract representation of a file system object that can
145
160
* hold elements of interest.
146
161
*/
147
- abstract class Container extends @container {
148
- Container getParent ( ) { containerparent ( result , this ) }
149
-
150
- /**
151
- * Gets a textual representation of the path of this container.
152
- *
153
- * This is the absolute path of the container.
154
- */
155
- string toString ( ) { result = this .getAbsolutePath ( ) }
156
-
157
- /**
158
- * Gets the relative path of this file or folder from the root folder of the
159
- * analyzed source location. The relative path of the root folder itself is
160
- * the empty string.
161
- *
162
- * This has no result if the container is outside the source root, that is,
163
- * if the root folder is not a reflexive, transitive parent of this container.
164
- */
165
- string getRelativePath ( ) {
166
- exists ( string absPath , string pref |
167
- absPath = this .getAbsolutePath ( ) and sourceLocationPrefix ( pref )
168
- |
169
- absPath = pref and result = ""
170
- or
171
- absPath = pref .regexpReplaceAll ( "/$" , "" ) + "/" + result and
172
- not result .matches ( "/%" )
173
- )
174
- }
162
+ class Container extends Impl:: Container {
163
+ Container getParent ( ) { result = this .getParentContainer ( ) }
175
164
176
165
/** Whether this file or folder is part of the standard library */
177
166
predicate inStdlib ( ) { this .inStdlib ( _, _) }
@@ -187,135 +176,13 @@ abstract class Container extends @container {
187
176
)
188
177
}
189
178
190
- /* Standard cross-language API */
191
- /** Gets a file or sub-folder in this container. */
192
- Container getAChildContainer ( ) { containerparent ( this , result ) }
193
-
194
- /** Gets a file in this container. */
195
- File getAFile ( ) { result = this .getAChildContainer ( ) }
196
-
197
- /** Gets a sub-folder in this container. */
198
- Folder getAFolder ( ) { result = this .getAChildContainer ( ) }
199
-
200
- /**
201
- * Gets the absolute, canonical path of this container, using forward slashes
202
- * as path separator.
203
- *
204
- * The path starts with a _root prefix_ followed by zero or more _path
205
- * segments_ separated by forward slashes.
206
- *
207
- * The root prefix is of one of the following forms:
208
- *
209
- * 1. A single forward slash `/` (Unix-style)
210
- * 2. An upper-case drive letter followed by a colon and a forward slash,
211
- * such as `C:/` (Windows-style)
212
- * 3. Two forward slashes, a computer name, and then another forward slash,
213
- * such as `//FileServer/` (UNC-style)
214
- *
215
- * Path segments are never empty (that is, absolute paths never contain two
216
- * contiguous slashes, except as part of a UNC-style root prefix). Also, path
217
- * segments never contain forward slashes, and no path segment is of the
218
- * form `.` (one dot) or `..` (two dots).
219
- *
220
- * Note that an absolute path never ends with a forward slash, except if it is
221
- * a bare root prefix, that is, the path has no path segments. A container
222
- * whose absolute path has no segments is always a `Folder`, not a `File`.
223
- */
224
- abstract string getAbsolutePath ( ) ;
225
-
226
- /**
227
- * Gets the base name of this container including extension, that is, the last
228
- * segment of its absolute path, or the empty string if it has no segments.
229
- *
230
- * Here are some examples of absolute paths and the corresponding base names
231
- * (surrounded with quotes to avoid ambiguity):
232
- *
233
- * <table border="1">
234
- * <tr><th>Absolute path</th><th>Base name</th></tr>
235
- * <tr><td>"/tmp/tst.py"</td><td>"tst.py"</td></tr>
236
- * <tr><td>"C:/Program Files (x86)"</td><td>"Program Files (x86)"</td></tr>
237
- * <tr><td>"/"</td><td>""</td></tr>
238
- * <tr><td>"C:/"</td><td>""</td></tr>
239
- * <tr><td>"D:/"</td><td>""</td></tr>
240
- * <tr><td>"//FileServer/"</td><td>""</td></tr>
241
- * </table>
242
- */
243
- string getBaseName ( ) {
244
- result = this .getAbsolutePath ( ) .regexpCapture ( ".*/(([^/]*?)(?:\\.([^.]*))?)" , 1 )
245
- }
246
-
247
- /**
248
- * Gets the extension of this container, that is, the suffix of its base name
249
- * after the last dot character, if any.
250
- *
251
- * In particular,
252
- *
253
- * - if the name does not include a dot, there is no extension, so this
254
- * predicate has no result;
255
- * - if the name ends in a dot, the extension is the empty string;
256
- * - if the name contains multiple dots, the extension follows the last dot.
257
- *
258
- * Here are some examples of absolute paths and the corresponding extensions
259
- * (surrounded with quotes to avoid ambiguity):
260
- *
261
- * <table border="1">
262
- * <tr><th>Absolute path</th><th>Extension</th></tr>
263
- * <tr><td>"/tmp/tst.py"</td><td>"py"</td></tr>
264
- * <tr><td>"/tmp/.gitignore"</td><td>"gitignore"</td></tr>
265
- * <tr><td>"/bin/bash"</td><td>not defined</td></tr>
266
- * <tr><td>"/tmp/tst2."</td><td>""</td></tr>
267
- * <tr><td>"/tmp/x.tar.gz"</td><td>"gz"</td></tr>
268
- * </table>
269
- */
270
- string getExtension ( ) {
271
- result = this .getAbsolutePath ( ) .regexpCapture ( ".*/([^/]*?)(\\.([^.]*))?" , 3 )
272
- }
273
-
274
- /**
275
- * Gets the stem of this container, that is, the prefix of its base name up to
276
- * (but not including) the last dot character if there is one, or the entire
277
- * base name if there is not.
278
- *
279
- * Here are some examples of absolute paths and the corresponding stems
280
- * (surrounded with quotes to avoid ambiguity):
281
- *
282
- * <table border="1">
283
- * <tr><th>Absolute path</th><th>Stem</th></tr>
284
- * <tr><td>"/tmp/tst.py"</td><td>"tst"</td></tr>
285
- * <tr><td>"/tmp/.gitignore"</td><td>""</td></tr>
286
- * <tr><td>"/bin/bash"</td><td>"bash"</td></tr>
287
- * <tr><td>"/tmp/tst2."</td><td>"tst2"</td></tr>
288
- * <tr><td>"/tmp/x.tar.gz"</td><td>"x.tar"</td></tr>
289
- * </table>
290
- */
291
- string getStem ( ) {
292
- result = this .getAbsolutePath ( ) .regexpCapture ( ".*/([^/]*?)(?:\\.([^.]*))?" , 1 )
293
- }
294
-
295
- File getFile ( string baseName ) {
296
- result = this .getAFile ( ) and
297
- result .getBaseName ( ) = baseName
298
- }
299
-
300
- Folder getFolder ( string baseName ) {
301
- result = this .getAFolder ( ) and
302
- result .getBaseName ( ) = baseName
303
- }
304
-
305
- Container getParentContainer ( ) { this = result .getAChildContainer ( ) }
179
+ override Container getParentContainer ( ) { result = super .getParentContainer ( ) }
306
180
307
181
Container getChildContainer ( string baseName ) {
308
182
result = this .getAChildContainer ( ) and
309
183
result .getBaseName ( ) = baseName
310
184
}
311
185
312
- /**
313
- * Gets a URL representing the location of this container.
314
- *
315
- * For more information see [Providing URLs](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/#providing-urls).
316
- */
317
- abstract string getURL ( ) ;
318
-
319
186
/** Holds if this folder is on the import path. */
320
187
predicate isImportRoot ( ) { this .isImportRoot ( _) }
321
188
0 commit comments