Class: Solargraph::ApiMap::Source

Inherits:
Object
  • Object
show all
Includes:
NodeMethods
Defined in:
lib/solargraph/api_map/source.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from NodeMethods

#const_from, #infer_literal_node_type, #pack_name, #resolve_node_signature, #unpack_name

Constructor Details

#initialize(code, node, comments, filename) ⇒ Source

Returns a new instance of Source.



20
21
22
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
# File 'lib/solargraph/api_map/source.rb', line 20

def initialize code, node, comments, filename
  @code = code
  root = AST::Node.new(:source, [filename])
  root = root.append node
  @node = root
  @comments = comments
  @directives = {}
  @docstring_hash = associate_comments(node, comments)
  @filename = filename
  @namespace_nodes = {}
  @all_nodes = []
  @node_stack = []
  @node_tree = {}
  inner_map_node @node
  @directives.each_pair do |k, v|
    v.each do |d|
      ns = namespace_for(k.node)
      docstring = YARD::Docstring.parser.parse(d.tag.text).to_docstring
      if d.tag.tag_name == 'attribute'
        t = (d.tag.types.nil? || d.tag.types.empty?) ? nil : d.tag.types.flatten.join('')
        if t.nil? or t.include?('r')
          attribute_pins.push Solargraph::Pin::Directed::Attribute.new(self, k.node, ns, :reader, docstring, d.tag.name)
        end
        if t.nil? or t.include?('w')
          attribute_pins.push Solargraph::Pin::Directed::Attribute.new(self, k.node, ns, :writer, docstring, "#{d.tag.name}=")
        end
      elsif d.tag.tag_name == 'method'
        gen_src = Source.virtual("def #{d.tag.name};end", filename)
        gen_pin = gen_src.method_pins.first
        method_pins.push Solargraph::Pin::Directed::Method.new(gen_src, gen_pin.node, ns, :instance, :public, docstring, gen_pin.name)
      else
        STDERR.puts "Nothing to do for directive: #{d}"
      end
    end
  end
end

Instance Attribute Details

#codeString (readonly)

Returns:

  • (String)


7
8
9
# File 'lib/solargraph/api_map/source.rb', line 7

def code
  @code
end

#commentsArray (readonly)

Returns:

  • (Array)


13
14
15
# File 'lib/solargraph/api_map/source.rb', line 13

def comments
  @comments
end

#filenameString (readonly)

Returns:

  • (String)


16
17
18
# File 'lib/solargraph/api_map/source.rb', line 16

def filename
  @filename
end

#nodeParser::AST::Node (readonly)

Returns:

  • (Parser::AST::Node)


10
11
12
# File 'lib/solargraph/api_map/source.rb', line 10

def node
  @node
end

Class Method Details

.beginning_of_line_from(str, i) ⇒ Object



364
365
366
367
368
369
370
371
372
# File 'lib/solargraph/api_map/source.rb', line 364

def beginning_of_line_from str, i
  while i > 0 and str[i] != "\n"
    i -= 1
  end
  if i > 0 and str[i..-1].strip == ''
    i = beginning_of_line_from str, i -1
  end
  i
end

.fix(code, filename = nil, cursor = nil) ⇒ Solargraph::ApiMap::Source



311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
# File 'lib/solargraph/api_map/source.rb', line 311

def fix code, filename = nil, cursor = nil
  tries = 0
  code.gsub!(/\r/, '')
  tmp = code
  cursor = CodeMap.get_offset(code, cursor[0], cursor[1]) if cursor.kind_of?(Array)
  fixed_cursor = false
  begin
    # HACK: The current file is parsed with a trailing underscore to fix
    # incomplete trees resulting from short scripts (e.g., a lone variable
    # assignment).
    node, comments = Parser::CurrentRuby.parse_with_comments(tmp + "\n_")
    Source.new(code, node, comments, filename)
  rescue Parser::SyntaxError => e
    if tries < 10
      tries += 1
      if tries == 10 and e.message.include?('token $end')
        tmp += "\nend"
      else
        if !fixed_cursor and !cursor.nil? and cursor >= 2 and (e.message.include?('token $end') or tmp[cursor - 1] == '$')
          fixed_cursor = true
          spot = cursor - 2
          if tmp[cursor - 1] == '.' or tmp[cursor - 1] == '$'
            repl = ';'
          else
            repl = '#'
          end
        else
          spot = e.diagnostic.location.begin_pos
          repl = '_'
          if tmp[spot] == '@' or tmp[spot] == ':'
            # Stub unfinished instance variables and symbols
            spot -= 1
          elsif tmp[spot - 1] == '.'
            # Stub unfinished method calls
            repl = '#' if spot == tmp.length or tmp[spot] == '\n'
            spot -= 2
          else
            # Stub the whole line
            spot = beginning_of_line_from(tmp, spot)
            repl = '#'
            if tmp[spot+1..-1].rstrip == 'end'
              repl= 'end;end'
            end
          end
        end
        tmp = tmp[0..spot] + repl + tmp[spot+repl.length+1..-1].to_s
      end
      retry
    end
    raise e
  end
