solargraph 0.21.0 → 0.22.0

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.
Files changed (50) hide show
  1. checksums.yaml +5 -5
  2. data/lib/solargraph/api_map/completion.rb +3 -0
  3. data/lib/solargraph/api_map/probe.rb +21 -45
  4. data/lib/solargraph/api_map/store.rb +6 -2
  5. data/lib/solargraph/api_map/type_methods.rb +40 -0
  6. data/lib/solargraph/api_map.rb +45 -35
  7. data/lib/solargraph/diagnostics/require_not_found.rb +5 -0
  8. data/lib/solargraph/diagnostics/rubocop.rb +9 -0
  9. data/lib/solargraph/diagnostics.rb +5 -0
  10. data/lib/solargraph/language_server/host.rb +9 -1
  11. data/lib/solargraph/language_server/message/base.rb +1 -8
  12. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +5 -1
  13. data/lib/solargraph/language_server/message/extended/download_core.rb +25 -0
  14. data/lib/solargraph/language_server/message/extended.rb +1 -0
  15. data/lib/solargraph/language_server/message/initialize.rb +3 -1
  16. data/lib/solargraph/language_server/message/text_document/definition.rb +1 -1
  17. data/lib/solargraph/language_server/message/text_document/hover.rb +1 -1
  18. data/lib/solargraph/language_server/message/text_document/references.rb +14 -0
  19. data/lib/solargraph/language_server/message/text_document/rename.rb +17 -0
  20. data/lib/solargraph/language_server/message/text_document.rb +13 -11
  21. data/lib/solargraph/language_server/message.rb +3 -0
  22. data/lib/solargraph/language_server/request.rb +4 -0
  23. data/lib/solargraph/language_server/transport/socket.rb +4 -4
  24. data/lib/solargraph/language_server/uri_helpers.rb +2 -0
  25. data/lib/solargraph/library.rb +37 -0
  26. data/lib/solargraph/live_map/cache.rb +7 -0
  27. data/lib/solargraph/live_map.rb +8 -2
  28. data/lib/solargraph/pin/attribute.rb +5 -1
  29. data/lib/solargraph/pin/namespace.rb +0 -2
  30. data/lib/solargraph/pin/proxy_method.rb +31 -0
  31. data/lib/solargraph/pin.rb +1 -0
  32. data/lib/solargraph/plugin/process.rb +1 -1
  33. data/lib/solargraph/plugin/runtime.rb +6 -3
  34. data/lib/solargraph/shell.rb +0 -1
  35. data/lib/solargraph/source/flawed_builder.rb +3 -0
  36. data/lib/solargraph/source/fragment.rb +12 -15
  37. data/lib/solargraph/source/location.rb +3 -0
  38. data/lib/solargraph/source/mapper.rb +60 -18
  39. data/lib/solargraph/source/node_methods.rb +111 -0
  40. data/lib/solargraph/source/position.rb +18 -0
  41. data/lib/solargraph/source/range.rb +5 -1
  42. data/lib/solargraph/source.rb +31 -1
  43. data/lib/solargraph/version.rb +1 -1
  44. data/lib/solargraph/workspace/config.rb +6 -2
  45. data/lib/solargraph/workspace.rb +7 -1
  46. data/lib/solargraph/yard_map/core_docs.rb +1 -1
  47. data/lib/solargraph/yard_map.rb +43 -5
  48. data/lib/solargraph.rb +0 -1
  49. metadata +27 -8
  50. data/lib/solargraph/node_methods.rb +0 -101
@@ -56,6 +56,8 @@ module Solargraph
56
56
  register 'textDocument/formatting', TextDocument::Formatting
57
57
  register 'textDocument/onTypeFormatting', TextDocument::OnTypeFormatting
58
58
  register 'textDocument/documentSymbol', TextDocument::DocumentSymbol
