Skip to content

Commit 7bc0c54

Browse files
committed
QL: Use shared FileSystem library.
1 parent 73521ca commit 7bc0c54

File tree

1 file changed

+16
-157
lines changed

1 file changed

+16
-157
lines changed

ql/ql/src/codeql/files/FileSystem.qll

Lines changed: 16 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -2,177 +2,36 @@
22

33
private import codeql_ql.ast.internal.TreeSitter
44
private import codeql.Locations
5+
private import codeql.util.FileSystem
56

6-
/** A file or folder. */
7-
abstract class Container extends @container {
8-
/** Gets a file or sub-folder in this container. */
9-
Container getAChildContainer() { this = result.getParentContainer() }
10-
11-
/** Gets a file in this container. */
12-
File getAFile() { result = this.getAChildContainer() }
13-
14-
/** Gets a sub-folder in this container. */
15-
Folder getAFolder() { result = this.getAChildContainer() }
16-
17-
/**
18-
* Gets the absolute, canonical path of this container, using forward slashes
19-
* as path separator.
20-
*
21-
* The path starts with a _root prefix_ followed by zero or more _path
22-
* segments_ separated by forward slashes.
23-
*
24-
* The root prefix is of one of the following forms:
25-
*
26-
* 1. A single forward slash `/` (Unix-style)
27-
* 2. An upper-case drive letter followed by a colon and a forward slash,
28-
* such as `C:/` (Windows-style)
29-
* 3. Two forward slashes, a computer name, and then another forward slash,
30-
* such as `//FileServer/` (UNC-style)
31-
*
32-
* Path segments are never empty (that is, absolute paths never contain two
33-
* contiguous slashes, except as part of a UNC-style root prefix). Also, path
34-
* segments never contain forward slashes, and no path segment is of the
35-
* form `.` (one dot) or `..` (two dots).
36-
*
37-
* Note that an absolute path never ends with a forward slash, except if it is
38-
* a bare root prefix, that is, the path has no path segments. A container
39-
* whose absolute path has no segments is always a `Folder`, not a `File`.
40-
*/
41-
abstract string getAbsolutePath();
42-
43-
/**
44-
* Gets the base name of this container including extension, that is, the last
45-
* segment of its absolute path, or the empty string if it has no segments.
46-
*
47-
* Here are some examples of absolute paths and the corresponding base names
48-
* (surrounded with quotes to avoid ambiguity):
49-
*
50-
* <table border="1">
51-
* <tr><th>Absolute path</th><th>Base name</th></tr>
52-
* <tr><td>"/tmp/tst.go"</td><td>"tst.go"</td></tr>
53-
* <tr><td>"C:/Program Files (x86)"</td><td>"Program Files (x86)"</td></tr>
54-
* <tr><td>"/"</td><td>""</td></tr>
55-
* <tr><td>"C:/"</td><td>""</td></tr>
56-
* <tr><td>"D:/"</td><td>""</td></tr>
57-
* <tr><td>"//FileServer/"</td><td>""</td></tr>
58-
* </table>
59-
*/
60-
string getBaseName() {
61-
result = this.getAbsolutePath().regexpCapture(".*/(([^/]*?)(?:\\.([^.]*))?)", 1)
62-
}
7+
private module Input implements InputSig {
8+
abstract class ContainerBase extends @container {
9+
abstract string getAbsolutePath();
6310

64-
/**
65-
* Gets the extension of this container, that is, the suffix of its base name
66-
* after the last dot character, if any.
67-
*
68-
* In particular,
69-
*
70-
* - if the name does not include a dot, there is no extension, so this
71-
* predicate has no result;
72-
* - if the name ends in a dot, the extension is the empty string;
73-
* - if the name contains multiple dots, the extension follows the last dot.
74-
*
75-
* Here are some examples of absolute paths and the corresponding extensions
76-
* (surrounded with quotes to avoid ambiguity):
77-
*
78-
* <table border="1">
79-
* <tr><th>Absolute path</th><th>Extension</th></tr>
80-
* <tr><td>"/tmp/tst.go"</td><td>"go"</td></tr>
81-
* <tr><td>"/tmp/.classpath"</td><td>"classpath"</td></tr>
82-
* <tr><td>"/bin/bash"</td><td>not defined</td></tr>
83-
* <tr><td>"/tmp/tst2."</td><td>""</td></tr>
84-
* <tr><td>"/tmp/x.tar.gz"</td><td>"gz"</td></tr>
85-
* </table>
86-
*/
87-
string getExtension() {
88-
result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3)
89-
}
11+
ContainerBase getParentContainer() { containerparent(result, this) }
9012

91-
/** Gets the file in this container that has the given `baseName`, if any. */
92-
File getFile(string baseName) {
93-
result = this.getAFile() and
94-
result.getBaseName() = baseName
13+
string toString() { result = this.getAbsolutePath() }
9514
}
9615

97-
/** Gets the sub-folder in this container that has the given `baseName`, if any. */
98-
Folder getFolder(string baseName) {
99-
result = this.getAFolder() and
100-
result.getBaseName() = baseName
101-
}
102-
103-
/** Gets the parent container of this file or folder, if any. */
104-
Container getParentContainer() { containerparent(result, this) }
105-
106-
/**
107-
* Gets the relative path of this file or folder from the root folder of the
108-
* analyzed source location. The relative path of the root folder itself is
109-
* the empty string.
110-
*
111-
* This has no result if the container is outside the source root, that is,
112-
* if the root folder is not a reflexive, transitive parent of this container.
113-
*/
114-
string getRelativePath() {
115-
exists(string absPath, string pref |
116-
absPath = this.getAbsolutePath() and sourceLocationPrefix(pref)
117-
|
118-
absPath = pref and result = ""
119-
or
120-
absPath = pref.regexpReplaceAll("/$", "") + "/" + result and
121-
not result.matches("/%")
122-
)
16+
class FolderBase extends ContainerBase, @folder {
17+
override string getAbsolutePath() { folders(this, result) }
12318
}
12419

125-
/**
126-
* Gets the stem of this container, that is, the prefix of its base name up to
127-
* (but not including) the last dot character if there is one, or the entire
128-
* base name if there is not.
129-
*
130-
* Here are some examples of absolute paths and the corresponding stems
131-
* (surrounded with quotes to avoid ambiguity):
132-
*
133-
* <table border="1">
134-
* <tr><th>Absolute path</th><th>Stem</th></tr>
135-
* <tr><td>"/tmp/tst.go"</td><td>"tst"</td></tr>
136-
* <tr><td>"/tmp/.classpath"</td><td>""</td></tr>
137-
* <tr><td>"/bin/bash"</td><td>"bash"</td></tr>
138-
* <tr><td>"/tmp/tst2."</td><td>"tst2"</td></tr>
139-
* <tr><td>"/tmp/x.tar.gz"</td><td>"x.tar"</td></tr>
140-
* </table>
141-
*/
142-
string getStem() {
143-
result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1)
20+
class FileBase extends ContainerBase, @file {
21+
override string getAbsolutePath() { files(this, result) }
14422
}
14523

146-
/**
147-
* Gets a URL representing the location of this container.
148-
*
149-
* For more information see https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/#providing-urls.
150-
*/
151-
abstract string getURL();
152-
153-
/**
154-
* Gets a textual representation of the path of this container.
155-
*
156-
* This is the absolute path of the container.
157-
*/
158-
string toString() { result = this.getAbsolutePath() }
24+
predicate hasSourceLocationPrefix = sourceLocationPrefix/1;
15925
}
16026

161-
/** A folder. */
162-
class Folder extends Container, @folder {
163-
override string getAbsolutePath() { folders(this, result) }
27+
private module Impl = Make<Input>;
16428

165-
/** Gets the URL of this folder. */
166-
override string getURL() { result = "folder://" + this.getAbsolutePath() }
167-
}
168-
169-
/** A file. */
170-
class File extends Container, @file {
171-
override string getAbsolutePath() { files(this, result) }
29+
class Container = Impl::Container;
17230

173-
/** Gets the URL of this file. */
174-
override string getURL() { result = "file://" + this.getAbsolutePath() + ":0:0:0:0" }
31+
class Folder = Impl::Folder;
17532

33+
/** A file. */
34+
class File extends Container, Impl::File {
17635
/** Gets a token in this file. */
17736
private QL::Token getAToken() { result.getLocation().getFile() = this }
17837

0 commit comments

Comments
 (0)