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, Solargraph::Position.normalize(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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/solargraph/source/source_chainer.rb', line 33

def chain
  # Special handling for files that end with an integer and a period
  if phrase =~ /^[0-9]+\.$/
    return Chain.new([Chain::Literal.new('Integer', Integer(phrase[0..-2])),
                      Chain::UNDEFINED_CALL])
  end
  if phrase.start_with?(':') && !phrase.start_with?('::')
    return Chain.new([Chain::Literal.new('Symbol',
                                         # @sg-ignore Need to add nil check here
                                         phrase[1..].to_sym)])
  end
  if end_of_phrase.strip == '::' && source.code[Position.to_offset(
    source.code, position
  )].to_s.match?(/[a-z]/i)
    return SourceChainer.chain(source,
                               Position.new(position.line,
                                            position.character + 1))
  end
  begin
    return Chain.new([]) if phrase.end_with?('..')
    # @type [::Parser::AST::Node, nil]
    node = nil
    # @type [::Parser::AST::Node, nil]
    parent = nil
    if !source.repaired? && source.parsed? && source.synchronized?
      tree = source.tree_at(position.line, position.column)
      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]
      # provide filename and line so that we can look up local variables there later
      node = Parser.parse(fixed_phrase, source.filename, fixed_position.line) if node.nil?
    elsif source.repaired?
      node = Parser.parse(fixed_phrase, source.filename, fixed_position.line)
    else
      unless source.error_ranges.any? do |r|
        r.nil? || r.include?(fixed_position)
      end
        node, parent = source.tree_at(fixed_position.line,
                                      fixed_position.column)[0..2]
      end
      # 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, source.filename, fixed_position.line) 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)
  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