diff --git a/ql/src/codeql_ruby/ast/Expr.qll b/ql/src/codeql_ruby/ast/Expr.qll index 3073501e477..e48f091dfd1 100644 --- a/ql/src/codeql_ruby/ast/Expr.qll +++ b/ql/src/codeql_ruby/ast/Expr.qll @@ -12,6 +12,18 @@ class Expr extends Stmt { Expr() { this = range } } +/** + * A reference to the current object. For example: + * - `self == other` + * - `self.method_name` + * - `def self.method_name ... end` + */ +class Self extends Expr, @token_self { + override Self::Range range; + + final override string getAPrimaryQlClass() { result = "Self" } +} + /** * A literal. * diff --git a/ql/src/codeql_ruby/ast/internal/AST.qll b/ql/src/codeql_ruby/ast/internal/AST.qll index d92810b8e2f..38df294bf98 100644 --- a/ql/src/codeql_ruby/ast/internal/AST.qll +++ b/ql/src/codeql_ruby/ast/internal/AST.qll @@ -47,8 +47,6 @@ module AstNode { or this instanceof Generated::BareString or - this instanceof Generated::Self - or this instanceof Generated::Float or this instanceof Generated::Superclass diff --git a/ql/src/codeql_ruby/ast/internal/Expr.qll b/ql/src/codeql_ruby/ast/internal/Expr.qll index b61d54835ee..7b848910580 100644 --- a/ql/src/codeql_ruby/ast/internal/Expr.qll +++ b/ql/src/codeql_ruby/ast/internal/Expr.qll @@ -6,6 +6,14 @@ module Expr { abstract class Range extends Stmt::Range { } } +module Self { + class Range extends Expr::Range, @token_self { + final override Generated::Self generated; + + final override string toString() { result = "self" } + } +} + module Literal { abstract class Range extends Expr::Range { abstract string getValueText(); diff --git a/ql/test/library-tests/ast/calls/calls.expected b/ql/test/library-tests/ast/calls/calls.expected index 893e3fb4e99..813b19f1ba8 100644 --- a/ql/test/library-tests/ast/calls/calls.expected +++ b/ql/test/library-tests/ast/calls/calls.expected @@ -74,7 +74,6 @@ callsWithNoReceiverArgumentsOrBlock | calls.rb:286:5:286:9 | call to super | super | | calls.rb:287:5:287:11 | call to super | super | | calls.rb:303:5:303:7 | call to foo | foo | -| calls.rb:304:5:304:14 | call to super | super | | calls.rb:305:5:305:9 | call to super | super | callsWithArguments | calls.rb:14:1:14:11 | call to foo | foo | 0 | calls.rb:14:5:14:5 | 0 | @@ -174,6 +173,7 @@ callsWithReceiver | calls.rb:275:7:275:12 | call to bar | calls.rb:275:7:275:7 | X | | calls.rb:279:11:279:16 | call to bar | calls.rb:279:11:279:11 | X | | calls.rb:303:5:303:13 | call to super | calls.rb:303:5:303:7 | call to foo | +| calls.rb:304:5:304:14 | call to super | calls.rb:304:5:304:8 | self | | calls.rb:305:5:305:15 | call to super | calls.rb:305:5:305:9 | call to super | callsWithBlock | calls.rb:17:1:17:17 | call to foo | calls.rb:17:5:17:17 | { ... } | diff --git a/ql/test/library-tests/ast/calls/calls.rb b/ql/test/library-tests/ast/calls/calls.rb index c38896ccf47..fa44b5fad0b 100644 --- a/ql/test/library-tests/ast/calls/calls.rb +++ b/ql/test/library-tests/ast/calls/calls.rb @@ -301,7 +301,7 @@ end class AnotherClass def another_method foo.super - self.super # TODO: this shows up as a call without a receiver, but that should be fixed once we handle `self` expressions + self.super super.super # we expect the receiver to be a SuperCall, while the outer call should not (it's just a regular Call) end -end \ No newline at end of file +end