Class: Solargraph::Source::SourceChainer

Inherits:
Object
  • Object
show all
Defined in:
lib/solargraph/source/source_chainer.rb

Overview

Information about a location in a source, including the location’s word and signature, literal values at the base of signatures, and whether the location is inside a string or comment. ApiMaps use Fragments to provide results for completion and definition queries.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(source, position) ⇒ SourceChainer

Returns a new instance of SourceChainer.

Parameters:



26
27
28
29
30
# File 'lib/solargraph/source/source_chainer.rb', line 26

def initialize source, position
  @source = source
  @position = position
  @calculated_literal = false
end

Class Method Details

.chain(source, position) ⇒ Source::Chain

Parameters:

Returns:



19
20
21
# File 'lib/solargraph/source/source_chainer.rb', line 19

def chain source, position
  new(source, position).chain
end

Instance Method Details

#chainSource::Chain

Returns:



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
# File 'lib/solargraph/source/source_chainer.rb', line 33

def chain
  # Special handling for files that end with an integer and a period
  return Chain.new([Chain::Literal.new('Integer'), Chain::UNDEFINED_CALL]) if phrase =~ /^[0-9]+\.$/
  return Chain.new([Chain::Literal.new('Symbol')]) if phrase.start_with?(':') && !phrase.start_with?('::')
  return SourceChainer.chain(source, Position.new(position.line, position.character + 1)) if end_of_phrase.strip == '::' && source.code[Position.to_offset(source.code, position)].to_s.match?(/[a-z]/i)
  begin
    return Chain.new([]) if phrase.end_with?('..')
    node = nil
    parent = nil
    if !source.repaired? && source.parsed? && source.synchronized?
      tree = source.tree_at(position.line, position.column)
      # node, parent = source.tree_at(position.line, position.column)[0..2]
      tree.shift while tree.length > 1 && tree.first.type == :SCOPE
      node, parent = tree[0..2]
    elsif source.parsed? && source.repaired? && end_of_phrase == '.'
      node, parent = source.tree_at(fixed_position.line, fixed_position.column)[0..2]
      node = Parser.parse(fixed_phrase) if node.nil?
    else
      node, parent = source.tree_at(fixed_position.line, fixed_position.column)[0..2] unless source.error_ranges.any?{|r| r.nil? || r.include?(fixed_position)}
      # Exception for positions that chain literal nodes in unsynchronized sources
      node = nil unless source.synchronized? || !Parser.infer_literal_node_type(node).nil?
      node = Parser.parse(fixed_phrase) if node.nil?
    end
  rescue Parser::SyntaxError
    return Chain.new([Chain::UNDEFINED_CALL])
  end
  return Chain.new([Chain::UNDEFINED_CALL]) if node.nil? || (node.type == :sym && !phrase.start_with?(':'))
  # chain = NodeChainer.chain(node, source.filename, parent && parent.type == :block)
  chain = Parser.chain(node, source.filename, parent && [:ITER, :block].include?(parent.type))
  if source.repaired? || !source.parsed? || !source.synchronized?
    if end_of_phrase.strip == '.'
      chain.links.push Chain::UNDEFINED_CALL
    elsif end_of_phrase.strip == '::'
      chain.links.push Chain::UNDEFINED_CONSTANT
    end
  elsif chain.links.last.is_a?(Source::Chain::Constant) && end_of_phrase.strip == '::'
    chain.links.push Source::Chain::UNDEFINED_CONSTANT
  end
  chain
end