Skip to content

Commit

Permalink
Merge pull request #71 from pocke/csend
Browse files Browse the repository at this point in the history
Detect safe navigation operator as a method call
  • Loading branch information
soutaro authored May 16, 2020
2 parents 6bfde87 + 2578051 commit 99a0012
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 21 deletions.
12 changes: 7 additions & 5 deletions lib/querly/pattern/expr.rb
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,8 @@ def initialize(receiver:, name:, block:, args: Argument::AnySeq.new)

def =~(pair)
# Skip send node with block
if pair.node.type == :send && pair.parent
type = pair.node.type
if (type == :send || type == :csend) && pair.parent
if pair.parent.node.type == :block
if pair.parent.node.children.first.equal? pair.node
return false
Expand Down Expand Up @@ -176,7 +177,7 @@ def test_node(node)
node = node.children.first if node&.type == :block

case node&.type
when :send
when :send, :csend
return false unless test_name(node)
return false unless test_receiver(node.children[0])
return false unless test_args(node.children.drop(2), args)
Expand Down Expand Up @@ -290,7 +291,8 @@ def test_node(node)
if receiver.test_node(node)
true
else
node&.type == :send && test_node(node.children[0])
type = node&.type
(type == :send || type == :csend) && test_node(node.children[0])
end
end
end
Expand All @@ -315,7 +317,7 @@ def =~(pair)
# We don't want lvar without method call
# Skips when the node is not receiver of :send
parent_node = pair.parent&.node
if parent_node && parent_node.type == :send && parent_node.children.first.equal?(node)
if parent_node && (parent_node.type == :send || parent_node.type == :csend) && parent_node.children.first.equal?(node)
test_node(node)
end
else
Expand All @@ -325,7 +327,7 @@ def =~(pair)

def test_node(node)
case node&.type
when :send
when :send, :csend
node.children[1] == name
when :lvar
node.children.first == name
Expand Down
39 changes: 23 additions & 16 deletions test/pattern_test_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -241,40 +241,42 @@ def test_call_with_names
end

def test_call_without_receiver
nodes = query_pattern("foo", "foo; bar.foo")
assert_equal 2, nodes.size
nodes = query_pattern("foo", "foo; bar.foo; bar&.foo")
assert_equal 3, nodes.size
end

def test_call_with_any_receiver
nodes = query_pattern("_.foo", "foo; bar.foo")
assert_equal 1, nodes.size
assert_equal ruby("bar.foo"), nodes.first
nodes = query_pattern("_.foo", "foo; bar.foo; bar&.foo")
assert_equal 2, nodes.size
assert_equal [ruby("bar.foo"), ruby("bar&.foo")], nodes
end

def test_call_any_method
nodes = query_pattern("foo._", "foo; foo.bar; foo.baz")
assert_equal 2, nodes.size
assert_equal [ruby("foo.bar"), ruby("foo.baz")], nodes
nodes = query_pattern("foo._", "foo; foo.bar; foo.baz; foo&.baz")
assert_equal 3, nodes.size
assert_equal [ruby("foo.bar"), ruby("foo.baz"), ruby("foo&.baz")], nodes
end

def test_call_any_method_with_args
nodes = query_pattern("foo._(baz)", "foo.bar(baz); foo.bar(bar)")
assert_equal 1, nodes.size
assert_equal ruby("foo.bar(baz)"), nodes.first
nodes = query_pattern("foo._(baz)", "foo.bar(baz); foo.bar(bar); foo&.bar(baz)")
assert_equal 2, nodes.size
assert_equal [ruby("foo.bar(baz)"), ruby("foo&.bar(baz)")], nodes
end

def test_call_any_method_with_block
nodes = query_pattern("foo._{}", "foo.bar; foo.baz{}")
assert_equal 1, nodes.size
assert_equal ruby("foo.baz{}"), nodes.first
nodes = query_pattern("foo._{}", "foo.bar; foo.baz{}; foo&.foobar{}")
assert_equal 2, nodes.size
assert_equal [ruby("foo.baz{}"), ruby("foo&.foobar{}")], nodes
end

def test_vcall
# Vcall pattern matches with local variable
nodes = query_pattern("foo", "foo = 1; foo.bar")
assert_equal 1, nodes.size
nodes = query_pattern("foo", "foo = 1; foo.bar; foo&.bar")
assert_equal 2, nodes.size
assert_equal :lvar, nodes.first.type
assert_equal :foo, nodes.first.children.first
assert_equal :lvar, nodes[1].type
assert_equal :foo, nodes[1].children.first
end

def test_vcall2
Expand Down Expand Up @@ -345,6 +347,11 @@ def test_any_receiver5
assert_equal Set.new([ruby("a.b.b"), ruby("a.b")]), Set.new(nodes)
end

def test_any_receiver6
nodes = query_pattern("f...h", "f&.g&.h")
assert_equal [ruby("f&.g&.h")], nodes
end

def test_self
nodes = query_pattern("self.f", "f(); self.f(); foo.f()")
assert_equal Set.new([ruby("self.f"), ruby("f()")]), Set.new(nodes)
Expand Down

0 comments on commit 99a0012

Please sign in to comment.