Files
codeql/ruby/ql/test/library-tests/ast/calls/calls.rb

343 lines
5.2 KiB
Ruby

# call with no receiver, arguments, or block
foo()
# call whose name is a scope resolution
Foo::bar()
# call whose name is a global scope resolution
::bar()
# call with a receiver, no arguments or block
123.bar
# call with arguments
foo 0, 1, 2
# call with curly brace block
foo { |x| x + 1 }
# call with do block
foo do |x|
x + 1
end
# call with receiver, arguments, and a block
123.bar('foo') do |x|
x + 1
end
# a yield call
def method_that_yields
yield
end
# a yield call with arguments
def another_method_that_yields
yield 100, 200
end
# ------------------------------------------------------------------------------
# Calls without parentheses or arguments are parsed by tree-sitter simply as
# `identifier` nodes (or `scope_resolution` nodes whose `name` field is an
# `identifier), so here we test that our AST library correctly represents them
# as calls in all the following contexts.
# root level (child of program)
foo
X::foo
# in a parenthesized statement
(foo)
(X::foo)
# in an argument list
some_func(foo)
some_func(X::foo)
# in an array
[foo]
[X::foo]
# RHS of an assignment
var1 = foo
var1 = X::foo
# RHS an operator assignment
var1 += bar
var1 += X::bar
# RHS assignment list
var1 = foo, X::bar
# in a begin-end block
begin
foo
X::foo
end
# in a BEGIN block
BEGIN { foo; X::bar }
# in an END block
END { foo; X::bar }
# both operands of a binary operation
foo + X::bar
# unary operand
!foo
~X::bar
# in a curly brace block
foo() { bar; X::baz }
# in a do-end block
foo() do
bar
X::baz
end
# the receiver in a call can itself be a call
foo.bar()
bar.baz()
# the value for a case expr
# and the when pattern and body
case foo
when bar
baz
end
case X::foo
when X::bar
X::baz
end
# in a class definition
class MyClass
foo
X::bar
end
# in a superclass
class MyClass < foo
end
class MyClass2 < X::foo
end
# in a singleton class value or body
class << foo
bar
end
class << X::foo
X::bar
end
# in a method body
def some_method
foo
X::bar
end
# in a singleton method object or body
def foo.some_method
bar
X::baz
end
# in the default value for a keyword parameter
def method_with_keyword_param(keyword: foo)
end
def method_with_keyword_param2(keyword: X::foo)
end
# in the default value for an optional parameter
def method_with_optional_param(param = foo)
end
def method_with_optional_param2(param = X::foo)
end
# in a module
module SomeModule
foo
X::bar
end
# ternary if: condition, consequence, and alternative can all be calls
foo ? bar : baz
X::foo ? X::bar : X::baz
# if/elsif/else conditions and bodies
if foo
wibble
elsif bar
wobble
else
wabble
end
if X::foo
X::wibble
elsif X::bar
X::wobble
else
X::wabble
end
# if-modifier condition/body
bar if foo
X::bar if X::foo
# unless condition/body
unless foo
bar
end
unless X::foo
X::bar
end
# unless-modifier condition/body
bar unless foo
X::bar unless X::foo
# while loop condition/body
while foo do
bar
end
while X::foo do
X::bar
end
# while-modifier loop condition/body
bar while foo
X::bar while X::foo
# until loop condition/body
until foo do
bar
end
until X::foo do
X::bar
end
# until-modifier loop condition/body
bar until foo
X::bar until X::foo
# the collection being iterated over in a for loop, and the body
for x in bar
baz
end
for x in X::bar
X::baz
end
# in an array indexing operation, both the object and the index can be calls
foo[bar]
X::foo[X::bar]
# interpolation
"foo-#{bar}-#{X::baz}"
# the scope in a scope resolution
foo::Bar
X::foo::Bar
# in a range
foo..bar
X::foo..X::bar
# the key/value in a hash pair
{ foo => bar, X::foo => X::bar }
# rescue exceptions and ensure
begin
rescue foo
ensure bar
end
begin
rescue X::foo
ensure X::bar
end
# rescue-modifier body and handler
foo rescue bar
X::foo rescue X::bar
# block argument
foo(&bar)
foo(&X::bar)
# splat argument
foo(*bar)
foo(*X::bar)
# hash-splat argument
foo(**bar)
foo(**X::bar)
# the value in a keyword argument
foo(blah: bar)
foo(blah: X::bar)
# ------------------------------------------------------------------------------
# calls to `super`
class MyClass
def my_method
super
super()
super 'blah'
super 1, 2, 3
super { |x| x + 1 }
super do |x| x * 2 end
super 4, 5 { |x| x + 100 }
super 6, 7 do |x| x + 200 end
end
end
# ------------------------------------------------------------------------------
# calls to methods simply named `super`, i.e. *not* calls to the same method in
# a parent classs, so these should be Call but not SuperCall
class AnotherClass
def another_method
foo.super
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
# calls without method name
foo.()
foo.(1)
# setter calls
self.foo = 10
foo[0] = 10
self.foo, *self.bar, foo[4] = [1, 2, 3, 4]
a, *foo[5] = [1, 2, 3]
self.count += 1
foo[0] += 1
foo.bar[0, foo.baz, foo.boo + 1] *= 2
# endless method definitions
def foo = bar
def foo() = bar
def foo(x) = bar
def Object.foo = bar
def Object.foo (x) = bar
def foo() = bar rescue (print "error")
# forward parameter and forwarded arguments
def foo(...)
super(...)
end
def foo(a, b, ...)
bar(b, ...)
end
# for loop over nested array
for x, y, z in [[1,2,3], [4,5,6]]
foo x, y, z
end