-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathFileSystem.qll
More file actions
121 lines (102 loc) · 3.6 KB
/
FileSystem.qll
File metadata and controls
121 lines (102 loc) · 3.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/** Provides classes for working with files and folders. */
private import codeql.Locations
private import codeql.util.FileSystem
private import codeql.rust.elements.SourceFile
private import codeql.rust.elements.AstNode
private import codeql.rust.elements.Comment
private import codeql.rust.Diagnostics
private import codeql.rust.elements.internal.ExtractorStep
private module Input implements InputSig {
abstract class ContainerBase extends @container {
abstract string getAbsolutePath();
ContainerBase getParentContainer() { containerparent(result, this) }
string toString() { result = this.getAbsolutePath() }
}
class FolderBase extends ContainerBase, @folder {
override string getAbsolutePath() { folders(this, result) }
}
class FileBase extends ContainerBase, @file {
override string getAbsolutePath() { files(this, result) }
}
predicate hasSourceLocationPrefix = sourceLocationPrefix/1;
}
private module Impl = Make<Input>;
class Container = Impl::Container;
class Folder = Impl::Folder;
module Folder = Impl::Folder;
/**
* Holds if the file identified by `relativePath` should be treated as though it is external
* to the target project, even though it is within the source code directory. This is used for
* testing.
*/
extensible predicate additionalExternalFile(string relativePath);
/** A file. */
class File extends Container, Impl::File {
/**
* Holds if this file was extracted from the source code of the target project
* (rather than another location such as inside a dependency).
*/
predicate fromSource() {
exists(ExtractorStep s | s.getAction() = "Extract" and s.getFile() = this) and
not additionalExternalFile(this.getRelativePath())
}
/**
* Gets the number of lines containing code in this file. This value
* is approximate.
*/
int getNumberOfLinesOfCode() {
result =
count(int line |
exists(AstNode node, Location loc |
not node instanceof Comment and
not node instanceof SourceFile and
loc = node.getLocation()
|
node.getFile() = this and
line = [/*loc.getStartLine(), */ loc.getEndLine()] and // ignore start locations for now as we're getting them wrong for things with a comment attached
not loc instanceof EmptyLocation and
line > 0
)
)
}
}
/**
* A source file that was extracted.
*
* TODO: rename `SourceFile` from the generated AST to give that name to this class.
*/
class ExtractedFile extends File {
ExtractedFile() { this.fromSource() }
private Diagnostic getNoSemanticsDiagnostic() {
result.getTag() = "semantics" and result.getLocation().getFile() = this
}
/**
* Holds if we have semantical information about this file, which means
* we should be able to
* * expand any macros
* * skip any blocks that are conditionally compiled out
*/
predicate hasSemantics() { not exists(this.getNoSemanticsDiagnostic()) }
/**
* Holds if we know this file was skipped by conditional compilation.
* This is not the same as `not this.hasSemantics()`, as a file
* might not have semantics because of some error.
*/
predicate isSkippedByCompilation() { this.getNoSemanticsDiagnostic().getSeverityText() = "Info" }
}
/**
* A successfully extracted file, that is, a file that was extracted and
* contains no extraction errors or warnings.
*/
class SuccessfullyExtractedFile extends ExtractedFile {
SuccessfullyExtractedFile() {
not exists(Diagnostic d |
d.getLocation().getFile() = this and
(
d instanceof ExtractionError
or
d instanceof ExtractionWarning
)
)
}
}