Skip to content

Commit

Permalink
NodePattern: Fix $<>
Browse files Browse the repository at this point in the history
  • Loading branch information
marcandre authored and bbatsov committed Apr 29, 2019
1 parent 87a6ec4 commit 666587c
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 3 deletions.
11 changes: 8 additions & 3 deletions lib/rubocop/node_pattern.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ class NodePattern
class Compiler
SYMBOL = %r{:(?:[\w+@*/?!<>=~|%^-]+|\[\]=?)}.freeze
IDENTIFIER = /[a-zA-Z_][a-zA-Z0-9_-]*/.freeze
META = /\(|\)|\{|\}|\[|\]|\<|\>|\$\.\.\.|\$|!|\^|\.\.\./.freeze
META = Regexp.union(%w"( ) { } [ ] $< < > $... $ ! ^ ...").freeze
NUMBER = /-?\d+(?:\.\d+)?/.freeze
STRING = /".+?"/.freeze
METHOD_NAME = /\#?#{IDENTIFIER}[\!\?]?\(?/.freeze
Expand Down Expand Up @@ -143,7 +143,9 @@ class Compiler
line = __LINE__
ANY_ORDER_TEMPLATE = ERB.new <<-RUBY.strip_indent.gsub("-%>\n", '%>')
<% if capture_rest %>(<%= capture_rest %> = []) && <% end -%>
<%= CUR_NODE %>.children[<%= range %>].each_with_object({}) { |<%= child %>, <%= matched %>|
<% if capture_all %>(<%= capture_all %> = <% end -%>
<%= CUR_NODE %>.children[<%= range %>]<% if capture_all %>)<% end -%>
.each_with_object({}) { |<%= child %>, <%= matched %>|
case
<% patterns.each_with_index do |pattern, i| -%>
when !<%= matched %>[<%= i %>] && <%=
Expand Down Expand Up @@ -234,6 +236,7 @@ def variadic_seq_term
case token
when CAPTURED_REST then compile_captured_ellipsis
when REST then compile_ellipsis
when '$<' then compile_any_order(next_capture)
when '<' then compile_any_order
else [1, compile_expr(token)]
end
Expand Down Expand Up @@ -351,7 +354,8 @@ def compile_ellipsis
[0..Float::INFINITY, 'true']
end

def compile_any_order # rubocop:disable Metrics/MethodLength
# rubocop:disable Metrics/MethodLength
def compile_any_order(capture_all = nil)
rest = capture_rest = nil
patterns = []
with_temp_variables do |child, matched|
Expand All @@ -368,6 +372,7 @@ def compile_any_order # rubocop:disable Metrics/MethodLength
->(range) { ANY_ORDER_TEMPLATE.result(binding) }]
end
end
# rubocop:enable Metrics/MethodLength

def insure_same_captures(enum, what)
return to_enum __method__, enum, what unless block_given?
Expand Down
10 changes: 10 additions & 0 deletions spec/rubocop/node_pattern_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@

describe 'yaml compatibility' do
let(:instance) do
$VERBOSE = false
YAML.safe_load(YAML.dump(super()), [described_class])
end
let(:ruby) { 'obj.method' }
Expand Down Expand Up @@ -1354,6 +1355,15 @@ def withargs(foo, bar, qux)
it_behaves_like 'single capture'
end

context 'captured' do
context 'without ellipsis' do
let(:pattern) { '(array sym $<int int _ _>)' }
let(:captured_val) { node.children.last(4) }

it_behaves_like 'single capture'
end
end

context 'doubled' do
context 'separated by fixed argument' do
let(:pattern) { '(array <(str $_) (sym $_)> $_ <(int 3) (int $_)>)' }
Expand Down

0 comments on commit 666587c

Please sign in to comment.