Search code examples
rubocoprubocop-nodepattern

Node pattern to match some, but not all nodes within a begin


I'm struggling a bit to write a single node match to detect this sort of condition:

chef_gem 'deep_merge' do
  action :nothing
  compile_time true
end.run_action(:install)

I wrote this pattern initially

def_node_matcher :compile_time_and_run_action?, <<-PATTERN
(send
  $(block
    (send nil? ... )
    (args)
    (begin
      (send nil? :action (sym $_) )
      (send nil? :compile_time (true) )
    )
  ) :run_action (sym $_) )
PATTERN

The problem is the action method and compile_time method could be in any order and there could be additional methods within the begin there:

chef_gem 'deep_merge' do
  compile_time true
  action :nothing
  foo bar
end.run_action(:install)

In the past I've used <> in arrays and hash, but that doesn't seem to work in a begin so something like this won't cut it:

def_node_matcher :compile_time_and_run_action?, <<-PATTERN
(send
  $(block
    (send nil? ... )
    (args)
    <(begin
      ...
      (send nil? :action (sym $_) )
      (send nil? :compile_time (true) )
    )>
  ) :run_action (sym $_) )
PATTERN

Is there a nice way to do this in a single matcher that I'm missing?

-Tim


Solution

  • Using <> is the way to go, but use this for begin's children. I believe this should work:

    def_node_matcher :compile_time_and_run_action?, <<-PATTERN
    (send
      $(block
        (send nil? ... )
        (args)
        (begin <
          (send nil? :action (sym $_) )
          (send nil? :compile_time (true) )
          ...
        >)
      ) :run_action (sym $_) )
    PATTERN