mirror of
https://github.com/github/codeql.git
synced 2026-05-05 13:45:19 +02:00
Java: add draft of generated vs manual MaD metrics query
This commit is contained in:
100
java/ql/src/Metrics/Summaries/GeneratedVsManualCoverage.ql
Normal file
100
java/ql/src/Metrics/Summaries/GeneratedVsManualCoverage.ql
Normal file
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* @id java/summary/generated-vs-manual-coverage
|
||||
* @name Metrics of generated versus manual MaD coverage
|
||||
* @description Expose metrics for the number of API endpoints covered by generated versus manual MaD models.
|
||||
* @kind table
|
||||
* @tags summary
|
||||
*/
|
||||
|
||||
//import java // not needed I guess
|
||||
import semmle.code.java.dataflow.FlowSummary // for SummarizedCallable
|
||||
import utils.modelgenerator.internal.CaptureModels // for DataFlowTargetApi
|
||||
|
||||
// ! improve QLDoc?
|
||||
/**
|
||||
* A callable for a given library that is modeled by MaD.
|
||||
* Specifically, this callable is the intersection of
|
||||
* DataFlowTargetApis and SummarizedCallables.
|
||||
*/
|
||||
class MadModeledCallable extends SummarizedCallableBase {
|
||||
// ! better name for this class?
|
||||
MadModeledCallable() {
|
||||
this instanceof SummarizedCallable and
|
||||
exists(DataFlowTargetApi dataFlowTargApi |
|
||||
this.asCallable() = dataFlowTargApi and
|
||||
not exists(FunctionalExpr funcExpr | dataFlowTargApi = funcExpr.asMethod()) // ! remove this if DataFlowTargetApi itself is adjusted to exclude FunctionalExpr (see static-team slack thread)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// ! move to other file
|
||||
/**
|
||||
* Returns the number of APIs with MaD models
|
||||
* for a given package and provenance.
|
||||
*/
|
||||
float getNumMadModels(string package, string provenance) {
|
||||
exists(MadModeledCallable mc |
|
||||
package = mc.asCallable().getDeclaringType().getPackage().toString() and
|
||||
provenance in ["generated", "manual", "both"]
|
||||
|
|
||||
result =
|
||||
count(MadModeledCallable c |
|
||||
package = c.asCallable().getDeclaringType().getPackage().toString() and
|
||||
(
|
||||
c.(SummarizedCallable).isAutoGenerated() and // generated and NOT manual = "auto-only"
|
||||
provenance = "generated"
|
||||
or
|
||||
c.(SummarizedCallable).isManuallyGenerated() and // manual and NOT generated = "manual-only"
|
||||
provenance = "manual"
|
||||
or
|
||||
c.(SummarizedCallable).isBothAutoAndManuallyGenerated() and // BOTH generated and manual = "both"
|
||||
provenance = "both"
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// ! move to other file
|
||||
/**
|
||||
* Returns the number of APIs without MaD
|
||||
* models for a given package.
|
||||
*/
|
||||
float getNumApisWithoutMadModel(string package) {
|
||||
exists(DataFlowTargetApi dataFlowTargApi |
|
||||
package = dataFlowTargApi.getDeclaringType().getPackage().toString() and
|
||||
not exists(FunctionalExpr fe | dataFlowTargApi = fe.asMethod()) // remove lambdas // ! remove this if DataFlowTargetApi itself is adjusted to exclude FunctionalExpr (see static-team slack thread)
|
||||
|
|
||||
result =
|
||||
count(DataFlowTargetApi d |
|
||||
package = d.getDeclaringType().getPackage().toString() and
|
||||
not exists(FunctionalExpr funcExpr | d = funcExpr.asMethod()) and // remove lambdas // ! remove this if DataFlowTargetApi itself is adjusted to exclude FunctionalExpr (see static-team slack thread)
|
||||
not exists(SummarizedCallable sc | d = sc.asCallable()) // set minus with SummarizedCallables
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// ! Note: adjust metric formulas as needed after more discussion with Yorck
|
||||
/*
|
||||
* metric1:
|
||||
* Proportion of manual models covered by automation: “both” / (“both” + “manual-only”)
|
||||
* Auto-generated vs all positive manual (percentage of manual models covered by auto-generation)
|
||||
*/
|
||||
|
||||
/*
|
||||
* metric2:
|
||||
* Coverage relative to total number of APIs: (“auto-only” + “both” + “manual-only”) / “all”
|
||||
* Auto-generated vs specific pos+neg subset (top-N manual, random)
|
||||
*/
|
||||
|
||||
from
|
||||
string package, float generated, float manual, float both, float notModeled, float all,
|
||||
float metric1, float metric2
|
||||
where
|
||||
generated = getNumMadModels(package, "generated") and
|
||||
manual = getNumMadModels(package, "manual") and
|
||||
both = getNumMadModels(package, "both") and
|
||||
notModeled = getNumApisWithoutMadModel(package) and // ! better name for this?, "none" is a reserved keyword :(
|
||||
all = generated + manual + both + notModeled and
|
||||
metric1 = (both / (both + manual)) and
|
||||
metric2 = (generated + both + manual) / all
|
||||
select package, generated, manual, both, notModeled, all, metric1, metric2 order by package
|
||||
Reference in New Issue
Block a user