Class: Solargraph::SourceMap::Clip

Inherits:
Object
  • Object
show all
Defined in:
lib/solargraph/source_map/clip.rb

Overview

A static analysis tool for obtaining definitions, completions, signatures, and type inferences from a cursor.

Instance Method Summary collapse

Constructor Details

#initialize(api_map, cursor) ⇒ Clip


9
10
11
12
# File 'lib/solargraph/source_map/clip.rb', line 9

def initialize api_map, cursor
  @api_map = api_map
  @cursor = cursor
end

Instance Method Details

#completeCompletion


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
# File 'lib/solargraph/source_map/clip.rb', line 23

def complete
  return package_completions([]) if !source_map.source.parsed? || cursor.string?
  return package_completions(api_map.get_symbols) if cursor.chain.literal? && cursor.chain.links.last.word == '<Symbol>'
  return Completion.new([], cursor.range) if cursor.chain.literal? || cursor.comment?
  result = []
  if cursor.chain.constant? || cursor.start_of_constant?
    if cursor.chain.undefined?
      type = cursor.chain.base.infer(api_map, context_pin, locals)
    else
      full = cursor.chain.links.first.word
      if full.include?('::') && cursor.chain.links.length == 1
        type = ComplexType.try_parse(full.split('::')[0..-2].join('::'))
      elsif cursor.chain.links.length > 1
        type = ComplexType.try_parse(full)
      else
        type = ComplexType::UNDEFINED
      end
    end
    result.concat api_map.get_constants(type.undefined? ? '' : type.namespace, cursor.start_of_constant? ? '' : context_pin.full_context.namespace)
  else
    type = cursor.chain.base.infer(api_map, block, locals)
    result.concat api_map.get_complex_type_methods(type, block.binder.namespace, cursor.chain.links.length == 1)
    if cursor.chain.links.length == 1
      if cursor.word.start_with?('@@')
        return package_completions(api_map.get_class_variable_pins(context_pin.full_context.namespace))
      elsif cursor.word.start_with?('@')
        return package_completions(api_map.get_instance_variable_pins(block.binder.namespace, block.binder.scope))
      elsif cursor.word.start_with?('$')
        return package_completions(api_map.get_global_variable_pins)
      end
      result.concat locals
      result.concat api_map.get_constants('', context_pin.context.namespace)
      result.concat api_map.get_methods(block.binder.namespace, scope: block.binder.scope, visibility: [:public, :private, :protected])
      result.concat api_map.get_methods('Kernel')
      result.concat ApiMap.keywords
      result.concat yielded_self_pins
    end
  end
  package_completions(result)
end

#defineArray<Pin::Base>


15
16
17
18
19
20
# File 'lib/solargraph/source_map/clip.rb', line 15

def define
  return [] if cursor.comment? || cursor.chain.literal?
  result = cursor.chain.define(api_map, block, locals)
  result.concat((source_map.pins + source_map.locals).select{ |p| p.name == cursor.word && p.location.range.contain?(cursor.position) }) if result.empty?
  result
end

#inferComplexType


72
73
74
75
76
# File 'lib/solargraph/source_map/clip.rb', line 72

def infer
  result = cursor.chain.infer(api_map, block, locals)
  return result unless result.tag == 'self'
  ComplexType.try_parse(cursor.chain.base.infer(api_map, block, locals).namespace)
end

#localsArray<Solargraph::Pin::Base>

Get an array of all the locals that are visible from the cursors's position. Locals can be local variables, method parameters, or block parameters. The array starts with the nearest local pin.


83
84
85
86
87
88
89
# File 'lib/solargraph/source_map/clip.rb', line 83

def locals
  loc_pos = context_pin.location.range.contain?(cursor.position) ? cursor.position : context_pin.location.range.ending
  adj_pos = Position.new(loc_pos.line, (loc_pos.column.zero? ? 0 : loc_pos.column - 1))
  @locals ||= source_map.locals.select { |pin|
    pin.visible_from?(block, adj_pos)
  }.reverse
end

#signifyArray<Pin::Base>


65
66
67
68
69
# File 'lib/solargraph/source_map/clip.rb', line 65

def signify
  return [] unless cursor.argument?
  chain = Source::NodeChainer.chain(cursor.recipient_node, cursor.filename)
  chain.define(api_map, context_pin, locals).select { |pin| pin.is_a?(Pin::Method) }
end