Skip to content

Commit 614b3ce

Browse files
authored
Merge pull request #18697 from hvitved/rust/telemetry
Rust: Implement database quality telemetry query
2 parents b5c0754 + 11bf4c8 commit 614b3ce

File tree

6 files changed

+185
-54
lines changed

6 files changed

+185
-54
lines changed

csharp/ql/src/Telemetry/DatabaseQuality.qll

+1-27
Original file line numberDiff line numberDiff line change
@@ -4,33 +4,7 @@
44
*/
55

66
import csharp
7-
8-
signature module StatsSig {
9-
int getNumberOfOk();
10-
11-
int getNumberOfNotOk();
12-
13-
string getOkText();
14-
15-
string getNotOkText();
16-
}
17-
18-
module ReportStats<StatsSig Stats> {
19-
predicate numberOfOk(string key, int value) {
20-
value = Stats::getNumberOfOk() and
21-
key = "Number of " + Stats::getOkText()
22-
}
23-
24-
predicate numberOfNotOk(string key, int value) {
25-
value = Stats::getNumberOfNotOk() and
26-
key = "Number of " + Stats::getNotOkText()
27-
}
28-
29-
predicate percentageOfOk(string key, float value) {
30-
value = Stats::getNumberOfOk() * 100.0 / (Stats::getNumberOfOk() + Stats::getNumberOfNotOk()) and
31-
key = "Percentage of " + Stats::getOkText()
32-
}
33-
}
7+
import codeql.util.ReportStats
348

