diff --git a/lib/rubocop/node_pattern.rb b/lib/rubocop/node_pattern.rb index c822467c0d6..c427d0d6ecf 100644 --- a/lib/rubocop/node_pattern.rb +++ b/lib/rubocop/node_pattern.rb @@ -180,11 +180,16 @@ def compile_seq(tokens, cur_node, seq_head) # temp variable as 'cur_node' with_temp_node(cur_node) do |init, temp_node| terms = compile_seq_terms(tokens, temp_node) + terms.unshift(compile_guard_clause(temp_node)) - join_terms(init, terms, ' && ') + join_terms(init, terms, " &&\n") end end + def compile_guard_clause(cur_node) + "#{cur_node}.is_a?(RuboCop::AST::Node)" + end + def compile_seq_terms(tokens, cur_node) ret, size = compile_seq_terms_with_size(tokens, cur_node) do |token, terms, index| @@ -444,12 +449,6 @@ def emit_trailing_params params.empty? ? '' : ",#{params}" end - def emit_guard_clause - <<-RUBY - return unless node.is_a?(RuboCop::AST::Node) - RUBY - end - def emit_method_code <<-RUBY return unless #{@match_code} @@ -491,7 +490,6 @@ def def_node_matcher(method_name, pattern_str) compiler = Compiler.new(pattern_str, 'node') src = "def #{method_name}(node = self" \ "#{compiler.emit_trailing_params});" \ - "#{compiler.emit_guard_clause}" \ "#{compiler.emit_method_code};end" location = caller_locations(1, 1).first @@ -556,7 +554,7 @@ def initialize(str) compiler = Compiler.new(str) src = "def match(node0#{compiler.emit_trailing_params});" \ "#{compiler.emit_method_code}end" - instance_eval(src) + instance_eval(src, __FILE__, __LINE__ + 1) end end end diff --git a/spec/rubocop/node_pattern_spec.rb b/spec/rubocop/node_pattern_spec.rb index 2fd33ef7dcf..0f741ea27e5 100644 --- a/spec/rubocop/node_pattern_spec.rb +++ b/spec/rubocop/node_pattern_spec.rb @@ -160,6 +160,13 @@ it_behaves_like 'matching' end + + context 'against a node pattern (bug #5470)' do + let(:pattern) { '(:send (:const ...) ...)' } + let(:ruby) { 'foo' } + + it_behaves_like 'nonmatching' + end end describe 'simple sequence' do @@ -435,6 +442,20 @@ it_behaves_like 'single capture' end + context 'in head position in a sequence against nil (bug #5470)' do + let(:pattern) { '($_ ...)' } + let(:ruby) { '' } + + it_behaves_like 'nonmatching' + end + + context 'in head position in a sequence against literal (bug #5470)' do + let(:pattern) { '(int ($_ ...))' } + let(:ruby) { '42' } + + it_behaves_like 'nonmatching' + end + context 'in non-head position in a sequence' do let(:pattern) { '(send $_ ...)' } let(:ruby) { 'A.method' }