@@ -50,110 +50,130 @@ module AiohttpWebModel {
5050 result = applicationInstance ( ) .getMember ( "router" )
5151 }
5252
53- /** A route setup in `aiohttp.web` */
54- abstract class AiohttpRouteSetup extends HTTP:: Server:: RouteSetup:: Range {
53+ /**
54+ * A route setup in `aiohttp.web`. Since all route-setups can technically use either
55+ * coroutines or view-classes as the handler argument (although that's not how you're
56+ * **supposed** to do things), we also need to handle this.
57+ *
58+ * Extend this class to refine existing API models. If you want to model new APIs,
59+ * extend `AiohttpRouteSetup::Range` instead.
60+ */
61+ class AiohttpRouteSetup extends HTTP:: Server:: RouteSetup:: Range {
62+ AiohttpRouteSetup:: Range range ;
63+
64+ AiohttpRouteSetup ( ) { this = range }
65+
5566 override Parameter getARoutedParameter ( ) { none ( ) }
5667
5768 override string getFramework ( ) { result = "aiohttp.web" }
58- }
59-
60- /** An aiohttp route setup that uses coroutines (async function) as request handler. */
61- abstract class AiohttpCoroutineRouteSetup extends AiohttpRouteSetup {
62- /** Gets the argument specifying the request handler (which is a coroutine/async function) */
63- abstract DataFlow:: Node getRequestHandlerArg ( ) ;
6469
65- override Function getARequestHandler ( ) {
66- this .getRequestHandlerArg ( ) = poorMansFunctionTracker ( result )
67- }
68- }
70+ /** Gets the argument specifying the handler (either a coroutine or a view-class). */
71+ DataFlow:: Node getHandlerArg ( ) { result = range .getHandlerArg ( ) }
6972
70- /**
71- * Gets a reference to a class, that has been backtracked from the view-class handler
72- * argument `origin` (to a route-setup for view-classes).
73- */
74- private DataFlow:: LocalSourceNode viewClassBackTracker (
75- DataFlow:: TypeBackTracker t , DataFlow:: Node origin
76- ) {
77- t .start ( ) and
78- origin = any ( AiohttpViewRouteSetup rs ) .getViewClassArg ( ) and
79- result = origin .getALocalSource ( )
80- or
81- exists ( DataFlow:: TypeBackTracker t2 |
82- result = viewClassBackTracker ( t2 , origin ) .backtrack ( t2 , t )
83- )
84- }
73+ override DataFlow:: Node getUrlPatternArg ( ) { result = range .getUrlPatternArg ( ) }
8574
86- /**
87- * Gets a reference to a class, that has been backtracked from the view-class handler
88- * argument `origin` (to a route-setup for view-classes).
89- */
90- DataFlow:: LocalSourceNode viewClassBackTracker ( DataFlow:: Node origin ) {
91- result = viewClassBackTracker ( DataFlow:: TypeBackTracker:: end ( ) , origin )
92- }
75+ /** Gets the view-class that is referenced in the view-class handler argument, if any. */
76+ Class getViewClass ( ) { result = range .getViewClass ( ) }
9377
94- Class getBackTrackedViewClass ( DataFlow:: Node origin ) {
95- result .getParent ( ) = viewClassBackTracker ( origin ) .asExpr ( )
78+ override Function getARequestHandler ( ) { result = range .getARequestHandler ( ) }
9679 }
9780
98- /** An aiohttp route setup that uses view-classes as request handlers. */
99- abstract class AiohttpViewRouteSetup extends AiohttpRouteSetup {
100- /** Gets the argument specifying the view-class handler. */
101- abstract DataFlow:: Node getViewClassArg ( ) ;
102-
103- /** Gets the view-class that is referenced in the view-class handler argument. */
104- Class getViewClass ( ) { result = getBackTrackedViewClass ( this .getViewClassArg ( ) ) }
105-
106- override Function getARequestHandler ( ) {
107- exists ( AiohttpViewClass cls |
108- cls = this .getViewClass ( ) and
109- result = cls .getARequestHandler ( )
110- )
81+ /** Provides a class for modeling new aiohttp.web route setups. */
82+ private module AiohttpRouteSetup {
83+ /**
84+ * A route setup in `aiohttp.web`. Since all route-setups can technically use either
85+ * coroutines or view-classes as the handler argument (although that's not how you're
86+ * **supposed** to do things), we also need to handle this.
87+ *
88+ * Extend this class to model new APIs. If you want to refine existing API models,
89+ * extend `AiohttpRouteSetup` instead.
90+ */
91+ abstract class Range extends DataFlow:: Node {
92+ /** Gets the argument used to set the URL pattern. */
93+ abstract DataFlow:: Node getUrlPatternArg ( ) ;
94+
95+ /** Gets the argument specifying the handler (either a coroutine or a view-class). */
96+ abstract DataFlow:: Node getHandlerArg ( ) ;
97+
98+ /** Gets the view-class that is referenced in the view-class handler argument, if any. */
99+ Class getViewClass ( ) { result = getBackTrackedViewClass ( this .getHandlerArg ( ) ) }
100+
101+ /**
102+ * Gets a function that will handle incoming requests for this route, if any.
103+ *
104+ * NOTE: This will be modified in the near future to have a `RequestHandler` result, instead of a `Function`.
105+ */
106+ Function getARequestHandler ( ) {
107+ this .getHandlerArg ( ) = poorMansFunctionTracker ( result )
108+ or
109+ exists ( AiohttpViewClass cls |
110+ cls = this .getViewClass ( ) and
111+ result = cls .getARequestHandler ( )
112+ )
113+ }
111114 }
112- }
113115
114- /**
115- * A route-setup from `add_route` or any of `add_get`, `add_post`, etc. on an
116- * `aiohttp.web.UrlDispatcher`.
117- */
118- class AiohttpUrlDispatcherAddRouteCall extends AiohttpCoroutineRouteSetup , DataFlow:: CallCfgNode {
119- /** At what index route arguments starts, so we can handle "route" version together with get/post/... */
120- int routeArgsStart ;
121-
122- AiohttpUrlDispatcherAddRouteCall ( ) {
123- this = urlDispathcerInstance ( ) .getMember ( "add_" + HTTP:: httpVerbLower ( ) ) .getACall ( ) and
124- routeArgsStart = 0
116+ /**
117+ * Gets a reference to a class, that has been backtracked from the view-class handler
118+ * argument `origin` (to a route-setup for view-classes).
119+ */
120+ private DataFlow:: LocalSourceNode viewClassBackTracker (
121+ DataFlow:: TypeBackTracker t , DataFlow:: Node origin
122+ ) {
123+ t .start ( ) and
124+ origin = any ( Range rs ) .getHandlerArg ( ) and
125+ result = origin .getALocalSource ( )
125126 or
126- this = urlDispathcerInstance ( ) .getMember ( "add_route" ) .getACall ( ) and
127- routeArgsStart = 1
127+ exists ( DataFlow:: TypeBackTracker t2 |
128+ result = viewClassBackTracker ( t2 , origin ) .backtrack ( t2 , t )
129+ )
128130 }
129131
130- override DataFlow:: Node getUrlPatternArg ( ) {
131- result in [ this .getArg ( routeArgsStart + 0 ) , this .getArgByName ( "path" ) ]
132+ /**
133+ * Gets a reference to a class, that has been backtracked from the view-class handler
134+ * argument `origin` (to a route-setup for view-classes).
135+ */
136+ DataFlow:: LocalSourceNode viewClassBackTracker ( DataFlow:: Node origin ) {
137+ result = viewClassBackTracker ( DataFlow:: TypeBackTracker:: end ( ) , origin )
132138 }
133139
134- override DataFlow:: Node getRequestHandlerArg ( ) {
135- result in [ this . getArg ( routeArgsStart + 1 ) , this . getArgByName ( "handler" ) ]
140+ Class getBackTrackedViewClass ( DataFlow:: Node origin ) {
141+ result . getParent ( ) = viewClassBackTracker ( origin ) . asExpr ( )
136142 }
137143 }
138144
145+ /** An aiohttp route setup that uses coroutines (async function) as request handler. */
146+ class AiohttpCoroutineRouteSetup extends AiohttpRouteSetup {
147+ AiohttpCoroutineRouteSetup ( ) { this .getHandlerArg ( ) = poorMansFunctionTracker ( _) }
148+ }
149+
150+ /** An aiohttp route setup that uses view-classes as request handlers. */
151+ class AiohttpViewRouteSetup extends AiohttpRouteSetup {
152+ AiohttpViewRouteSetup ( ) { exists ( this .getViewClass ( ) ) }
153+ }
154+
139155 /**
140- * A route-setup from using `route` or any of `get`, `post`, etc. functions from `aiohttp.web`.
141- *
142- * Note that technically, this does not set up a route in itself (since it needs to be added to an application first).
143- * However, modeling this way makes it easier, and we don't expect it to lead to many problems.
156+ * A route-setup from
157+ * - `add_route`, `add_view`, `add_get`, `add_post`, , etc. on an `aiohttp.web.UrlDispatcher`.
158+ * - `route`, `view`, `get`, `post`, etc. functions from `aiohttp.web`.
144159 */
145- class AiohttpWebRouteCall extends AiohttpCoroutineRouteSetup , DataFlow:: CallCfgNode {
160+ class AiohttpAddRouteCall extends AiohttpRouteSetup :: Range , DataFlow:: CallCfgNode {
146161 /** At what index route arguments starts, so we can handle "route" version together with get/post/... */
147162 int routeArgsStart ;
148163
149- AiohttpWebRouteCall ( ) {
164+ AiohttpAddRouteCall ( ) {
150165 exists ( string funcName |
151166 funcName = HTTP:: httpVerbLower ( ) and
152167 routeArgsStart = 0
153168 or
169+ funcName = "view" and
170+ routeArgsStart = 0
171+ or
154172 funcName = "route" and
155173 routeArgsStart = 1
156174 |
175+ this = urlDispathcerInstance ( ) .getMember ( "add_" + funcName ) .getACall ( )
176+ or
157177 this = API:: moduleImport ( "aiohttp" ) .getMember ( "web" ) .getMember ( funcName ) .getACall ( )
158178 )
159179 }
@@ -162,21 +182,24 @@ module AiohttpWebModel {
162182 result in [ this .getArg ( routeArgsStart + 0 ) , this .getArgByName ( "path" ) ]
163183 }
164184
165- override DataFlow:: Node getRequestHandlerArg ( ) {
185+ override DataFlow:: Node getHandlerArg ( ) {
166186 result in [ this .getArg ( routeArgsStart + 1 ) , this .getArgByName ( "handler" ) ]
167187 }
168188 }
169189
170- /** A route-setup from using a `route` or any of `get`, `post`, etc. decorators from a `aiohttp.web.RouteTableDef`. */
171- class AiohttpRouteTableDefRouteCall extends AiohttpCoroutineRouteSetup , DataFlow:: CallCfgNode {
190+ /** A route-setup using a decorator, such as `route`, `view`, `get`, `post`, etc. on a `aiohttp.web.RouteTableDef`. */
191+ class AiohttpDecoratorRouteSetup extends AiohttpRouteSetup :: Range , DataFlow:: CallCfgNode {
172192 /** At what index route arguments starts, so we can handle "route" version together with get/post/... */
173193 int routeArgsStart ;
174194
175- AiohttpRouteTableDefRouteCall ( ) {
195+ AiohttpDecoratorRouteSetup ( ) {
176196 exists ( string decoratorName |
177197 decoratorName = HTTP:: httpVerbLower ( ) and
178198 routeArgsStart = 0
179199 or
200+ decoratorName = "view" and
201+ routeArgsStart = 0
202+ or
180203 decoratorName = "route" and
181204 routeArgsStart = 1
182205 |
@@ -194,63 +217,21 @@ module AiohttpWebModel {
194217 result in [ this .getArg ( routeArgsStart + 0 ) , this .getArgByName ( "path" ) ]
195218 }
196219
197- override DataFlow:: Node getRequestHandlerArg ( ) { none ( ) }
220+ override DataFlow:: Node getHandlerArg ( ) { none ( ) }
198221
199- override Function getARequestHandler ( ) { result .getADecorator ( ) = this .asExpr ( ) }
200- }
222+ override Class getViewClass ( ) { result .getADecorator ( ) = this .asExpr ( ) }
201223
202- /**
203- * A view-class route-setup from either:
204- * - `add_view` method on a `aiohttp.web.UrlDispatcher`
205- * - `view` function from `aiohttp.web`
206- */
207- class AiohttpViewRouteSetupFromFunction extends AiohttpViewRouteSetup , DataFlow:: CallCfgNode {
208- AiohttpViewRouteSetupFromFunction ( ) {
209- this = urlDispathcerInstance ( ) .getMember ( "add_view" ) .getACall ( )
210- or
211- this = API:: moduleImport ( "aiohttp" ) .getMember ( "web" ) .getMember ( "view" ) .getACall ( )
224+ override Function getARequestHandler ( ) {
225+ // we're decorating a class
226+ exists ( this .getViewClass ( ) ) and
227+ result = super .getARequestHandler ( )
212228 or
213- this =
214- API:: moduleImport ( "aiohttp" )
215- .getMember ( "web" )
216- .getMember ( "RouteTableDef" )
217- .getReturn ( )
218- .getMember ( "view" )
219- .getACall ( )
220- }
221-
222- override DataFlow:: Node getUrlPatternArg ( ) {
223- result in [ this .getArg ( 0 ) , this .getArgByName ( "path" ) ]
224- }
225-
226- override DataFlow:: Node getViewClassArg ( ) {
227- result in [ this .getArg ( 1 ) , this .getArgByName ( "handler" ) ]
229+ // we're decorating a function
230+ not exists ( this .getViewClass ( ) ) and
231+ result .getADecorator ( ) = this .asExpr ( )
228232 }
229233 }
230234
231- /**
232- * A view-class route-setup from the `view` decorator from a `aiohttp.web.RouteTableDef`.
233- */
234- class AiohttpViewRouteSetupFromDecorator extends AiohttpViewRouteSetup , DataFlow:: CallCfgNode {
235- AiohttpViewRouteSetupFromDecorator ( ) {
236- this =
237- API:: moduleImport ( "aiohttp" )
238- .getMember ( "web" )
239- .getMember ( "RouteTableDef" )
240- .getReturn ( )
241- .getMember ( "view" )
242- .getACall ( )
243- }
244-
245- override DataFlow:: Node getUrlPatternArg ( ) {
246- result in [ this .getArg ( 0 ) , this .getArgByName ( "path" ) ]
247- }
248-
249- override DataFlow:: Node getViewClassArg ( ) { none ( ) }
250-
251- override Class getViewClass ( ) { result .getADecorator ( ) = this .asExpr ( ) }
252- }
253-
254235 /** A class that we consider a aiohttp.web View class. */
255236 abstract class AiohttpViewClass extends Class , SelfRefMixin {
256237 /** Gets a function that could handle incoming requests, if any. */
@@ -269,7 +250,7 @@ module AiohttpWebModel {
269250
270251 /** A class that is used in a route-setup, therefore being considered a aiohttp.web View class. */
271252 class AiohttpViewClassFromRouteSetup extends AiohttpViewClass {
272- AiohttpViewClassFromRouteSetup ( ) { this = any ( AiohttpViewRouteSetup rs ) .getViewClass ( ) }
253+ AiohttpViewClassFromRouteSetup ( ) { this = any ( AiohttpRouteSetup rs ) .getViewClass ( ) }
273254 }
274255
275256 /** A request handler defined in an `aiohttp.web` view class, that has no known route. */
0 commit comments