Skip to content

Commit f397ab2

Browse files
committed
Java: add diagnostic query indicating low database quality
1 parent 6c727b1 commit f397ab2

File tree

3 files changed

+106
-59
lines changed

3 files changed

+106
-59
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/**
2+
* Provides database quality statistics that are reported by java/telemetry/extractor-information
3+
* and perhaps warned about by java/diagnostics/database-quality.
4+
*/
5+
6+
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+
}
34+
35+
module CallTargetStats implements StatsSig {
36+
int getNumberOfOk() { result = count(Call c | exists(c.getCallee())) }
37+
38+
int getNumberOfNotOk() { result = count(Call c | not exists(c.getCallee())) }
39+
40+
string getOkText() { result = "calls with call target" }
41+
42+
string getNotOkText() { result = "calls with missing call target" }
43+
}
44+
45+
private class SourceExpr extends Expr {
46+
SourceExpr() { this.getFile().isSourceFile() }
47+
}
48+
49+
private predicate hasGoodType(Expr e) {
50+
exists(e.getType()) and not e.getType() instanceof ErrorType
51+
}
52+
53+
module ExprTypeStats implements StatsSig {
54+
int getNumberOfOk() { result = count(SourceExpr e | hasGoodType(e)) }
55+
56+
int getNumberOfNotOk() { result = count(SourceExpr e | not hasGoodType(e)) }
57+
58+
string getOkText() { result = "expressions with known type" }
59+
60+
string getNotOkText() { result = "expressions with unknown type" }
61+
}
62+
63+
module CallTargetStatsReport = ReportStats<CallTargetStats>;
64+
65+
module ExprTypeStatsReport = ReportStats<ExprTypeStats>;
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/**
2+
* @name Low Java analysis quality
3+
* @description Low Java analysis quality
4+
* @kind diagnostic
5+
* @id java/diagnostic/database-quality
6+
*/
7+
8+
import java
9+
import DatabaseQuality
10+
11+
private newtype TDbQualityDiagnostic =
12+
TTheDbQualityDiagnostic() {
13+
exists(float percentageGood |
14+
CallTargetStatsReport::percentageOfOk(_, percentageGood)
15+
or
16+
ExprTypeStatsReport::percentageOfOk(_, percentageGood)
17+
|
18+
percentageGood < 95
19+
)
20+
}
21+
22+
class DbQualityDiagnostic extends TDbQualityDiagnostic {
23+
string toString() {
24+
result =
25+
"There were significant issues scanning Java code. " +
26+
"This may be caused by problems identifying dependencies or use of generated source code, among other reasons -- "
27+
+ "see other CodeQL diagnostics reported here for more details of possible causes. " +
28+
"This may lead to false-positive or missing results. Consider analysing Java using the `autobuild` or `manual` build modes."
29+
}
30+
}
31+
32+
query predicate diagnosticAttributes(DbQualityDiagnostic e, string key, string value) {
33+
e = e and // Quieten warning about unconstrained 'e'
34+
key = ["visibilityCliSummaryTable", "visibilityTelemetry", "visibilityStatusPage"] and
35+
value = "true"
36+
}
37+
38+
from DbQualityDiagnostic d
39+
select d, d.toString(), 1
40+
/* Warning severity */

java/ql/src/Telemetry/ExtractorInformation.ql

Lines changed: 1 addition & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
import java
1010
import semmle.code.java.Diagnostics
11+
import DatabaseQuality
1112

1213
extensible predicate extractorInformationSkipKey(string key);
1314

@@ -85,65 +86,6 @@ predicate extractorTotalDiagnostics(string key, int value) {
8586
)
8687
}
8788

88-
signature module StatsSig {
89-
int getNumberOfOk();
90-
91-
int getNumberOfNotOk();
92-
93-
string getOkText();
94-
95-
string getNotOkText();
96-
}
97-
98-
module ReportStats<StatsSig Stats> {
99-
predicate numberOfOk(string key, int value) {
100-
value = Stats::getNumberOfOk() and
101-
key = "Number of " + Stats::getOkText()
102-
}
103-
104-
predicate numberOfNotOk(string key, int value) {
105-
value = Stats::getNumberOfNotOk() and
106-
key = "Number of " + Stats::getNotOkText()
107-
}
108-
109-
predicate percentageOfOk(string key, float value) {
110-
value = Stats::getNumberOfOk() * 100.0 / (Stats::getNumberOfOk() + Stats::getNumberOfNotOk()) and
111-
key = "Percentage of " + Stats::getOkText()
112-
}
113-
}
114-
115-
module CallTargetStats implements StatsSig {
116-
int getNumberOfOk() { result = count(Call c | exists(c.getCallee())) }
117-
118-
int getNumberOfNotOk() { result = count(Call c | not exists(c.getCallee())) }
119-
120-
string getOkText() { result = "calls with call target" }
121-
122-
string getNotOkText() { result = "calls with missing call target" }
123-
}
124-
125-
private class SourceExpr extends Expr {
126-
SourceExpr() { this.getFile().isSourceFile() }
127-
}
128-
129-
private predicate hasGoodType(Expr e) {
130-
exists(e.getType()) and not e.getType() instanceof ErrorType
131-
}
132-
133-
module ExprTypeStats implements StatsSig {
134-
int getNumberOfOk() { result = count(SourceExpr e | hasGoodType(e)) }
135-
136-
int getNumberOfNotOk() { result = count(SourceExpr e | not hasGoodType(e)) }
137-
138-
string getOkText() { result = "expressions with known type" }
139-
140-
string getNotOkText() { result = "expressions with unknown type" }
141-
}
142-
143-
module CallTargetStatsReport = ReportStats<CallTargetStats>;
144-
145-
module ExprTypeStatsReport = ReportStats<ExprTypeStats>;
146-
14789
from string key, int value
14890
where
14991
not exists(string pattern | extractorInformationSkipKey(pattern) and key.matches(pattern)) and

0 commit comments

Comments
 (0)