end

.load(filename) ⇒ Solargraph::ApiMap::Source



299
300
301
302
# File 'lib/solargraph/api_map/source.rb', line 299

def load filename
  code = File.read(filename).gsub(/\r/, '')
  Source.virtual(code, filename)
end

.virtual(code, filename = nil) ⇒ Solargraph::ApiMap::Source



305
306
307
308
# File 'lib/solargraph/api_map/source.rb', line 305

def virtual code, filename = nil
  node, comments = Parser::CurrentRuby.parse_with_comments(code)
  Source.new(code, node, comments, filename)
end

Instance Method Details

#attribute_pinsObject



77
78
79
# File 'lib/solargraph/api_map/source.rb', line 77

def attribute_pins
  @attribute_pins ||= []
end

#class_variable_pinsObject



85
86
87
# File 'lib/solargraph/api_map/source.rb', line 85

def class_variable_pins
  @class_variable_pins ||= []
end

#code_for(node) ⇒ Object



113
114
115
116
117
118
# File 'lib/solargraph/api_map/source.rb', line 113

def code_for node
  b = node.location.expression.begin.begin_pos
  e = node.location.expression.end.end_pos
  frag = code[b..e-1].to_s
  frag.strip.gsub(/,$/, '')
end

#constant_pinsObject



97
98
99
# File 'lib/solargraph/api_map/source.rb', line 97

def constant_pins
  @constant_pins ||= []
end

#docstring_for(node) ⇒ Object



109
110
111
# File 'lib/solargraph/api_map/source.rb', line 109

def docstring_for node
  @docstring_hash[node.loc]
end

#global_variable_pinsObject



93
94
95
# File 'lib/solargraph/api_map/source.rb', line 93

def global_variable_pins
  @global_variable_pins ||= []
end

#include?(node) ⇒ Boolean

Returns:

  • (Boolean)


134
135
136
# File 'lib/solargraph/api_map/source.rb', line 134

def include? node
  @all_nodes.include? node
end

#instance_variable_pinsObject



81
82
83
# File 'lib/solargraph/api_map/source.rb', line 81

def instance_variable_pins
  @instance_variable_pins ||= []
end

#local_variable_pinsObject



89
90
91
# File 'lib/solargraph/api_map/source.rb', line 89

def local_variable_pins
  @local_variable_pins ||= []
end

#method_pinsObject



73
74
75
# File 'lib/solargraph/api_map/source.rb', line 73

def method_pins
  @method_pins ||= []
end

#namespace_for(node) ⇒ Object



124
125
126
127
128
129
130
131
132
# File 'lib/solargraph/api_map/source.rb', line 124

def namespace_for node
  parts = []
  ([node] + (@node_tree[node] || [])).each do |n|
    if n.type == :class or n.type == :module
      parts.unshift unpack_name(n.children[0])
    end
  end
  parts.join('::')
end

#namespace_includesObject



65
66
67
# File 'lib/solargraph/api_map/source.rb', line 65

def namespace_includes
  @namespace_includes ||= {}
end

#namespace_nodesObject



61
62
63
# File 'lib/solargraph/api_map/source.rb', line 61

def namespace_nodes
  @namespace_nodes
end

#namespacesObject



57
58
59
# File 'lib/solargraph/api_map/source.rb', line 57

def namespaces
  @namespace_nodes.keys
end

#requiredObject



105
106
107
# File 'lib/solargraph/api_map/source.rb', line 105

def required
  @required ||= []
end

#superclassesObject



69
70
71
# File 'lib/solargraph/api_map/source.rb', line 69

def superclasses
  @superclasses ||= {}
end

#symbol_pinsObject



101
102
103
# File 'lib/solargraph/api_map/source.rb', line 101

def symbol_pins
  @symbol_pins ||= []
end

#tree_for(node) ⇒ Object



120
121
122
# File 'lib/solargraph/api_map/source.rb', line 120

def tree_for node
  @node_tree[node] || []
end