5
5
import semmle.code.cpp.Element
6
6
import semmle.code.cpp.Declaration
7
7
import semmle.code.cpp.metrics.MetricFile
8
+ private import codeql.util.FileSystem
8
9
9
- /** A file or folder. */
10
- class Container extends Locatable , @container {
11
- /**
12
- * Gets the absolute, canonical path of this container, using forward slashes
13
- * as path separator.
14
- *
15
- * The path starts with a _root prefix_ followed by zero or more _path
16
- * segments_ separated by forward slashes.
17
- *
18
- * The root prefix is of one of the following forms:
19
- *
20
- * 1. A single forward slash `/` (Unix-style)
21
- * 2. An upper-case drive letter followed by a colon and a forward slash,
22
- * such as `C:/` (Windows-style)
23
- * 3. Two forward slashes, a computer name, and then another forward slash,
24
- * such as `//FileServer/` (UNC-style)
25
- *
26
- * Path segments are never empty (that is, absolute paths never contain two
27
- * contiguous slashes, except as part of a UNC-style root prefix). Also, path
28
- * segments never contain forward slashes, and no path segment is of the
29
- * form `.` (one dot) or `..` (two dots).
30
- *
31
- * Note that an absolute path never ends with a forward slash, except if it is
32
- * a bare root prefix, that is, the path has no path segments. A container
33
- * whose absolute path has no segments is always a `Folder`, not a `File`.
34
- */
35
- string getAbsolutePath ( ) { none ( ) } // overridden by subclasses
10
+ private module Input implements InputSig {
11
+ abstract class ContainerBase extends @container {
12
+ abstract string getAbsolutePath ( ) ;
36
13
37
- /**
38
- * Gets the relative path of this file or folder from the root folder of the
39
- * analyzed source location. The relative path of the root folder itself is
40
- * the empty string.
41
- *
42
- * This has no result if the container is outside the source root, that is,
43
- * if the root folder is not a reflexive, transitive parent of this container.
44
- */
45
- string getRelativePath ( ) {
46
- exists ( string absPath , string pref |
47
- absPath = this .getAbsolutePath ( ) and sourceLocationPrefix ( pref )
48
- |
49
- absPath = pref and result = ""
50
- or
51
- absPath = pref .regexpReplaceAll ( "/$" , "" ) + "/" + result and
52
- not result .matches ( "/%" )
53
- )
54
- }
14
+ ContainerBase getParentContainer ( ) {
15
+ containerparent ( unresolveElement ( result ) , underlyingElement ( this ) )
16
+ }
55
17
56
- /**
57
- * Gets the base name of this container including extension, that is, the last
58
- * segment of its absolute path, or the empty string if it has no segments.
59
- *
60
- * Here are some examples of absolute paths and the corresponding base names
61
- * (surrounded with quotes to avoid ambiguity):
62
- *
63
- * <table border="1">
64
- * <tr><th>Absolute path</th><th>Base name</th></tr>
65
- * <tr><td>"/tmp/tst.js"</td><td>"tst.js"</td></tr>
66
- * <tr><td>"C:/Program Files (x86)"</td><td>"Program Files (x86)"</td></tr>
67
- * <tr><td>"/"</td><td>""</td></tr>
68
- * <tr><td>"C:/"</td><td>""</td></tr>
69
- * <tr><td>"D:/"</td><td>""</td></tr>
70
- * <tr><td>"//FileServer/"</td><td>""</td></tr>
71
- * </table>
72
- */
73
- string getBaseName ( ) {
74
- result = this .getAbsolutePath ( ) .regexpCapture ( ".*/(([^/]*?)(?:\\.([^.]*))?)" , 1 )
18
+ string toString ( ) { result = this .getAbsolutePath ( ) }
75
19
}
76
20
77
- /**
78
- * Gets the extension of this container, that is, the suffix of its base name
79
- * after the last dot character, if any.
80
- *
81
- * In particular,
82
- *
83
- * - if the name does not include a dot, there is no extension, so this
84
- * predicate has no result;
85
- * - if the name ends in a dot, the extension is the empty string;
86
- * - if the name contains multiple dots, the extension follows the last dot.
87
- *
88
- * Here are some examples of absolute paths and the corresponding extensions
89
- * (surrounded with quotes to avoid ambiguity):
90
- *
91
- * <table border="1">
92
- * <tr><th>Absolute path</th><th>Extension</th></tr>
93
- * <tr><td>"/tmp/tst.js"</td><td>"js"</td></tr>
94
- * <tr><td>"/tmp/.classpath"</td><td>"classpath"</td></tr>
95
- * <tr><td>"/bin/bash"</td><td>not defined</td></tr>
96
- * <tr><td>"/tmp/tst2."</td><td>""</td></tr>
97
- * <tr><td>"/tmp/x.tar.gz"</td><td>"gz"</td></tr>
98
- * </table>
99
- */
100
- string getExtension ( ) {
101
- result = this .getAbsolutePath ( ) .regexpCapture ( ".*/([^/]*?)(\\.([^.]*))?" , 3 )
102
- }
103
-
104
- /**
105
- * Gets the stem of this container, that is, the prefix of its base name up to
106
- * (but not including) the last dot character if there is one, or the entire
107
- * base name if there is not.
108
- *
109
- * Here are some examples of absolute paths and the corresponding stems
110
- * (surrounded with quotes to avoid ambiguity):
111
- *
112
- * <table border="1">
113
- * <tr><th>Absolute path</th><th>Stem</th></tr>
114
- * <tr><td>"/tmp/tst.js"</td><td>"tst"</td></tr>
115
- * <tr><td>"/tmp/.classpath"</td><td>""</td></tr>
116
- * <tr><td>"/bin/bash"</td><td>"bash"</td></tr>
117
- * <tr><td>"/tmp/tst2."</td><td>"tst2"</td></tr>
118
- * <tr><td>"/tmp/x.tar.gz"</td><td>"x.tar"</td></tr>
119
- * </table>
120
- */
121
- string getStem ( ) {
122
- result = this .getAbsolutePath ( ) .regexpCapture ( ".*/([^/]*?)(?:\\.([^.]*))?" , 1 )
123
- }
124
-
125
- /** Gets the parent container of this file or folder, if any. */
126
- Container getParentContainer ( ) {
127
- containerparent ( unresolveElement ( result ) , underlyingElement ( this ) )
21
+ class FolderBase extends ContainerBase , @folder {
22
+ override string getAbsolutePath ( ) { folders ( underlyingElement ( this ) , result ) }
128
23
}
129
24
130
- /** Gets a file or sub-folder in this container. */
131
- Container getAChildContainer ( ) { this = result .getParentContainer ( ) }
132
-
133
- /** Gets a file in this container. */
134
- File getAFile ( ) { result = this .getAChildContainer ( ) }
135
-
136
- /** Gets the file in this container that has the given `baseName`, if any. */
137
- File getFile ( string baseName ) {
138
- result = this .getAFile ( ) and
139
- result .getBaseName ( ) = baseName
25
+ class FileBase extends ContainerBase , @file {
26
+ override string getAbsolutePath ( ) { files ( underlyingElement ( this ) , result ) }
140
27
}
141
28
142
- /** Gets a sub-folder in this container. */
143
- Folder getAFolder ( ) { result = this . getAChildContainer ( ) }
29
+ predicate hasSourceLocationPrefix = sourceLocationPrefix / 1 ;
30
+ }
144
31
145
- /** Gets the sub-folder in this container that has the given `baseName`, if any. */
146
- Folder getFolder ( string baseName ) {
147
- result = this .getAFolder ( ) and
148
- result .getBaseName ( ) = baseName
149
- }
32
+ private module Impl = Make< Input > ;
150
33
151
- /**
152
- * Gets a textual representation of the path of this container.
153
- *
154
- * This is the absolute path of the container.
155
- */
156
- override string toString ( ) { result = this .getAbsolutePath ( ) }
34
+ /** A file or folder. */
35
+ class Container extends Locatable , Impl:: Container {
36
+ override string toString ( ) { result = Impl:: Container .super .toString ( ) }
157
37
}
158
38
159
39
/**
@@ -166,9 +46,7 @@ class Container extends Locatable, @container {
166
46
*
167
47
* To get the full path, use `getAbsolutePath`.
168
48
*/
169
- class Folder extends Container , @folder {
170
- override string getAbsolutePath ( ) { folders ( underlyingElement ( this ) , result ) }
171
-
49
+ class Folder extends Container , Impl:: Folder {
172
50
override Location getLocation ( ) {
173
51
result .getContainer ( ) = this and
174
52
result .hasLocationInfo ( _, 0 , 0 , 0 , 0 )
@@ -189,9 +67,7 @@ class Folder extends Container, @folder {
189
67
* The base name further decomposes into the _stem_ and _extension_ -- see
190
68
* `getStem` and `getExtension`. To get the full path, use `getAbsolutePath`.
191
69
*/
192
- class File extends Container , @file {
193
- override string getAbsolutePath ( ) { files ( underlyingElement ( this ) , result ) }
194
-
70
+ class File extends Container , Impl:: File {
195
71
override string getAPrimaryQlClass ( ) { result = "File" }
196
72
197
73
override Location getLocation ( ) {
0 commit comments