Add SuperCall class for calls to super

This commit is contained in:
Nick Rolfe
2021-01-26 18:03:13 +00:00
parent d19053deda
commit 7ac46bf8f8
7 changed files with 126 additions and 5 deletions

View File

@@ -108,6 +108,22 @@ class YieldCall extends Call, @yield {
final override string getAPrimaryQlClass() { result = "YieldCall" }
}
/**
* A call to `super`.
* ```rb
* class Foo < Bar
* def baz
* super
* end
* end
* ```
*/
class SuperCall extends Call {
final override SuperCall::Range range;
final override string getAPrimaryQlClass() { result = "SuperCall" }
}
/**
* A block argument in a method call.
* ```rb

View File

@@ -66,6 +66,47 @@ module YieldCall {
}
}
module SuperCall {
abstract class Range extends Call::Range { }
private class SuperTokenCallRange extends SuperCall::Range, @token_super {
final override Generated::Super generated;
SuperTokenCallRange() { vcall(this) and not access(this, _) }
final override Expr getReceiver() { none() }
final override string getMethodName() { result = generated.getValue() }
final override ScopeResolution getMethodScopeResolution() { none() }
final override Expr getArgument(int n) { none() }
final override Block getBlock() { none() }
}
private class RegularSuperCallRange extends SuperCall::Range, @call {
final override Generated::Call generated;
RegularSuperCallRange() {
generated = this and
generated.getMethod() instanceof Generated::Super
}
final override Expr getReceiver() { result = generated.getReceiver() }
final override string getMethodName() {
result = generated.getMethod().(Generated::Super).getValue()
}
final override ScopeResolution getMethodScopeResolution() { none() }
final override Expr getArgument(int n) { result = generated.getArguments().getChild(n) }
final override Block getBlock() { result = generated.getBlock() }
}
}
module BlockArgument {
class Range extends Expr::Range, @block_argument {
final override Generated::BlockArgument generated;

View File

@@ -125,6 +125,11 @@ private module Cached {
not scope.(CapturingScope).inherits(name, _)
}
// Token types that can be accesses/vcalls
private class AccessTokenUnion = @token_identifier or @token_super;
private class AccessToken extends Generated::Token, AccessTokenUnion { }
/**
* Holds if `i` is an `identifier` node occurring in the context where it
* should be considered a VCALL. VCALL is the term that MRI/Ripper uses
@@ -139,7 +144,7 @@ private module Cached {
* ```
*/
cached
predicate vcall(Generated::Identifier i) {
predicate vcall(AccessToken i) {
i = any(Generated::ArgumentList x).getChild(_)
or
i = any(Generated::Array x).getChild(_)
@@ -266,7 +271,7 @@ private module Cached {
}
cached
predicate access(Generated::Identifier access, Variable variable) {
predicate access(AccessToken access, Variable variable) {
exists(string name | name = access.getValue() |
variable = enclosingScope(access).getVariable(name) and
not strictlyBefore(access.getLocation(), variable.getLocation()) and