mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Rust: Implement database quality telemetry query
This commit is contained in:
@@ -4,33 +4,7 @@
|
||||
*/
|
||||
|
||||
import csharp
|
||||
|
||||
signature module StatsSig {
|
||||
int getNumberOfOk();
|
||||
|
||||
int getNumberOfNotOk();
|
||||
|
||||
string getOkText();
|
||||
|
||||
string getNotOkText();
|
||||
}
|
||||
|
||||
module ReportStats<StatsSig Stats> {
|
||||
predicate numberOfOk(string key, int value) {
|
||||
value = Stats::getNumberOfOk() and
|
||||
key = "Number of " + Stats::getOkText()
|
||||
}
|
||||
|
||||
predicate numberOfNotOk(string key, int value) {
|
||||
value = Stats::getNumberOfNotOk() and
|
||||
key = "Number of " + Stats::getNotOkText()
|
||||
}
|
||||
|
||||
predicate percentageOfOk(string key, float value) {
|
||||
value = Stats::getNumberOfOk() * 100.0 / (Stats::getNumberOfOk() + Stats::getNumberOfNotOk()) and
|
||||
key = "Percentage of " + Stats::getOkText()
|
||||
}
|
||||
}
|
||||
import codeql.util.ReportStats
|
||||
|
||||
module CallTargetStats implements StatsSig {
|
||||
int getNumberOfOk() { result = count(Call c | exists(c.getTarget())) }
|
||||
|
||||
@@ -4,33 +4,7 @@
|
||||
*/
|
||||
|
||||
import java
|
||||
|
||||
signature module StatsSig {
|
||||
int getNumberOfOk();
|
||||
|
||||
int getNumberOfNotOk();
|
||||
|
||||
string getOkText();
|
||||
|
||||
string getNotOkText();
|
||||
}
|
||||
|
||||
module ReportStats<StatsSig Stats> {
|
||||
predicate numberOfOk(string key, int value) {
|
||||
value = Stats::getNumberOfOk() and
|
||||
key = "Number of " + Stats::getOkText()
|
||||
}
|
||||
|
||||
predicate numberOfNotOk(string key, int value) {
|
||||
value = Stats::getNumberOfNotOk() and
|
||||
key = "Number of " + Stats::getNotOkText()
|
||||
}
|
||||
|
||||
predicate percentageOfOk(string key, float value) {
|
||||
value = Stats::getNumberOfOk() * 100.0 / (Stats::getNumberOfOk() + Stats::getNumberOfNotOk()) and
|
||||
key = "Percentage of " + Stats::getOkText()
|
||||
}
|
||||
}
|
||||
import codeql.util.ReportStats
|
||||
|
||||
module CallTargetStats implements StatsSig {
|
||||
int getNumberOfOk() { result = count(Call c | exists(c.getCallee())) }
|
||||
|
||||
46
rust/ql/src/queries/telemetry/DatabaseQuality.qll
Normal file
46
rust/ql/src/queries/telemetry/DatabaseQuality.qll
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* Provides database quality statistics that are reported by
|
||||
* `rust/telemetry/extractor-information`
|
||||
* and perhaps warned about by `rust/diagnostics/database-quality`.
|
||||
*/
|
||||
|
||||
import rust
|
||||
import codeql.util.ReportStats
|
||||
|
||||
module CallTargetStats implements StatsSig {
|
||||
int getNumberOfOk() { result = count(CallExprBase c | exists(c.getStaticTarget())) }
|
||||
|
||||
private predicate isLambdaCall(CallExpr call) {
|
||||
exists(Expr receiver | receiver = call.getFunction() |
|
||||
// All calls to complex expressions and local variable accesses are lambda calls
|
||||
receiver instanceof PathExpr implies receiver = any(Variable v).getAnAccess()
|
||||
)
|
||||
}
|
||||
|
||||
additional predicate isNotOkCall(CallExprBase c) {
|
||||
not exists(c.getStaticTarget()) and
|
||||
not isLambdaCall(c)
|
||||
}
|
||||
|
||||
int getNumberOfNotOk() { result = count(CallExprBase c | isNotOkCall(c)) }
|
||||
|
||||
string getOkText() { result = "calls with call target" }
|
||||
|
||||
string getNotOkText() { result = "calls with missing call target" }
|
||||
}
|
||||
|
||||
module MacroCallTargetStats implements StatsSig {
|
||||
int getNumberOfOk() { result = count(MacroCall c | c.hasExpanded()) }
|
||||
|
||||
additional predicate isNotOkCall(MacroCall c) { not c.hasExpanded() }
|
||||
|
||||
int getNumberOfNotOk() { result = count(MacroCall c | isNotOkCall(c)) }
|
||||
|
||||
string getOkText() { result = "macro calls with call target" }
|
||||
|
||||
string getNotOkText() { result = "macro calls with missing call target" }
|
||||
}
|
||||
|
||||
module CallTargetStatsReport = ReportStats<CallTargetStats>;
|
||||
|
||||
module MacroCallTargetStatsReport = ReportStats<MacroCallTargetStats>;
|
||||
41
rust/ql/src/queries/telemetry/DatabaseQualityDiagnostics.ql
Normal file
41
rust/ql/src/queries/telemetry/DatabaseQualityDiagnostics.ql
Normal file
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* @name Low Rust analysis quality
|
||||
* @description Low Rust analysis quality
|
||||
* @kind diagnostic
|
||||
* @id rust/diagnostic/database-quality
|
||||
*/
|
||||
|
||||
import rust
|
||||
import DatabaseQuality
|
||||
import codeql.util.Unit
|
||||
|
||||
class DbQualityDiagnostic extends Unit {
|
||||
DbQualityDiagnostic() {
|
||||
exists(float percentageGood |
|
||||
CallTargetStatsReport::percentageOfOk(_, percentageGood)
|
||||
or
|
||||
MacroCallTargetStatsReport::percentageOfOk(_, percentageGood)
|
||||
|
|
||||
percentageGood < 95
|
||||
)
|
||||
}
|
||||
|
||||
string toString() {
|
||||
result =
|
||||
"Scanning Rust code completed successfully, but the scan encountered issues. " +
|
||||
"This may be caused by problems identifying dependencies or use of generated source code, among other reasons -- "
|
||||
+
|
||||
"see other CodeQL diagnostics reported on the CodeQL status page for more details of possible causes. "
|
||||
+ "Addressing these warnings is advisable to avoid false-positive or missing results."
|
||||
}
|
||||
}
|
||||
|
||||
query predicate diagnosticAttributes(DbQualityDiagnostic e, string key, string value) {
|
||||
exists(e) and // Quieten warning about unconstrained 'e'
|
||||
key = ["visibilityCliSummaryTable", "visibilityTelemetry", "visibilityStatusPage"] and
|
||||
value = "true"
|
||||
}
|
||||
|
||||
from DbQualityDiagnostic d
|
||||
select d, d.toString(), 1
|
||||
/* Warning severity */
|
||||
65
rust/ql/src/queries/telemetry/ExtractorInformation.ql
Normal file
65
rust/ql/src/queries/telemetry/ExtractorInformation.ql
Normal file
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* @name Rust extraction information
|
||||
* @description Information about the extraction for a Rust database
|
||||
* @kind metric
|
||||
* @tags summary telemetry
|
||||
* @id rust/telemetry/extraction-information
|
||||
*/
|
||||
|
||||
import rust
|
||||
import DatabaseQuality
|
||||
import codeql.rust.Diagnostics
|
||||
|
||||
predicate fileCount(string key, int value) {
|
||||
key = "Number of files" and
|
||||
value = strictcount(File f)
|
||||
}
|
||||
|
||||
predicate fileCountByExtension(string key, int value) {
|
||||
exists(string extension |
|
||||
key = "Number of files with extension " + extension and
|
||||
value = strictcount(File f | f.getExtension() = extension)
|
||||
)
|
||||
}
|
||||
|
||||
predicate numberOfLinesOfCode(string key, int value) {
|
||||
key = "Number of lines of code" and
|
||||
value = strictsum(File f | any() | f.getNumberOfLinesOfCode())
|
||||
}
|
||||
|
||||
predicate numberOfLinesOfCodeByExtension(string key, int value) {
|
||||
exists(string extension |
|
||||
key = "Number of lines of code with extension " + extension and
|
||||
value = strictsum(File f | f.getExtension() = extension | f.getNumberOfLinesOfCode())
|
||||
)
|
||||
}
|
||||
|
||||
predicate extractorDiagnostics(string key, int value) {
|
||||
exists(int severity |
|
||||
key = "Number of diagnostics with severity " + severity.toString() and
|
||||
value = strictcount(Diagnostic d | d.getSeverity() = severity)
|
||||
)
|
||||
}
|
||||
|
||||
from string key, float value
|
||||
where
|
||||
(
|
||||
fileCount(key, value) or
|
||||
fileCountByExtension(key, value) or
|
||||
numberOfLinesOfCode(key, value) or
|
||||
numberOfLinesOfCodeByExtension(key, value) or
|
||||
extractorDiagnostics(key, value) or
|
||||
CallTargetStatsReport::numberOfOk(key, value) or
|
||||
CallTargetStatsReport::numberOfNotOk(key, value) or
|
||||
CallTargetStatsReport::percentageOfOk(key, value) or
|
||||
MacroCallTargetStatsReport::numberOfOk(key, value) or
|
||||
MacroCallTargetStatsReport::numberOfNotOk(key, value) or
|
||||
MacroCallTargetStatsReport::percentageOfOk(key, value)
|
||||
) and
|
||||
/* Infinity */
|
||||
value != 1.0 / 0.0 and
|
||||
/* -Infinity */
|
||||
value != -1.0 / 0.0 and
|
||||
/* NaN */
|
||||
value != 0.0 / 0.0
|
||||
select key, value
|
||||
31
shared/util/codeql/util/ReportStats.qll
Normal file
31
shared/util/codeql/util/ReportStats.qll
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Provides the `ReportStats` module for reporting database quality statistics.
|
||||
*/
|
||||
module;
|
||||
|
||||
signature module StatsSig {
|
||||
int getNumberOfOk();
|
||||
|
||||
int getNumberOfNotOk();
|
||||
|
||||
string getOkText();
|
||||
|
||||
string getNotOkText();
|
||||
}
|
||||
|
||||
module ReportStats<StatsSig Stats> {
|
||||
predicate numberOfOk(string key, int value) {
|
||||
value = Stats::getNumberOfOk() and
|
||||
key = "Number of " + Stats::getOkText()
|
||||
}
|
||||
|
||||
predicate numberOfNotOk(string key, int value) {
|
||||
value = Stats::getNumberOfNotOk() and
|
||||
key = "Number of " + Stats::getNotOkText()
|
||||
}
|
||||
|
||||
predicate percentageOfOk(string key, float value) {
|
||||
value = Stats::getNumberOfOk() * 100.0 / (Stats::getNumberOfOk() + Stats::getNumberOfNotOk()) and
|
||||
key = "Percentage of " + Stats::getOkText()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user