@@ -15,11 +15,64 @@ class File extends Generated::File {
1515 /** Gets the URL of this file. */
1616 string getURL ( ) { result = "file://" + this .getAbsolutePath ( ) + ":0:0:0:0" }
1717
18- /** Gets the base name of this file. */
19- string getBaseName ( ) {
20- result = this .getAbsolutePath ( ) .regexpCapture ( ".*/(([^/]*?)(?:\\.([^.]*))?)" , 1 )
18+ /**
19+ * Holds if either,
20+ * - `part` is the base name of this container and `i = 1`, or
21+ * - `part` is the stem of this container and `i = 2`, or
22+ * - `part` is the extension of this container and `i = 3`.
23+ */
24+ cached
25+ private predicate splitAbsolutePath ( string part , int i ) {
26+ part = this .getAbsolutePath ( ) .regexpCapture ( ".*/(([^/]*?)(?:\\.([^.]*))?)" , i )
2127 }
2228
29+ /** Gets the base name of this file. */
30+ string getBaseName ( ) { this .splitAbsolutePath ( result , 1 ) }
31+
32+ /**
33+ * Gets the extension of this container, that is, the suffix of its base name
34+ * after the last dot character, if any.
35+ *
36+ * In particular,
37+ *
38+ * - if the name does not include a dot, there is no extension, so this
39+ * predicate has no result;
40+ * - if the name ends in a dot, the extension is the empty string;
41+ * - if the name contains multiple dots, the extension follows the last dot.
42+ *
43+ * Here are some examples of absolute paths and the corresponding extensions
44+ * (surrounded with quotes to avoid ambiguity):
45+ *
46+ * <table border="1">
47+ * <tr><th>Absolute path</th><th>Extension</th></tr>
48+ * <tr><td>"/tmp/tst.txt"</td><td>"txt"</td></tr>
49+ * <tr><td>"/tmp/.classpath"</td><td>"classpath"</td></tr>
50+ * <tr><td>"/bin/bash"</td><td>not defined</td></tr>
51+ * <tr><td>"/tmp/tst2."</td><td>""</td></tr>
52+ * <tr><td>"/tmp/x.tar.gz"</td><td>"gz"</td></tr>
53+ * </table>
54+ */
55+ string getExtension ( ) { this .splitAbsolutePath ( result , 3 ) }
56+
57+ /**
58+ * Gets the stem of this container, that is, the prefix of its base name up to
59+ * (but not including) the last dot character if there is one, or the entire
60+ * base name if there is not.
61+ *
62+ * Here are some examples of absolute paths and the corresponding stems
63+ * (surrounded with quotes to avoid ambiguity):
64+ *
65+ * <table border="1">
66+ * <tr><th>Absolute path</th><th>Stem</th></tr>
67+ * <tr><td>"/tmp/tst.txt"</td><td>"tst"</td></tr>
68+ * <tr><td>"/tmp/.classpath"</td><td>""</td></tr>
69+ * <tr><td>"/bin/bash"</td><td>"bash"</td></tr>
70+ * <tr><td>"/tmp/tst2."</td><td>"tst2"</td></tr>
71+ * <tr><td>"/tmp/x.tar.gz"</td><td>"x.tar"</td></tr>
72+ * </table>
73+ */
74+ string getStem ( ) { this .splitAbsolutePath ( result , 2 ) }
75+
2376 /**
2477 * Gets the number of lines containing code in this file. This value
2578 * is approximate.
0 commit comments