solargraph 0.39.0 → 0.40.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 (96) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +2 -7
  3. data/CHANGELOG.md +984 -0
  4. data/Rakefile +12 -1
  5. data/SPONSORS.md +6 -0
  6. data/lib/.rubocop.yml +21 -0
  7. data/lib/solargraph/api_map/cache.rb +4 -0
  8. data/lib/solargraph/api_map/store.rb +35 -51
  9. data/lib/solargraph/api_map.rb +94 -87
  10. data/lib/solargraph/{bundle.rb → bench.rb} +6 -2
  11. data/lib/solargraph/compat.rb +23 -0
  12. data/lib/solargraph/complex_type.rb +2 -2
  13. data/lib/solargraph/convention/base.rb +16 -8
  14. data/lib/solargraph/convention/gemfile.rb +2 -5
  15. data/lib/solargraph/convention/gemspec.rb +3 -6
  16. data/lib/solargraph/convention/rspec.rb +3 -6
  17. data/lib/solargraph/convention.rb +14 -5
  18. data/lib/solargraph/diagnostics/rubocop.rb +2 -1
  19. data/lib/solargraph/diagnostics/rubocop_helpers.rb +4 -1
  20. data/lib/solargraph/documentor.rb +4 -0
  21. data/lib/solargraph/environ.rb +11 -6
  22. data/lib/solargraph/language_server/host.rb +1 -1
  23. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +6 -1
  24. data/lib/solargraph/language_server/message/text_document/definition.rb +1 -1
  25. data/lib/solargraph/language_server/message/text_document/formatting.rb +7 -3
  26. data/lib/solargraph/language_server/uri_helpers.rb +23 -3
  27. data/lib/solargraph/library.rb +22 -8
  28. data/lib/solargraph/parser/legacy/class_methods.rb +4 -0
  29. data/lib/solargraph/parser/legacy/node_chainer.rb +10 -7
  30. data/lib/solargraph/parser/legacy/node_methods.rb +16 -3
  31. data/lib/solargraph/parser/legacy/node_processors/ivasgn_node.rb +1 -1
  32. data/lib/solargraph/parser/legacy/node_processors/send_node.rb +48 -23
  33. data/lib/solargraph/parser/node_processor/base.rb +3 -0
  34. data/lib/solargraph/parser/rubyvm/class_methods.rb +6 -2
  35. data/lib/solargraph/parser/rubyvm/node_chainer.rb +11 -9
  36. data/lib/solargraph/parser/rubyvm/node_methods.rb +6 -1
  37. data/lib/solargraph/parser/rubyvm/node_processors/args_node.rb +35 -11
  38. data/lib/solargraph/parser/rubyvm/node_processors/ivasgn_node.rb +1 -1
  39. data/lib/solargraph/parser/rubyvm/node_processors/kw_arg_node.rb +6 -1
  40. data/lib/solargraph/parser/rubyvm/node_processors/opt_arg_node.rb +6 -1
  41. data/lib/solargraph/parser/rubyvm/node_processors/send_node.rb +52 -67
  42. data/lib/solargraph/parser/rubyvm/node_processors.rb +2 -0
  43. data/lib/solargraph/pin/base.rb +2 -2
  44. data/lib/solargraph/pin/base_variable.rb +1 -1
  45. data/lib/solargraph/pin/block.rb +28 -14
  46. data/lib/solargraph/pin/closure.rb +1 -1
  47. data/lib/solargraph/pin/common.rb +1 -1
  48. data/lib/solargraph/pin/constant.rb +1 -1
  49. data/lib/solargraph/pin/conversions.rb +3 -4
  50. data/lib/solargraph/pin/documenting.rb +6 -11
  51. data/lib/solargraph/pin/local_variable.rb +1 -1
  52. data/lib/solargraph/pin/method.rb +143 -9
  53. data/lib/solargraph/pin/method_alias.rb +2 -2
  54. data/lib/solargraph/pin/namespace.rb +1 -1
  55. data/lib/solargraph/pin/parameter.rb +2 -2
  56. data/lib/solargraph/pin/proxy_type.rb +1 -1
  57. data/lib/solargraph/pin.rb +0 -3
  58. data/lib/solargraph/position.rb +2 -14
  59. data/lib/solargraph/shell.rb +2 -1
  60. data/lib/solargraph/source/chain/call.rb +9 -0
  61. data/lib/solargraph/source/chain/head.rb +14 -8
  62. data/lib/solargraph/source/chain/z_super.rb +30 -0
  63. data/lib/solargraph/source/chain.rb +19 -36
  64. data/lib/solargraph/source/source_chainer.rb +2 -1
  65. data/lib/solargraph/source.rb +24 -9
  66. data/lib/solargraph/source_map/clip.rb +78 -44
  67. data/lib/solargraph/source_map/mapper.rb +41 -21
  68. data/lib/solargraph/source_map.rb +20 -2
  69. data/lib/solargraph/type_checker/param_def.rb +1 -1
  70. data/lib/solargraph/type_checker.rb +61 -42
  71. data/lib/solargraph/version.rb +1 -1
  72. data/lib/solargraph/views/_name_type_tag.erb +1 -1
  73. data/lib/solargraph/workspace.rb +1 -1
  74. data/lib/solargraph/yard_map/core_fills.rb +185 -0
  75. data/lib/solargraph/yard_map/helpers.rb +16 -0
  76. data/lib/solargraph/{pin/yard_pin/constant.rb → yard_map/mapper/to_constant.rb} +6 -6
  77. data/lib/solargraph/yard_map/mapper/to_method.rb +78 -0
  78. data/lib/solargraph/{pin/yard_pin/namespace.rb → yard_map/mapper/to_namespace.rb} +6 -6
  79. data/lib/solargraph/yard_map/mapper.rb +17 -8
  80. data/lib/solargraph/yard_map/rdoc_to_yard.rb +26 -15
  81. data/lib/solargraph/yard_map/stdlib_fills.rb +43 -0
  82. data/lib/solargraph/yard_map/to_method.rb +79 -0
  83. data/lib/solargraph/yard_map.rb +140 -92
  84. data/lib/solargraph.rb +5 -4
  85. data/solargraph.gemspec +5 -5
  86. data/yardoc/2.2.2.tar.gz +0 -0
  87. metadata +29 -41
  88. data/.rubocop.yml +0 -6
  89. data/lib/solargraph/core_fills.rb +0 -159
  90. data/lib/solargraph/pin/attribute.rb +0 -49
  91. data/lib/solargraph/pin/base_method.rb +0 -141
  92. data/lib/solargraph/pin/yard_pin/method.rb +0 -65
  93. data/lib/solargraph/pin/yard_pin/yard_mixin.rb +0 -26
  94. data/lib/solargraph/pin/yard_pin.rb +0 -12
  95. data/lib/solargraph/stdlib_fills.rb +0 -32
  96. data/travis-bundler.rb +0 -11
