@@ -11,6 +11,19 @@ class XMLRecordedCall extends XMLElement {
1111 XMLCall getXMLCall ( ) { result .getParent ( ) = this }
1212
1313 XMLCallee getXMLCallee ( ) { result .getParent ( ) = this }
14+
15+ /** Get a different `XMLRecordedCall` with the same result-set for `getCall`. */
16+ XMLRecordedCall getOtherWithSameSetOfCalls ( ) {
17+ // `rc` is for a different bytecode instruction on same line
18+ not result .getXMLCall ( ) .get_inst_index_data ( ) = this .getXMLCall ( ) .get_inst_index_data ( ) and
19+ result .getXMLCall ( ) .get_filename_data ( ) = this .getXMLCall ( ) .get_filename_data ( ) and
20+ result .getXMLCall ( ) .get_linenum_data ( ) = this .getXMLCall ( ) .get_linenum_data ( ) and
21+ // set of calls is equal
22+ // 1. this.getCall() issubset result.getCall()
23+ not exists ( Call call | call = this .getCall ( ) | not result .getCall ( ) = call ) and
24+ // 2. result.getCall() issubset this.getCall()
25+ not exists ( Call call | call = result .getCall ( ) | not this .getCall ( ) = call )
26+ }
1427}
1528
1629class XMLCall extends XMLElement {
@@ -43,8 +56,7 @@ class XMLCall extends XMLElement {
4356 matchBytecodeExpr ( expr .( Attribute ) .getObject ( ) ,
4457 bytecode .( XMLBytecodeAttribute ) .get_object_data ( ) )
4558 or
46- matchBytecodeExpr ( expr .( Call ) .getFunc ( ) ,
47- bytecode .( XMLBytecodeCall ) .get_function_data ( ) )
59+ matchBytecodeExpr ( expr .( Call ) .getFunc ( ) , bytecode .( XMLBytecodeCall ) .get_function_data ( ) )
4860 )
4961 }
5062}
@@ -111,6 +123,25 @@ class ValidRecordedCall extends XMLRecordedCall {
111123 or
112124 strictcount ( this .getXMLCallee ( ) .( XMLExternalCallee ) .getCallee ( ) ) = 1
113125 )
126+ or
127+ // Handle case where the same function is called multiple times in one line, for
128+ // example `func(); func()`. This only works if:
129+ // - all the callees for these calls is the same
130+ // - all these calls were recorded
131+ //
132+ // without this `strictcount`, in the case `func(); func(); func()`, if 1 of the calls
133+ // is not recorded, we woulld still mark the other two recorded calls as valid
134+ // (which is not following the rules above). + 1 to count `this` as well.
135+ strictcount ( this .getCall ( ) ) = strictcount ( this .getOtherWithSameSetOfCalls ( ) ) + 1 and
136+ forex ( XMLRecordedCall rc |
137+ rc = this .getOtherWithSameSetOfCalls ( )
138+ |
139+ unique( Function f | f = this .getXMLCallee ( ) .( XMLPythonCallee ) .getCallee ( ) ) =
140+ unique( Function f | f = rc .getXMLCallee ( ) .( XMLPythonCallee ) .getCallee ( ) )
141+ or
142+ unique( Builtin b | b = this .getXMLCallee ( ) .( XMLExternalCallee ) .getCallee ( ) ) =
143+ unique( Builtin b | b = rc .getXMLCallee ( ) .( XMLExternalCallee ) .getCallee ( ) )
144+ )
114145 }
115146}
116147
0 commit comments