@@ -198,33 +198,12 @@ module Filters {
198
198
199
199
FilterKind getKind ( ) { result = kind }
200
200
201
- private ModuleBase getEnclosingModule ( ) { result = call .getExpr ( ) .getEnclosingModule ( ) }
202
-
203
201
/**
204
202
* Holds if this callback is registered before `other`. This does not
205
203
* guarantee that the callback will be executed before `other`. For example,
206
204
* `after_action` callbacks are executed in reverse order.
207
205
*/
208
- predicate registeredBefore ( Filter other ) {
209
- // before_action :this, :other
210
- //
211
- // before_action :this
212
- // before_action :other
213
- this .getBasicBlock ( ) = other .getBasicBlock ( ) and this .getASuccessor + ( ) = other
214
- or
215
- this .getEnclosingModule ( ) = other .getEnclosingModule ( ) and
216
- this .getBasicBlock ( ) .strictlyDominates ( other .getBasicBlock ( ) ) and
217
- this != other
218
- or
219
- // This callback is in a superclass of `other`'s class.
220
- //
221
- // class A
222
- // before_action :this
223
- //
224
- // class B < A
225
- // before_action :other
226
- other .getEnclosingModule ( ) .getModule ( ) = this .getEnclosingModule ( ) .getModule ( ) .getASubClass + ( )
227
- }
206
+ predicate registeredBefore ( Filter other ) { callbackRegisteredBefore ( call , _, this , other ) }
228
207
229
208
/**
230
209
* Holds if this callback runs before `other`.
@@ -277,7 +256,9 @@ module Filters {
277
256
* with the same name is registered later one, overriding this one.
278
257
*/
279
258
predicate skipped ( ActionControllerActionMethod action ) {
280
- this = any ( SkipFilter f | f .getKind ( ) = this .getKind ( ) ) .getSkippedFilter ( action ) or
259
+ this =
260
+ any ( SkipFilter f | f .getKind ( ) = this .getKind ( ) and this .registeredBefore ( f ) )
261
+ .getSkippedFilter ( action ) or
281
262
this .overridden ( )
282
263
}
283
264
@@ -339,6 +320,11 @@ module Filters {
339
320
340
321
ActionControllerActionMethod getAction ( ) { result = call .getAction ( ) }
341
322
323
+ predicate registeredBefore ( StringlikeLiteralCfgNode other ) {
324
+ ( other instanceof SkipFilter or other instanceof Filter ) and
325
+ callbackRegisteredBefore ( call , _, this , other )
326
+ }
327
+
342
328
Filter getSkippedFilter ( ActionControllerActionMethod action ) {
343
329
not result instanceof SkipFilter and
344
330
action = this .getAction ( ) and
@@ -347,6 +333,47 @@ module Filters {
347
333
}
348
334
}
349
335
336
+ /**
337
+ * Holds if `predCall` (resp. `succCall`) registers or skips the callback referred to by `pred` (`succ`) and `predCall` is evaluated called before `succCall`.
338
+ * Typically this means that `pred` is registered before `succ`, or `pred` is skipped before `succ`, depending on the nature of the call.
339
+ * `pred` and `succ` are expected to be arguments. In the examples below, `pred` is `:foo` and `succ` is `:bar`.
340
+ * ```rb
341
+ * before_action :foo, :bar
342
+ * skip_before_action :foo, :bar
343
+ * ```
344
+ * This does not guarantee that the callback referred to by `pred` will be executed before
345
+ * `succ`. For example, `after_action` callbacks are executed in reverse order.
346
+ */
347
+ private predicate callbackRegisteredBefore (
348
+ FilterCall predCall , FilterCall succCall , StringlikeLiteralCfgNode pred ,
349
+ StringlikeLiteralCfgNode succ
350
+ ) {
351
+ pred = predCall .getFilterArgument ( ) and
352
+ succ = succCall .getFilterArgument ( ) and
353
+ (
354
+ // before_action :this, :other
355
+ //
356
+ // before_action :this
357
+ // before_action :other
358
+ pred .getBasicBlock ( ) = succ .getBasicBlock ( ) and
359
+ pred .getASuccessor + ( ) = succ
360
+ or
361
+ predCall .getExpr ( ) .getEnclosingModule ( ) = succCall .getExpr ( ) .getEnclosingModule ( ) and
362
+ pred .getBasicBlock ( ) .strictlyDominates ( succ .getBasicBlock ( ) ) and
363
+ pred != succ
364
+ or
365
+ // This callback is in a superclass of `other`'s class.
366
+ //
367
+ // class A
368
+ // before_action :this
369
+ //
370
+ // class B < A
371
+ // before_action :other
372
+ succCall .getExpr ( ) .getEnclosingModule ( ) .getModule ( ) =
373
+ predCall .getExpr ( ) .getEnclosingModule ( ) .getModule ( ) .getASubClass + ( )
374
+ )
375
+ }
376
+
350
377
/**
351
378
* Holds if `pred` is called before `succ` in the callback chain for action `action`.
352
379
* `pred` and `succ` may be methods bound to callbacks or controller actions.
@@ -381,6 +408,5 @@ module Filters {
381
408
* Holds if `pred` is called before `succ` in the callback chain for some action.
382
409
* `pred` and `succ` may be methods bound to callbacks or controller actions.
383
410
*/
384
- cached
385
411
predicate next ( Method pred , Method succ ) { next ( _, pred , succ ) }
386
412
}
0 commit comments