@@ -10,20 +10,7 @@ module Solargraph
10
10
  def process
11
11
  if node.children[0].nil?
12
12
  if [:private, :public, :protected].include?(node.children[1])
13
- if (node.children.length > 2)
14
- node.children[2..-1].each do |child|
15
- next unless child.is_a?(AST::Node) && (child.type == :sym || child.type == :str)
16
- name = child.children[0].to_s
17
- matches = pins.select{ |pin| pin.is_a?(Pin::BaseMethod) && pin.name == name && pin.namespace == region.closure.full_context.namespace && pin.context.scope == (region.scope || :instance)}
18
- matches.each do |pin|
19
- # @todo Smelly instance variable access
20
- pin.instance_variable_set(:@visibility, node.children[1])
21
- end
22
- end
23
- else
24
- # @todo Smelly instance variable access
25
- region.instance_variable_set(:@visibility, node.children[1])
26
- end
13
+ process_visibility
27
14
  elsif node.children[1] == :module_function
28
15
  process_module_function
29
16
  elsif [:attr_reader, :attr_writer, :attr_accessor].include?(node.children[1])
@@ -36,6 +23,8 @@ module Solargraph
36
23
  process_prepend
37
24
  elsif node.children[1] == :require
38
25
  process_require
26
+ elsif node.children[1] == :autoload
27
+ process_autoload
39
28
  elsif node.children[1] == :private_constant
40
29
  process_private_constant
41
30
  elsif node.children[1] == :alias_method && node.children[2] && node.children[2] && node.children[2].type == :sym && node.children[3] && node.children[3].type == :sym
@@ -52,6 +41,27 @@ module Solargraph
52
41
 
53
42
  private
54
43
 
44
+ # @return [void]
45
+ def process_visibility
46
+ if (node.children.length > 2)
47
+ node.children[2..-1].each do |child|
48
+ if child.is_a?(AST::Node) && (child.type == :sym || child.type == :str)
49
+ name = child.children[0].to_s
50
+ matches = pins.select{ |pin| pin.is_a?(Pin::Method) && pin.name == name && pin.namespace == region.closure.full_context.namespace && pin.context.scope == (region.scope || :instance)}
51
+ matches.each do |pin|
52
+ # @todo Smelly instance variable access
53
+ pin.instance_variable_set(:@visibility, node.children[1])
54
+ end
55
+ else
56
+ process_children region.update(visibility: node.children[1])
57
+ end
58
+ end
59
+ else
60
+ # @todo Smelly instance variable access
61
+ region.instance_variable_set(:@visibility, node.children[1])
62
+ end
63
+ end
64
+
55
65
  # @return [void]
