123456789_123456789_123456789_123456789_123456789_

Class: RSpec::Core::Formatters::SnippetExtractor Private

Do not use. This class is for internal use only.
Relationships & Source Files
Inherits: Object
Defined in: rspec-core/lib/rspec/core/formatters/snippet_extractor.rb

Constant Summary

Class Method Summary

Instance Attribute Summary

Instance Method Summary

Class Method Details

.extract_expression_lines_at(file_path, beginning_line_number)

:nocov:

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters/snippet_extractor.rb', line 122

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

.extract_line_at(file_path, line_number)

Raises:

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters/snippet_extractor.rb', line 9

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

.least_indentation_from(lines)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters/snippet_extractor.rb', line 128

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

.source_from_file(path)

Raises:

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters/snippet_extractor.rb', line 16

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

Instance Attribute Details

#beginning_line_number (readonly)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters/snippet_extractor.rb', line 24

attr_reader :source, :beginning_line_number, :max_line_count

#max_line_count (readonly)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters/snippet_extractor.rb', line 24

attr_reader :source, :beginning_line_number, :max_line_count

#source (readonly)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters/snippet_extractor.rb', line 24

attr_reader :source, :beginning_line_number, :max_line_count

Instance Method Details

#expression_lines

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters/snippet_extractor.rb', line 41

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

#expression_node (private)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters/snippet_extractor.rb', line 95

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

#expression_outmost_node?(node) ⇒ Boolean (private)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters/snippet_extractor.rb', line 107

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

#line_range_of_expression (private)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters/snippet_extractor.rb', line 55

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

#line_range_of_location_nodes_in_expression (private)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters/snippet_extractor.rb', line 87

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

#location_nodes_at_beginning_line (private)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters/snippet_extractor.rb', line 117

def location_nodes_at_beginning_line
  source.[beginning_line_number]
end

#unclosed_tokens_in_line_range(line_range) (private)

[ GitHub ]

  
# File 'rspec-core/lib/rspec/core/formatters/snippet_extractor.rb', line 70

def unclosed_tokens_in_line_range(line_range)
  tokens = FlatMap.flat_map(line_range) do |line_number|
    source.[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