diff --git a/rust/ql/src/change-notes/2025-10-21-database-quality-diagnostic.md b/rust/ql/src/change-notes/2025-10-21-database-quality-diagnostic.md new file mode 100644 index 000000000000..322bdb7c5ab1 --- /dev/null +++ b/rust/ql/src/change-notes/2025-10-21-database-quality-diagnostic.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The "Low Rust analysis quality" query (`rust/diagnostic/database-quality`), used by the tool status page, has been extended with a measure of successful type inference. diff --git a/rust/ql/src/queries/telemetry/DatabaseQuality.qll b/rust/ql/src/queries/telemetry/DatabaseQuality.qll index 15826fec4c45..0b874a9b9cef 100644 --- a/rust/ql/src/queries/telemetry/DatabaseQuality.qll +++ b/rust/ql/src/queries/telemetry/DatabaseQuality.qll @@ -6,6 +6,7 @@ import rust import codeql.util.ReportStats +import codeql.rust.internal.TypeInference as TypeInference module CallTargetStats implements StatsSig { int getNumberOfOk() { result = count(CallExprBase c | exists(c.getStaticTarget())) } @@ -41,6 +42,20 @@ module MacroCallTargetStats implements StatsSig { string getNotOkText() { result = "macro calls with missing call target" } } +private predicate hasGoodType(Expr e) { exists(TypeInference::inferType(e, _)) } + +module ExprTypeStats implements StatsSig { + int getNumberOfOk() { result = count(Expr e | e.fromSource() and hasGoodType(e)) } + + int getNumberOfNotOk() { result = count(Expr e | e.fromSource() and not hasGoodType(e)) } + + string getOkText() { result = "expressions with known type" } + + string getNotOkText() { result = "expressions with unknown type" } +} + module CallTargetStatsReport = ReportStats; module MacroCallTargetStatsReport = ReportStats; + +module ExprTypeStatsReport = ReportStats; diff --git a/rust/ql/src/queries/telemetry/DatabaseQualityDiagnostics.ql b/rust/ql/src/queries/telemetry/DatabaseQualityDiagnostics.ql index 63fb1e4c6cc5..02933b3bd5f6 100644 --- a/rust/ql/src/queries/telemetry/DatabaseQualityDiagnostics.ql +++ b/rust/ql/src/queries/telemetry/DatabaseQualityDiagnostics.ql @@ -13,6 +13,8 @@ private predicate diagnostic(string msg, float value, float threshold) { CallTargetStatsReport::percentageOfOk(msg, value) and threshold = 50 or MacroCallTargetStatsReport::percentageOfOk(msg, value) and threshold = 50 + or + ExprTypeStatsReport::percentageOfOk(msg, value) and threshold = 20 } private string getDbHealth() { diff --git a/rust/ql/src/queries/telemetry/ExtractorInformation.ql b/rust/ql/src/queries/telemetry/ExtractorInformation.ql index f61dfe515a9e..ab18ecf489f3 100644 --- a/rust/ql/src/queries/telemetry/ExtractorInformation.ql +++ b/rust/ql/src/queries/telemetry/ExtractorInformation.ql @@ -54,7 +54,10 @@ where CallTargetStatsReport::percentageOfOk(key, value) or MacroCallTargetStatsReport::numberOfOk(key, value) or MacroCallTargetStatsReport::numberOfNotOk(key, value) or - MacroCallTargetStatsReport::percentageOfOk(key, value) + MacroCallTargetStatsReport::percentageOfOk(key, value) or + ExprTypeStatsReport::numberOfOk(key, value) or + ExprTypeStatsReport::numberOfNotOk(key, value) or + ExprTypeStatsReport::percentageOfOk(key, value) ) and /* Infinity */ value != 1.0 / 0.0 and