Skip to content

Commit fa36a11

Browse files
committed
unified: Sharpen set of candidates when measuring static name binding
1 parent b1ca110 commit fa36a11

1 file changed

Lines changed: 36 additions & 3 deletions

File tree

unified/ql/lib/codeql/unified/internal/AnalysisQuality.qll

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,45 @@ private import codeql.unified.internal.NameBindingPlugin
66

77
/** Stats about identifiers that static name binding could resolve. */
88
module StaticNameResolutionStats implements EntityStatsSig {
9+
/**
10+
* Holds if `name` has been positively identified as something that refer to a value, and static name binding
11+
* is thus not expected to resolve its members.
12+
*/
13+
private predicate resolvesToValue(Identifier name) {
14+
exists(AstNode decl |
15+
decl = getStaticBindingTarget(name).getDeclaration() and
16+
not decl instanceof ClassLikeDeclaration and
17+
not decl instanceof TypeAliasDeclaration and
18+
not decl instanceof TypeParameter and
19+
not decl instanceof AssociatedTypeDeclaration
20+
)
21+
}
22+
23+
/**
24+
* Holds if name-binding for `expr` depends on type inference, and is thus not subject to static name binding.
25+
*
26+
* Usually this holds for qualified instance member accesses (`foo().x`) and leading-dot expressions (`.x`).
27+
*/
28+
private predicate memberAccessDependsOnTypeInference(MemberAccessExpr expr) {
29+
exists(Expr base | base = expr.getBase() |
30+
// Base expression resolves to a value, e.g. a field, variable, or function (for languages where functions are values).
31+
resolvesToValue(getIdentifierFromRef(base))
32+
or
33+
// Base expression is of a kind that is not subject to static name resolution, e.g. `foo().x`
34+
not exists(getIdentifierFromRef(base))
35+
or
36+
// Base expression is a confirmed to depend on type inference
37+
memberAccessDependsOnTypeInference(base)
38+
)
39+
}
40+
941
class Candidate extends Identifier {
1042
Candidate() {
11-
this = getIdentifierFromRef(_) and
43+
exists(AstNode ref |
44+
this = getIdentifierFromRef(ref) and
45+
not memberAccessDependsOnTypeInference(ref)
46+
) and
1247
not this instanceof NameDeclaration
13-
// TODO: exclude names we know are not static references, e.g. unqualified instance-field access,
14-
// currently blocked on getting static name binding to report this information.
1548
}
1649

1750
NameBindingNode getTarget() {

0 commit comments

Comments
 (0)