solargraph 0.14.2 → 0.14.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,50 +5,65 @@ module Solargraph
5
5
  class Config
6
6
  # @return [String]
7
7
  attr_reader :workspace
8
- attr_reader :raw_data
9
-
10
- # @return [Array<String>]
11
- attr_reader :included
12
-
13
- # @return [Array<String>]
14
- attr_reader :excluded
15
8
 
16
- # @return [Array<String>]
17
- attr_reader :domains
9
+ # @return [Hash]
10
+ attr_reader :raw_data
18
11
 
19
12
  def initialize workspace = nil
20
13
  @workspace = workspace
21
14
  include_globs = ['**/*.rb']
22
15
  exclude_globs = ['spec/**/*', 'test/**/*']
23
- @included = []
24
- @excluded = []
25
- @domains = []
26
16
  unless @workspace.nil?
27
- include_globs = ['**/*.rb']
28
- exclude_globs = ['spec/**/*', 'test/**/*']
29
17
  sfile = File.join(@workspace, '.solargraph.yml')
30
18
  if File.file?(sfile)
31
- @raw_data = YAML.load(File.read(sfile))
32
- conf = YAML.load(File.read(sfile))
33
- include_globs = conf['include'] || include_globs
34
- exclude_globs = conf['exclude'] || []
35
- @domains = conf['domains'] || []
19
+ begin
20
+ @raw_data = YAML.load(File.read(sfile))
21
+ conf = YAML.load(File.read(sfile))
22
+ include_globs = conf['include'] || include_globs
23
+ exclude_globs = conf['exclude'] || []
24
+ rescue Exception => e
25
+ STDERR.puts "Unable to read .solargraph.yml: #{e.class} #{e.message}"
26
+ @raw_data = {}
27
+ end
36
28
  end
37
- @included.concat process_globs(include_globs)
38
- @excluded.concat process_globs(exclude_globs)
39
29
  end
40
30
  @raw_data ||= {}
41
- @raw_data['include'] = @raw_data['include'] || include_globs
42
- @raw_data['exclude'] = @raw_data['exclude'] || exclude_globs
43
- # @todo If the domains config goes stable, add it to @raw_data
31
+ @raw_data['include'] ||= include_globs
32
+ @raw_data['exclude'] ||= exclude_globs
33
+ @raw_data['domains'] ||= []
34
+ @raw_data['required'] ||= []
44
35
  end
45
36
 
37
+ # An array of files included in the workspace (before calculating excluded files).
38
+ #
39
+ # @return [Array<String>]
46
40
  def included
47
- process_globs @raw_data['include']
41
+ return [] if workspace.nil?
42
+ @included ||= process_globs(@raw_data['include'])
48
43
  end
49
44
 
45
+ # An array of files excluded from the workspace.
46
+ #
47
+ # @return [Array<String>]
50
48
  def excluded
51
- process_globs @raw_data['exclude']
49
+ return [] if workspace.nil?
50
+ @excluded ||= process_globs(@raw_data['exclude'])
51
+ end
52
+
53
+ # The calculated array of (included - excluded) files in the workspace.
54
+ #
55
+ # @return [Array<String>]
56
+ def calculated
57
+ @calculated ||= (included - excluded)
58
+ end
59
+
60
+ # @return [Array<String>]
61
+ def domains
62
+ raw_data['domains']
63
+ end
64
+
65
+ def required
66
+ raw_data['required']
52
67
  end
53
68
 
54
69
  private
@@ -70,46 +70,63 @@ module Solargraph
70
70
  @superclasses ||= {}
71
71
  end
72
72
 
73
+ # @return [Array<Solargraph::Pin::Method>]
73
74
  def method_pins
74
75
  @method_pins ||= []
75
76
  end
76
77
 
78
+ # @return [Array<Solargraph::Pin::Attribute>]
77
79
  def attribute_pins
78
80
  @attribute_pins ||= []
79
81
  end
80
82
 
83
+ # @return [Array<Solargraph::Pin::InstanceVariable>]
81
84
  def instance_variable_pins
82
85
  @instance_variable_pins ||= []
83
86
  end
84
87
 
88
+ # @return [Array<Solargraph::Pin::ClassVariable>]
85
89
  def class_variable_pins
86
90
  @class_variable_pins ||= []
87
91
  end
88
92
 
93
+ # @return [Array<Solargraph::Pin::LocalVariable>]
89
94
  def local_variable_pins
90
95
  @local_variable_pins ||= []
91
96
  end
