1+ /** Provides classes for working with files and folders. */
2+
13import 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 > ;
227
328/** A file */
4- class File extends Container , @file {
29+ class File extends Container , Impl :: File {
530 /**
631 * Holds if this element is at the specified location.
732 * The location spans column `startcolumn` of line `startline` to
@@ -45,11 +70,6 @@ class File extends Container, @file {
4570 )
4671 }
4772
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-
5373 override Container getImportRoot ( int n ) {
5474 /* File stem must be a legal Python identifier */
5575 this .getStem ( ) .regexpMatch ( "[^\\d\\W]\\w*" ) and
@@ -108,7 +128,7 @@ private predicate occupied_line(File f, int n) {
108128}
109129
110130/** A folder (directory) */
111- class Folder extends Container , @folder {
131+ class Folder extends Container , Impl :: Folder {
112132 /**
113133 * Holds if this element is at the specified location.
114134 * The location spans column `startcolumn` of line `startline` to
@@ -126,11 +146,6 @@ class Folder extends Container, @folder {
126146 endcolumn = 0
127147 }
128148
129- override string getAbsolutePath ( ) { folders ( this , result ) }
130-
131- /** Gets the URL of this folder. */
132- override string getURL ( ) { result = "folder://" + this .getAbsolutePath ( ) }
133-
134149 override Container getImportRoot ( int n ) {
135150 this .isImportRoot ( n ) and result = this
136151 or
@@ -144,34 +159,8 @@ class Folder extends Container, @folder {
144159 * A container is an abstract representation of a file system object that can
145160 * hold elements of interest.
146161 */
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 ( ) }
175164
176165 /** Whether this file or folder is part of the standard library */
177166 predicate inStdlib ( ) { this .inStdlib ( _, _) }
@@ -187,135 +176,13 @@ abstract class Container extends @container {
187176 )
188177 }
189178
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 ( ) }
306180
307181 Container getChildContainer ( string baseName ) {
308182 result = this .getAChildContainer ( ) and
309183 result .getBaseName ( ) = baseName
310184 }
311185
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-
319186 /** Holds if this folder is on the import path. */
320187 predicate isImportRoot ( ) { this .isImportRoot ( _) }
321188
0 commit comments