class RubyNext::Language::Rewriters::SafeNavigation

Constants

MIN_SUPPORTED_VERSION
NAME
SAFE_LVAR
SYNTAX_PROBE

Public Instance Methods

on_block(node) click to toggle source
Calls superclass method
# File lib/ruby-next/language/rewriters/safe_navigation.rb, line 34
def on_block(node)
  return super(node) unless node.children[0].type == :csend

  context.track!(self)

  super(decsendize(node))
end
on_csend(node) click to toggle source
Calls superclass method
# File lib/ruby-next/language/rewriters/safe_navigation.rb, line 13
def on_csend(node)
  node = super(node)

  context.track! self

  receiver, *args = *node

  new_node = s(:begin,
    node.updated(
      :and,
      [
        process(safe_navigation(receiver)),
        s(:send, safe_lvar, *args)
      ]
    ))

  replace(node.loc.expression, new_node)

  new_node
end
on_numblock(node) click to toggle source
Calls superclass method
# File lib/ruby-next/language/rewriters/safe_navigation.rb, line 42
def on_numblock(node)
  return super(node) unless node.children[0].type == :csend

  context.track!(self)

  super(decsendize(node))
end
on_op_asgn(node) click to toggle source
Calls superclass method
# File lib/ruby-next/language/rewriters/safe_navigation.rb, line 50
def on_op_asgn(node)
  return super(node) unless node.children[0].type == :csend

  context.track!(self)

  super(decsendize(node))
end

Private Instance Methods

decsendize(node) click to toggle source
# File lib/ruby-next/language/rewriters/safe_navigation.rb, line 60
def decsendize(node)
  csend, *children = node.children

  receiver, *other = csend.children

  new_csend = csend.updated(:send, [safe_lvar, *other])

  new_node = s(:begin,
    node.updated(
      :and,
      [
        process(safe_navigation(receiver)),
        process(node.updated(nil, [new_csend, *children]))
      ]
    ))

  replace(node.loc.expression, new_node)

  new_node
end
safe_lvar() click to toggle source
# File lib/ruby-next/language/rewriters/safe_navigation.rb, line 98
def safe_lvar
  s(:lvar, SAFE_LVAR)
end
safe_navigation(node) click to toggle source

Transform: x&.y -> ((tmp = x) || true) && (!tmp.nil? || nil) && tmp.y This allows us to handle `false&.to_s == “false”`

# File lib/ruby-next/language/rewriters/safe_navigation.rb, line 83
def safe_navigation(node)
  s(:begin,
    s(:and,
      s(:begin,
        s(:or,
          s(:begin, s(:lvasgn, SAFE_LVAR, node)),
          s(:true))),
      s(:begin,
        s(:or,
          s(:send,
            s(:send, safe_lvar, :nil?),
            :!),
          s(:nil)))))
end