92
97
 
98
+ # @return [Array<Solargraph::Pin::GlobalVariable>]
93
99
  def global_variable_pins
94
100
  @global_variable_pins ||= []
95
101
  end
96
102
 
103
+ # @return [Array<Solargraph::Pin::Constant>]
97
104
  def constant_pins
98
105
  @constant_pins ||= []
99
106
  end
100
107
 
108
+ # @return [Array<Solargraph::Pin::Symbol>]
101
109
  def symbol_pins
102
110
  @symbol_pins ||= []
103
111
  end
104
112
 
113
+ # @return [Array<Solargraph::Pin::Namespace>]
114
+ def namespace_pins
115
+ @namespace_pins ||= []
116
+ end
117
+
118
+ # @return [Array<String>]
105
119
  def required
106
120
  @required ||= []
107
121
  end
108
122
 
123
+ # @return [YARD::Docstring]
109
124
  def docstring_for node
110
- @docstring_hash[node.loc]
125
+ return @docstring_hash[node.loc] if node.respond_to?(:loc)
126
+ nil
111
127
  end
112
128
 
129
+ # @return [String]
113
130
  def code_for node
114
131
  b = node.location.expression.begin.begin_pos
115
132
  e = node.location.expression.end.end_pos
@@ -121,6 +138,7 @@ module Solargraph
121
138
  @node_tree[node] || []
122
139
  end
123
140
 
141
+ # @return [String]
124
142
  def namespace_for node
125
143
  parts = []
126
144
  ([node] + (@node_tree[node] || [])).each do |n|
@@ -188,6 +206,7 @@ module Solargraph
188
206
  fqn = tree.join('::')
189
207
  @namespace_nodes[fqn] ||= []
190
208
  @namespace_nodes[fqn].push node
209
+ namespace_pins.push Solargraph::Pin::Namespace.new(self, node, tree[0..-2].join('::') || '')
191
210
  if node.type == :class and !node.children[1].nil?
192
211
  sc = unpack_name(node.children[1])
193
212
  superclasses[fqn] = sc
@@ -205,6 +224,7 @@ module Solargraph
205
224
  unless ora.nil?
206
225
  u = c.updated(:ivasgn, c.children + ora.children[1..-1], nil)
207
226
  @node_tree[u] = @node_stack.clone
227
+ @docstring_hash[u.loc] = docstring_for(ora)
208
228
  instance_variable_pins.push Solargraph::Pin::InstanceVariable.new(self, u, fqn || '', local_scope)
209
229
  end
210
230
  else
@@ -216,6 +236,7 @@ module Solargraph
216
236
  unless ora.nil?
217
237
  u = c.updated(:cvasgn, c.children + ora.children[1..-1], nil)
218
238
  @node_tree[u] = @node_stack.clone
239
+ @docstring_hash[u.loc] = docstring_for(ora)
219
240
  class_variable_pins.push Solargraph::Pin::ClassVariable.new(self, u, fqn || '')
220
241
  end
221
242
  else
@@ -241,38 +262,34 @@ module Solargraph
241
262
  elsif c.type == :casgn
242
263
  constant_pins.push Solargraph::Pin::Constant.new(self, c, fqn)
243
264
  else
244
- #unless fqn.nil?
245
- if c.kind_of?(AST::Node)
246
- if c.type == :def and c.children[0].to_s[0].match(/[a-z]/i)
247
- method_pins.push Solargraph::Pin::Method.new(source, c, fqn || '', scope, visibility)
248
- #inner_map_node c, tree, visibility, scope, fqn, stack
249
- #next
250
- elsif c.type == :defs
251
- method_pins.push Solargraph::Pin::Method.new(source, c, fqn || '', :class, :public)
252
- inner_map_node c, tree, :public, :class, fqn, stack
253
- next
254
- elsif c.type == :send and [:public, :protected, :private].include?(c.children[1])
255
- visibility = c.children[1]
256
- elsif c.type == :send and c.children[1] == :include #and node.type == :class
257
- namespace_includes[fqn] ||= []
258
- c.children[2..-1].each do |i|
259
- namespace_includes[fqn].push unpack_name(i)
265
+ if c.kind_of?(AST::Node)
266
+ if c.type == :def and c.children[0].to_s[0].match(/[a-z]/i)
267
+ method_pins.push Solargraph::Pin::Method.new(source, c, fqn || '', scope, visibility)
268
+ elsif c.type == :defs
269
+ method_pins.push Solargraph::Pin::Method.new(source, c, fqn || '', :class, :public)
270
+ inner_map_node c, tree, :public, :class, fqn, stack
271
+ next
272
+ elsif c.type == :send and [:public, :protected, :private].include?(c.children[1])
273
+ visibility = c.children[1]
274
+ elsif c.type == :send and c.children[1] == :include #and node.type == :class
275
+ namespace_includes[fqn] ||= []
276
+ c.children[2..-1].each do |i|
277
+ namespace_includes[fqn].push unpack_name(i)
278
+ end
279
+ elsif c.type == :send and [:attr_reader, :attr_writer, :attr_accessor].include?(c.children[1])
280
+ c.children[2..-1].each do |a|
281
+ if c.children[1] == :attr_reader or c.children[1] == :attr_accessor
282
+ attribute_pins.push Solargraph::Pin::Attribute.new(self, a, fqn || '', :reader, docstring_for(c)) #AttrPin.new(c)
260
283
  end