59
+ register 'textDocument/references', TextDocument::References
60
+ register 'textDocument/rename', TextDocument::Rename
59
61
  register 'workspace/didChangeWatchedFiles', Workspace::DidChangeWatchedFiles
60
62
  register 'workspace/didChangeConfiguration', Workspace::DidChangeConfiguration
61
63
  register 'workspace/symbol', Workspace::WorkspaceSymbol
@@ -64,6 +66,7 @@ module Solargraph
64
66
  register '$/solargraph/search', Extended::Search
65
67
  register '$/solargraph/checkGemVersion', Extended::CheckGemVersion
66
68
  register '$/solargraph/documentGems', Extended::DocumentGems
69
+ register '$/solargraph/downloadCore', Extended::DownloadCore
67
70
  register 'shutdown', Shutdown
68
71
  register 'exit', ExitNotification
69
72
  end
@@ -9,6 +9,10 @@ module Solargraph
9
9
  def process result
10
10
  @block.call(result) unless @block.nil?
11
11
  end
12
+
13
+ def send_response
14
+ # noop
15
+ end
12
16
  end
13
17
  end
14
18
  end
@@ -18,13 +18,13 @@ module Solargraph
18
18
  start_timers
19
19
  end
20
20
 
21
- def process message
21
+ def process request
22
22
  Thread.new do
23
- message = @host.start(message)
24
- message.send
23
+ message = @host.start(request)
24
+ message.send_response
25
25
  tmp = @host.flush
26
26
  send_data tmp unless tmp.empty?
27
- GC.start unless message['method'] == 'textDocument/didChange'
27
+ GC.start unless request['method'] == 'textDocument/didChange'
28
28
  end
29
29
  end
30
30
 
@@ -1,6 +1,8 @@
1
1
  module Solargraph
2
2
  module LanguageServer
3
3
  module UriHelpers
4
+ module_function
5
+
4
6
  # Convert a file URI to a path.
5
7
  #
6
8
  # @param uri [String]
@@ -141,6 +141,30 @@ module Solargraph
141
141
  api_map.signify(fragment)
142
142
  end
143
143
 
144
+ def references_from filename, line, column
145
+ source = read(filename)
146
+ api_map.virtualize source
147
+ fragment = source.fragment_at(line, column)
148
+ pins = api_map.define(fragment)
149
+ return [] if pins.empty?
150
+ result = []
151
+ # @param pin [Solargraph::Pin::Base]
152
+ pins.uniq.each do |pin|
153
+ if pin.kind != Solargraph::Pin::NAMESPACE and !pin.location.nil?
154
+ mn_loc = get_symbol_name_location(pin)
155
+ result.push mn_loc unless mn_loc.nil?
156
+ end
157
+ (workspace.sources + source_hash.values).uniq(&:filename).each do |source|
158
+ found = source.references(pin.name).select do |loc|
159
+ referenced = definitions_at(loc.filename, loc.range.ending.line, loc.range.ending.character).first
160
+ !referenced.nil? and referenced.path == pin.path
161
+ end
162
+ result.concat found.sort{|a, b| a.range.start.line <=> b.range.start.line}
163
+ end
164
+ end
165
+ result
166
+ end
167
+
144
168
  # Get the pin at the specified location or nil if the pin does not exist.
145
169
  #
146
170
  # @return [Solargraph::Pin::Base]
@@ -270,5 +294,18 @@ module Solargraph
270
294
  raise FileNotFoundError, "File not found: #{filename}" unless File.file?(filename)
271
295
  Solargraph::Source.load(filename)
272
296
  end
297
+
298
+ def get_symbol_name_location pin
299
+ decsrc = read(pin.location.filename)
300
+ offset = Solargraph::Source::Position.to_offset(decsrc.code, pin.location.range.start)
301
+ soff = decsrc.code.index(pin.name, offset)
302
+ eoff = soff + pin.name.length
303
+ Solargraph::Source::Location.new(
304
+ pin.location.filename, Solargraph::Source::Range.new(
305
+ Solargraph::Source::Position.from_offset(decsrc.code, soff),
306
+ Solargraph::Source::Position.from_offset(decsrc.code, eoff)
307
+ )
308
+ )
309
+ end
273
310
  end
