@@ -2,22 +2,22 @@ import python
22
33/** Gets the comment on the line above `ast` */
44Comment commentFor ( AstNode ast ) {
5- exists ( int line | line = ast .getLocation ( ) .getStartLine ( ) - 1 |
6- result
7- .getLocation ( )
8- .hasLocationInfo ( ast .getLocation ( ) .getFile ( ) .getAbsolutePath ( ) , line , _, line , _)
9- )
5+ exists ( int line | line = ast .getLocation ( ) .getStartLine ( ) - 1 |
6+ result
7+ .getLocation ( )
8+ .hasLocationInfo ( ast .getLocation ( ) .getFile ( ) .getAbsolutePath ( ) , line , _, line , _)
9+ )
1010}
1111
1212/** Gets the value from `tag:value` in the comment for `ast` */
1313string getAnnotation ( AstNode ast , string tag ) {
14- exists ( Comment comment , string match , string theRegex |
15- theRegex = "([\\w]+):([\\w.]+)" and
16- comment = commentFor ( ast ) and
17- match = comment .getText ( ) .regexpFind ( theRegex , _, _) and
18- tag = match .regexpCapture ( theRegex , 1 ) and
19- result = match .regexpCapture ( theRegex , 2 )
20- )
14+ exists ( Comment comment , string match , string theRegex |
15+ theRegex = "([\\w]+):([\\w.]+)" and
16+ comment = commentFor ( ast ) and
17+ match = comment .getText ( ) .regexpFind ( theRegex , _, _) and
18+ tag = match .regexpCapture ( theRegex , 1 ) and
19+ result = match .regexpCapture ( theRegex , 2 )
20+ )
2121}
2222
2323/** Gets a callable annotated with `name:name` */
@@ -27,121 +27,121 @@ Function annotatedCallable(string name) { name = getAnnotation(result, "name") }
2727Call annotatedCall ( string name ) { name = getAnnotation ( result , "calls" ) }
2828
2929predicate missingAnnotationForCallable ( string name , Call call ) {
30- call = annotatedCall ( name ) and
31- not exists ( annotatedCallable ( name ) )
30+ call = annotatedCall ( name ) and
31+ not exists ( annotatedCallable ( name ) )
3232}
3333
3434predicate nonUniqueAnnotationForCallable ( string name , Function callable ) {
35- strictcount ( annotatedCallable ( name ) ) > 1 and
36- callable = annotatedCallable ( name )
35+ strictcount ( annotatedCallable ( name ) ) > 1 and
36+ callable = annotatedCallable ( name )
3737}
3838
3939predicate missingAnnotationForCall ( string name , Function callable ) {
40- not exists ( annotatedCall ( name ) ) and
41- callable = annotatedCallable ( name )
40+ not exists ( annotatedCall ( name ) ) and
41+ callable = annotatedCallable ( name )
4242}
4343
4444/** There is an obvious problem with the annotation `name` */
4545predicate nameInErrorState ( string name ) {
46- missingAnnotationForCallable ( name , _)
47- or
48- nonUniqueAnnotationForCallable ( name , _)
49- or
50- missingAnnotationForCall ( name , _)
46+ missingAnnotationForCallable ( name , _)
47+ or
48+ nonUniqueAnnotationForCallable ( name , _)
49+ or
50+ missingAnnotationForCall ( name , _)
5151}
5252
5353/** Source code has annotation with `name` showing that `call` will call `callable` */
5454predicate annotatedCallEdge ( string name , Call call , Function callable ) {
55- not nameInErrorState ( name ) and
56- call = annotatedCall ( name ) and
57- callable = annotatedCallable ( name )
55+ not nameInErrorState ( name ) and
56+ call = annotatedCall ( name ) and
57+ callable = annotatedCallable ( name )
5858}
5959
6060// ------------------------- Annotation debug query predicates -------------------------
6161query predicate debug_missingAnnotationForCallable ( Call call , string message ) {
62- exists ( string name |
63- message =
64- "This call is annotated with '" + name +
65- "', but no callable with that annotation was extracted. Please fix." and
66- missingAnnotationForCallable ( name , call )
67- )
62+ exists ( string name |
63+ message =
64+ "This call is annotated with '" + name +
65+ "', but no callable with that annotation was extracted. Please fix." and
66+ missingAnnotationForCallable ( name , call )
67+ )
6868}
6969
7070query predicate debug_nonUniqueAnnotationForCallable ( Function callable , string message ) {
71- exists ( string name |
72- message = "Multiple callables are annotated with '" + name + "'. Please fix." and
73- nonUniqueAnnotationForCallable ( name , callable )
74- )
71+ exists ( string name |
72+ message = "Multiple callables are annotated with '" + name + "'. Please fix." and
73+ nonUniqueAnnotationForCallable ( name , callable )
74+ )
7575}
7676
7777query predicate debug_missingAnnotationForCall ( Function callable , string message ) {
78- exists ( string name |
79- message =
80- "This callable is annotated with '" + name +
81- "', but no call with that annotation was extracted. Please fix." and
82- missingAnnotationForCall ( name , callable )
83- )
78+ exists ( string name |
79+ message =
80+ "This callable is annotated with '" + name +
81+ "', but no call with that annotation was extracted. Please fix." and
82+ missingAnnotationForCall ( name , callable )
83+ )
8484}
8585
8686// ------------------------- Call Graph resolution -------------------------
8787private newtype TCallGraphResolver =
88- TPointsToResolver ( ) or
89- TTypeTrackerResolver ( )
88+ TPointsToResolver ( ) or
89+ TTypeTrackerResolver ( )
9090
9191/** Describes a method of call graph resolution */
9292abstract class CallGraphResolver extends TCallGraphResolver {
93- abstract predicate callEdge ( Call call , Function callable ) ;
94-
95- /**
96- * Holds if annotations show that `call` will call `callable`,
97- * but our call graph resolver was not able to figure that out
98- */
99- predicate expectedCallEdgeNotFound ( Call call , Function callable ) {
100- annotatedCallEdge ( _, call , callable ) and
101- not this .callEdge ( call , callable )
102- }
103-
104- /**
105- * Holds if there are no annotations that show that `call` will call `callable` (where at least one of these are annotated),
106- * but the call graph resolver claims that `call` will call `callable`
107- */
108- predicate unexpectedCallEdgeFound ( Call call , Function callable , string message ) {
109- this .callEdge ( call , callable ) and
110- not annotatedCallEdge ( _, call , callable ) and
111- (
112- exists ( string name |
113- message = "Call resolved to the callable named '" + name + "' but was not annotated as such" and
114- callable = annotatedCallable ( name ) and
115- not nameInErrorState ( name )
116- )
117- or
118- exists ( string name |
119- message = "Annotated call resolved to unannotated callable" and
120- call = annotatedCall ( name ) and
121- not nameInErrorState ( name ) and
122- not exists ( | callable = annotatedCallable ( _) )
123- )
124- )
125- }
126-
127- string toString ( ) { result = "CallGraphResolver" }
93+ abstract predicate callEdge ( Call call , Function callable ) ;
94+
95+ /**
96+ * Holds if annotations show that `call` will call `callable`,
97+ * but our call graph resolver was not able to figure that out
98+ */
99+ predicate expectedCallEdgeNotFound ( Call call , Function callable ) {
100+ annotatedCallEdge ( _, call , callable ) and
101+ not this .callEdge ( call , callable )
102+ }
103+
104+ /**
105+ * Holds if there are no annotations that show that `call` will call `callable` (where at least one of these are annotated),
106+ * but the call graph resolver claims that `call` will call `callable`
107+ */
108+ predicate unexpectedCallEdgeFound ( Call call , Function callable , string message ) {
109+ this .callEdge ( call , callable ) and
110+ not annotatedCallEdge ( _, call , callable ) and
111+ (
112+ exists ( string name |
113+ message = "Call resolved to the callable named '" + name + "' but was not annotated as such" and
114+ callable = annotatedCallable ( name ) and
115+ not nameInErrorState ( name )
116+ )
117+ or
118+ exists ( string name |
119+ message = "Annotated call resolved to unannotated callable" and
120+ call = annotatedCall ( name ) and
121+ not nameInErrorState ( name ) and
122+ not exists ( | callable = annotatedCallable ( _) )
123+ )
124+ )
125+ }
126+
127+ string toString ( ) { result = "CallGraphResolver" }
128128}
129129
130130/** A call graph resolver based on the existing points-to analysis */
131131class PointsToResolver extends CallGraphResolver , TPointsToResolver {
132- override predicate callEdge ( Call call , Function callable ) {
133- exists ( PythonFunctionValue funcValue |
134- funcValue .getScope ( ) = callable and
135- call = funcValue .getACall ( ) .getNode ( )
136- )
137- }
138-
139- override string toString ( ) { result = "PointsToResolver" }
132+ override predicate callEdge ( Call call , Function callable ) {
133+ exists ( PythonFunctionValue funcValue |
134+ funcValue .getScope ( ) = callable and
135+ call = funcValue .getACall ( ) .getNode ( )
136+ )
137+ }
138+
139+ override string toString ( ) { result = "PointsToResolver" }
140140}
141141
142142/** A call graph resolved based on Type Trackers */
143143class TypeTrackerResolver extends CallGraphResolver , TTypeTrackerResolver {
144- override predicate callEdge ( Call call , Function callable ) { none ( ) }
144+ override predicate callEdge ( Call call , Function callable ) { none ( ) }
145145
146- override string toString ( ) { result = "TypeTrackerResolver" }
146+ override string toString ( ) { result = "TypeTrackerResolver" }
147147}
0 commit comments