261
- elsif c.type == :send and [:attr_reader, :attr_writer, :attr_accessor].include?(c.children[1])
262
- c.children[2..-1].each do |a|
263
- if c.children[1] == :attr_reader or c.children[1] == :attr_accessor
264
- attribute_pins.push Solargraph::Pin::Attribute.new(self, a, fqn || '', :reader, docstring_for(c)) #AttrPin.new(c)
265
- end
266
- if c.children[1] == :attr_writer or c.children[1] == :attr_accessor
267
- attribute_pins.push Solargraph::Pin::Attribute.new(self, a, fqn || '', :writer, docstring_for(c)) #AttrPin.new(c)
268
- end
284
+ if c.children[1] == :attr_writer or c.children[1] == :attr_accessor
285
+ attribute_pins.push Solargraph::Pin::Attribute.new(self, a, fqn || '', :writer, docstring_for(c)) #AttrPin.new(c)
269
286
  end
270
- elsif c.type == :sclass and c.children[0].type == :self
271
- inner_map_node c, tree, :public, :class, fqn || '', stack
272
- next
273
287
  end
288
+ elsif c.type == :sclass and c.children[0].type == :self
289
+ inner_map_node c, tree, :public, :class, fqn || '', stack
290
+ next
274
291
  end
275
- #end
292
+ end
276
293
  if c.type == :send and c.children[1] == :require
277
294
  if c.children[2].kind_of?(AST::Node) and c.children[2].type == :str
278
295
  required.push c.children[2].children[0].to_s
@@ -316,8 +333,8 @@ module Solargraph
316
333
  fixed_cursor = false
317
334
  begin
318
335
  # HACK: The current file is parsed with a trailing underscore to fix
319
- # incomplete trees resulting from short scripts (e.g., a lone variable
320
- # assignment).
336
+ # incomplete trees resulting from short scripts (e.g., an unfinished
337
+ # variable assignment).
321
338
  node, comments = Parser::CurrentRuby.parse_with_comments(tmp + "\n_")
322
339
  Source.new(code, node, comments, filename)
323
340
  rescue Parser::SyntaxError => e
@@ -25,6 +25,7 @@ module Solargraph
25
25
 
26
26
  # The root directory of the project. The ApiMap will search here for
27
27
  # additional files to parse and analyze.
28
+ # @deprecated CodeMap will be server-agnostic in a future version.
28
29
  #
29
30
  # @return [String]
30
31
  attr_reader :workspace
@@ -32,6 +33,7 @@ module Solargraph
32
33
  include NodeMethods
33
34
 
34
35
  def initialize code: '', filename: nil, workspace: nil, api_map: nil, cursor: nil
36
+ STDERR.puts "WARNING: the `workspace` parameter in Solargraph::CodeMap#new is deprecated and will be removed in a future version." unless workspace.nil?
35
37
  @workspace = workspace
36
38
  # HACK: Adjust incoming filename's path separator for yardoc file comparisons
37
39
  filename = filename.gsub(File::ALT_SEPARATOR, File::SEPARATOR) unless filename.nil? or File::ALT_SEPARATOR.nil?
@@ -225,7 +227,7 @@ module Solargraph
225
227
  if signature.include?('::')
226
228
  parts = signature.split('::', -1)
227
229
  ns = parts[0..-2].join('::')
228
- result = api_map.namespaces_in(ns, namespace)
230
+ result = api_map.get_constants(ns, namespace)
229
231
  else
230
232
  type = infer_literal_node_type(node_at(index - 2))
231
233
  if type.nil?
