11/**
22 * Provides predicates for measuring the quality of the call graph, that is,
3- * the number of calls that could be resolved to a callee .
3+ * the number of calls that could be resolved to a target .
44 */
55
66import python
77import meta.MetaMetrics
88
9+ newtype TTarget =
10+ TFunction ( Function func ) or
11+ TClass ( Class cls )
12+
13+ class Target extends TTarget {
14+ /** Gets a textual representation of this element. */
15+ abstract string toString ( ) ;
16+
17+ /** Gets the location of this dataflow call. */
18+ abstract Location getLocation ( ) ;
19+
20+ /** Whether this target is relevant. */
21+ predicate isRelevant ( ) { exists ( this .getLocation ( ) .getFile ( ) .getRelativePath ( ) ) }
22+ }
23+
24+ class TargetFunction extends Target , TFunction {
25+ Function func ;
26+
27+ TargetFunction ( ) { this = TFunction ( func ) }
28+
29+ override string toString ( ) { result = func .toString ( ) }
30+
31+ override Location getLocation ( ) { result = func .getLocation ( ) }
32+
33+ Function getFunction ( ) { result = func }
34+ }
35+
36+ class TargetClass extends Target , TClass {
37+ Class cls ;
38+
39+ TargetClass ( ) { this = TClass ( cls ) }
40+
41+ override string toString ( ) { result = cls .toString ( ) }
42+
43+ override Location getLocation ( ) { result = cls .getLocation ( ) }
44+
45+ Class getClass ( ) { result = cls }
46+ }
47+
948/**
1049 * A call that is (possibly) relevant for analysis quality.
1150 * See `IgnoredFile` for details on what is excluded.
1251 */
13- class RelevantCall extends Call {
52+ class RelevantCall extends CallNode {
1453 RelevantCall ( ) { not this .getLocation ( ) .getFile ( ) instanceof IgnoredFile }
1554}
1655
1756/** Provides classes for call-graph resolution by using points-to. */
1857module PointsToBasedCallGraph {
1958 /** A call that can be resolved by points-to. */
2059 class ResolvableCall extends RelevantCall {
21- Value callee ;
60+ Value targetValue ;
2261
23- ResolvableCall ( ) { callee .getACall ( ) = this . getAFlowNode ( ) }
62+ ResolvableCall ( ) { targetValue .getACall ( ) = this }
2463
25- /** Gets a resolved callee of this call. */
26- Value getCallee ( ) { result = callee }
64+ /** Gets a resolved target of this call. */
65+ Target getTarget ( ) {
66+ result .( TargetFunction ) .getFunction ( ) = targetValue .( CallableValue ) .getScope ( )
67+ or
68+ result .( TargetClass ) .getClass ( ) = targetValue .( ClassValue ) .getScope ( )
69+ }
2770 }
2871
2972 /** A call that cannot be resolved by points-to. */
@@ -32,34 +75,68 @@ module PointsToBasedCallGraph {
3275 }
3376
3477 /**
35- * A call that can be resolved by points-to, where the resolved callee is relevant.
36- * Relevant callees include:
37- * - builtins
38- * - standard library
78+ * A call that can be resolved by points-to, where the resolved target is relevant.
79+ * Relevant targets include:
3980 * - source code of the project
4081 */
41- class ResolvableCallRelevantCallee extends ResolvableCall {
42- ResolvableCallRelevantCallee ( ) {
43- callee .isBuiltin ( )
44- or
45- exists ( File file |
46- file = callee .( CallableValue ) .getScope ( ) .getLocation ( ) .getFile ( )
47- or
48- file = callee .( ClassValue ) .getScope ( ) .getLocation ( ) .getFile ( )
49- |
50- file .inStdlib ( )
51- or
52- // part of the source code of the project
53- exists ( file .getRelativePath ( ) )
82+ class ResolvableCallRelevantTarget extends ResolvableCall {
83+ ResolvableCallRelevantTarget ( ) {
84+ exists ( Target target | target = getTarget ( ) |
85+ exists ( target .getLocation ( ) .getFile ( ) .getRelativePath ( ) )
86+ )
87+ }
88+ }
89+
90+ /**
91+ * A call that can be resolved by points-to, where the resolved target is not considered relevant.
92+ * See `ResolvableCallRelevantTarget` for the definition of relevance.
93+ */
94+ class ResolvableCallIrrelevantTarget extends ResolvableCall {
95+ ResolvableCallIrrelevantTarget ( ) { not this instanceof ResolvableCallRelevantTarget }
96+ }
97+ }
98+
99+ /** Provides classes for call-graph resolution by using type-tracking. */
100+ module TypeTrackingBasedCallGraph {
101+ private import semmle.python.dataflow.new.internal.DataFlowDispatch as TT
102+
103+ /** A call that can be resolved by type-tracking. */
104+ class ResolvableCall extends RelevantCall {
105+ TT:: DataFlowCallable dataflowTarget ;
106+
107+ ResolvableCall ( ) { dataflowTarget = TT:: viableCallable ( TT:: TNormalCall ( this ) ) }
108+
109+ /** Gets a resolved target of this call. */
110+ Target getTarget ( ) {
111+ result .( TargetFunction ) .getFunction ( ) = dataflowTarget .( TT:: DataFlowFunction ) .getScope ( )
112+ // TODO: class calls
113+ // result.(TargetClass).getClass()
114+ }
115+ }
116+
117+ /** A call that cannot be resolved by type-tracking. */
118+ class UnresolvableCall extends RelevantCall {
119+ UnresolvableCall ( ) { not this instanceof ResolvableCall }
120+ }
121+
122+ /**
123+ * A call that can be resolved by type-tracking, where the resolved callee is relevant.
124+ * Relevant targets include:
125+ * - source code of the project
126+ */
127+ class ResolvableCallRelevantTarget extends ResolvableCall {
128+ ResolvableCallRelevantTarget ( ) {
129+ exists ( Target target | target = getTarget ( ) |
130+ exists ( target .getLocation ( ) .getFile ( ) .getRelativePath ( ) )
54131 )
55132 }
56133 }
57134
58135 /**
59- * A call that can be resolved by points-to , where the resolved callee is not considered relevant.
60- * See `ResolvableCallRelevantCallee ` for the definition of relevance.
136+ * A call that can be resolved by type-tracking , where the resolved target is not considered relevant.
137+ * See `ResolvableCallRelevantTarget ` for the definition of relevance.
61138 */
62- class ResolvableCallIrrelevantCallee extends ResolvableCall {
63- ResolvableCallIrrelevantCallee ( ) { not this instanceof ResolvableCallRelevantCallee }
139+ class ResolvableCallIrrelevantTarget extends ResolvableCall {
140+ ResolvableCallIrrelevantTarget ( ) { not this instanceof ResolvableCallRelevantTarget }
64141 }
65142}
0 commit comments