Ruby: Fix bad join in ActionControllerHelperMethod

```
[2022-01-25 12:35:14] (234s) Tuple counts for ActionController::ActionControllerHelperMethod#class#ff/2@ef816fil after 1.5s:
                      7685     ~0%     {3} r1 = JOIN ActionController::ActionControllerContextCall#ff#shared WITH Method::Method::getName_dispred#ff ON FIRST 1 OUTPUT Rhs.1, Lhs.1 'controllerClass', Lhs.0 'this'
                      13198    ~0%     {3} r2 = JOIN r1 WITH Constant::ConstantValue::getStringOrSymbol_dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Lhs.1 'controllerClass', Lhs.2 'this', Rhs.1
                      15835365 ~4%     {5} r3 = JOIN r2 WITH AST::AstNode::getEnclosingModule_dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, "helper_method", Lhs.0 'controllerClass', Lhs.1 'this', Lhs.2
                      12943    ~1%     {4} r4 = JOIN r3 WITH Call::MethodCall::getMethodName_dispred#ff ON FIRST 2 OUTPUT Lhs.4, Lhs.2 'controllerClass', Lhs.3 'this', Lhs.0
                      1146184  ~0%     {4} r5 = JOIN r4 WITH Expr::Expr::getConstantValue_dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Lhs.3, Rhs.1, Lhs.1 'controllerClass', Lhs.2 'this'
                      212      ~0%     {2} r6 = JOIN r5 WITH project#Call::Call::getArgument_dispred#fff ON FIRST 2 OUTPUT Lhs.3 'this', Lhs.2 'controllerClass'
                                       return r6
```

Joining on enclosing module and name simultaneously yields a much better join.
This commit is contained in:
Tom Hvitved
2022-01-25 13:00:13 +01:00
parent 26d9848fca
commit 49488fa0a0

View File

@@ -202,6 +202,21 @@ class ActionControllerRedirectResponse extends HTTP::Server::HttpRedirectRespons
}
}
pragma[nomagic]
private predicate isActionControllerMethod(Method m, string name, ActionControllerControllerClass c) {
m.getName() = name and
m.getEnclosingModule() = c
}
pragma[nomagic]
private predicate actionControllerHasHelperMethodCall(ActionControllerControllerClass c, string name) {
exists(MethodCall mc |
mc.getMethodName() = "helper_method" and
mc.getAnArgument().getConstantValue().isStringOrSymbol(name) and
mc.getEnclosingModule() = c
)
}
/**
* A method in an `ActionController` class that is accessible from within a
* Rails view as a helper method. For instance, in:
@@ -222,11 +237,9 @@ class ActionControllerHelperMethod extends Method {
private ActionControllerControllerClass controllerClass;
ActionControllerHelperMethod() {
this.getEnclosingModule() = controllerClass and
exists(MethodCall helperMethodMarker |
helperMethodMarker.getMethodName() = "helper_method" and
helperMethodMarker.getAnArgument().getConstantValue().isStringOrSymbol(this.getName()) and
helperMethodMarker.getEnclosingModule() = controllerClass
exists(string name |
isActionControllerMethod(this, name, controllerClass) and
actionControllerHasHelperMethodCall(controllerClass, name)
)
}