solargraph 0.4.1 → 0.4.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 28954a2882b95c72c093ab8e9f8a56d36581353e
4
- data.tar.gz: c49221b919b8f14239eea72d8f7a1ba59ac42c87
3
+ metadata.gz: ef9da7f38a0665ebb95d8e779b511d54da955619
4
+ data.tar.gz: 4715dd2076a1497cf00cebb8456510a33f5ca43e
5
5
  SHA512:
6
- metadata.gz: ebe9048897e96e214df878cdb6d8e596e9a3d56b15fa269ee885a966991c62f930ebbe821e54b2d43c1a2ac2119eadfaad40778e99ac1254ad658147df54ebb3
7
- data.tar.gz: 5a8b6875aced160a813b3285e45604aada791663f4e4581d3d007828f304db717619c4a5c92682366bd7754e8e50c8a5faa4f4ab737c49ca57910a5cff7b5625
6
+ metadata.gz: 7999e6032efaf061fbf36a7e9ae2b6f1b81955324c68c465bd8b17039a740cdb2015fbb71207df9ebce2235d60847a07dfca118296dcb6b7b4a05b9abe9049d2
7
+ data.tar.gz: 9a8632ccc9e26c082df9162f945257414562558fb65629b33b07e218399c76e7c93d43a9b31ef38465ac331f58acc1b172948245fdae10e076ebe40443300bb7
@@ -1,6 +1,7 @@
1
1
  require 'rubygems'
2
2
  require 'parser/current'
3
3
  require 'yard'
4
+ require 'yaml'
4
5
 
5
6
  module Solargraph
6
7
  class ApiMap
@@ -25,9 +26,16 @@ module Solargraph
25
26
  @workspace = workspace
26
27
  clear
27
28
  unless @workspace.nil?