@@ -235,10 +237,10 @@ module Solargraph
235
237
  result += ApiMap.get_keywords
236
238
  while parts.length > 0
237
239
  ns = parts.join('::')
238
- result += api_map.namespaces_in(ns, namespace)
240
+ result += api_map.get_constants(ns, namespace)
239
241
  parts.pop
240
242
  end
241
- result += api_map.namespaces_in('')
243
+ result += api_map.get_constants('')
242
244
  result += api_map.get_instance_methods('Kernel')
243
245
  result += api_map.get_methods('')
244
246
  result += api_map.get_instance_methods('')
@@ -434,8 +436,9 @@ module Solargraph
434
436
  return type unless type.nil?
435
437
  else
436
438
  # Signature starts with a local variable
437
- type = get_type_comment(var)
438
- type = infer_literal_node_type(var.children[1]) if type.nil?
439
+ type = nil
440
+ lvp = source.local_variable_pins.select{|p| p.name == var.children[0].to_s and p.visible_from?(node) and (!p.nil_assignment? or p.return_type)}.first
441
+ type = lvp.return_type unless lvp.nil?
439
442
  if type.nil?
440
443
  vsig = resolve_node_signature(var.children[1])
441
444
  type = infer_signature_from_node vsig, node
@@ -458,16 +461,6 @@ module Solargraph
458
461
  inferred
459
462
  end
460
463
 
461
- def get_type_comment node
462
- obj = nil
463
- cmnt = @source.docstring_for(node)
464
- unless cmnt.nil?
465
- tag = cmnt.tag(:type)
466
- obj = tag.types[0] unless tag.nil? or tag.types.empty?
467
- end
468
- obj
469
- end
470
-
471
464
  # Get the signature at the specified index.
472
465
  # A signature is a method call that can start with a constant, method, or
473
466
  # variable and does not include any method arguments. Examples:
@@ -513,7 +506,6 @@ module Solargraph
513
506
  def get_local_variables_and_methods_at(index)
514
507
  result = []
515
508
  local = parent_node_from(index, :class, :module, :def, :defs) || @node
516
- #result += get_local_variables_from(local)
517
509
  result += get_local_variables_from(node_at(index))
518
510
  scope = namespace_at(index) || @node
519
511
  if local.type == :def
@@ -580,7 +572,7 @@ module Solargraph
580
572
  def get_method_arguments_from node
581
573
  return [] unless node.type == :def or node.type == :defs
582
574
  param_hash = {}
583
- cmnt = api_map.get_comment_for(node)
575
+ cmnt = api_map.get_docstring_for(node)
584
576
  unless cmnt.nil?
585
577
  tags = cmnt.tags(:param)
586
578
  tags.each do |tag|
@@ -649,9 +641,20 @@ module Solargraph
649
641
  node ||= @node
650
642
  namespace = namespace_from(node)
651
643
  arr = []
644
+ nil_pins = []
645
+ val_names = []
652
646
  @source.local_variable_pins.select{|p| p.visible_from?(node) }.each do |pin|
653
- #arr.push Suggestion.new(pin.name, kind: Suggestion::VARIABLE, return_type: api_map.infer_assignment_node_type(pin.node, namespace))
654
- arr.push Suggestion.new(pin.name, kind: Suggestion::VARIABLE, location: pin.location)
647
+ if pin.nil_assignment? and pin.return_type.nil?
648
+ nil_pins.push pin
649
+ else
650
+ unless val_names.include?(pin.name)
651
+ arr.push Suggestion.pull(pin)
652
+ val_names.push pin.name
653
+ end
654
+ end
655
+ end
656
+ nil_pins.reject{|p| val_names.include?(p.name)}.each do |pin|
657
+ arr.push Suggestion.pull(pin)
655
658
  end
656
659
  arr
657
660
  end
@@ -44,13 +44,14 @@ module Solargraph
44
44
  end
45
45
  suggestions = []
46
46
  result.uniq.each do |r|
47
+ path = (r['namespace'].empty? ? '' : "#{r['namespace']}::") + r['name']
47
48
  kind = Suggestion::CONSTANT
48
49
  if r['class'] == 'Class'
49
50
  kind = Suggestion::CLASS
50
51
  elsif r['class'] == 'Module'
51
52
  kind = Suggestion::MODULE
52
53
  end
53
- suggestions.push(Suggestion.new(r['name'], kind: kind))
54
+ suggestions.push(Suggestion.new(r['name'], kind: kind, path: path))
54
55
  end
