Python: Support type annotations in call graph

Adds support for tracking instances via type annotations. Also adds a
convenience method to the newly added `Annotation` class,
`getAnnotatedExpression`, that returns the expression that is annotated
with the given type. For return annotations this is any value returned
from the annotated function in question.

Co-authored-by: Napalys Klicius <napalys@github.com>
This commit is contained in:
Taus
2025-06-04 14:40:07 +00:00
parent 76544f2966
commit d1cf7f0624
2 changed files with 16 additions and 0 deletions

View File

@@ -762,6 +762,17 @@ class Annotation extends Expr {
or
this = any(FunctionExpr f).getReturns()
}
/** Gets the expression that this annotation annotates. */
Expr getAnnotatedExpression() {
result = any(AnnAssign a | a.getAnnotation() = this).getTarget()
or
result = any(Parameter p | p.getAnnotation() = this)
or
exists(FunctionExpr f |
this = f.getReturns() and result = f.getInnerScope().getReturnNode().getNode()
)
}
}
/* Expression Contexts */

View File

@@ -580,6 +580,11 @@ private module TrackClassInstanceInput implements CallGraphConstruction::Simple:
class State = Class;
predicate start(Node start, Class cls) {
exists(Annotation ann |
ann = classTracker(cls).asExpr() and
start.asExpr() = ann.getAnnotatedExpression()
)
or
resolveClassCall(start.(CallCfgNode).asCfgNode(), cls)
or
// result of `super().__new__` as used in a `__new__` method implementation