28
- files = Dir[File.join @workspace, 'lib', '**', '*.rb'] + Dir[File.join @workspace, 'app', '**', '*.rb']
29
- files.each { |f|
30
- append_file f unless yardoc_has_file?(f)
29
+ files = []
30
+ opts = options
31
+ (opts[:include] - opts[:exclude]).each { |glob|
32
+ files += Dir[File.join @workspace, glob]
33
+ }
34
+ opts[:exclude].each { |glob|
35
+ files -= Dir[File.join @workspace, glob]
36
+ }
37
+ files.uniq.each { |f|
38
+ append_file f #unless yardoc_has_file?(f)
31
39
  }
32
40
  end
33
41
  end
@@ -41,17 +49,18 @@ module Solargraph
41
49
  @required = []
42
50
  end
43
51
 
44
- def has_yardoc?
45
- workspace and File.exist?(File.join(workspace, '.yardoc'))
46
- end
47
-
48
- def yardoc_has_file?(filename)
49
- return false unless has_yardoc?
50
- return false if filename.nil?
51
- if filename.start_with?(File.join(workspace, 'lib/'), File.join(workspace, 'app/'))
52
- return true
52
+ def options
53
+ o = {
54
+ include: ['app/**/*.rb', 'lib/**/*.rb'],
55
+ exclude: []
56
+ }
57
+ yaml = File.join(workspace, '.solargraph.yml')
58
+ if workspace && File.exist?(yaml)
59
+ l = YAML.load_file(yaml)
60
+ o[:include].concat l['include'] unless l['include'].nil?
61
+ o[:exclude].concat l[:exclude] unless l['exclude'].nil?
53
62
  end
54
- false
63
+ o
55
64
  end
56
65
 
57
66
  def append_file filename
@@ -67,9 +76,7 @@ module Solargraph
67
76
  @file_comments[filename] = associate_comments(node, comments)
68
77
  mapified = reduce(node, @file_comments[filename])
69
78
  root = AST::Node.new(:begin, [filename])
70
- mapified.children.each { |c|
71
- root = root.append c
72
- }
79
+ root = root.append mapified
73
80
  @file_nodes[filename] = root
74
81
  @required.uniq!
75
82
  process_maps
@@ -110,20 +117,20 @@ module Solargraph
110
117
  @namespace_map = {}
111
118
  @namespace_tree = {}
112
119
  @file_nodes.values.each { |f|
113
- map_parents f #AST::Node.new(:tmp, @file_nodes.values)
114
- map_namespaces f #AST::Node.new(:tmp, @file_nodes.values)
120
+ map_parents f
121
+ map_namespaces f
115
122
  }
116
123
  end
117
-
124
+
118
125
  def namespaces
119
126
  @namespace_map.keys
120
127
  end
121
-
128
+
122
129
  def namespace_exists? name, root = ''
123
130
  !find_fully_qualified_namespace(name, root).nil?
124
131
  end
125
-
126
- def namespaces_in name, root = '' #, skip = []
132
+
133
+ def namespaces_in name, root = ''
127
134
  result = []
128
135
  result += inner_namespaces_in(name, root, [])
129
136
  yard = YardMap.new(required: @required, workspace: @workspace)
@@ -137,43 +144,41 @@ module Solargraph
137
144
  end
138
145
  result
139
146
  end
140
-
147
+
141
148
  def inner_namespaces_in name, root, skip
142
149
  result = []
143
150
  fqns = find_fully_qualified_namespace(name, root)
144
- if fqns.nil?
145
- return result
146
- else
147
- return result if skip.include?(fqns)
151
+ unless fqns.nil? or skip.include?(fqns)
148
152
  skip.push fqns
149
153
  nodes = get_namespace_nodes(fqns)
150
- nodes.delete_if { |n| yardoc_has_file?(get_filename_for(n))}
151
- return result if nodes.empty?
152
- cursor = @namespace_tree
153
- parts = fqns.split('::')
154
- parts.each { |p|
155
- cursor = cursor[p]
156
- }
157
- unless cursor.nil?
158
- cursor.keys.each { |k|
159
- type = get_namespace_type(k, fqns)
160
- kind = nil
161
- detail = nil
162
- if type == :class
163
- kind = Suggestion::CLASS
164
- detail = 'Class'
165
- elsif type == :module
166
- kind = Suggestion::MODULE
167
- detail = 'Module'
168
- end
169
- result.push Suggestion.new(k, kind: kind, detail: detail)
154
+ #nodes.delete_if { |n| yardoc_has_file?(get_filename_for(n))}
155
+ unless nodes.empty?
156
+ cursor = @namespace_tree
157
+ parts = fqns.split('::')
158
+ parts.each { |p|
159
+ cursor = cursor[p]
170
160
  }
171
- nodes = get_namespace_nodes(fqns)
172
- nodes.each { |n|
173
- get_include_strings_from(n).each { |i|
174
- result += inner_namespaces_in(i, fqns, skip)
161
+ unless cursor.nil?
162
+ cursor.keys.each { |k|
163
+ type = get_namespace_type(k, fqns)
164
+ kind = nil
165
+ detail = nil
166
+ if type == :class
167
+ kind = Suggestion::CLASS
168
+ detail = 'Class'
169
+ elsif type == :module
170
+ kind = Suggestion::MODULE
171
+ detail = 'Module'
172
+ end
173
+ result.push Suggestion.new(k, kind: kind, detail: detail)
175
174
  }
176
- }
175
+ nodes = get_namespace_nodes(fqns)
176
+ nodes.each { |n|
177
+ get_include_strings_from(n).each { |i|
178
+ result += inner_namespaces_in(i, fqns, skip)
179
+ }
180
+ }
181
+ end
177
182
  end
178
183
  end
179
184
  result
@@ -217,7 +222,7 @@ module Solargraph
217
222
  return @file_nodes.values if fqns == ''
218
223
  @namespace_map[fqns] || []
219
224
  end
220
-
225
+
221
226
  def get_instance_variables(namespace, scope = :instance)
222
227
  nodes = get_namespace_nodes(namespace) || @file_nodes.values
223
228
  arr = []
@@ -226,7 +231,7 @@ module Solargraph
226
231
  }
227
232
  arr
228
233
  end
229
-
234
+
230
235
  def find_parent(node, *types)
231
236
  parents = @parent_stack[node]
232
237
  parents.each { |p|
@@ -234,7 +239,7 @@ module Solargraph
234
239
  }
235
240
  nil
236
241
  end
237
-
242
+
238
243
  def get_root_for(node)
239
244
  s = @parent_stack[node]
240
245
  return nil if s.nil?
@@ -253,7 +258,7 @@ module Solargraph
253
258
  node.children.each { |c|
254
259
  if c.kind_of?(AST::Node)
255
260
  is_inst = !find_parent(c, :def).nil?
256
- if c.type == :ivasgn and ( (scope == :instance and is_inst) or (scope != :instance and !is_inst) )
261
+ if c.type == :ivasgn and c.children[0] and ( (scope == :instance and is_inst) or (scope != :instance and !is_inst) )
257
262
  arr.push Suggestion.new(c.children[0], kind: Suggestion::VARIABLE)
258
263
  end
259
264
  arr += inner_get_instance_variables(c, scope) unless [:class, :module].include?(c.type)
@@ -409,7 +414,7 @@ module Solargraph
409
414
  return meths if fqns.nil?
410
415
  nodes = get_namespace_nodes(fqns)
411
416
  nodes.each { |n|
412
- unless yardoc_has_file?(get_filename_for(n))
417
+ #unless yardoc_has_file?(get_filename_for(n))
413
418
  if n.kind_of?(AST::Node)
414
419
  if n.type == :class and !n.children[1].nil?
415
420
  s = unpack_name(n.children[1])
@@ -430,7 +435,7 @@ module Solargraph
430
435
  end
431
436
  }
432
437
  end
433
- end
438
+ #end
434
439
  }
435
440
  meths.uniq
436
441
  end
@@ -442,7 +447,7 @@ module Solargraph
442
447
  skip.push fqns
443
448
  nodes = get_namespace_nodes(fqns)
444
449
  nodes.each { |n|
445
- unless yardoc_has_file?(get_filename_for(n))
450
+ #unless yardoc_has_file?(get_filename_for(n))
446
451
  if n.kind_of?(AST::Node)
447
452
  if n.type == :class and !n.children[1].nil?
448
453
  s = unpack_name(n.children[1])
@@ -481,7 +486,7 @@ module Solargraph
481
486
  }
482
487
  }
483
488
  end
484
- end
489
+ #end
485
490
  }