359
module CallTargetStats implements StatsSig {
3610
int getNumberOfOk() { result = count(Call c | exists(c.getTarget())) }

java/ql/src/Telemetry/DatabaseQuality.qll

+1-27
Original file line numberDiff line numberDiff line change
@@ -4,33 +4,7 @@
44
*/
55

66
import java
7-
8-
signature module StatsSig {
9-
int getNumberOfOk();
10-
11-
int getNumberOfNotOk();
12-
13-
string getOkText();
14-
15-
string getNotOkText();
16-
}
17-
18-
module ReportStats<StatsSig Stats> {
19-
predicate numberOfOk(string key, int value) {
20-
value = Stats::getNumberOfOk() and
21-
key = "Number of " + Stats::getOkText()
22-
}
23-
24-
predicate numberOfNotOk(string key, int value) {
25-
value = Stats::getNumberOfNotOk() and
26-
key = "Number of " + Stats::getNotOkText()
27-
}
28-
29-
predicate percentageOfOk(string key, float value) {
30-
value = Stats::getNumberOfOk() * 100.0 / (Stats::getNumberOfOk() + Stats::getNumberOfNotOk()) and
31-
key = "Percentage of " + Stats::getOkText()
32-
}
33-
}
7+
import codeql.util.ReportStats
348

359
module CallTargetStats implements StatsSig {
3610
int getNumberOfOk() { result = count(Call c | exists(c.getCallee())) }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* Provides database quality statistics that are reported by
3+
* `rust/telemetry/extractor-information`
4+
* and perhaps warned about by `rust/diagnostics/database-quality`.
5+
*/
6+
7+
import rust
8+
import codeql.util.ReportStats
9+
10+
module CallTargetStats implements StatsSig {
11+
int getNumberOfOk() { result = count(CallExprBase c | exists(c.getStaticTarget())) }
12+
13+
private predicate isLambdaCall(CallExpr call) {
14+
exists(Expr receiver | receiver = call.getFunction() |
15+
// All calls to complex expressions and local variable accesses are lambda calls
16+
receiver instanceof PathExpr implies receiver = any(Variable v).getAnAccess()
17+
)
18+
}
19+
20+
additional predicate isNotOkCall(CallExprBase c) {
21+
not exists(c.getStaticTarget()) and
22+
not isLambdaCall(c)
23+
}
24+
25+
int getNumberOfNotOk() { result = count(CallExprBase c | isNotOkCall(c)) }
26+
27+
string getOkText() { result = "calls with call target" }
28+
29+
string getNotOkText() { result = "calls with missing call target" }
30+
}
31+
32+
module MacroCallTargetStats implements StatsSig {
33+
int getNumberOfOk() { result = count(MacroCall c | c.hasExpanded()) }
34+
35+
additional predicate isNotOkCall(MacroCall c) { not c.hasExpanded() }
36+
37+
int getNumberOfNotOk() { result = count(MacroCall c | isNotOkCall(c)) }
38+
39+
string getOkText() { result = "macro calls with call target" }
40+
41+
string getNotOkText() { result = "macro calls with missing call target" }
42+
}
43+
44+
module CallTargetStatsReport = ReportStats<CallTargetStats>;
45+
46+
module MacroCallTargetStatsReport = ReportStats<MacroCallTargetStats>;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/**
2+
* @name Low Rust analysis quality
3+
* @description Low Rust analysis quality
4+
* @kind diagnostic
5+
* @id rust/diagnostic/database-quality
6+
*/
7+
8+
import rust
9+
import DatabaseQuality
10+
import codeql.util.Unit
11+
12+
class DbQualityDiagnostic extends Unit {
13+
DbQualityDiagnostic() {
14+
exists(float percentageGood |
15+
CallTargetStatsReport::percentageOfOk(_, percentageGood)
16+
or
17+
MacroCallTargetStatsReport::percentageOfOk(_, percentageGood)
18+
|
19+
percentageGood < 95
20+
)
21+
}
22+
23+
string toString() {
24+
result =
25+
"Scanning Rust code completed successfully, but the scan encountered issues. " +
26+
"This may be caused by problems identifying dependencies or use of generated source code, among other reasons -- "
27+
+
28+
"see other CodeQL diagnostics reported on the CodeQL status page for more details of possible causes. "
29+
+ "Addressing these warnings is advisable to avoid false-positive or missing results."
30+
}
31+
}
32+
33+
query predicate diagnosticAttributes(DbQualityDiagnostic e, string key, string value) {
34+
exists(e) and // Quieten warning about unconstrained 'e'
35+
key = ["visibilityCliSummaryTable", "visibilityTelemetry", "visibilityStatusPage"] and
36+
value = "true"
37+
}
38+
39+
from DbQualityDiagnostic d
40+
select d, d.toString(), 1
41+
/* 1 = Warning severity */
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/**
2+
* @name Rust extraction information
3+
* @description Information about the extraction for a Rust database
4+
* @kind metric
5+
* @tags summary telemetry
6+
* @id rust/telemetry/extraction-information
7+
*/
8+
9+
import rust
10+
import DatabaseQuality
11+
import codeql.rust.Diagnostics
12+
13+
predicate fileCount(string key, int value) {
14+
key = "Number of files" and
15+
value = strictcount(File f)
16+
}
17+
18+
predicate fileCountByExtension(string key, int value) {
19+
exists(string extension |
20+
key = "Number of files with extension " + extension and
21+
value = strictcount(File f | f.getExtension() = extension)
22+
)
23+
}
24+
25+
predicate numberOfLinesOfCode(string key, int value) {
26+
key = "Number of lines of code" and
27+
value = strictsum(File f | any() | f.getNumberOfLinesOfCode())
28+
}
29+
30+
predicate numberOfLinesOfCodeByExtension(string key, int value) {
31+
exists(string extension |
32+
key = "Number of lines of code with extension " + extension and
33+
value = strictsum(File f | f.getExtension() = extension | f.getNumberOfLinesOfCode())
34+
)
35+
}
36+
37+
predicate extractorDiagnostics(string key, int value) {
38+
exists(int severity |
39+
key = "Number of diagnostics with severity " + severity.toString() and
40+
value = strictcount(Diagnostic d | d.getSeverity() = severity)
41+
)
42+
}
43+
44+
from string key, float value
45+
where
46+
(
47+
fileCount(key, value) or
48+
fileCountByExtension(key, value) or
49+
numberOfLinesOfCode(key, value) or
50+
numberOfLinesOfCodeByExtension(key, value) or
51+
extractorDiagnostics(key, value) or
52+
CallTargetStatsReport::numberOfOk(key, value) or
53+
CallTargetStatsReport::numberOfNotOk(key, value) or
54+
CallTargetStatsReport::percentageOfOk(key, value) or
55+
MacroCallTargetStatsReport::numberOfOk(key, value) or
56+
MacroCallTargetStatsReport::numberOfNotOk(key, value) or
57+
MacroCallTargetStatsReport::percentageOfOk(key, value)
58+
) and
59+
/* Infinity */
60+
value != 1.0 / 0.0 and
61+
/* -Infinity */
62+
value != -1.0 / 0.0 and
63+
/* NaN */
64+
value != 0.0 / 0.0
65+
select key, value
+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* Provides the `ReportStats` module for reporting database quality statistics.
3+
*/
4+
module;
5+
6+
signature module StatsSig {
7+
int getNumberOfOk();
8+
9+
int getNumberOfNotOk();
10+
11+
string getOkText();
12+
13+
string getNotOkText();
14+
}
15+
16+
module ReportStats<StatsSig Stats> {
17+
predicate numberOfOk(string key, int value) {
18+
value = Stats::getNumberOfOk() and
19+
key = "Number of " + Stats::getOkText()
20+
}
21+
22+
predicate numberOfNotOk(string key, int value) {
23+
value = Stats::getNumberOfNotOk() and
24+
key = "Number of " + Stats::getNotOkText()
25+
}
26+
27+
predicate percentageOfOk(string key, float value) {
28+
value = Stats::getNumberOfOk() * 100.0 / (Stats::getNumberOfOk() + Stats::getNumberOfNotOk()) and
29+
key = "Percentage of " + Stats::getOkText()
30+
}
31+
}

0 commit comments

Comments
 (0)