class DeepCover::Node::SendBase

Public Instance Methods

loc_hash() click to toggle source
# File lib/deep_cover/node/send.rb, line 14
def loc_hash
  hash = super.dup
  selector = hash.delete(:selector)

  # Special case for foo[bar]=baz, but not for foo.[]= bar, baz: we split selector into begin and end
  if base_node.location.dot == nil && [:[], :[]=].include?(message)
    hash[:selector_begin] = selector.resize(1)
    hash[:selector_end] = Parser::Source::Range.new(selector.source_buffer, selector.end_pos - 1, selector.end_pos)
  else
    hash.delete(:dot) if type == :safe_send # Hack. API to get a Parser::AST::Send::Map without the dot is crappy.
    hash[:selector_begin] = selector
  end

  hash
end
rewriting_rules() click to toggle source

Rules must be ordered inner-most first

# File lib/deep_cover/node/send.rb, line 31
def rewriting_rules
  rules = super
  if need_parentheses?
    range = arguments.last.expression.with(begin_pos: loc_hash[:selector_begin].end_pos)
    rules.unshift [range, '(%{node})']
  end
  rules
end

Private Instance Methods

need_parentheses?() click to toggle source

In different circumstances, we need (). Deal with ambiguous cases where a method is hidden by a local. Ex:

foo 42, 'hello'  #=> Works
foo (42), 'hello'  #=> Simplification of what DeepCover would generate, still works
foo = 1; foo 42, 'hello'  #=> works
foo = 1; foo (42), 'hello'  #=> syntax error.
foo = 1; foo((42), 'hello')  #=> works

Deal with do/end block. Ex:

x.foo 42, 43 # => ok
x.foo (42), 43 # => ok
x.foo ((42)), 43 # => ok
x.foo 42, 43 do ; end # => ok
x.foo (42), 43 do ; end # => ok
x.foo ((42)), 43 do ; end # => parse error!
# File lib/deep_cover/node/send.rb, line 56
def need_parentheses?
  true unless
    arguments.empty? || # No issue when no arguments
    loc_hash[:selector_end] || # No issue with foo[bar]= and such
    loc_hash[:operator] || # No issue with foo.bar=
    (receiver && !loc_hash[:dot]) || # No issue with foo + bar
    loc_hash[:begin] # Ok if has parentheses
end