274
311
  end
@@ -4,6 +4,7 @@ module Solargraph
4
4
  def initialize
5
5
  @method_cache = {}
6
6
  @constant_cache = {}
7
+ @path_cache = {}
7
8
  end
8
9
 
9
10
  def get_methods options
@@ -12,6 +13,7 @@ module Solargraph
12
13
 
13
14
  def set_methods options, values
14
15
  @method_cache[options] = values
16
+ values.each { |pin| @path_cache[pin.path] = pin }
15
17
  end
16
18
 
17
19
  def get_constants namespace, root
@@ -22,9 +24,14 @@ module Solargraph
22
24
  @constant_cache[[namespace, root]] = values
23
25
  end
24
26
 
27
+ def get_path_pin path
28
+ @path_cache[path]
29
+ end
30
+
25
31
  def clear
26
32
  @method_cache.clear
27
33
  @constant_cache.clear
34
+ @path_cache.clear
28
35
  end
29
36
  end
30
37
  end
@@ -9,11 +9,17 @@ module Solargraph
9
9
  # @return [Solargraph::ApiMap]
10
10
  attr_reader :api_map
11
11
 
12
+ # @param api_map [Solargraph::ApiMap]
12
13
  def initialize api_map
13
14
  @api_map = api_map
14
15
  runners
15
16
  end
16
17
 
18
+ def get_path_pin path
19
+ cache.get_path_pin(path)
20
+ end
21
+
22
+ # @return [Array<Solargraph::Pin::Base>]
17
23
  def get_methods(namespace, root = '', scope = 'instance', with_private = false)
18
24
  fqns = api_map.find_fully_qualified_namespace(namespace, root)
