Merge pull request #1565 from asger-semmle/uncalled-function-metric

Approved by xiemaisi
This commit is contained in:
semmle-qlci
2019-07-10 09:59:51 +01:00
committed by GitHub
5 changed files with 102 additions and 1 deletions

View File

@@ -40,6 +40,14 @@ class RelevantInvoke extends InvokeNode {
RelevantInvoke() { not getFile() instanceof IgnoredFile }
}
/** An call site that is relevant for analysis quality. */
class RelevantFunction extends Function {
RelevantFunction() {
not getFile() instanceof IgnoredFile and
hasBody() // ignore abstract or ambient functions
}
}
/**
* Holds if `name` is a the name of an external module.
*/
@@ -136,7 +144,7 @@ SourceNode externalNode() {
}
/**
* Gets a data flow node that can be resolved to a callback.
* Gets a data flow node that can be resolved to a function, usually a callback.
*
* These are not part of the static call graph, but the data flow analysis can
* track them, so we consider them resolved.
@@ -150,6 +158,26 @@ SourceNode resolvableCallback() {
)
}
/**
* Gets a data flow node that can be resolved to an invocation of a callback.
*
* These are not part of the static call graph, but the data flow analysis can
* track them, so we consider them resolved.
*/
SourceNode nodeLeadingToInvocation() {
exists(result.getAnInvocation())
or
exists(Node arg |
FlowSteps::argumentPassing(_, arg, _, nodeLeadingToInvocation()) and
result.flowsTo(arg)
)
or
exists(AdditionalPartialInvokeNode invoke, Node arg |
invoke.isPartialArgument(arg, _, _) and
result.flowsTo(arg)
)
}
/**
* A call site that can be resolved to a function in the same project.
*/
@@ -205,3 +233,23 @@ class NonExternalCall extends RelevantInvoke {
not this instanceof ExternalCall
}
}
/**
* A function with at least one call site.
*/
class FunctionWithCallers extends RelevantFunction {
FunctionWithCallers() {
FlowSteps::calls(_, this)
or
this = nodeLeadingToInvocation().getAstNode()
}
}
/**
* A function without any call sites.
*/
class FunctionWithoutCallers extends RelevantFunction {
FunctionWithoutCallers() {
not this instanceof FunctionWithCallers
}
}

View File

@@ -0,0 +1,14 @@
/**
* @name Called function candidates
* @description The number of functions for which finding call sites is relevant
* for analysis quality.
* @kind metric
* @metricType project
* @metricAggregate sum
* @tags meta
* @id js/meta/called-function-candidates
*/
import javascript
import CallGraphQuality
select projectRoot(), count(RelevantFunction f)

View File

@@ -0,0 +1,13 @@
/**
* @name Called function ratio
* @description The percentage of relevant functions for which a call site was found.
* @kind metric
* @metricType project
* @metricAggregate sum min max avg
* @tags meta
* @id js/meta/called-function-ratio
*/
import javascript
import CallGraphQuality
select projectRoot(), 100.0 * count(FunctionWithCallers f) / (float) count(RelevantFunction f)

View File

@@ -0,0 +1,13 @@
/**
* @name Called functions
* @description The number of functions for which a call site was found.
* @kind metric
* @metricType project
* @metricAggregate sum
* @tags meta
* @id js/meta/called-functions
*/
import javascript
import CallGraphQuality
select projectRoot(), count(FunctionWithCallers f)

View File

@@ -0,0 +1,13 @@
/**
* @name Uncalled functions
* @description The number of functions for which no call site could be found.
* @kind metric
* @metricType project
* @metricAggregate sum
* @tags meta
* @id js/meta/uncalled-functions
*/
import javascript
import CallGraphQuality
select projectRoot(), count(FunctionWithoutCallers f)