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

Returns a new instance of Clip

Parameters:


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

Returns:


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>

Returns:


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

Returns:


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.

Returns:


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>

Returns:


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