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



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



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



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
# 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?('::')
  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 == '::' && !source.code[Position.to_offset(source.code, position)].match?(/[a-z]/i)
    chain.links.push Source::Chain::UNDEFINED_CONSTANT
  end
  chain
end