19
25
  params = {
@@ -26,7 +32,7 @@ module Solargraph
26
32
  runners.each do |p|
27
33
  next if did_runtime and p.runtime?
28
34
  p.get_methods(namespace: namespace, root: root, scope: scope, with_private: with_private).each do |m|
29
- result.push Suggestion.new(m['name'], kind: Suggestion::METHOD, docstring: YARD::Docstring.new('(defined at runtime)'), path: "#{fqns}.#{m['name']}", arguments: m['parameters'])
35
+ result.push Solargraph::Pin::Method.new(nil, namespace, m['name'], YARD::Docstring.new('(defined at runtime)'), scope.to_sym, nil, [])
30
36
  end
31
37
  did_runtime = true if p.runtime?
32
38
  end
@@ -34,7 +40,7 @@ module Solargraph
34
40
  result
35
41
  end
36
42
 
37
- # @return [Array<Solargraph::Suggestion>]
43
+ # @return [Array<Solargraph::Pin::Base>]
38
44
  def get_constants(namespace, root = '')
39
45
  cached = cache.get_constants(namespace, root)
40
46
  return cached unless cached.nil?
@@ -4,10 +4,14 @@ module Solargraph
4
4
  # @return [Symbol] :reader or :writer
5
5
  attr_reader :access
6
6
 
7
- def initialize location, namespace, name, docstring, access
7
+ # @return [Symbol] :class or :instance
8
+ attr_reader :scope
9
+
10
+ def initialize location, namespace, name, docstring, access, scope
8
11
  super(location, namespace, name, docstring)
9
12
  @access = access
10
13
  @docstring = docstring
14
+ @scope = scope
11
15
  end
12
16
 
13
17
  def kind
@@ -1,8 +1,6 @@
1
1
  module Solargraph
2
2
  module Pin
3
3
  class Namespace < Pin::Base
4
- include Solargraph::NodeMethods
5
-
6
4
  attr_reader :visibility
7
5
 
8
6
  attr_reader :type
@@ -0,0 +1,31 @@
1
+ module Solargraph
2
+ module Pin
3
+ # ProxyMethod serves as a quick, disposable shortcut for providing context
4
+ # to type inference methods. ApiMap::Probe can treat it as an anonymous
5
+ # method while analyzing signatures.
6
+ #
7
+ class ProxyMethod
8
+ # @return [String]
9
+ attr_reader :return_type
10
+
11
+ def initialize return_type
12
+ @return_type = return_type
13
+ end
14
+
15
+ # @return [String]
16
+ def namespace
17
+ @namespace ||= ApiMap::TypeMethods.extract_namespace(@return_type)
18
+ end
19
+
20
+ # @return [Integer]
21
+ def kind
22
+ Pin::METHOD
23
+ end
24
+
25
+ # @return [Symbol]
26
+ def scope
27
+ :instance
28
+ end
29
+ end
30
+ end
31
+ end
@@ -21,6 +21,7 @@ module Solargraph
21
21
  autoload :Documenting, 'solargraph/pin/documenting'
22
22
  autoload :Block, 'solargraph/pin/block'
23
23
  autoload :Localized, 'solargraph/pin/localized'
24
+ autoload :ProxyMethod, 'solargraph/pin/proxy_method'
24
25
 
25
26
  ATTRIBUTE = 1
26
27
  CLASS_VARIABLE = 2
@@ -33,7 +33,7 @@ module Solargraph
33
33
  rescue JSON::ParserError => e
34
34
  STDOUT.puts respond_err "Error parsing input: #{e.message}"
35
35
  rescue Exception => e
36
- STDOUT.puts respond_err "Error processing input: #{e.message}"
36
+ STDOUT.puts respond_err "Error processing input: #{e.message}\n#{e.backtrace}"
37
37
  end
38
38
  STDOUT.flush
39
39
  end
@@ -53,11 +53,14 @@ module Solargraph
53
53
  end
54
54
  end
55
55
 
56
+ def stop
57
+ @io.close
58
+ end
59
+
56
60
  protected
57
61
 
58
62
  def load_environment
59
63
  return if api_map.nil?
60
- STDERR.puts "Required paths given to Runtime: #{api_map.required}"
61
64
  send_require api_map.required
62
65
  @current_required = api_map.required.clone
63
66
  end
@@ -66,8 +69,8 @@ module Solargraph
66
69
 
67
70
  def start_process
68
71
  dir = Dir.pwd
69
- unless api_map.nil? or api_map.workspace.nil?
70
- dir = api_map.workspace
72
+ unless api_map.nil? or api_map.workspace.nil? or api_map.workspace.directory.nil?
73
+ dir = api_map.workspace.directory
71
74
  end
72
75
  Dir.chdir(dir) do
73
76
  @io = IO.popen(executable, 'r+')
@@ -69,7 +69,6 @@ module Solargraph
69
69
  matches = []
70
70
  if options[:extensions]
71
71
  Gem::Specification.each do |g|
72
- puts g.name
73
72
  if g.name.match(/^solargraph\-[A-Za-z0-9_\-]*?\-ext/)
74
73
  require g.name
75
74
  matches.push g.name
@@ -1,5 +1,8 @@
1
1
  module Solargraph
2
2
  class Source
3
+ # A custom builder for source parsers that ignores character encoding
4
+ # issues in literal strings.
5
+ #
3
6
  class FlawedBuilder < Parser::Builders::Default
4
7
  def string_value(token)
5
8
  value(token)
@@ -3,12 +3,11 @@ module Solargraph
3
3
  class Fragment
4
4
  include NodeMethods
5
5
 
6
- attr_reader :tree
7
-
8
6
  attr_reader :line
9
7
 
10
8
  attr_reader :column
11
9
 
10
+ # @return [Solargraph::Source]
12
11
  attr_reader :source
13
12
 
14
13
  # @param source [Solargraph::Source]
@@ -46,17 +45,6 @@ module Solargraph
46
45
  @argument ||= !signature_position.nil?
47
46
  end
48
47
 
49
- def chained?
50
- if @chained.nil?
51
- @chained = false
52
- @tree.each do |n|
53
- @chained = true if n.type == :send
54
- break
55
- end
56
- end
57
- @chained
58
- end
59
-
60
48
  # @return [Fragment]
61
49
  def recipient
62
50
  return nil if signature_position.nil?
@@ -319,9 +307,18 @@ module Solargraph
319
307
  @base_literal = 'Integer'
320
308
  # @todo Smelly exceptional case for array literals
321
309
  elsif signature.start_with?('.[]')
322
- index += 3
323
- signature = signature[index+3..-1].to_s
310
+ index += 2
311
+ signature = signature[3..-1].to_s
324
312
  @base_literal = 'Array'
313
+ elsif signature.start_with?('.')
314
+ pos = Position.from_offset(source.code, index)
315
+ node = source.node_at(pos.line, pos.character)
316
+ lit = infer_literal_node_type(node)
317
+ unless lit.nil?
318
+ signature = signature[1..-1].to_s
319
+ index += 1
320
+ @base_literal = lit
321
+ end
325
322
  end
326
323
  [index + 1, signature]
327
324
  end
@@ -1,7 +1,10 @@
1
1
  module Solargraph
2
2
  class Source
3
3
  class Location
4
+ # @return [String]
4
5
  attr_reader :filename
6
+
7
+ # @return [Solargraph::Source::Range]
5
8
  attr_reader :range
6
9
 
7
10
  def initialize filename, range
@@ -1,11 +1,19 @@
1
1
  module Solargraph
2
2
  class Source
3
+ # The Mapper generates pins and other data for Sources.
4
+ #
5
+ # This class is used internally by the Source class on initialization,
6
+ # e.g., via Source.new or Source.load. Users should not normally need to
7
+ # call it directly.
8
+ #
3
9
  class Mapper
4
10
  include NodeMethods
5
11
 
6
12
  private_class_method :new
7
13
 
8
- # @return [Array<Solargraph::Pin::Base>]
14
+ # Generate the data.
15
+ #
16
+ # @return [Array]
9
17
  def map filename, code, node, comments
10
18
  @filename = filename
11
19
  @code = code
@@ -37,7 +45,7 @@ module Solargraph
37
45
  end
38
46
 
39
47
  class << self
40
- # @return [Array<Solargraph::Pin::Base>]
48
+ # @return [Array]
41
49
  def map filename, code, node, comments
42
50
  new.map filename, code, node, comments
43
51
  end
@@ -98,9 +106,17 @@ module Solargraph
98
106
  u = c.updated(:ivasgn, c.children + ora.children[1..-1], nil)
99
107
  @docstring_hash[u.loc] = docstring_for(ora)
100
108
  pins.push Solargraph::Pin::InstanceVariable.new(get_node_location(u), fqn || '', c.children[0].to_s, docstring_for(u), resolve_node_signature(u.children[1]), infer_literal_node_type(u.children[1]), context)
109
+ if visibility == :module_function and context.kind == Pin::METHOD
110
+ other = pins.select{|pin| pin.path == "#{context.namespace}.#{context.name}"}.first
111
+ pins.push Solargraph::Pin::InstanceVariable.new(get_node_location(u), fqn || '', c.children[0].to_s, docstring_for(u), resolve_node_signature(u.children[1]), infer_literal_node_type(u.children[1]), other) unless other.nil?
112
+ end
101
113
  end
102
114
  else
103
115
  pins.push Solargraph::Pin::InstanceVariable.new(get_node_location(c), fqn || '',c.children[0].to_s, docstring_for(c), resolve_node_signature(c.children[1]), infer_literal_node_type(c.children[1]), context)
116
+ if visibility == :module_function and context.kind == Pin::METHOD
117
+ other = pins.select{|pin| pin.path == "#{context.namespace}.#{context.name}"}.first
118
+ pins.push Solargraph::Pin::InstanceVariable.new(get_node_location(c), fqn || '',c.children[0].to_s, docstring_for(c), resolve_node_signature(c.children[1]), infer_literal_node_type(c.children[1]), other)
119
+ end
104
120
  end
105
121
  elsif c.type == :cvasgn
106
122
  here = get_node_start_position(c)
@@ -134,7 +150,6 @@ module Solargraph
134
150
  pins.push Solargraph::Pin::GlobalVariable.new(get_node_location(c), fqn, c.children[0].to_s, docstring_for(c), resolve_node_signature(c.children[1]), infer_literal_node_type(c.children[1]), @pins.first)
135
151
  elsif c.type == :sym
136
152
  @symbols.push Solargraph::Pin::Symbol.new(get_node_location(c), ":#{c.children[0]}")
137
-
138
153
  elsif c.type == :casgn
139
154
  here = get_node_start_position(c)
140
155
  block = get_block_pin(here)
@@ -146,12 +161,15 @@ module Solargraph
146
161
  # @todo Smelly instance variable access.
147
162
  pins.last.instance_variable_set(:@return_type, methpin.namespace)
148
163
  pins.push Solargraph::Pin::Method.new(methpin.location, methpin.namespace, methpin.name, methpin.docstring, methpin.scope, :private, methpin.parameters)
164
+ elsif visibility == :module_function
165
+ pins.push Solargraph::Pin::Method.new(methpin.location, methpin.namespace, methpin.name, methpin.docstring, :class, :public, methpin.parameters)
166
+ pins.push Solargraph::Pin::Method.new(methpin.location, methpin.namespace, methpin.name, methpin.docstring, :instance, :private, methpin.parameters)
149
167
  else
150
168
  pins.push methpin
151
169
  end
152
170
  elsif c.type == :defs
153
171
  s_visi = visibility
154
- s_visi = :public if scope != :class
172
+ s_visi = :public if s_visi == :module_function or scope != :class
155
173
  if c.children[0].is_a?(AST::Node) and c.children[0].type == :self
156
174
  dfqn = fqn || ''
157
175
  else
@@ -191,6 +209,32 @@ module Solargraph
191
209
  end
192
210
  end
193
211
  next
212
+ elsif c.type == :send and c.children[1] == :module_function
213
+ # @todo Handle module_function
214
+ if c.children[2].nil?
215
+ visibility = :module_function
216
+ elsif c.children[2].type == :sym or c.children[2].type == :str
217
+ # @todo What to do about references?
218
+ c.children[2..-1].each do |x|
219
+ cn = x.children[0].to_s
220
+ ref = pins.select{|p| p.namespace == (fqn || '') and p.name == cn}.first
221
+ unless ref.nil?
222
+ pins.delete ref
223
+ mm = Solargraph::Pin::Method.new(ref.location, ref.namespace, ref.name, ref.docstring, :class, :public, ref.parameters)
224
+ cm = Solargraph::Pin::Method.new(ref.location, ref.namespace, ref.name, ref.docstring, :instance, :private, ref.parameters)
225
+ pins.push mm, cm
226
+ pins.select{|pin| pin.kind == Pin::INSTANCE_VARIABLE and pin.context == ref}.each do |ivar|
227
+ pins.delete ivar
228
+ pins.push Solargraph::Pin::InstanceVariable.new(ivar.location, ivar.namespace, ivar.name, ivar.docstring, ivar.signature, ivar.instance_variable_get(:@literal), mm)
229
+ pins.push Solargraph::Pin::InstanceVariable.new(ivar.location, ivar.namespace, ivar.name, ivar.docstring, ivar.signature, ivar.instance_variable_get(:@literal), cm)
230
+ end
231
+ end
232
+ end
233
+ elsif c.children[2].type == :def
234
+ # @todo A single function
235
+ process c, tree, :module_function, :class, fqn, stack
236
+ next
237
+ end
194
238
  elsif c.type == :send and c.children[1] == :include and c.children[0].nil?
195
239
  last_node = get_last_in_stack_not_begin(stack)
196
240
  if last_node.nil? or last_node.type == :class or last_node.type == :module or last_node.type == :source
@@ -207,24 +251,26 @@ module Solargraph
207
251
  elsif c.type == :send and c.children[1] == :extend and c.children[0].nil?
208
252
  last_node = get_last_in_stack_not_begin(stack)
209
253
  if last_node.nil? or last_node.type == :class or last_node.type == :module or last_node.type == :source
210
- if c.children[2].kind_of?(AST::Node) and c.children[2].type == :const
211
- # namespace_extends[fqn || ''] ||= []
212
- c.children[2..-1].each do |i|
213
- nspin = @pins.select{|pin| pin.kind == Pin::NAMESPACE and pin.path == fqn}.last
214
- unless nspin.nil?
254
+ c.children[2..-1].each do |i|
255
+ nspin = @pins.select{|pin| pin.kind == Pin::NAMESPACE and pin.path == fqn}.last
256
+ unless nspin.nil?
257
+ ref = nil
258
+ if i.type == :self
259
+ ref = Pin::Reference.new(get_node_location(c), nspin.path, nspin.path)
260
+ elsif i.type == :const
215
261
  ref = Pin::Reference.new(get_node_location(c), nspin.path, unpack_name(i))
216
- nspin.extend_references.push(ref)
217
262
  end
263
+ nspin.extend_references.push(ref) unless ref.nil?
218
264
  end
219
265
  end
220
266
  end
221
267
  elsif c.type == :send and [:attr_reader, :attr_writer, :attr_accessor].include?(c.children[1])
222
268
  c.children[2..-1].each do |a|
223
269
  if c.children[1] == :attr_reader or c.children[1] == :attr_accessor
224
- pins.push Solargraph::Pin::Attribute.new(get_node_location(c), fqn || '', "#{a.children[0]}", docstring_for(c), :reader) #AttrPin.new(c)
270
+ pins.push Solargraph::Pin::Attribute.new(get_node_location(c), fqn || '', "#{a.children[0]}", docstring_for(c), :reader, scope)
225
271
  end
226
272
  if c.children[1] == :attr_writer or c.children[1] == :attr_accessor
227
- pins.push Solargraph::Pin::Attribute.new(get_node_location(c), fqn || '', "#{a.children[0]}=", docstring_for(c), :writer) #AttrPin.new(c)
273
+ pins.push Solargraph::Pin::Attribute.new(get_node_location(c), fqn || '', "#{a.children[0]}=", docstring_for(c), :writer, scope)
228
274
  end
229
275
  end
230
276
  elsif c.type == :sclass and c.children[0].type == :self
@@ -298,10 +344,6 @@ module Solargraph
298
344
  nil
299
345
  end
300
346
 
301
- def get_node_start_position(node)
302
- Position.new(node.loc.line - 1, node.loc.column)
303
- end
304
-
305
347
  def get_node_location(node)
306
348
  if node.nil?
307
349
  st = Position.new(0, 0)
@@ -360,10 +402,10 @@ module Solargraph
360
402
  t = (d.tag.types.nil? || d.tag.types.empty?) ? nil : d.tag.types.flatten.join('')
361
403
  if t.nil? or t.include?('r')
362
404
  # location, namespace, name, docstring, access
363
- pins.push Solargraph::Pin::Attribute.new(get_node_location(k.node), namespace_for(k.node).path, d.tag.name, docstring, :reader)
405
+ pins.push Solargraph::Pin::Attribute.new(get_node_location(k.node), namespace_for(k.node).path, d.tag.name, docstring, :reader, :instance)
364
406
  end
365
407
  if t.nil? or t.include?('w')
366
- pins.push Solargraph::Pin::Attribute.new(get_node_location(k.node), namespace_for(k.node).path, "#{d.tag.name}=", docstring, :reader)
408
+ pins.push Solargraph::Pin::Attribute.new(get_node_location(k.node), namespace_for(k.node).path, "#{d.tag.name}=", docstring, :writer, :instance)
367
409
  end
368
410
  elsif d.tag.tag_name == 'method'
369
411
  gen_src = Source.new("def #{d.tag.name};end", filename)
@@ -0,0 +1,111 @@
1
+ module Solargraph
2
+ class Source
3
+ module NodeMethods
4
+ module_function
5
+
6
+ # @return [String]
7
+ def unpack_name(node)
8
+ pack_name(node).join("::")
9
+ end
10
+
11
+ # @return [Array<String>]
12
+ def pack_name(node)
13
+ parts = []
14
+ if node.kind_of?(AST::Node)
15
+ node.children.each { |n|
16
+ if n.kind_of?(AST::Node)
17
+ if n.type == :cbase
18
+ parts = pack_name(n)
19
+ else
20
+ parts += pack_name(n)
21
+ end
22
+ else
23
+ parts.push n unless n.nil?
24
+ end
25
+ }
26
+ end
27
+ parts
28
+ end
29
+
30
+ # @return [String]
31
+ def const_from node
32
+ if node.kind_of?(AST::Node) and node.type == :const
33
+ result = ''
34
+ unless node.children[0].nil?
35
+ result = const_from(node.children[0])
36
+ end
37
+ if result == ''
38
+ result = node.children[1].to_s
39
+ else
40
+ result = result + '::' + node.children[1].to_s
41
+ end
42
+ result
43
+ else
44
+ nil
45
+ end
46
+ end
47
+
48
+ # @return [String]
49
+ def infer_literal_node_type node
50
+ return nil unless node.kind_of?(AST::Node)
51
+ if node.type == :str or node.type == :dstr
52
+ return 'String'
53
+ elsif node.type == :array
54
+ return 'Array'
55
+ elsif node.type == :hash
56
+ return 'Hash'
57
+ elsif node.type == :int
58
+ return 'Integer'
59
+ elsif node.type == :float
60
+ return 'Float'
61
+ elsif node.type == :sym
62
+ return 'Symbol'
63
+ # @todo Maybe ignore nils
64
+ # elsif node.type == :nil
65
+ # return 'NilClass'
66
+ end
67
+ nil
68
+ end
69
+
70
+ # Get a call signature from a node.
71
+ # The result should be a string in the form of a method path, e.g.,
72
+ # String.new or variable.method.
73
+ #
74
+ # @return [String]
75
+ def resolve_node_signature node
76
+ result = drill_signature node, ''
77
+ return nil if result.empty?
78
+ result
79
+ end
80
+
81
+ def get_node_start_position(node)
82
+ Position.new(node.loc.line - 1, node.loc.column)
83
+ end
84
+
85
+ def get_node_end_position(node)
86
+ Position.new(node.loc.last_line - 1, node.loc.last_column)
87
+ end
88
+
89
+ def drill_signature node, signature
90
+ return signature unless node.kind_of?(AST::Node)
91
+ if node.type == :const or node.type == :cbase
92
+ unless node.children[0].nil?
93
+ signature += drill_signature(node.children[0], signature)
94
+ end
95
+ signature += '::' unless signature.empty?
96
+ signature += node.children[1].to_s
97
+ elsif node.type == :lvar or node.type == :ivar or node.type == :cvar
98
+ signature += '.' unless signature.empty?
99
+ signature += node.children[0].to_s
100
+ elsif node.type == :send
101
+ unless node.children[0].nil?
102
+ signature += drill_signature(node.children[0], signature)
103
+ end
104
+ signature += '.' unless signature.empty?
105
+ signature += node.children[1].to_s
106
+ end
107
+ signature
108
+ end
109
+ end
110
+ end
111
+ end