486
491
  meths.uniq
487
492
  end
@@ -498,6 +503,7 @@ module Solargraph
498
503
  end
499
504
 
500
505
  def reduce node, comment_hash
506
+ return node unless node.kind_of?(AST::Node)
501
507
  mappable = get_mappable_nodes(node.children, comment_hash)
502
508
  result = node.updated nil, mappable
503
509
  result
@@ -575,7 +581,7 @@ module Solargraph
575
581
  def map_namespaces node, tree = []
576
582
  if node.kind_of?(AST::Node)
577
583
  if node.type == :class or node.type == :module
578
- if node.children[0].children[0].kind_of?(AST::Node) and node.children[0].children[0].type == :cbase
584
+ if node.children[0].kind_of?(AST::Node) and node.children[0].children[0].kind_of?(AST::Node) and node.children[0].children[0].type == :cbase
579
585
  tree = pack_name(node.children[0])
580
586
  else
581
587
  tree = tree + pack_name(node.children[0])
@@ -207,6 +207,7 @@ module Solargraph
207
207
  scope = parent_node_from(index, :class, :module, :def, :defs) || @node
208
208
  var = find_local_variable_node(first, scope)
209
209
  if var.nil?
210
+ # It's not a locally assigned variable.
210
211
  if ['STDERR','STDOUT','STDIN'].include?(first)
211
212
  obj = 'IO'
212
213
  if parts.length == 0
@@ -214,13 +215,32 @@ module Solargraph
214
215
  end
215
216
  else
216
217
  if parts.length == 0