56
66
  def process_attribute
57
67
  node.children[2..-1].each do |a|
@@ -59,26 +69,30 @@ module Solargraph
59
69
  clos = region.closure
60
70
  cmnt = comments_for(node)
61
71
  if node.children[1] == :attr_reader || node.children[1] == :attr_accessor
62
- pins.push Solargraph::Pin::Attribute.new(
72
+ pins.push Solargraph::Pin::Method.new(
63
73
  location: loc,
64
74
  closure: clos,
65
75
  name: a.children[0].to_s,
66
76
  comments: cmnt,
67
- access: :reader,
68
77
  scope: region.scope || :instance,
69
- visibility: region.visibility
78
+ visibility: region.visibility,
79
+ attribute: true
70
80
  )
71
81
  end
72
82
  if node.children[1] == :attr_writer || node.children[1] == :attr_accessor
73
- pins.push Solargraph::Pin::Attribute.new(
83
+ pins.push Solargraph::Pin::Method.new(
74
84
  location: loc,
75
85
  closure: clos,
76
86
  name: "#{a.children[0]}=",
77
87
  comments: cmnt,
78
- access: :writer,
79
88
  scope: region.scope || :instance,
80
- visibility: region.visibility
89
+ visibility: region.visibility,
90
+ attribute: true
81
91
  )
92
+ pins.last.parameters.push Pin::Parameter.new(name: 'value', decl: :arg, closure: pins.last)
93
+ if pins.last.return_type.defined?
94
+ pins.last.docstring.add_tag YARD::Tags::Tag.new(:param, '', pins.last.return_type.to_s.split(', '), 'value')
95
+ end
82
96
  end
83
97
  end
84
98
  end
@@ -88,7 +102,8 @@ module Solargraph
88
102
  if node.children[2].is_a?(AST::Node) && node.children[2].type == :const
89
103
  cp = region.closure
90
104
  node.children[2..-1].each do |i|
91
- pins.push Pin::Reference::Include.new(
105
+ type = region.scope == :class ? Pin::Reference::Extend : Pin::Reference::Include
106
+ pins.push type.new(
92
107
  location: get_node_location(i),
93
108
  closure: cp,
94
109
  name: unpack_name(i)
@@ -138,6 +153,14 @@ module Solargraph
138
153
  end
139
154
  end
140
155
 
156
+ # @return [void]
157
+ def process_autoload
158
+ if node.children[3].is_a?(AST::Node) && node.children[3].type == :str
159
+ path = node.children[3].children[0].to_s
160
+ pins.push Pin::Reference::Require.new(get_node_location(node), path)
161
+ end
162
+ end
163
+
141
164
  # @return [void]
142
165
  def process_module_function
143
166
  if node.children[2].nil?
@@ -146,13 +169,14 @@ module Solargraph
146
169
  elsif node.children[2].type == :sym || node.children[2].type == :str
147
170
  node.children[2..-1].each do |x|
148
171
  cn = x.children[0].to_s
149
- ref = pins.select{|p| [Solargraph::Pin::Method, Solargraph::Pin::Attribute].include?(p.class) && p.namespace == region.closure.full_context.namespace && p.name == cn}.first
172
+ ref = pins.select{ |p| p.is_a?(Pin::Method) && p.namespace == region.closure.full_context.namespace && p.name == cn }.first
150
173
  unless ref.nil?
151
174
  pins.delete ref
152
175
  mm = Solargraph::Pin::Method.new(
153
176
  location: ref.location,
154
177
  closure: ref.closure,
155
178
  name: ref.name,
179
+ parameters: ref.parameters,
156
180
  comments: ref.comments,
157
181
  scope: :class,
158
182
  visibility: :public,
@@ -162,6 +186,7 @@ module Solargraph
162
186
  location: ref.location,
163
187
  closure: ref.closure,
164
188
  name: ref.name,
189
+ parameters: ref.parameters,
165
190
  comments: ref.comments,
166
191
  scope: :instance,
167
192
  visibility: :private,
@@ -216,7 +241,7 @@ module Solargraph
216
241
  # @return [Boolean]
217
242
  def process_private_class_method
218
243
  if node.children[2].type == :sym || node.children[2].type == :str
219
- ref = pins.select{|p| [Solargraph::Pin::Method, Solargraph::Pin::Attribute].include?(p.class) && p.namespace == region.closure.full_context.namespace && p.name == node.children[2].children[0].to_s}.first
244
+ ref = pins.select { |p| p.is_a?(Pin::Method) && p.namespace == region.closure.full_context.namespace && p.name == node.children[2].children[0].to_s }.first
220
245
  # HACK: Smelly instance variable access
221
246
  ref.instance_variable_set(:@visibility, :private) unless ref.nil?
222
247
  false
@@ -27,6 +27,7 @@ module Solargraph
27
27
  @region = region
28
28
  @pins = pins
29
29
  @locals = locals
30
+ @processed_children = false
30
31
  end
31
32
 
32
33
  # Subclasses should override this method to generate new pins.
@@ -41,6 +42,8 @@ module Solargraph
41
42
  # @param subregion [Region]
42
43
  # @return [void]
43
44
  def process_children subregion = region
45
+ return if @processed_children
46
+ @processed_children = true
44
47
  node.children.each do |child|
45
48
  next unless Parser.is_ast_node?(child)
46
49
  NodeProcessor.process(child, subregion, pins, locals)
@@ -8,7 +8,7 @@ module Solargraph
8
8
  # @param filename [String]
9
9
  # @return [Array(Parser::AST::Node, Array<Parser::Source::Comment>)]
10
10
  def parse_with_comments code, filename = nil
11
- node = RubyVM::AbstractSyntaxTree.parse(code)
11
+ node = RubyVM::AbstractSyntaxTree.parse(code).children[2]
12
12
  comments = CommentRipper.new(code).parse
13
13
  [node, comments]
14
14
  rescue ::SyntaxError => e
@@ -20,7 +20,7 @@ module Solargraph
20
20
  # @param line [Integer]
21
21
  # @return [Parser::AST::Node]
22
22
  def parse code, filename = nil, line = 0
23
- RubyVM::AbstractSyntaxTree.parse(code)
23
+ RubyVM::AbstractSyntaxTree.parse(code).children[2]
24
24
  rescue ::SyntaxError => e
25
25
  raise Parser::SyntaxError, e.message
26
26
  end
@@ -83,6 +83,10 @@ module Solargraph
83
83
  NodeChainer.chain *args
84
84
  end
85
85
 
86
+ def chain_string *args
87
+ NodeChainer.load_string *args
88
+ end
89
+
86
90
  def process_node *args
87
91
  Solargraph::Parser::NodeProcessor.process *args
88
92
  end
@@ -15,7 +15,7 @@ module Solargraph
15
15
  def initialize node, filename = nil, in_block = false
16
16
  @node = node
17
17
  @filename = filename
18
- @in_block = in_block
18
+ @in_block = in_block ? 1 : 0
19
19
  end
20
20
 
21
21
  # @return [Source::Chain]
@@ -52,25 +52,27 @@ module Solargraph
52
52
  return generate_links(n.children[0]) if n.type == :SPLAT
53
53
  result = []
54
54
  if n.type == :ITER
55
- @in_block = true
55
+ @in_block += 1
56
56
  result.concat generate_links(n.children[0])
57
- @in_block = false
57
+ @in_block -= 1
58
58
  elsif n.type == :CALL || n.type == :OPCALL
59
59
  n.children[0..-3].each do |c|
60
60
  result.concat generate_links(c)
61
61
  end
62
- result.push Chain::Call.new(n.children[-2].to_s, node_to_argchains(n.children.last), @in_block || block_passed?(n))
62
+ result.push Chain::Call.new(n.children[-2].to_s, node_to_argchains(n.children.last), @in_block > 0 || block_passed?(n))
63
63
  elsif n.type == :ATTRASGN
64
64
  result.concat generate_links(n.children[0])
65
- result.push Chain::Call.new(n.children[1].to_s, node_to_argchains(n.children[2]), @in_block || block_passed?(n))
65
+ result.push Chain::Call.new(n.children[1].to_s, node_to_argchains(n.children[2]), @in_block > 0 || block_passed?(n))
66
66
  elsif n.type == :VCALL
67
- result.push Chain::Call.new(n.children[0].to_s, [], @in_block || block_passed?(n))
67
+ result.push Chain::Call.new(n.children[0].to_s, [], @in_block > 0 || block_passed?(n))
68
68
  elsif n.type == :FCALL
69
- result.push Chain::Call.new(n.children[0].to_s, node_to_argchains(n.children[1]), @in_block || block_passed?(n))
69
+ result.push Chain::Call.new(n.children[0].to_s, node_to_argchains(n.children[1]), @in_block > 0 || block_passed?(n))
70
70
  elsif n.type == :SELF
71
71
  result.push Chain::Head.new('self')
72
- elsif [:SUPER, :ZSUPER].include?(n.type)
73
- result.push Chain::Head.new('super')
72
+ elsif n.type == :ZSUPER
73
+ result.push Chain::ZSuper.new('super', @in_block > 0 || block_passed?(n))
74
+ elsif n.type == :SUPER
75
+ result.push Chain::Call.new('super', node_to_argchains(n.children.last), @in_block > 0 || block_passed?(n))
74
76
  elsif [:COLON2, :COLON3, :CONST].include?(n.type)
75
77
  const = unpack_name(n)
76
78
  result.push Chain::Constant.new(const)
@@ -76,6 +76,10 @@ module Solargraph
76
76
  if node.type == :ITER
77
77
  result.push node.children[0]
78
78
  node.children[1..-1].each { |child| result.concat call_nodes_from(child) }
79
+ elsif node.type == :MASGN
80
+ # @todo We're treating a mass assignment as a call node, but the
81
+ # type checker still needs the logic to handle it.
82
+ result.push node
79
83
  elsif [:CALL, :VCALL, :FCALL, :ATTRASGN, :OPCALL].include?(node.type)
80
84
  result.push node
81
85
  node.children.each { |child| result.concat call_nodes_from(child) }
@@ -91,6 +95,7 @@ module Solargraph
91
95
  index = 0
92
96
  until index > node.children[0].children.length - 2
93
97
  k = node.children[0].children[index]
98
+ return {} unless node?(k)
94
99
  v = node.children[0].children[index + 1]
95
100
  result[k.children[0]] = Solargraph::Parser.chain(v)
96
101
  index += 2
@@ -192,7 +197,7 @@ module Solargraph
192
197
  result.push node
193
198
  result.concat get_return_nodes_only(node.children[1])
194
199
  elsif node.type == :CASE
195
- node.children.each do |cc|
200
+ node.children[1..-1].each do |cc|
196
201
  result.concat reduce_to_value_nodes(cc.children[1..-1])
197
202
  end
198
203
  else
@@ -6,17 +6,31 @@ module Solargraph
6
6
  module NodeProcessors
7
7
  class ArgsNode < Parser::NodeProcessor::Base
8
8
  def process
9
- if region.closure.is_a?(Pin::BaseMethod) || region.closure.is_a?(Pin::Block)
10
- node.children[0].times do |i|
11
- locals.push Solargraph::Pin::Parameter.new(
12
- location: region.closure.location,
13
- closure: region.closure,
14
- comments: comments_for(node),
15
- name: region.lvars[i].to_s,
16
- presence: region.closure.location.range,
17
- decl: :arg
18
- )
19
- region.closure.parameters.push locals.last
9
+ if region.closure.is_a?(Pin::Method) || region.closure.is_a?(Pin::Block)
10
+ if region.lvars[0].nil?
11
+ node.children[0].times do |i|
12
+ locals.push Solargraph::Pin::Parameter.new(
13
+ location: region.closure.location,
14
+ closure: region.closure,
15
+ comments: comments_for(node),
16
+ name: extract_name(node.children[i + 1]),
17
+ presence: region.closure.location.range,
18
+ decl: :arg
19
+ )
20
+ region.closure.parameters.push locals.last
21
+ end
22
+ else
23
+ node.children[0].times do |i|
24
+ locals.push Solargraph::Pin::Parameter.new(
25
+ location: region.closure.location,
26
+ closure: region.closure,
27
+ comments: comments_for(node),
28
+ name: region.lvars[i].to_s,
29
+ presence: region.closure.location.range,
30
+ decl: :arg
31
+ )
32
+ region.closure.parameters.push locals.last
33
+ end
20
34
  end
21
35
  # @todo Optional args, keyword args, etc.
22
36
  if node.children[6]
@@ -55,6 +69,16 @@ module Solargraph
55
69
  end
56
70
  process_children
57
71
  end
72
+
73
+ private
74
+
75
+ def extract_name var
76
+ if Parser.is_ast_node?(var)
77
+ var.children[0].to_s
78
+ else
79
+ var.to_s
80
+ end
81
+ end
58
82
  end
59
83
  end
60
84
  end
@@ -19,7 +19,7 @@ module Solargraph
19
19
  if region.visibility == :module_function
20
20
  rng = Range.from_node(node)
21
21
  named_path = named_path_pin(rng.start)
22
- if named_path.is_a?(Pin::BaseMethod)
22
+ if named_path.is_a?(Pin::Method)
23
23
  pins.push Solargraph::Pin::InstanceVariable.new(
24
24
  location: loc,
25
25
  closure: Pin::Namespace.new(type: :module, closure: region.closure.closure, name: region.closure.name),
@@ -16,7 +16,12 @@ module Solargraph
16
16
  presence: region.closure.location.range,
17
17
  decl: require_keyword?(node) ? :kwarg : :kwoptarg
18
18
  )
19
- region.closure.parameters.push locals.last
19
+ idx = region.closure.parameters.find_index { |par| [:kwrestarg, :blockarg].include?(par.decl) }
20
+ if idx
21
+ region.closure.parameters.insert idx, locals.last
22
+ else
23
+ region.closure.parameters.push locals.last
24
+ end
20
25
  node.children[1] && NodeProcessor.process(node.children[1], region, pins, locals)
21
26
  end
22
27
 
@@ -16,7 +16,12 @@ module Solargraph
16
16
  presence: region.closure.location.range,
17
17
  decl: :optarg
18
18
  )
19
- region.closure.parameters.push locals.last
19
+ idx = region.closure.parameters.find_index { |par| par.decl != :arg }
20
+ if idx
21
+ region.closure.parameters.insert idx, locals.last
22
+ else
23
+ region.closure.parameters.push locals.last
24
+ end
20
25
  node.children[1] && NodeProcessor.process(node.children[1], region, pins, locals)
21
26
  end
22
27
  end
@@ -9,30 +9,17 @@ module Solargraph
9
9
 
10
10
  def process
11
11
  if [:private, :public, :protected].include?(node.children[0])
12
- if (node.type == :FCALL && node.children.last.children.length > 1)
13
- node.children.last.children[0..-2].each do |child|
14
- # next unless child.is_a?(AST::Node) && (child.type == :sym || child.type == :str)
15
- next unless child.type == :LIT || child.type == :STR
16
- name = child.children[0].to_s
17
- matches = pins.select{ |pin| pin.is_a?(Pin::BaseMethod) && pin.name == name && pin.namespace == region.closure.full_context.namespace && pin.context.scope == (region.scope || :instance)}
18
- matches.each do |pin|
19
- # @todo Smelly instance variable access
20
- pin.instance_variable_set(:@visibility, node.children[0])
21
- end
22
- end
23
- else
24
- # @todo Smelly instance variable access
25
- region.instance_variable_set(:@visibility, node.children[0])
26
- end
12
+ process_visibility
27
13
  elsif node.children[0] == :module_function
28
14
  process_module_function
29
15
  elsif node.children[0] == :require
30
16
  process_require
17
+ elsif node.children[0] == :autoload
18
+ process_autoload
31
19
  elsif node.children[0] == :alias_method
32
20
  process_alias_method
33
- elsif node.children[0] == :private_class_method && Parser.is_ast_node?(node)
34
- # Processing a private class can potentially handle children on its own
35
- return if process_private_class_method
21
+ elsif node.children[0] == :private_class_method
22
+ process_private_class_method
36
23
  elsif [:attr_reader, :attr_writer, :attr_accessor].include?(node.children[0])
37
24
  process_attribute
38
25
  elsif node.children[0] == :include
@@ -43,52 +30,36 @@ module Solargraph
43
30
  process_prepend
44
31
  elsif node.children[0] == :private_constant
45
32
  process_private_constant
33
+ elsif node.children[1] == :require && unpack_name(node.children[0]) == 'Bundler'
34
+ pins.push Pin::Reference::Require.new(Solargraph::Location.new(region.filename, Solargraph::Range.from_to(0, 0, 0, 0)), 'bundler/require')
46
35
  end
47
36
  process_children
48
- return
49
- # @todo Get rid of legacy
50
- if node.children[0].nil?
51
- if [:private, :public, :protected].include?(node.children[1])
52
- if (node.children.length > 2)
53
- node.children[2..-1].each do |child|
54
- next unless child.is_a?(AST::Node) && (child.type == :sym || child.type == :str)
55
- name = child.children[0].to_s
56
- matches = pins.select{ |pin| pin.is_a?(Pin::BaseMethod) && pin.name == name && pin.namespace == region.closure.full_context.namespace && pin.context.scope == (region.scope || :instance)}
57
- matches.each do |pin|
58
- # @todo Smelly instance variable access
59
- pin.instance_variable_set(:@visibility, node.children[1])
60
- end
37
+ end
38
+
39
+ private
40
+
41
+ # @return [void]
42
+ def process_visibility
43
+ if node.type == :FCALL && Parser.is_ast_node?(node.children.last)
44
+ node.children.last.children[0..-2].each do |child|
45
+ # next unless child.is_a?(AST::Node) && (child.type == :sym || child.type == :str)
46
+ if child.type == :LIT || child.type == :STR
47
+ name = child.children[0].to_s
48
+ matches = pins.select{ |pin| pin.is_a?(Pin::Method) && pin.name == name && pin.namespace == region.closure.full_context.namespace && pin.context.scope == (region.scope || :instance)}
49
+ matches.each do |pin|
50
+ # @todo Smelly instance variable access
51
+ pin.instance_variable_set(:@visibility, node.children[0])
61
52
  end
62
53
  else
63
- # @todo Smelly instance variable access
64
- region.instance_variable_set(:@visibility, node.children[1])
54
+ process_children region.update(visibility: node.children[0])
65
55
  end
66
- elsif node.children[1] == :module_function
67
- process_module_function
68
- elsif [:attr_reader, :attr_writer, :attr_accessor].include?(node.children[1])
69
- process_attribute
70
- elsif node.children[1] == :include
71
- process_include
72
- elsif node.children[1] == :extend
73
- process_extend
74
- elsif node.children[1] == :require
75
- process_require
76
- elsif node.children[1] == :private_constant
77
- process_private_constant
78
- elsif node.children[1] == :alias_method && node.children[2] && node.children[2] && node.children[2].type == :sym && node.children[3] && node.children[3].type == :sym
79
- process_alias_method
80
- elsif node.children[1] == :private_class_method && node.children[2].is_a?(AST::Node)
81
- # Processing a private class can potentially handle children on its own
82
- return if process_private_class_method
83
56
  end
84
- elsif node.children[1] == :require && node.children[0].to_s == '(const nil :Bundler)'
85
- pins.push Pin::Reference::Require.new(Solargraph::Location.new(region.filename, Solargraph::Range.from_to(0, 0, 0, 0)), 'bundler/require')
57
+ else
58
+ # @todo Smelly instance variable access
59
+ region.instance_variable_set(:@visibility, node.children[0])
86
60
  end
87
- process_children
88
61
  end
89
62
 
90
- private
91
-
92
63
  # @return [void]
93
64
  def process_attribute
94
65
  return unless Parser.is_ast_node?(node.children[1])
@@ -98,26 +69,30 @@ module Solargraph
98
69
  clos = region.closure
99
70
  cmnt = comments_for(node)
100
71
  if node.children[0] == :attr_reader || node.children[0] == :attr_accessor
101
- pins.push Solargraph::Pin::Attribute.new(
72
+ pins.push Solargraph::Pin::Method.new(
102
73
  location: loc,
103
74
  closure: clos,
104
75
  name: a.children[0].to_s,
105
76
  comments: cmnt,
106
- access: :reader,
107
77
  scope: region.scope || :instance,
108
- visibility: region.visibility
78
+ visibility: region.visibility,
79
+ attribute: true
109
80
  )
110
81
  end
111
82
  if node.children[0] == :attr_writer || node.children[0] == :attr_accessor
112
- pins.push Solargraph::Pin::Attribute.new(
83
+ pins.push Solargraph::Pin::Method.new(
113
84
  location: loc,
114
85
  closure: clos,
115
86
  name: "#{a.children[0]}=",
116
87
  comments: cmnt,
117
- access: :writer,
118
88
  scope: region.scope || :instance,
119
- visibility: region.visibility
89
+ visibility: region.visibility,
90
+ attribute: true
120
91
  )
92
+ pins.last.parameters.push Pin::Parameter.new(name: 'value', decl: :arg, closure: pins.last)
93
+ if pins.last.return_type.defined?
94
+ pins.last.docstring.add_tag YARD::Tags::Tag.new(:param, '', pins.last.return_type.to_s.split(', '), 'value')
95
+ end
121
96
  end
122
97
  end
123
98
  end
@@ -127,7 +102,8 @@ module Solargraph
127
102
  return unless Parser.is_ast_node?(node.children.last)
128
103
  node.children.last.children[0..-2].each do |i|
129
104
  next unless [:COLON2, :COLON3, :CONST].include?(i.type)
130
- pins.push Pin::Reference::Include.new(
105
+ type = region.scope == :class ? Pin::Reference::Extend : Pin::Reference::Include
106
+ pins.push type.new(
131
107
  location: get_node_location(i),
132
108
  closure: region.closure,
133
109
  name: unpack_name(i)
@@ -181,6 +157,15 @@ module Solargraph
181
157
  end
182
158
  end
183
159
 
160
+ # @return [void]
161
+ def process_autoload
162
+ return unless Parser.is_ast_node?(node.children[1]) && Parser.is_ast_node?(node.children[1].children[1])
163
+ arg = node.children[1].children[1]
164
+ if arg.type == :STR
165
+ pins.push Pin::Reference::Require.new(get_node_location(arg), arg.children[0])
166
+ end
167
+ end
168
+
184
169
  # @return [void]
185
170
  def process_module_function
186
171
  if node.type == :VCALL
@@ -192,7 +177,7 @@ module Solargraph
192
177
  node.children.last.children[0..-2].each do |x|
193
178
  next unless [:LIT, :STR].include?(x.type)
194
179
  cn = x.children[0].to_s
195
- ref = pins.select{|p| [Solargraph::Pin::Method, Solargraph::Pin::Attribute].include?(p.class) && p.namespace == region.closure.full_context.namespace && p.name == cn}.first
180
+ ref = pins.select { |p| p.is_a?(Pin::Method) && p.namespace == region.closure.full_context.namespace && p.name == cn }.first
196
181
  unless ref.nil?
197
182
  pins.delete ref
198
183
  mm = Solargraph::Pin::Method.new(
@@ -241,6 +226,7 @@ module Solargraph
241
226
 
242
227
  # @return [void]
243
228
  def process_private_constant
229
+ # @todo Bare `private_constant` causes an error
244
230
  node.children.last.children[0..-2].each do |child|
245
231
  if [:LIT, :STR].include?(child.type)
246
232
  cn = child.children[0].to_s
@@ -268,19 +254,18 @@ module Solargraph
268
254
  )
269
255
  end
270
256
 
271
- # @return [Boolean]
257
+ # @return [void]
272
258
  def process_private_class_method
259
+ return false unless Parser.is_ast_node?(node.children.last)
273
260
  if node.children.last.children.first.type == :DEFN
274
261
  process_children region.update(scope: :class, visibility: :private)
275
- true
276
262
  else
277
263
  node.children.last.children[0..-2].each do |child|
278
264
  if child.type == :LIT && child.children.first.is_a?(::Symbol)
279
265
  sym_name = child.children.first.to_s
280
- ref = pins.select{|p| [Solargraph::Pin::Method, Solargraph::Pin::Attribute].include?(p.class) && p.namespace == region.closure.full_context.namespace && p.name == sym_name}.first
266
+ ref = pins.select { |p| p.is_a?(Pin::Method) && p.namespace == region.closure.full_context.namespace && p.name == sym_name }.first
281
267
  # HACK: Smelly instance variable access
282
268
  ref.instance_variable_set(:@visibility, :private) unless ref.nil?
283
- false
284
269
  end
285
270
  end
286
271
  end
@@ -36,6 +36,7 @@ module Solargraph
36
36
  register :RESBODY, Rubyvm::NodeProcessors::ResbodyNode
37
37
  register :DEFN, Rubyvm::NodeProcessors::DefNode
38
38
  register :DEFS, Rubyvm::NodeProcessors::DefsNode
39
+ register :CALL, Rubyvm::NodeProcessors::SendNode
39
40
  register :FCALL, Rubyvm::NodeProcessors::SendNode
40
41
  register :VCALL, Rubyvm::NodeProcessors::SendNode
41
42
  register :CLASS, Rubyvm::NodeProcessors::NamespaceNode
@@ -53,6 +54,7 @@ module Solargraph
53
54
  register :KW_ARG, Rubyvm::NodeProcessors::KwArgNode
54
55
  register :ITER, Rubyvm::NodeProcessors::BlockNode
55
56
  register :LAMBDA, Rubyvm::NodeProcessors::BlockNode
57
+ register :FOR, Rubyvm::NodeProcessors::BlockNode
56
58
  register :OP_ASGN_OR, Rubyvm::NodeProcessors::OrasgnNode
57
59
  register :LIT, Rubyvm::NodeProcessors::LitNode
58
60
  end
@@ -23,7 +23,7 @@ module Solargraph
23
23
 
24
24
  # @param location [Solargraph::Location]
25
25
  # @param kind [Integer]
26
- # @param closure [String]
26
+ # @param closure [Solargraph::Pin::Closure]
27
27
  # @param name [String]
28
28
  # @param comments [String]
29
29
  def initialize location: nil, closure: nil, name: '', comments: ''
@@ -38,7 +38,7 @@ module Solargraph
38
38
  @comments ||= ''
39
39
  end
40
40
 
41
- # @return [String]
41
+ # @return [String, nil]
42
42
  def filename
43
43
  return nil if location.nil?
44
44
  location.filename
@@ -11,7 +11,7 @@ module Solargraph
11
11
 
12
12
  # @param assignment [Parser::AST::Node, nil]
13
13
  def initialize assignment: nil, **splat
14
- super(splat)
14
+ super(**splat)
15
15
  @assignment = assignment
16
16
  end
17
17