solargraph 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
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