AST: add MethodCall as a subclass of Call

This commit is contained in:
Arthur Baars
2021-02-22 12:31:11 +01:00
parent 5fe7bd57fa
commit 79bb20b31f
12 changed files with 89 additions and 73 deletions

View File

@@ -9,32 +9,6 @@ class Call extends Expr {
override string getAPrimaryQlClass() { result = "Call" }
/**
* Gets the receiver of this call, if any. For example:
*
* ```rb
* foo.bar
* Baz::qux
* corge()
* ```
*
* The result for the call to `bar` is the `Expr` for `foo`; the result for
* the call to `qux` is the `Expr` for `Baz`; for the call to `corge` there
* is no result.
*/
final Expr getReceiver() { result = range.getReceiver() }
/**
* Gets the name of the method being called. For example, in:
*
* ```rb
* foo.bar x, y
* ```
*
* the result is `"bar"`.
*/
final string getMethodName() { result = range.getMethodName() }
/**
* Gets the `n`th argument of this method call. In the following example, the
* result for n=0 is the `IntegerLiteral` 0, while for n=1 the result is a
@@ -44,6 +18,7 @@ class Call extends Expr {
* `getKeywordArgument(string keyword)` predicate.
* ```rb
* foo(0, bar: 1)
* yield 0, bar: 1
* ```
*/
final Expr getArgument(int n) { result = range.getArgument(n) }
@@ -73,6 +48,41 @@ class Call extends Expr {
* Gets the number of arguments of this method call.
*/
final int getNumberOfArguments() { result = count(this.getAnArgument()) }
}
/**
* A method call.
*/
class MethodCall extends Call {
override MethodCall::Range range;
override string getAPrimaryQlClass() { result = "MethodCall" }
/**
* Gets the receiver of this call, if any. For example:
*
* ```rb
* foo.bar
* Baz::qux
* corge()
* ```
*
* The result for the call to `bar` is the `Expr` for `foo`; the result for
* the call to `qux` is the `Expr` for `Baz`; for the call to `corge` there
* is no result.
*/
final Expr getReceiver() { result = range.getReceiver() }
/**
* Gets the name of the method being called. For example, in:
*
* ```rb
* foo.bar x, y
* ```
*
* the result is `"bar"`.
*/
final string getMethodName() { result = range.getMethodName() }
/**
* Gets the block of this method call, if any.
@@ -89,7 +99,7 @@ class Call extends Expr {
* a[0]
* ```
*/
class ElementReference extends Call, @element_reference {
class ElementReference extends MethodCall, @element_reference {
final override ElementReference::Range range;
final override string getAPrimaryQlClass() { result = "ElementReference" }
@@ -117,7 +127,7 @@ class YieldCall extends Call, @yield {
* end
* ```
*/
class SuperCall extends Call {
class SuperCall extends MethodCall {
final override SuperCall::Range range;
final override string getAPrimaryQlClass() { result = "SuperCall" }

View File

@@ -6,26 +6,34 @@ private import codeql_ruby.ast.internal.Variable
module Call {
abstract class Range extends Expr::Range {
abstract Expr getArgument(int n);
override predicate child(string label, AstNode::Range child) {
label = "getArgument" and child = getArgument(_)
}
}
}
module MethodCall {
abstract class Range extends Call::Range {
abstract Block getBlock();
abstract Expr getReceiver();
abstract string getMethodName();
abstract Expr getArgument(int n);
abstract Block getBlock();
override string toString() { result = "call to " + this.getMethodName() }
final override predicate child(string label, AstNode::Range child) {
label = "getReceiver" and child = getReceiver()
super.child(label, child)
or
label = "getArgument" and child = getArgument(_)
label = "getReceiver" and child = getReceiver()
or
label = "getBlock" and child = getBlock()
}
}
private class IdentifierCallRange extends Call::Range, @token_identifier {
private class IdentifierCallRange extends MethodCall::Range, @token_identifier {
final override Generated::Identifier generated;
IdentifierCallRange() { vcall(this) and not access(this, _) }
@@ -39,7 +47,7 @@ module Call {
final override Block getBlock() { none() }
}
private class ScopeResolutionIdentifierCallRange extends Call::Range, @scope_resolution {
private class ScopeResolutionIdentifierCallRange extends MethodCall::Range, @scope_resolution {
final override Generated::ScopeResolution generated;
Generated::Identifier identifier;
@@ -57,7 +65,7 @@ module Call {
final override Block getBlock() { none() }
}
private class RegularCallRange extends Call::Range, @call {
private class RegularCallRange extends MethodCall::Range, @call {
final override Generated::Call generated;
final override Expr getReceiver() {
@@ -88,7 +96,7 @@ module Call {
}
module ElementReference {
class Range extends Call::Range, @element_reference {
class Range extends MethodCall::Range, @element_reference {
final override Generated::ElementReference generated;
final override Expr getReceiver() { result = generated.getObject() }
@@ -107,18 +115,14 @@ module YieldCall {
class Range extends Call::Range, @yield {
final override Generated::Yield generated;
final override Expr getReceiver() { none() }
final override string getMethodName() { result = "yield" }
final override Expr getArgument(int n) { result = generated.getChild().getChild(n) }
final override Block getBlock() { none() }
final override string toString() { result = "yield ..." }
}
}
module SuperCall {
abstract class Range extends Call::Range { }
abstract class Range extends MethodCall::Range { }
private class SuperTokenCallRange extends SuperCall::Range, @token_super {
final override Generated::Super generated;