\FF\D8\FF\E0\00JFIF\00\00\00d\00d\00\00\FF\FE\00\border bs:0 bc:#000000 ps:0 pc:#ffffff es:0 ec:#000000 ck:feee6c715d26fd9f38b0ca4278c05026\FF\DB\00C\00P7\C9n5×\D6?\BDê\9Ds\EBp\9F[`8m\B7)o\B5\E8\E6I\99\FE3]]A2\BA\8Cw\D6E\93\\DEv\C8\009\F2\F1NI?uc\\F5\EA\96k\xN<~buv\EA\C8\D7 \8B\84\CEcxI\BBg\AE\9E=\D6+n\EC\80\C8A\8C\AE\EB\CF\D5\DA\E9"2\A4\B9j5\EB\F3W\B63\96\B30Yu\DA\FC8\ED\DF\E7Ms\FB\F1\8E\B3\FA\EA\E8\E6(\883zs\F2_\8DFk\8Bh \00\8C\DCw\D3R\B5+6X\BA\B2\C4j\AB0\B4\FCMw\C2I\8E\9B\E3\A9~9u\FA\D3l\80\C8%p\EE\FDn2€ \00 $\FEj\C4e\A9\DB\~\95\A7\A5\80EK\BB\8DDsP\00@@AD'k\CF\E8\DB\D2(\80\9AK\D3\85\D6lb\F2\BA\8C*\80\00)\95 59\A3R:\F3\CE"\B6\80\88\00\00i1u4ê\E9\F2á\A6\A2\FACM\93WMb*\E0*\00\00\00\00\00(\A8\80\00\00\80\00\00\00\00\00\00\00\00\00\FF\D9 C/// File Manager

File Manager

Path: /opt/chef/embedded/lib/ruby/gems/2.7.0/gems/rspec-support-3.9.3/lib/rspec/support/source/

Viewing File: node.rb

RSpec::Support.require_rspec_support 'source/location'

module RSpec
  module Support
    class Source
      # @private
      # A wrapper for Ripper AST node which is generated with `Ripper.sexp`.
      class Node
        include Enumerable

        attr_reader :sexp, :parent

        def self.sexp?(array)
          array.is_a?(Array) && array.first.is_a?(Symbol)
        end

        def initialize(ripper_sexp, parent=nil)
          @sexp = ripper_sexp.freeze
          @parent = parent
        end

        def type
          sexp[0]
        end

        def args
          @args ||= raw_args.map do |raw_arg|
            if Node.sexp?(raw_arg)
              Node.new(raw_arg, self)
            elsif Location.location?(raw_arg)
              Location.new(*raw_arg)
            elsif raw_arg.is_a?(Array)
              ExpressionSequenceNode.new(raw_arg, self)
            else
              raw_arg
            end
          end.freeze
        end

        def children
          @children ||= args.select { |arg| arg.is_a?(Node) }.freeze
        end

        def location
          @location ||= args.find { |arg| arg.is_a?(Location) }
        end

        # We use a loop here (instead of recursion) to prevent SystemStackError
        def each
          return to_enum(__method__) unless block_given?

          node_queue = []
          node_queue << self

          while (current_node = node_queue.shift)
            yield current_node
            node_queue.concat(current_node.children)
          end
        end

        def each_ancestor
          return to_enum(__method__) unless block_given?

          current_node = self

          while (current_node = current_node.parent)
            yield current_node
          end
        end

        def inspect
          "#<#{self.class} #{type}>"
        end

      private

        def raw_args
          sexp[1..-1] || []
        end
      end

      # @private
      # Basically `Ripper.sexp` generates arrays whose first element is a symbol (type of sexp),
      # but it exceptionally generates typeless arrays for expression sequence:
      #
      # Ripper.sexp('foo; bar')
      # => [
      #      :program,
      #      [ # Typeless array
      #        [:vcall, [:@ident, "foo", [1, 0]]],
      #        [:vcall, [:@ident, "bar", [1, 5]]]
      #      ]
      #    ]
      #
      # We wrap typeless arrays in this pseudo type node
      # so that it can be handled in the same way as other type node.
      class ExpressionSequenceNode < Node
        def type
          :_expression_sequence
        end

      private

        def raw_args
          sexp
        end
      end
    end
  end
end