55
56
  cache.set_constants(namespace, root, suggestions)
56
57
  suggestions
@@ -1,15 +1,16 @@
1
1
  module Solargraph
2
2
  module Pin
3
- autoload :Base, 'solargraph/pin/base'
4
- autoload :Method, 'solargraph/pin/method'
5
- autoload :Attribute, 'solargraph/pin/attribute'
6
- autoload :BaseVariable, 'solargraph/pin/base_variable'
3
+ autoload :Base, 'solargraph/pin/base'
4
+ autoload :Method, 'solargraph/pin/method'
5
+ autoload :Attribute, 'solargraph/pin/attribute'
6
+ autoload :BaseVariable, 'solargraph/pin/base_variable'
7
7
  autoload :InstanceVariable, 'solargraph/pin/instance_variable'
8
- autoload :ClassVariable, 'solargraph/pin/class_variable'
9
- autoload :LocalVariable, 'solargraph/pin/local_variable'
10
- autoload :GlobalVariable, 'solargraph/pin/global_variable'
11
- autoload :Constant, 'solargraph/pin/constant'
12
- autoload :Symbol, 'solargraph/pin/symbol'
13
- autoload :Directed, 'solargraph/pin/directed'
8
+ autoload :ClassVariable, 'solargraph/pin/class_variable'
9
+ autoload :LocalVariable, 'solargraph/pin/local_variable'
10
+ autoload :GlobalVariable, 'solargraph/pin/global_variable'
11
+ autoload :Constant, 'solargraph/pin/constant'
12
+ autoload :Symbol, 'solargraph/pin/symbol'
13
+ autoload :Directed, 'solargraph/pin/directed'
14
+ autoload :Namespace, 'solargraph/pin/namespace'
14
15
  end
15
16
  end
@@ -19,6 +19,10 @@ module Solargraph
19
19
  @return_type ||= literal_from_assignment
20
20
  end
21
21
 
22
+ def nil_assignment?
23
+ node.children[(node.type == :casgn ? 2 : 1)].type == :nil
24
+ end
25
+
22
26
  def signature
23
27
  @signature ||= resolve_node_signature(node.children[(node.type == :casgn ? 2 : 1)])
24
28
  end
@@ -0,0 +1,23 @@
1
+ module Solargraph
2
+ module Pin
3
+ class Namespace < Pin::Base
4
+ include Solargraph::NodeMethods
5
+
6
+ def name
7
+ @name ||= pack_name(node.children[0]).last.to_s
8
+ end
9
+
10
+ def path
11
+ @path ||= (namespace.empty? ? '' : "#{namespace}::") + name
12
+ end
13
+
14
+ def kind
15
+ @kind ||= (node.type == :class ? Solargraph::Suggestion::CLASS : Solargraph::Suggestion::MODULE)
16
+ end
17
+
18
+ def return_type
19
+ @return_type ||= (node.type == :class ? 'Class' : 'Module') + "<#{path}>"
20
+ end
21
+ end
22
+ end
23
+ end
@@ -32,6 +32,8 @@ module Solargraph
32
32
  end
33
33
  rescue JSON::ParserError => e
34
34
  STDOUT.puts respond_err "Error parsing input: #{e.message}"
35
+ rescue Exception => e
36
+ STDOUT.puts respond_err "Error processing input: #{e.message}"
35
37
  end
36
38
  STDOUT.flush
37
39
  end
@@ -63,15 +65,15 @@ module Solargraph
63
65
  unless con.nil?
64
66
  if (args['scope'] == 'class')
65
67
  if args['with_private']
66
- result.concat con.methods
68
+ result.concat con.methods(false)
67
69
  else
68
- result.concat con.public_methods
70
+ result.concat con.public_methods(false)
69
71
  end
70
72
  elsif (args['scope'] == 'instance')
71
73
  if args['with_private']
72
- result.concat con.instance_methods
74
+ result.concat con.instance_methods(false)
73
75
  else
74
- result.concat con.public_instance_methods
76
+ result.concat con.public_instance_methods(false)
75
77
  end
76
78
  end
77
79
  end
@@ -85,8 +87,8 @@ module Solargraph
85
87
  #result.concat con.constants
86
88
  con.constants.each do |c|
87
89
  next if c == :Solargraph and !@required.include?('solargraph')
88
- item = { name: c }
89
90
  here = con.const_get(c)
91
+ item = { namespace: con.to_s, name: c.to_s }
90
92
  item[:class] = here.class.to_s
91
93
  result.push item
92
94
  end