217
- return @api_map.get_methods(first, ns_here)
218
+ # HACK: Assume that it's a constant (class or module) if it starts with an uppercase letter
219
+ if first[0] == first[0].upcase
220
+ return @api_map.get_methods(first, ns_here)
221
+ else
222
+ if scope.type == :def
223
+ meths = @api_map.get_instance_methods(ns_here).delete_if{|m| m.insert != first}
224
+ return [] if meths.empty?
225
+ return [] if meths[0].documentation.nil?
226
+ match = meths[0].documentation.all.match(/@return \[([a-z0-9:_]*)/i)
227
+ return [] if match[1].nil?
228
+ return @api_map.get_instance_methods(match[1], ns_here)
229
+ else
230
+ meths = @api_map.get_methods(ns_here).delete_if{|m| m.insert != first}
231
+ return [] if meths.empty?
232
+ return [] if meths[0].documentation.nil?
233
+ match = meths[0].documentation.all.match(/@return \[([a-z0-9:_]*)/i)
234
+ return [] if match[1].nil?
235
+ return @api_map.get_instance_methods(match[1], ns_here)
236
+ end
237
+ end
218
238
  end
219
239
  meth = parts.shift
220
240
  if meth == 'new'
221
241
  obj = first
222
242
  else
223
- obj = get_method_return_value first, ns_here, meth
243
+ obj = get_method_return_value first, ns_here, meth, :class
224
244
  end
225
245
  end
226
246
  while parts.length > 0
@@ -237,27 +257,30 @@ module Solargraph
237
257
  end
238
258
  end
239
259
 
240
- def get_method_return_value namespace, root, method
260
+ def get_method_return_value namespace, root, method, scope = :instance
241
261
  meths = @api_map.get_methods(namespace, root).delete_if{ |m| m.insert != method }
242
262
  meths.each { |m|
243
- unless m.documentation.nil?
244
- match = m.documentation.all.match(/@return \[([a-z0-9:_]*)/i)
245
- klass = match[1]
246
- return klass unless klass.nil?
247
- end
263
+ r = get_return_tag(m)
264
+ return r unless r.nil?
248
265
  }
249
- 'Object'
266
+ nil
250
267
  end
251
268
 
252
269
  def get_instance_method_return_value namespace, root, method
253
270
  meths = @api_map.get_instance_methods(namespace, root).delete_if{ |m| m.insert != method }
254
271
  meths.each { |m|
255
- unless m.documentation.nil?
256
- match = m.documentation.all.match(/@return \[([a-z0-9:_]*)/i)
257
- return match[1] unless match.nil?
258
- end
272
+ r = get_return_tag(m)
273
+ return r unless r.nil?
259
274
  }
260
- 'Object'
275
+ nil
276
+ end
277
+
278
+ def get_return_tag suggestion
279
+ unless suggestion.documentation.nil?
280
+ match = suggestion.documentation.all.match(/@return \[([a-z0-9:_]*)/i)
281
+ return match[1]
282
+ end
283
+ nil
261
284
  end
262
285
 
263
286
  def get_signature_at index
@@ -339,7 +362,7 @@ module Solargraph
339
362
  result += @api_map.get_methods(scope, visibility: [:public, :private, :protected])
340
363
  end
341
364
  result += @api_map.get_methods('Kernel')
342
- result
365
+ result
343
366
  end
344
367
 
345
368
  private
@@ -6,17 +6,19 @@ module Solargraph
6
6
 
7
7
  def pack_name(node)
8
8
  parts = []
9
- node.children.each { |n|
10
- if n.kind_of?(AST::Node)
11
- if n.type == :cbase
12
- parts = pack_name(n)
9
+ if node.kind_of?(AST::Node)
10
+ node.children.each { |n|
11
+ if n.kind_of?(AST::Node)
12
+ if n.type == :cbase
13
+ parts = pack_name(n)
14
+ else
15
+ parts += pack_name(n)
16
+ end
13
17
  else
14
- parts += pack_name(n)
18
+ parts.push n unless n.nil?
15
19
  end
16
- else
17
- parts.push n unless n.nil?
18
- end
19
- }
20
+ }
21
+ end
20
22
  parts
21
23
  end
22
24
 
@@ -1,3 +1,3 @@
1
1
  module Solargraph
2
- VERSION = '0.4.1'
2
+ VERSION = '0.4.2'
3
3
  end
@@ -6,10 +6,10 @@ module Solargraph
6
6
 
7
7
  class YardMap
8
8
  def initialize required: [], workspace: nil
9
- unless workspace.nil?
10
- wsy = File.join(workspace, '.yardoc')
11
- yardocs.push wsy if File.exist?(wsy)
12
- end
9
+ #unless workspace.nil?
10
+ # wsy = File.join(workspace, '.yardoc')
11
+ # yardocs.push wsy if File.exist?(wsy)
12
+ #end
13
13
  used = []
14
14
  required.each { |r|
15
15
  if workspace.nil? or !File.exist?(File.join workspace, 'lib', "#{r}.rb")
@@ -58,7 +58,11 @@ module Solargraph
58
58
  unless yard.nil?
59
59
  obj = yard.at query
60
60
  #found.push YARD::Templates::Engine.render(format: :html, object: obj) unless obj.nil?
61
- found.push obj unless obj.nil?
61
+ unless obj.nil?
62
+ # HACK: Fix return tags in core documentation
63
+ fix_return! obj if obj.kind_of?(YARD::CodeObjects::MethodObject) and y.include?('.solargraph')
64
+ found.push obj
65
+ end
62
66
  end
63
67
  }
64
68
  found
@@ -125,15 +129,17 @@ module Solargraph
125
129
  if scope == ''
126
130
  ns = yard.at(namespace)
127
131
  else
128
- ns = yard.resolve(P(scope), namespace)
132
+ ns = find_first_resolved_namespace(yard, namespace, scope)
129
133
  end
130
134
  unless ns.nil? or !ns.kind_of?(YARD::CodeObjects::NamespaceObject)
131
135
  ns.meths(scope: :class, visibility: visibility).each { |m|
136
+ # HACK: Fix return tags in core documentation
137
+ fix_return! m if y.include?('.solargraph')
132
138
  n = m.to_s.split(/[\.#]/).last
133
139
  label = "#{n}"
134
140
  args = get_method_args(m)
135
141
  label += " #{args.join(', ')}" unless args.empty?
136
- meths.push Suggestion.new(label, insert: "#{n}", kind: Suggestion::METHOD, detail: "#{ns}") if n.to_s.match(/^[a-z]/i)
142
+ meths.push Suggestion.new(label, insert: "#{n}", kind: Suggestion::METHOD, documentation: m.docstring, code_object: m, detail: "#{ns}", location: "#{m.file}:#{m.line}")
137
143
  }
138
144
  if ns.kind_of?(YARD::CodeObjects::ClassObject) and namespace != 'Class'
139
145
  meths += get_instance_methods('Class')
@@ -153,10 +159,12 @@ module Solargraph
153
159
  if scope == ''
154
160
  ns = yard.at(namespace)
155
161
  else
156
- ns = yard.resolve(P(scope), namespace)
162
+ ns = find_first_resolved_namespace(yard, namespace, scope)
157
163
  end
158
164
  unless ns.nil?
159
165
  ns.meths(scope: :instance, visibility: visibility).each { |m|
166
+ # HACK: Fix return tags in core documentation
167
+ fix_return! m if y.include?('.solargraph')
160
168
  n = m.to_s.split(/[\.#]/).last
161
169
  if n.to_s.match(/^[a-z]/i) and (namespace == 'Kernel' or !m.to_s.start_with?('Kernel#')) and !m.docstring.to_s.include?(':nodoc:')
162
170
  label = "#{n}"
@@ -174,6 +182,10 @@ module Solargraph
174
182
  meths
175
183
  end
176
184
 
185
+ def gem_names
186
+ Gem::Specification.map{ |s| s.name }.uniq
187
+ end
188
+
177
189
  private
178
190
 
179
191
  def get_method_args meth
@@ -183,6 +195,32 @@ module Solargraph
183
195
  }
184
196
  args
185
197
  end
198
+
199
+ def fix_return! meth
200
+ return unless meth.tag(:return).nil?
201
+ return unless meth.docstring.all.include?('@return')
202
+ text = ''
203
+ meth.docstring.all.lines.each { |line|
204
+ if line.strip.start_with?('@return')
205
+ text += line.strip
206
+ else
207
+ text += line
208
+ end
209
+ text += "\n"
210
+ }
211
+ doc = YARD::Docstring.new(text, meth)
212
+ meth.docstring = doc
213
+ end
214
+
215
+ def find_first_resolved_namespace yard, namespace, scope
216
+ parts = scope.split('::')
217
+ while parts.length > 0
218
+ ns = yard.resolve(P(scope), namespace)
219
+ return ns unless ns.nil?
220
+ parts.pop
221
+ end
222
+ yard.at(namespace)
223
+ end
186
224
  end
187
225
 
188
226
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solargraph
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fred Snyder
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-29 00:00:00.000000000 Z
11
+ date: 2017-04-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser