solargraph 0.8.3 → 0.8.4

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: e52db6d5b84e35fa182015ad0178c8fde5433534
4
- data.tar.gz: 4cb0dbfa89392f8fb4b9b04b506114d1b975fcb9
3
+ metadata.gz: 9f759172a51025a8b3000009fd8a0495ed8b4e09
4
+ data.tar.gz: 45599c0d4f5f61d08e5f1e9ef58ff383e14500c9
5
5
  SHA512:
6
- metadata.gz: 9f4d6d1f77fb88afb992b1a32eb12e017f74a310e090c0b275d4f5d6546313455c7e5d9230322007d1e15acc9686bc88f744e3cb18512b2ba6be5d356adb147e
7
- data.tar.gz: 74cd777945f475843b629de0613cd10949b9aed887a30f5a1423825bac943df4c4491f9caf98b8d3f231df12f22a4e09cb6c62836cc5047003a4a665a2f5a8fd
6
+ metadata.gz: ac26b06145aa273f6601808a83cfe19ede6cc97eb744514f7435aa0b4780cc8c7e33482662930838a20d3bc13008f976e6caa4460319c4637b72873b615e7f91
7
+ data.tar.gz: e5ae9a35a4ac2fccec2450ab6c96f790bed7173de95395fc7978357b5320abef3c47d95ceb3386d0e33b3178abc07ce39b0b76ae9702c54f72b92f85109c176c
@@ -39,7 +39,7 @@ module Solargraph
39
39
  files -= Dir[File.join @workspace, glob]
40
40
  }
41
41
  files.uniq.each { |f|
42
- append_file f #unless yardoc_has_file?(f)
42
+ append_file f if File.file?(f)
43
43
  }
44
44
  end
45
45
  end
@@ -373,6 +373,10 @@ module Solargraph
373
373
  type
374
374
  end
375
375
 
376
+ # Get an array of singleton methods that are available in the specified
377
+ # namespace.
378
+ #
379
+ # @return [Array<Solargraph::Suggestion>]
376
380
  def get_methods(namespace, root = '', visibility: [:public])
377
381
  meths = []
378
382
  meths += inner_get_methods(namespace, root, []) #unless has_yardoc?
@@ -410,6 +414,10 @@ module Solargraph
410
414
  args
411
415
  end
412
416
 
417
+ # Get an array of instance methods that are available in the specified
418
+ # namespace.
419
+ #
420
+ # @return [Array<Solargraph::Suggestion>]
413
421
  def get_instance_methods(namespace, root = '', visibility: [:public])
414
422
  meths = []
415
423
  meths += inner_get_instance_methods(namespace, root, []) #unless has_yardoc?
@@ -461,6 +469,8 @@ module Solargraph
461
469
  arr
462
470
  end
463
471
 
472
+ # Update the YARD documentation for the current workspace.
473
+ #
464
474
  def update_yardoc
465
475
  if workspace.nil?
466
476
  STDERR.puts "No workspace specified for yardoc update."
@@ -24,7 +24,10 @@ module Solargraph
24
24
  tries = 0
25
25
  tmp = @code
26
26
  begin
27
- node, comments = Parser::CurrentRuby.parse_with_comments(tmp)
27
+ # HACK: The current file is parsed with a trailing underscore to fix
28
+ # incomplete trees resulting from short scripts (e.g., a lone variable
29
+ # assignment).
30
+ node, comments = Parser::CurrentRuby.parse_with_comments(tmp + "\n_")
28
31
  @node = self.api_map.append_node(node, comments, filename)
29
32
  @parsed = tmp
30
33
  @code.freeze
@@ -83,6 +86,12 @@ module Solargraph
83
86
  result
84
87
  end
85
88
 
89
+ # Get the offset of the specified line and column.
90
+ # The offset (also called the "index") is typically used to identify the
91
+ # cursor's location in the code when generating suggestions.
92
+ # The line and column numbers should start at zero.
93
+ #
94
+ # @return [Integer]
86
95
  def get_offset line, col
87
96
  offset = 0
88
97
  if line > 0
@@ -93,10 +102,6 @@ module Solargraph
93
102
  offset + col
94
103
  end
95
104
 
96
- def merge node
97
- api_map.merge node
98
- end
99
-
100
105
  def tree_at(index)
101
106
  arr = []
102
107
  arr.push @node
@@ -126,6 +131,11 @@ module Solargraph
126
131
  @node
127
132
  end
128
133
 
134
+ # Get the namespace at the specified location. For example, given the code
135
+ # `class Foo; def bar; end; end`, index 14 (the center) is in the
136
+ # "Foo" namespace.
137
+ #
138
+ # @return [String]
129
139
  def namespace_at(index)
130
140
  tree = tree_at(index)
131
141
  return nil if tree.length == 0
@@ -140,11 +150,16 @@ module Solargraph
140
150
  parts.join("::")
141
151
  end
142
152
 
153
+ # Get the namespace for the specified node. For example, given the code
154
+ # `class Foo; def bar; end; end`, the node for `def bar` is in the "Foo"
155
+ # namespace.
156
+ #
157
+ # @return [String]
143
158
  def namespace_from(node)
144
159
  if node.respond_to?(:loc)
145
160
  namespace_at(node.loc.expression.begin_pos)
146
161
  else
147
- namespace_at(0)
162
+ ''
148
163
  end
149
164
  end
150
165
 
@@ -180,6 +195,10 @@ module Solargraph
180
195
  api_map.get_instance_variables(ns, (node.type == :def ? :instance : :class))
181
196
  end
182
197
 
198
+ # Get suggestions for code completion at the specified location in the
199
+ # source.
200
+ #
201
+ # @return [Array<Suggestions>] The completion suggestions
183
202
  def suggest_at index, filtered: false, with_snippets: false
184
203
  return [] if string_at?(index) or string_at?(index - 1)
185
204
  result = []
@@ -236,7 +255,7 @@ module Solargraph
236
255
  #end
237
256
  end
238
257
  result = reduce_starting_with(result, word_at(index)) if filtered
239
- result.uniq{|s| s.path}
258
+ result.uniq{|s| s.path}.sort{|a,b| a.label <=> b.label}
240
259
  end
241
260
 
242
261
  def signatures_at index
@@ -307,7 +326,8 @@ module Solargraph
307
326
  var = find_local_variable_node(start, node)
308
327
  if var.nil?
309
328
  if start.start_with?('@')
310
- type = api_map.infer_instance_variable(start, ns_here, (node.type == :def ? :instance : :class))
329
+ scope2 = (node.type == :def ? :instance : :class)
330
+ type = api_map.infer_instance_variable(start, ns_here, scope2)
311
331
  else
312
332
  if node.type == :def or node.type == :defs
313
333
  args = get_method_arguments_from(node).keep_if{|a| a.label == start}
@@ -323,11 +343,15 @@ module Solargraph
323
343
  end
324
344
  else
325
345
  cmnt = api_map.get_comment_for(node)
326
- params = cmnt.tags(:param)
327
- params.each do |p|
328
- if p.name == args[0].label
329
- type = p.types[0]
330
- break
346
+ unless cmnt.nil?
347
+ params = cmnt.tags(:param)
348
+ unless params.nil?
349
+ params.each do |p|
350
+ if p.name == args[0].label
351
+ type = p.types[0]
352
+ break
353
+ end
354
+ end
331
355
  end
332
356
  end
333
357
  end
@@ -375,6 +399,17 @@ module Solargraph
375
399
  obj
376
400
  end
377
401
 
402
+ # Get the signature at the specified index.
403
+ # A signature is a method call that can start with a constant, method, or
404
+ # variable and does not include any method arguments. Examples:
405
+ #
406
+ # Code Signature
407
+ # -----------------------------------------
408
+ # String.new String.new
409
+ # @x.bar @x.bar
410
+ # y.split(', ').length y.split.length
411
+ #
412
+ # @return [String]
378
413
  def get_signature_at index
379
414
  brackets = 0
380
415
  squares = 0
@@ -407,6 +442,10 @@ module Solargraph
407
442
  signature
408
443
  end
409
444
 
445
+ # Build a signature from the specified node. This method returns the node
446
+ # as an array of strings.
447
+ #
448
+ # @return [Array<String>]
410
449
  def build_signature(node, parts)
411
450
  if node.kind_of?(AST::Node)
412
451
  if node.type == :send
@@ -437,6 +476,10 @@ module Solargraph
437
476
  result
438
477
  end
439
478
 
479
+ # Get an array of local variables and methods that can be accessed from
480
+ # the specified location in the code.
481
+ #
482
+ # @return [Array<Solargraph::Suggestion>]
440
483
  def get_local_variables_and_methods_at(index)
441
484
  result = []
442
485
  local = parent_node_from(index, :class, :module, :def, :defs) || @node
@@ -39,27 +39,6 @@ module Solargraph
39
39
  end
40
40
  end
41
41
 
42
- def drill_signature node, signature
43
- return signature unless node.kind_of?(AST::Node)
44
- if node.type == :const or node.type == :cbase
45
- unless node.children[0].nil?
46
- signature += drill_signature(node.children[0], signature)
47
- end
48
- signature += '::' unless signature.empty?
49
- signature += node.children[1].to_s
50
- elsif node.type == :lvar
51
- signature += '.' unless signature.empty?
52
- signature += node.children[0].to_s
53
- elsif node.type == :send
54
- unless node.children[0].nil?
55
- signature += drill_signature(node.children[0], signature)
56
- end
57
- signature += '.' unless signature.empty?
58
- signature += node.children[1].to_s
59
- end
60
- signature
61
- end
62
-
63
42
  def infer node
64
43
  if node.type == :str
65
44
  return 'String'
@@ -127,5 +106,28 @@ module Solargraph
127
106
  end
128
107
  @yard_options
129
108
  end
109
+
110
+ private
111
+
112
+ def drill_signature node, signature
113
+ return signature unless node.kind_of?(AST::Node)
114
+ if node.type == :const or node.type == :cbase
115
+ unless node.children[0].nil?
116
+ signature += drill_signature(node.children[0], signature)
117
+ end
118
+ signature += '::' unless signature.empty?
119
+ signature += node.children[1].to_s
120
+ elsif node.type == :lvar
121
+ signature += '.' unless signature.empty?
122
+ signature += node.children[0].to_s
123
+ elsif node.type == :send
124
+ unless node.children[0].nil?
125
+ signature += drill_signature(node.children[0], signature)
126
+ end
127
+ signature += '.' unless signature.empty?
128
+ signature += node.children[1].to_s
129
+ end
130
+ signature
131
+ end
130
132
  end
131
133
  end
@@ -25,7 +25,7 @@ module Solargraph
25
25
  @@semaphore.synchronize {
26
26
  code_map = CodeMap.new(code: params['text'], filename: params['filename'], api_map: @@api_hash[workspace])
27
27
  offset = code_map.get_offset(params['line'].to_i, params['column'].to_i)
28
- sugg = code_map.suggest_at(offset, with_snippets: params['with_snippets'] == '1' ? true : false)
28
+ sugg = code_map.suggest_at(offset, with_snippets: params['with_snippets'] == '1' ? true : false, filtered: (params['filtered'] || false))
29
29
  }
30
30
  { "status" => "ok", "suggestions" => sugg }.to_json
31
31
  rescue Exception => e
@@ -15,12 +15,13 @@ module Solargraph
15
15
  attr_reader :label, :kind, :insert, :detail, :documentation, :code_object, :location, :arguments
16
16
 
17
17
  def initialize label, kind: KEYWORD, insert: nil, detail: nil, documentation: nil, code_object: nil, location: nil, arguments: []
18
+ @helper = Server::Helpers.new
18
19
  @label = label.to_s
19
20
  @kind = kind
20
21
  @insert = insert || @label
21
22
  @detail = detail
22
23
  @code_object = code_object
23
- @documentation = documentation
24
+ @documentation = @helper.html_markup_rdoc(documentation.to_s) unless documentation.nil?
24
25
  @location = location
25
26
  @arguments = arguments
26
27
  end
@@ -36,7 +37,7 @@ module Solargraph
36
37
  def return_type
37
38
  if code_object.nil?
38
39
  unless documentation.nil?
39
- match = documentation.all.match(/@return \[([a-z0-9:_]*)/i)
40
+ match = documentation.match(/@return \[([a-z0-9:_]*)/i)
40
41
  return match[1] unless match.nil?
41
42
  end
42
43
  else
@@ -51,6 +52,15 @@ module Solargraph
51
52
  nil
52
53
  end
53
54
 
55
+ def documentation
56
+ if @documentation.nil?
57
+ unless @code_object.nil?
58
+ @documentation = @helper.html_markup_rdoc(@code_object.docstring.to_s) unless @code_object.docstring.nil?
59
+ end
60
+ end
61
+ @documentation.to_s
62
+ end
63
+
54
64
  def to_json args={}
55
65
  obj = {
56
66
  label: @label,
@@ -59,13 +69,10 @@ module Solargraph
59
69
  detail: @detail,
60
70
  path: path,
61
71
  location: (@location.nil? ? nil : @location.to_s),
62
- arguments: @arguments
72
+ arguments: @arguments,
73
+ return_type: return_type,
74
+ documentation: documentation
63
75
  }
64
- if @code_object.nil?
65
- obj[:documentation] = @documentation.to_s unless @documentation.nil?
66
- else
67
- obj[:documentation] = @code_object.docstring.to_s unless @code_object.docstring.nil?
68
- end
69
76
  obj.to_json(args)
70
77
  end
71
78
  end
@@ -1,3 +1,3 @@
1
1
  module Solargraph
2
- VERSION = '0.8.3'
2
+ VERSION = '0.8.4'
3
3
  end
@@ -197,10 +197,14 @@ module Solargraph
197
197
  end
198
198
  }
199
199
  if ns.kind_of?(YARD::CodeObjects::ClassObject) and namespace != 'Object'
200
- if ns.superclass.kind_of?(YARD::CodeObjects::Proxy)
200
+ #if ns.superclass.kind_of?(YARD::CodeObjects::Proxy)
201
+ unless ns.nil?
201
202
  meths += get_instance_methods(ns.superclass.to_s)
202
203
  end
203
204
  end
205
+ ns.instance_mixins.each do |m|
206
+ meths += get_instance_methods(m.to_s)
207
+ end
204
208
  end
205
209
  end
206
210
  }
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.8.3
4
+ version: 0.8.4
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-06-08 00:00:00.000000000 Z
11
+ date: 2017-06-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser
@@ -137,7 +137,6 @@ files:
137
137
  - lib/solargraph.rb
138
138
  - lib/solargraph/api_map.rb
139
139
  - lib/solargraph/code_map.rb
140
- - lib/solargraph/live_parser.rb
141
140
  - lib/solargraph/mapper.rb
142
141
  - lib/solargraph/node_methods.rb
143
142
  - lib/solargraph/server.rb
@@ -145,7 +144,6 @@ files:
145
144
  - lib/solargraph/snippets.rb
146
145
  - lib/solargraph/suggestion.rb
147
146
  - lib/solargraph/version.rb
148
- - lib/solargraph/views/foo.erb
149
147
  - lib/solargraph/views/layout.erb
150
148
  - lib/solargraph/views/search.erb
151
149
  - lib/solargraph/yard_map.rb
@@ -1,265 +0,0 @@
1
- # Solargraph Ruby Parser
2
- # Copyright (c) 2015 by Fred Snyder for Castwide Technologies LLC
3
- #
4
- # Solargraph::Parser builds a code representation of existing Ruby interfaces
5
- # for use in the Solargraph IDE.
6
- #
7
- # Example use:
8
- #
9
- # parser = Solargraph::Parser.new
10
- # parser.parse #=> String with the entire Ruby interface
11
- # parser.parse("Fixnum") #=> String with the Fixnum interface
12
- #require 'yard'
13
- #require 'yard/registry'
14
-
15
- module Solargraph
16
- class LiveParser
17
- def get_yard_return(path)
18
- objects = []
19
- yardocs = ['yard/2.2.0/.yardoc', 'ruby/yard/2.2.0/.yardoc-stdlib']
20
- yardocs.each { |y|
21
- YARD::Registry.load!(y)
22
- o = YARD::Registry.at(path)
23
- if !o.nil?
24
- objects.push o
25
- end
26
- }
27
- result = nil
28
- objects.each { |x|
29
- meth = x
30
- if !meth.tag(:return) and meth.tag(:overload) and meth.tag(:overload).tag(:return)
31
- meth = meth.tag(:overload)
32
- end
33
- meth.tags(:return).each { |r|
34
- result = "#{r.types[0]}"
35
- break
36
- }
37
- break if !result.nil?
38
- }
39
- result
40
- end
41
- def initialize
42
-
43
- end
44
- def parse namespace = nil
45
- #puts "Namespace: #{namespace}"
46
- @parsed = []
47
- code = ""
48
- fqns = namespace
49
- if fqns.nil?
50
- #code += parse("BasicObject")
51
- #code += parse("Object")
52
- #code += parse("Kernel")
53
- code += parse("Module")
54
- return code
55
- end
56
- mod = eval("#{fqns}")
57
- if !mod.nil?
58
- if mod.instance_of?(Class)
59
- #puts "Parsing class #{mod} to #{fqns}"
60
- code += parse_class mod, fqns
61
- elsif mod.instance_of?(Module)
62
- #puts "Parsing module #{mod} to #{fqns}"
63
- code += parse_module mod, fqns
64
- else
65
- #raise "I don't know what a #{fqns} is."
66
- code += "#{fqns} = nil\n"
67
- end
68
- else
69
- #puts "NIL!"
70
- end
71
- code
72
- end
73
- def self.parse n
74
- LiveParser.new.parse(n)
75
- end
76
- private
77
- def parse_class cls, rel_name
78
- return "" if @parsed.include?(cls)
79
- @parsed.push cls
80
- code = ""
81
- #code += "class #{rel_name}"
82
- code += "class #{cls}"
83
- if !cls.superclass.nil? && cls.superclass != cls
84
- code += " < #{cls.superclass}"
85
- end
86
- code += "\n"
87
- code += parse_class_internals(cls)
88
- code += "end\n"
89
- cls.constants().each { |c|
90
- #obj = cls.class_eval(c.to_s)
91
- begin
92
- obj = cls.const_get(c)
93
- if obj.kind_of?(Class)
94
- code += parse_class(obj, c)
95
- elsif obj.kind_of?(Module)
96
- code += parse_module(obj, c)
97
- else
98
- #code += subparse(obj)
99
- end
100
- #rescue NameError => e
101
- # #puts "NOPE! NOT #{c}"
102
- #end
103
- rescue Exception => e
104
- # TODO: Ignoring all exceptions for now
105
- end
106
- }
107
- code
108
- end
109
- def parse_module mod, rel_name
110
- return "" if @parsed.include?(mod) or mod == Solargraph
111
- @parsed.push mod
112
- code = ""
113
- #if (mod.to_s != "Kernel")
114
- code = "module #{mod}\n"
115
- #end
116
- code += parse_module_internals(mod)
117
- #if (mod.to_s != "Kernel")
118
- code += "end\n"
119
- #end
120
- mod.constants().each { |c|
121
- #obj = mod.class_eval(c.to_s)
122
- begin
123
- obj = mod.const_get(c)
124
- rescue LoadError => e
125
- code += "# @todo Failed to load #{c} from #{mod}\n"
126
- end
127
- if obj.kind_of?(Class)
128
- code += parse_class(obj, c)
129
- elsif obj.kind_of?(Module)
130
- code += parse_module(obj, c)
131
- else
132
- #code += subparse(obj)
133
- end
134
- }
135
- code
136
- end
137
- def parse_class_internals obj
138
- code = ""
139
- obj.included_modules.each { |inc|
140
- #if (inc.to_s != "Kernel")
141
- code += "include #{inc}\n"
142
- #end
143
- }
144
- obj.public_methods(false).each { |m|
145
- if !can_ignore?(obj, m)
146
- args = build_args obj.method(m)
147
- #ret = get_yard_return "#{obj}::#{m}"
148
- #if !ret.nil?
149
- # code += "# @return [#{ret}]\n"
150
- #end
151
- code += "def self.#{m}#{args};end\n"
152
- end
153
- }
154
- alloc = obj
155
- obj.singleton_methods(false).each { |m|
156
- if !can_ignore?(obj, m)
157
- args = build_args obj.method(m)
158
- #ret = get_yard_return "#{obj}::#{m}"
159
- #if !ret.nil?
160
- # code += "# @return [#{ret}]\n"
161
- #end
162
- code += "def self.#{m}#{args};end\n"
163
- end
164
- }
165
- obj.public_instance_methods(false).each { |m|
166
- if !can_ignore?(obj, m)
167
- begin
168
- args = build_args obj.public_instance_method(m)
169
- rescue TypeError => e
170
- args = ""
171
- end
172
- #ret = get_yard_return "#{obj}##{m}"
173
- #if !ret.nil?
174
- # code += "# @return [#{ret}]\n"
175
- #end
176
- code += "def #{m}#{args};end\n"
177
- end
178
- }
179
- code
180
- end
181
- def parse_module_internals obj
182
- code = ""
183
- obj.included_modules.each { |inc|
184
- #if (inc.to_s != "Kernel")
185
- code += "include #{inc}\n"
186
- #end
187
- }
188
- obj.public_methods(false).each { |m|
189
- if obj == Kernel #and obj.singleton_methods.include?(m)
190
- next
191
- end
192
- if !can_ignore?(obj, m)
193
- args = build_args obj.method(m)
194
- #ret = get_yard_return "#{obj}##{m}"
195
- #if !ret.nil?
196
- # code += "# @return [#{ret}]\n"
197
- #end
198
- code += "def #{m}#{args};end\n"
199
- end
200
- }
201
- obj.singleton_methods(false).each { |m|
202
- if !can_ignore?(obj, m)
203
- args = build_args obj.method(m)
204
- #ret = get_yard_return "#{obj}::#{m}"
205
- #if !ret.nil?
206
- # code += "# @return [#{ret}]\n"
207
- #end
208
- code += "def self.#{m}#{args};end\n"
209
- end
210
- }
211
- #obj.public_instance_methods(false).each { |m|
212
- obj.public_instance_methods(false).each { |m|
213
- #if !can_ignore?(obj, m)
214
- args = build_args obj.public_instance_method(m)
215
- #ret = get_yard_return "#{obj}##{m}"
216
- #if !ret.nil?
217
- # code += "# @return [#{ret}]\n"
218
- #end
219
- code += "def #{m}#{args};end\n"
220
- #end
221
- }
222
- code
223
- end
224
- def can_ignore?(obj, sym)
225
- #return false
226
- basics = [Kernel, Module, Object, BasicObject]
227
- return false if basics.include?(obj)
228
- result = false
229
- basics.each { |b|
230
- if b.respond_to?(sym)
231
- result = true
232
- break
233
- end
234
- }
235
- return result
236
- end
237
- def build_args method
238
- args = ""
239
- if (method.arity == -1)
240
- args = "(*args)"
241
- else
242
- arr = []
243
- num = 0
244
- method.parameters.each { |p|
245
- n = p[1]
246
- if n.to_s == ""
247
- n = "arg#{num}"
248
- end
249
- if p[0] == :req
250
- arr.push "#{n}"
251
- elsif p[0] == :opt
252
- arr.push "#{n} = nil"
253
- elsif p[0] == :rest
254
- arr.push "*#{n}"
255
- elsif p[0] == :block
256
- arr.push "&#{n}"
257
- end
258
- num += 1
259
- }
260
- args = "(" + arr.join(", ") + ")"
261
- end
262
- args
263
- end
264
- end
265
- end
@@ -1 +0,0 @@
1
- <p>Foo!</p>