class RuboCop::NodePattern::Compiler::Sequence

@private Builds Ruby code for a sequence (head *first_terms variadic_term *last_terms)

Public Class Methods

new(compiler, *arity_term_list) click to toggle source
Calls superclass method
# File lib/rubocop/node_pattern.rb, line 309
def initialize(compiler, *arity_term_list)
  @arities, @terms = arity_term_list.transpose

  super(compiler)
  @variadic_index = @arities.find_index { |a| a.is_a?(Range) }
  fail_due_to 'multiple variable patterns in same sequence' \
    if @variadic_index && !@arities.one? { |a| a.is_a?(Range) }
end

Public Instance Methods

compile() click to toggle source
# File lib/rubocop/node_pattern.rb, line 318
def compile
  [
    compile_guard_clause,
    compile_child_nb_guard,
    compile_seq_head,
    *compile_first_terms,
    compile_variadic_term,
    *compile_last_terms
  ].compact.join(" &&\n") << SEQ_HEAD_GUARD
end

Private Instance Methods

compile_child_nb_guard() click to toggle source
# File lib/rubocop/node_pattern.rb, line 355
def compile_child_nb_guard
  fixed = first_terms_arity + last_terms_arity
  min = fixed + variadic_term_min_arity
  op = if @variadic_index
         max_variadic = @arities[@variadic_index].end
         if max_variadic != Float::INFINITY
           range = min..fixed + max_variadic
           return "(#{range}).cover?(#{CUR_NODE}.children.size)"
         end
         '>='
       else
         '=='
       end
  "#{CUR_NODE}.children.size #{op} #{min}"
end
compile_first_terms() click to toggle source
# File lib/rubocop/node_pattern.rb, line 389
def compile_first_terms
  first_terms_range { |range| compile_terms(range, 0) }
end
compile_last_terms() click to toggle source
# File lib/rubocop/node_pattern.rb, line 393
def compile_last_terms
  last_terms_range { |r| compile_terms(r, -last_terms_arity) }
end
compile_seq_head() click to toggle source
# File lib/rubocop/node_pattern.rb, line 380
def compile_seq_head
  return unless seq_head?

  fail_due_to 'sequences can not start with <' \
    if @terms[0].respond_to? :call

  with_seq_head_context(@terms[0])
end
compile_terms(index_range, start) click to toggle source
# File lib/rubocop/node_pattern.rb, line 397
def compile_terms(index_range, start)
  index_range.map do |i|
    current = start
    start += @arities.fetch(i)
    term(i, current..start - 1)
  end
end
compile_variadic_term() click to toggle source
# File lib/rubocop/node_pattern.rb, line 405
def compile_variadic_term
  variadic_arity { |arity| term(@variadic_index, arity) }
end
first_terms_arity() click to toggle source
# File lib/rubocop/node_pattern.rb, line 331
def first_terms_arity
  first_terms_range { |r| @arities[r].inject(0, :+) } || 0
end
first_terms_range() { |1..(variadic_index || size) - 1| ... } click to toggle source
# File lib/rubocop/node_pattern.rb, line 343
def first_terms_range
  yield 1..(@variadic_index || @terms.size) - 1 if seq_head?
end
last_terms_arity() click to toggle source
# File lib/rubocop/node_pattern.rb, line 335
def last_terms_arity
  last_terms_range { |r| @arities[r].inject(0, :+) } || 0
end
last_terms_range() { |variadic_index| ... } click to toggle source
# File lib/rubocop/node_pattern.rb, line 347
def last_terms_range
  yield @variadic_index + 1...@terms.size if @variadic_index
end
seq_head?() click to toggle source
# File lib/rubocop/node_pattern.rb, line 351
def seq_head?
  @variadic_index != 0
end
term(index, range) click to toggle source
# File lib/rubocop/node_pattern.rb, line 371
def term(index, range)
  t = @terms[index]
  if t.respond_to? :call
    t.call(range)
  else
    with_child_context(t, range.begin)
  end
end
variadic_arity() { |first..-last_terms_arity - 1| ... } click to toggle source
# File lib/rubocop/node_pattern.rb, line 409
def variadic_arity
  return unless @variadic_index

  first = @variadic_index.positive? ? first_terms_arity : SEQ_HEAD_INDEX
  yield first..-last_terms_arity - 1
end
variadic_term_min_arity() click to toggle source
# File lib/rubocop/node_pattern.rb, line 339
def variadic_term_min_arity
  @variadic_index ? @arities[@variadic_index].begin : 0
end