This file is indexed.

/usr/lib/ruby/vendor_ruby/rspec/core/formatters/snippet_extractor.rb is in ruby-rspec-core 3.5.0c3e0m0s0-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
RSpec::Support.require_rspec_core "source"

module RSpec
  module Core
    module Formatters
      # @private
      class SnippetExtractor
        NoSuchFileError = Class.new(StandardError)
        NoSuchLineError = Class.new(StandardError)

        def self.extract_line_at(file_path, line_number)
          source = source_from_file(file_path)
          line = source.lines[line_number - 1]
          raise NoSuchLineError unless line
          line
        end

        def self.source_from_file(path)
          raise NoSuchFileError unless File.exist?(path)
          RSpec.world.source_cache.source_from_file(path)
        end

        if RSpec::Support::RubyFeatures.ripper_supported?
          NoExpressionAtLineError = Class.new(StandardError)

          attr_reader :source, :beginning_line_number, :max_line_count

          def self.extract_expression_lines_at(file_path, beginning_line_number, max_line_count=nil)
            if max_line_count == 1
              [extract_line_at(file_path, beginning_line_number)]
            else
              source = source_from_file(file_path)
              new(source, beginning_line_number, max_line_count).expression_lines
            end
          end

          def initialize(source, beginning_line_number, max_line_count=nil)
            @source = source
            @beginning_line_number = beginning_line_number
            @max_line_count = max_line_count
          end

          def expression_lines
            line_range = line_range_of_expression

            if max_line_count && line_range.count > max_line_count
              line_range = (line_range.begin)..(line_range.begin + max_line_count - 1)
            end

            source.lines[(line_range.begin - 1)..(line_range.end - 1)]
          rescue SyntaxError, NoExpressionAtLineError
            [self.class.extract_line_at(source.path, beginning_line_number)]
          end

          private

          def line_range_of_expression
            @line_range_of_expression ||= begin
              line_range = line_range_of_location_nodes_in_expression
              initial_unclosed_tokens = unclosed_tokens_in_line_range(line_range)
              unclosed_tokens = initial_unclosed_tokens

              until (initial_unclosed_tokens & unclosed_tokens).empty?
                line_range = (line_range.begin)..(line_range.end + 1)
                unclosed_tokens = unclosed_tokens_in_line_range(line_range)
              end

              line_range
            end
          end

          def unclosed_tokens_in_line_range(line_range)
            tokens = FlatMap.flat_map(line_range) do |line_number|
              source.tokens_by_line_number[line_number]
            end

            tokens.each_with_object([]) do |token, unclosed_tokens|
              if token.opening?
                unclosed_tokens << token
              else
                index = unclosed_tokens.rindex do |unclosed_token|
                  unclosed_token.closed_by?(token)
                end
                unclosed_tokens.delete_at(index) if index
              end
            end
          end

          def line_range_of_location_nodes_in_expression
            line_numbers = expression_node.each_with_object(Set.new) do |node, set|
              set << node.location.line if node.location
            end

            line_numbers.min..line_numbers.max
          end

          def expression_node
            raise NoExpressionAtLineError if location_nodes_at_beginning_line.empty?

            @expression_node ||= begin
              common_ancestor_nodes = location_nodes_at_beginning_line.map do |node|
                node.each_ancestor.to_a
              end.reduce(:&)

              common_ancestor_nodes.find { |node| expression_outmost_node?(node) }
            end
          end

          def expression_outmost_node?(node)
            return true unless node.parent
            return false if node.type.to_s.start_with?('@')
            ![node, node.parent].all? do |n|
              # See `Ripper::PARSER_EVENTS` for the complete list of sexp types.
              type = n.type.to_s
              type.end_with?('call') || type.start_with?('method_add_')
            end
          end

          def location_nodes_at_beginning_line
            source.nodes_by_line_number[beginning_line_number]
          end
        else
          # :nocov:
          def self.extract_expression_lines_at(file_path, beginning_line_number, *)
            [extract_line_at(file_path, beginning_line_number)]
          end
          # :nocov:
        end

        def self.least_indentation_from(lines)
          lines.map { |line| line[/^[ \t]*/] }.min
        end
      end
    end
  end
end