module Steep module NodeHelper def each_child_node(node, &block) if block node.children.each do |child| if child.is_a?(Parser::AST::Node) yield child end end else enum_for :each_child_node, node end end def each_descendant_node(node, &block) if block each_child_node(node) do |child| yield child each_descendant_node(child, &block) end else enum_for :each_descendant_node, node end end def value_node?(node) case node.type when :self true when :true, :false, :str, :sym, :int, :float, :nil true when :lvar true when :const each_child_node(node).all? {|child| child.type == :cbase || value_node?(child) } when :array each_child_node(node).all? {|child| value_node?(child) } when :hash each_child_node(node).all? do |pair| each_child_node(pair).all? {|child| value_node?(child) } end when :dstr each_child_node(node).all? {|child| value_node?(child)} when :begin each_child_node(node).all? {|child| value_node?(child) } else false end end def deconstruct_if_node(node) if node.type == :if [ node.children[0], node.children[1], node.children[2], _ = node.location ] end end def deconstruct_if_node!(node) deconstruct_if_node(node) or raise end def test_if_node(node) if (a, b, c, d = deconstruct_if_node(node)) yield(a, b, c, d) else false end end def deconstruct_whileish_node(node) case node.type when :while, :until, :while_post, :until_post [ node.children[0], node.children[1], _ = node.location ] end end def deconstruct_whileish_node!(node) deconstruct_whileish_node(node) or raise end def test_whileish_node(node) if (a, b, c = deconstruct_whileish_node(node)) yield(a, b, c) else false end end def deconstruct_case_node(node) case node.type when :case cond, *whens, else_ = node.children [ cond, whens, else_, _ = node.loc ] end end def deconstruct_case_node!(node) deconstruct_case_node(node) or raise end def test_case_node(node) if (a, b, c, d = deconstruct_case_node(node)) yield a, b, c, d else false end end def deconstruct_when_node(node) case node.type when :when *conds, body = node.children [ conds, body, _ = node.loc ] end end def deconstruct_when_node!(node) deconstruct_when_node(node) or raise end def test_when_node(node) if (a, b, c = deconstruct_when_node(node)) yield a, b, c else false end end def deconstruct_rescue_node(node) case node.type when :rescue body, *resbodies, else_ = node.children [ body, resbodies, else_, _ = node.loc ] end end def deconstruct_rescue_node!(node) deconstruct_rescue_node(node) or raise end def test_rescue_node(node) if (a, b, c, d = deconstruct_rescue_node(node)) yield a, b, c, d else false end end def deconstruct_resbody_node(node) case node.type when :resbody [ node.children[0], node.children[1], node.children[2], _ = node.loc ] end end def deconstruct_resbody_node!(node) deconstruct_resbody_node(node) or raise end def test_resbody_node(node) if (a, b, c, d = deconstruct_resbody_node(node)) yield a, b, c, d else false end end def deconstruct_send_node(node) case node.type when :send, :csend receiver, selector, *args = node.children [ receiver, selector, args, _ = node.loc ] end end def deconstruct_send_node!(node) deconstruct_send_node(node) or raise(node.inspect) end def test_send_node(node) if (a, b, c, d = deconstruct_send_node(node)) yield a, b, c, d else false end end def private_send?(node) case node.type when :block, :numblock private_send?(node.children[0]) when :send, :csend receiver, = deconstruct_send_node!(node) if receiver && receiver.type != :self return false end true else raise "Unexpected node is given: #{node.inspect}" end end def deconstruct_sendish_and_block_nodes(*nodes) send_node, block_node = nodes.take(2) if send_node case send_node.type when :send, :csend, :super if block_node case block_node.type when :block, :numblock if send_node.equal?(block_node.children[0]) return [send_node, block_node] end end end [send_node, nil] when :zsuper # zsuper doesn't receive block [send_node, nil] end end end def clone_node(node) children = node.children.map do |child| if child.is_a?(Parser::AST::Node) clone_node(child) else child.dup end end node.updated(nil, children) end end end