-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
Copy pathMetrics.qll
269 lines (198 loc) · 7.16 KB
/
Metrics.qll
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
import cpp
import Diagnostics
/**
* A metric is a string with a value.
*/
abstract class Metric extends string {
bindingset[this]
Metric() { any() }
}
/**
* A metric that we want to report in cpp/telemetry/extraction-metrics
*/
abstract class ExtractionMetric extends Metric {
bindingset[this]
ExtractionMetric() { any() }
/** Gets the value of this metric. */
abstract int getValue();
}
/**
* A metric that provides a baseline for a SuccessMetric.
*/
abstract class BaseMetric extends ExtractionMetric {
bindingset[this]
BaseMetric() { any() }
}
/**
* A metric that is relative to another metric,
* so can be used to calculate percentages.
*
* For clarity, metrics should express success,
* so higher values means better.
*/
abstract class SuccessMetric extends ExtractionMetric {
bindingset[this]
SuccessMetric() { any() }
/** Gets the metric this is relative to. */
abstract BaseMetric getBaseline();
}
/**
* A metric used to report database quality.
*/
class QualityMetric extends Metric {
BaseMetric baseMetric;
SuccessMetric relativeMetric;
QualityMetric() {
baseMetric = relativeMetric.getBaseline() and this = "Percentage of " + relativeMetric
}
float getValue() {
baseMetric.getValue() > 0 and
result = 100.0 * relativeMetric.getValue() / baseMetric.getValue()
}
}
signature class RankedMetric extends Metric {
int getValue();
}
module RankMetric<RankedMetric M> {
int getRank(M s) { s = rank[result](M m | | m order by m.getValue() desc) }
}
/** Various metrics we want to report. */
module CppMetrics {
class Compilations extends BaseMetric {
Compilations() { this = "compilations" }
override int getValue() { result = count(Compilation c) }
}
class SourceAndHeaderFiles extends BaseMetric {
SourceAndHeaderFiles() { this = "source/header files" }
override int getValue() { result = count(File f | f.fromSource()) }
}
class SourceAndHeaderFilesWithoutErrors extends SuccessMetric {
SourceAndHeaderFilesWithoutErrors() { this = "source/header files without errors" }
override int getValue() {
result = count(File f | f.fromSource() and not exists(CompilerError e | f = e.getFile()))
}
override SourceAndHeaderFiles getBaseline() { any() }
}
class CompilationsWithoutErrors extends SuccessMetric {
CompilationsWithoutErrors() { this = "compilations without errors" }
override int getValue() {
result = count(Compilation c | not exists(Diagnostic d | d.getFile() = c.getAFileCompiled()))
}
override Compilations getBaseline() { any() }
}
class Expressions extends BaseMetric {
Expressions() { this = "expressions" }
override int getValue() { result = count(Expr e) }
}
class SucceededExpressions extends SuccessMetric {
SucceededExpressions() { this = "non-error expressions" }
override int getValue() { result = count(Expr e) - count(ErrorExpr e) }
override Expressions getBaseline() { any() }
}
class TypedExpressions extends SuccessMetric {
TypedExpressions() { this = "expressions with a known type" }
override int getValue() { result = count(Expr e | not e.getType() instanceof ErroneousType) }
override Expressions getBaseline() { any() }
}
class Calls extends BaseMetric {
Calls() { this = "calls" }
override int getValue() { result = count(Call c) }
}
class CallsWithExplicitTarget extends SuccessMetric {
CallsWithExplicitTarget() { this = "calls with an explicit target" }
override int getValue() {
result = count(Call c | not c.getTarget().getADeclarationEntry().isImplicit())
}
override Calls getBaseline() { any() }
}
class Variables extends BaseMetric {
Variables() { this = "variables" }
override int getValue() { result = count(Variable v) }
}
class VariablesKnownType extends SuccessMetric {
VariablesKnownType() { this = "variables with a known type" }
override int getValue() {
result = count(Variable v | not v.getType() instanceof ErroneousType)
}
override Variables getBaseline() { any() }
}
class LinesOfText extends BaseMetric {
LinesOfText() { this = "lines of text" }
override int getValue() { result = sum(File f | | f.getMetrics().getNumberOfLines()) }
}
class LinesOfCode extends BaseMetric {
LinesOfCode() { this = "lines of code" }
override int getValue() { result = sum(File f | | f.getMetrics().getNumberOfLinesOfCode()) }
}
private predicate errorLine(File file, int line) {
exists(Locatable l, Location loc |
loc = l.getLocation() and
loc.getFile() = file and
line in [loc.getStartLine() .. loc.getEndLine()]
|
l instanceof Diagnostic
or
l instanceof ErrorExpr
)
}
class SucceededLines extends SuccessMetric {
SucceededLines() { this = "lines of code without errors" }
override int getValue() {
result =
sum(File f | | f.getMetrics().getNumberOfLinesOfCode()) -
count(File f, int line | errorLine(f, line))
}
override LinesOfCode getBaseline() { any() }
}
class Functions extends BaseMetric {
Functions() { this = "functions" }
override int getValue() { result = count(Function f) }
}
class SucceededFunctions extends SuccessMetric {
SucceededFunctions() { this = "functions without errors" }
override int getValue() { result = count(Function f | not f.hasErrors()) }
override Functions getBaseline() { any() }
}
class Includes extends BaseMetric {
Includes() { this = "#include directives" }
override int getValue() { result = count(Include i) + count(CannotOpenFileError e) }
}
class SucceededIncludes extends SuccessMetric {
SucceededIncludes() { this = "successfully resolved #include directives" }
override int getValue() { result = count(Include i) }
override Includes getBaseline() { any() }
}
class SucceededIncludeCount extends Metric {
string includeText;
SucceededIncludeCount() {
exists(Include i |
i.getIncludeText() = includeText and
exists(i.getFile().getRelativePath()) // Only report includes from the repo
) and
this = "Successfully included " + includeText
}
int getValue() { result = count(Include i | i.getIncludeText() = includeText) }
string getIncludeText() { result = includeText }
}
class MissingIncludeCount extends Metric {
string includeText;
MissingIncludeCount() {
exists(CannotOpenFileError e | e.getIncludedFile() = includeText) and
this = "Failed to include '" + includeText + "'"
}
int getValue() { result = count(CannotOpenFileError e | e.getIncludedFile() = includeText) }
string getIncludeText() { result = includeText }
}
class CompilerErrors extends ExtractionMetric {
CompilerErrors() { this = "compiler errors" }
override int getValue() { result = count(CompilerError e) }
}
class ErrorCount extends Metric {
ErrorCount() { exists(CompilerError e | e.getMessage() = this) }
int getValue() { result = count(CompilerError e | e.getMessage() = this) }
}
class SyntaxErrorCount extends ExtractionMetric {
SyntaxErrorCount() { this = "syntax errors" }
override int getValue() { result = count(SyntaxError e) }
}
}