solargraph 0.56.2 → 0.57.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 (122) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/linting.yml +125 -0
  3. data/.github/workflows/plugins.yml +148 -6
  4. data/.github/workflows/rspec.yml +39 -4
  5. data/.github/workflows/typecheck.yml +5 -2
  6. data/.gitignore +5 -0
  7. data/.overcommit.yml +72 -0
  8. data/.rspec +1 -0
  9. data/.rubocop.yml +66 -0
  10. data/.rubocop_todo.yml +2627 -0
  11. data/.yardopts +1 -0
  12. data/CHANGELOG.md +42 -0
  13. data/README.md +8 -4
  14. data/Rakefile +125 -13
  15. data/lib/solargraph/api_map/cache.rb +3 -2
  16. data/lib/solargraph/api_map/constants.rb +218 -0
  17. data/lib/solargraph/api_map/index.rb +20 -26
  18. data/lib/solargraph/api_map/source_to_yard.rb +10 -4
  19. data/lib/solargraph/api_map/store.rb +126 -18
  20. data/lib/solargraph/api_map.rb +212 -234
  21. data/lib/solargraph/bench.rb +1 -0
  22. data/lib/solargraph/complex_type/type_methods.rb +1 -0
  23. data/lib/solargraph/complex_type/unique_type.rb +7 -7
  24. data/lib/solargraph/complex_type.rb +5 -1
  25. data/lib/solargraph/convention/active_support_concern.rb +111 -0
  26. data/lib/solargraph/convention/base.rb +17 -0
  27. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +1 -0
  28. data/lib/solargraph/convention/data_definition/data_definition_node.rb +3 -1
  29. data/lib/solargraph/convention/data_definition.rb +2 -1
  30. data/lib/solargraph/convention/gemspec.rb +1 -1
  31. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +1 -0
  32. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +3 -1
  33. data/lib/solargraph/convention/struct_definition.rb +36 -13
  34. data/lib/solargraph/convention.rb +31 -2
  35. data/lib/solargraph/diagnostics/rubocop.rb +6 -1
  36. data/lib/solargraph/diagnostics/rubocop_helpers.rb +1 -1
  37. data/lib/solargraph/doc_map.rb +40 -12
  38. data/lib/solargraph/environ.rb +9 -2
  39. data/lib/solargraph/gem_pins.rb +17 -11
  40. data/lib/solargraph/language_server/host/dispatch.rb +2 -0
  41. data/lib/solargraph/language_server/host/message_worker.rb +3 -0
  42. data/lib/solargraph/language_server/host.rb +2 -1
  43. data/lib/solargraph/language_server/message/base.rb +2 -1
  44. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +1 -1
  45. data/lib/solargraph/language_server/message/text_document/definition.rb +2 -0
  46. data/lib/solargraph/language_server/message/text_document/formatting.rb +16 -2
  47. data/lib/solargraph/language_server/message/text_document/type_definition.rb +1 -0
  48. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +2 -0
  49. data/lib/solargraph/language_server/progress.rb +8 -0
  50. data/lib/solargraph/language_server/request.rb +1 -0
  51. data/lib/solargraph/library.rb +8 -15
  52. data/lib/solargraph/location.rb +2 -0
  53. data/lib/solargraph/logging.rb +11 -2
  54. data/lib/solargraph/page.rb +4 -0
  55. data/lib/solargraph/parser/comment_ripper.rb +8 -1
  56. data/lib/solargraph/parser/flow_sensitive_typing.rb +32 -4
  57. data/lib/solargraph/parser/node_methods.rb +2 -2
  58. data/lib/solargraph/parser/node_processor/base.rb +1 -1
  59. data/lib/solargraph/parser/node_processor.rb +6 -2
  60. data/lib/solargraph/parser/parser_gem/class_methods.rb +1 -1
  61. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +1 -0
  62. data/lib/solargraph/parser/parser_gem/node_chainer.rb +3 -1
  63. data/lib/solargraph/parser/parser_gem/node_methods.rb +4 -2
  64. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +3 -2
  65. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +2 -0
  66. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -0
  67. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +35 -14
  68. data/lib/solargraph/parser/region.rb +3 -0
  69. data/lib/solargraph/parser/snippet.rb +2 -0
  70. data/lib/solargraph/pin/base.rb +50 -8
  71. data/lib/solargraph/pin/base_variable.rb +1 -2
  72. data/lib/solargraph/pin/callable.rb +9 -0
  73. data/lib/solargraph/pin/closure.rb +2 -0
  74. data/lib/solargraph/pin/common.rb +6 -2
  75. data/lib/solargraph/pin/constant.rb +2 -0
  76. data/lib/solargraph/pin/delegated_method.rb +1 -0
  77. data/lib/solargraph/pin/local_variable.rb +4 -1
  78. data/lib/solargraph/pin/method.rb +8 -5
  79. data/lib/solargraph/pin/method_alias.rb +3 -0
  80. data/lib/solargraph/pin/parameter.rb +18 -8
  81. data/lib/solargraph/pin/proxy_type.rb +1 -0
  82. data/lib/solargraph/pin/reference/override.rb +15 -1
  83. data/lib/solargraph/pin/reference/superclass.rb +5 -0
  84. data/lib/solargraph/pin/reference.rb +26 -0
  85. data/lib/solargraph/pin/search.rb +3 -1
  86. data/lib/solargraph/pin/signature.rb +2 -0
  87. data/lib/solargraph/pin/symbol.rb +5 -0
  88. data/lib/solargraph/pin_cache.rb +64 -4
  89. data/lib/solargraph/position.rb +2 -0
  90. data/lib/solargraph/range.rb +1 -0
  91. data/lib/solargraph/rbs_map/conversions.rb +7 -5
  92. data/lib/solargraph/rbs_map/core_map.rb +3 -0
  93. data/lib/solargraph/rbs_map.rb +15 -2
  94. data/lib/solargraph/shell.rb +3 -0
  95. data/lib/solargraph/source/chain/link.rb +10 -1
  96. data/lib/solargraph/source/chain.rb +9 -2
  97. data/lib/solargraph/source/change.rb +2 -2
  98. data/lib/solargraph/source/cursor.rb +2 -3
  99. data/lib/solargraph/source/source_chainer.rb +1 -1
  100. data/lib/solargraph/source.rb +5 -2
  101. data/lib/solargraph/source_map/clip.rb +1 -1
  102. data/lib/solargraph/source_map/data.rb +4 -0
  103. data/lib/solargraph/source_map/mapper.rb +4 -2
  104. data/lib/solargraph/source_map.rb +21 -14
  105. data/lib/solargraph/type_checker/param_def.rb +2 -0
  106. data/lib/solargraph/type_checker/rules.rb +8 -0
  107. data/lib/solargraph/type_checker.rb +173 -120
  108. data/lib/solargraph/version.rb +1 -1
  109. data/lib/solargraph/workspace/config.rb +0 -2
  110. data/lib/solargraph/workspace/require_paths.rb +98 -0
  111. data/lib/solargraph/workspace.rb +16 -48
  112. data/lib/solargraph/yard_map/mapper/to_method.rb +2 -2
  113. data/lib/solargraph/yardoc.rb +16 -3
  114. data/lib/solargraph.rb +2 -0
  115. data/rbs/fills/tuple.rbs +2 -3
  116. data/sig/shims/parser/3.2.0.1/builders/default.rbs +195 -0
  117. data/sig/shims/thor/1.2.0.1/.rbs_meta.yaml +9 -0
  118. data/sig/shims/thor/1.2.0.1/manifest.yaml +7 -0
  119. data/sig/shims/thor/1.2.0.1/thor.rbs +17 -0
  120. data/solargraph.gemspec +14 -4
  121. metadata +123 -9
  122. data/lib/.rubocop.yml +0 -22
@@ -4,14 +4,20 @@ module Solargraph
4
4
  include Solargraph::Parser::NodeMethods
5
5
 
6
6
  # @param locals [Array<Solargraph::Pin::LocalVariable, Solargraph::Pin::Parameter>]
7
+ # @param enclosing_breakable_pin [Solargraph::Pin::Breakable, nil]
7
8
  def initialize(locals, enclosing_breakable_pin = nil)
8
9
  @locals = locals
9
10
  @enclosing_breakable_pin = enclosing_breakable_pin
10
11
  end
11
12
 
12
13
  # @param and_node [Parser::AST::Node]
14
+ # @param true_ranges [Array<Range>]
15
+ #
16
+ # @return [void]
13
17
  def process_and(and_node, true_ranges = [])
18
+ # @type [Parser::AST::Node]
14
19
  lhs = and_node.children[0]
20
+ # @type [Parser::AST::Node]
15
21
  rhs = and_node.children[1]
16
22
 
17
23
  before_rhs_loc = rhs.location.expression.adjust(begin_pos: -1)
@@ -23,6 +29,8 @@ module Solargraph
23
29
  end
24
30
 
25
31
  # @param if_node [Parser::AST::Node]
32
+ #
33
+ # @return [void]
26
34
  def process_if(if_node)
27
35
  #
28
36
  # See if we can refine a type based on the result of 'if foo.nil?'
@@ -36,7 +44,9 @@ module Solargraph
36
44
  # s(:send, nil, :bar))
37
45
  # [4] pry(main)>
38
46
  conditional_node = if_node.children[0]
47
+ # @type [Parser::AST::Node]
39
48
  then_clause = if_node.children[1]
49
+ # @type [Parser::AST::Node]
40
50
  else_clause = if_node.children[2]
41
51
 
42
52
  true_ranges = []
@@ -72,8 +82,11 @@ module Solargraph
72
82
  # them based on the Closure and Location.
73
83
  #
74
84
  # @param pins [Array<Pin::LocalVariable>]
85
+ # @param name [String]
75
86
  # @param closure [Pin::Closure]
76
87
  # @param location [Location]
88
+ #
89
+ # @return [Array<Pin::LocalVariable>]
77
90
  def self.visible_pins(pins, name, closure, location)
78
91
  logger.debug { "FlowSensitiveTyping#visible_pins(name=#{name}, closure=#{closure}, location=#{location})" }
79
92
  pins_with_name = pins.select { |p| p.name == name }
@@ -107,7 +120,10 @@ module Solargraph
107
120
  private
108
121
 
109
122
  # @param pin [Pin::LocalVariable]
110
- # @param if_node [Parser::AST::Node]
123
+ # @param downcast_type_name [String]
124
+ # @param presence [Range]
125
+ #
126
+ # @return [void]
111
127
  def add_downcast_local(pin, downcast_type_name, presence)
112
128
  # @todo Create pin#update method
113
129
  new_pin = Solargraph::Pin::LocalVariable.new(
@@ -126,6 +142,7 @@ module Solargraph
126
142
 
127
143
  # @param facts_by_pin [Hash{Pin::LocalVariable => Array<Hash{Symbol => String}>}]
128
144
  # @param presences [Array<Range>]
145
+ #
129
146
  # @return [void]
130
147
  def process_facts(facts_by_pin, presences)
131
148
  #
@@ -142,6 +159,9 @@ module Solargraph
142
159
  end
143
160
 
144
161
  # @param conditional_node [Parser::AST::Node]
162
+ # @param true_ranges [Array<Range>]
163
+ #
164
+ # @return [void]
145
165
  def process_conditional(conditional_node, true_ranges)
146
166
  if conditional_node.type == :send
147
167
  process_isa(conditional_node, true_ranges)
@@ -176,12 +196,20 @@ module Solargraph
176
196
  [isa_type_name, variable_name]
177
197
  end
178
198
 
199
+ # @param variable_name [String]
200
+ # @param position [Position]
201
+ #
202
+ # @return [Solargraph::Pin::LocalVariable, nil]
179
203
  def find_local(variable_name, position)
180
204
  pins = locals.select { |pin| pin.name == variable_name && pin.presence.include?(position) }
181
205
  return unless pins.length == 1
182
206
  pins.first
183
207
  end
184
208
 
209
+ # @param isa_node [Parser::AST::Node]
210
+ # @param true_presences [Array<Range>]
211
+ #
212
+ # @return [void]
185
213
  def process_isa(isa_node, true_presences)
186
214
  isa_type_name, variable_name = parse_isa(isa_node)
187
215
  return if variable_name.nil? || variable_name.empty?
@@ -197,10 +225,12 @@ module Solargraph
197
225
  end
198
226
 
199
227
  # @param node [Parser::AST::Node]
228
+ #
229
+ # @return [String, nil]
200
230
  def type_name(node)
201
231
  # e.g.,
202
232
  # s(:const, nil, :Baz)
203
- return unless node.type == :const
233
+ return unless node&.type == :const
204
234
  module_node = node.children[0]
205
235
  class_node = node.children[1]
206
236
 
@@ -212,8 +242,6 @@ module Solargraph
212
242
  "#{module_type_name}::#{class_node}"
213
243
  end
214
244
 
215
- # @todo "return type could not be inferred" should not trigger here
216
- # @sg-ignore
217
245
  # @param clause_node [Parser::AST::Node]
218
246
  def always_breaks?(clause_node)
219
247
  clause_node&.type == :break
@@ -1,6 +1,6 @@
1
1
  module Solargraph
2
2
  module Parser
3
- class NodeMethods
3
+ module NodeMethods
4
4
  module_function
5
5
 
6
6
  # @abstract
@@ -74,7 +74,7 @@ module Solargraph
74
74
 
75
75
  # @abstract
76
76
  # @param node [Parser::AST::Node]
77
- # @return [Hash{Parser::AST::Node => Source::Chain}]
77
+ # @return [Hash{Symbol => Source::Chain}]
78
78
  def convert_hash node
79
79
  raise NotImplementedError
80
80
  end
@@ -13,7 +13,7 @@ module Solargraph
13
13
  # @return [Array<Pin::Base>]
14
14
  attr_reader :pins
15
15
 
16
- # @return [Array<Pin::BaseVariable>]
16
+ # @return [Array<Pin::LocalVariable>]
17
17
  attr_reader :locals
18
18
 
19
19
  # @param node [Parser::AST::Node]
@@ -9,7 +9,7 @@ module Solargraph
9
9
  autoload :Base, 'solargraph/parser/node_processor/base'
10
10
 
11
11
  class << self
12
- # @type [Hash<Symbol, Array<Class<NodeProcessor::Base>>>]
12
+ # @type [Hash{Symbol => Array<Class<NodeProcessor::Base>>}]
13
13
  @@processors ||= {}
14
14
 
15
15
  # Register a processor for a node type. You can register multiple processors for the same type.
@@ -17,12 +17,16 @@ module Solargraph
17
17
  #
18
18
  # @param type [Symbol]
19
19
  # @param cls [Class<NodeProcessor::Base>]
20
- # @return [Class<NodeProcessor::Base>]
20
+ # @return [Array<Class<NodeProcessor::Base>>]
21
21
  def register type, cls
22
22
  @@processors[type] ||= []
23
23
  @@processors[type] << cls
24
24
  end
25
25
 
26
+ # @param type [Symbol]
27
+ # @param cls [Class<NodeProcessor::Base>]
28
+ #
29
+ # @return [void]
26
30
  def deregister type, cls
27
31
  @@processors[type].delete(cls)
28
32
  end
@@ -17,7 +17,7 @@ module Solargraph
17
17
  module ClassMethods
18
18
  # @param code [String]
19
19
  # @param filename [String, nil]
20
- # @return [Array(Parser::AST::Node, Hash{Integer => String})]
20
+ # @return [Array(Parser::AST::Node, Hash{Integer => Solargraph::Parser::Snippet})]
21
21
  def parse_with_comments code, filename = nil
22
22
  node = parse(code, filename)
23
23
  comments = CommentRipper.new(code, filename, 0).parse
@@ -9,6 +9,7 @@ module Solargraph
9
9
  class FlawedBuilder < ::Parser::Builders::Default
10
10
  # @param token [::Parser::AST::Node]
11
11
  # @return [String]
12
+ # @sg-ignore
12
13
  def string_value(token)
13
14
  value(token)
14
15
  end
@@ -7,6 +7,7 @@ module Solargraph
7
7
  #
8
8
  class NodeChainer
9
9
  include NodeMethods
10
+
10
11
  Chain = Source::Chain
11
12
 
12
13
  # @param node [Parser::AST::Node]
@@ -98,7 +99,8 @@ module Solargraph
98
99
  elsif [:gvar, :gvasgn].include?(n.type)
99
100
  result.push Chain::GlobalVariable.new(n.children[0].to_s)
100
101
  elsif n.type == :or_asgn
101
- result.concat generate_links n.children[1]
102
+ new_node = n.updated(n.children[0].type, n.children[0].children + [n.children[1]])
103
+ result.concat generate_links new_node
102
104
  elsif [:class, :module, :def, :defs].include?(n.type)
103
105
  # @todo Undefined or what?
104
106
  result.push Chain::UNDEFINED_CALL
@@ -120,7 +120,7 @@ module Solargraph
120
120
  end
121
121
 
122
122
  # @param node [Parser::AST::Node]
123
- # @return [Hash{Parser::AST::Node => Chain}]
123
+ # @return [Hash{Symbol => Chain}]
124
124
  def convert_hash node
125
125
  return {} unless Parser.is_ast_node?(node)
126
126
  return convert_hash(node.children[0]) if node.type == :kwsplat
@@ -179,6 +179,7 @@ module Solargraph
179
179
  node.children[1..-1].each { |child| result.concat call_nodes_from(child) }
180
180
  elsif node.type == :send
181
181
  result.push node
182
+ result.concat call_nodes_from(node.children.first)
182
183
  node.children[2..-1].each { |child| result.concat call_nodes_from(child) }
183
184
  elsif [:super, :zsuper].include?(node.type)
184
185
  result.push node
@@ -232,6 +233,7 @@ module Solargraph
232
233
  else
233
234
  source.tree_at(position.line, position.column - 1)
234
235
  end
236
+ # @type [AST::Node, nil]
235
237
  prev = nil
236
238
  tree.each do |node|
237
239
  if node.type == :send
@@ -242,7 +244,7 @@ module Solargraph
242
244
  if source.synchronized?
243
245
  return node if source.code[0..offset-1] =~ /\(\s*\z/ && source.code[offset..-1] =~ /^\s*\)/
244
246
  else
245
- return node if source.code[0..offset-1] =~ /\([^\(]*\z/
247
+ return node if source.code[0..offset-1] =~ /\([^(]*\z/
246
248
  end
247
249
  end
248
250
  end
@@ -19,7 +19,7 @@ module Solargraph
19
19
  else
20
20
  region.closure
21
21
  end
22
- pins.push Solargraph::Pin::Block.new(
22
+ block_pin = Solargraph::Pin::Block.new(
23
23
  location: location,
24
24
  closure: parent,
25
25
  node: node,
@@ -28,7 +28,8 @@ module Solargraph
28
28
  scope: region.scope || region.closure.context.scope,
29
29
  source: :parser
30
30
  )
31
- process_children region.update(closure: pins.last)
31
+ pins.push block_pin
32
+ process_children region.update(closure: block_pin)
32
33
  end
33
34
 
34
35
  private
@@ -11,6 +11,8 @@ module Solargraph
11
11
  process_children
12
12
 
13
13
  position = get_node_start_position(node)
14
+ # @sg-ignore
15
+ # @type [Solargraph::Pin::Breakable, nil]
14
16
  enclosing_breakable_pin = pins.select{|pin| pin.is_a?(Pin::Breakable) && pin.location.range.contain?(position)}.last
15
17
  FlowSensitiveTyping.new(locals, enclosing_breakable_pin).process_if(node)
16
18
  end
@@ -22,8 +22,11 @@ module Solargraph
22
22
  # s(:int, 2),
23
23
  # s(:int, 3)))
24
24
  masgn = node
25
+ # @type [Parser::AST::Node]
25
26
  mlhs = masgn.children.fetch(0)
27
+ # @type [Array<Parser::AST::Node>]
26
28
  lhs_arr = mlhs.children
29
+ # @type [Parser::AST::Node]
27
30
  mass_rhs = node.children.fetch(1)
28
31
 
29
32
  # Get pins created for the mlhs node
@@ -8,32 +8,44 @@ module Solargraph
8
8
  include ParserGem::NodeMethods
9
9
 
10
10
  def process
11
+ # @sg-ignore Variable type could not be inferred for method_name
12
+ # @type [Symbol]
13
+ method_name = node.children[1]
14
+ # :nocov:
15
+ unless method_name.instance_of?(Symbol)
16
+ Solargraph.assert_or_log(:parser_method_name, "Expected method name to be a Symbol, got #{method_name.class} for node #{node.inspect}")
17
+ return process_children
18
+ end
19
+ # :nocov:
11
20
  if node.children[0].nil?
12
- if [:private, :public, :protected].include?(node.children[1])
21
+ if [:private, :public, :protected].include?(method_name)
13
22
  process_visibility
14
- elsif node.children[1] == :module_function
23
+ elsif method_name == :module_function
15
24
  process_module_function
16
- elsif [:attr_reader, :attr_writer, :attr_accessor].include?(node.children[1])
25
+ elsif [:attr_reader, :attr_writer, :attr_accessor].include?(method_name)
17
26
  process_attribute
18
- elsif node.children[1] == :include
27
+ elsif method_name == :include
19
28
  process_include
20
- elsif node.children[1] == :extend
29
+ elsif method_name == :extend
21
30
  process_extend
22
- elsif node.children[1] == :prepend
31
+ elsif method_name == :prepend
23
32
  process_prepend
24
- elsif node.children[1] == :require
33
+ elsif method_name == :require
25
34
  process_require
26
- elsif node.children[1] == :autoload
35
+ elsif method_name == :autoload
27
36
  process_autoload
28
- elsif node.children[1] == :private_constant
37
+ elsif method_name == :private_constant
29
38
  process_private_constant
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
39
+ # @sg-ignore
40
+ elsif method_name == :alias_method && node.children[2] && node.children[2] && node.children[2].type == :sym && node.children[3] && node.children[3].type == :sym
31
41
  process_alias_method
32
- elsif node.children[1] == :private_class_method && node.children[2].is_a?(AST::Node)
42
+ # @sg-ignore
43
+ elsif method_name == :private_class_method && node.children[2].is_a?(AST::Node)
33
44
  # Processing a private class can potentially handle children on its own
34
45
  return if process_private_class_method
35
46
  end
36
- elsif node.children[1] == :require && node.children[0].to_s == '(const nil :Bundler)'
47
+ # @sg-ignore
48
+ elsif method_name == :require && node.children[0].to_s == '(const nil :Bundler)'
37
49
  pins.push Pin::Reference::Require.new(Solargraph::Location.new(region.filename, Solargraph::Range.from_to(0, 0, 0, 0)), 'bundler/require', source: :parser)
38
50
  end
39
51
  process_children
@@ -45,15 +57,24 @@ module Solargraph
45
57
  def process_visibility
46
58
  if (node.children.length > 2)
47
59
  node.children[2..-1].each do |child|
60
+ # @sg-ignore Variable type could not be inferred for method_name
61
+ # @type [Symbol]
62
+ visibility = node.children[1]
63
+ # :nocov:
64
+ unless visibility.instance_of?(Symbol)
65
+ Solargraph.assert_or_log(:parser_visibility, "Expected visibility name to be a Symbol, got #{visibility.class} for node #{node.inspect}")
66
+ return process_children
67
+ end
68
+ # :nocov:
48
69
  if child.is_a?(AST::Node) && (child.type == :sym || child.type == :str)
49
70
  name = child.children[0].to_s
50
71
  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
72
  matches.each do |pin|
52
73
  # @todo Smelly instance variable access
53
- pin.instance_variable_set(:@visibility, node.children[1])
74
+ pin.instance_variable_set(:@visibility, visibility)
54
75
  end
55
76
  else
56
- process_children region.update(visibility: node.children[1])
77
+ process_children region.update(visibility: visibility)
57
78
  end
58
79
  end
59
80
  else
@@ -23,8 +23,10 @@ module Solargraph
23
23
 
24
24
  # @param source [Source]
25
25
  # @param namespace [String]
26
+ # @param closure [Pin::Closure, nil]
26
27
  # @param scope [Symbol, nil]
27
28
  # @param visibility [Symbol]
29
+ # @param lvars [Array<Symbol>]
28
30
  def initialize source: Solargraph::Source.load_string(''), closure: nil,
29
31
  scope: nil, visibility: :public, lvars: []
30
32
  @source = source
@@ -45,6 +47,7 @@ module Solargraph
45
47
  # @param closure [Pin::Closure, nil]
46
48
  # @param scope [Symbol, nil]
47
49
  # @param visibility [Symbol, nil]
50
+ # @param lvars [Array<Symbol>, nil]
48
51
  # @return [Region]
49
52
  def update closure: nil, scope: nil, visibility: nil, lvars: nil
50
53
  Region.new(
@@ -6,6 +6,8 @@ module Solargraph
6
6
  # @return [String]
7
7
  attr_reader :text
8
8
 
9
+ # @param range [Solargraph::Range]
10
+ # @param text [String]
9
11
  def initialize range, text
10
12
  @range = range
11
13
  @text = text
@@ -13,10 +13,10 @@ module Solargraph
13
13
  # @return [YARD::CodeObjects::Base]
14
14
  attr_reader :code_object
15
15
 
16
- # @return [Solargraph::Location]
16
+ # @return [Solargraph::Location, nil]
17
17
  attr_reader :location
18
18
 
19
- # @return [Solargraph::Location]
19
+ # @return [Solargraph::Location, nil]
20
20
  attr_reader :type_location
21
21
 
22
22
  # @return [String]
@@ -28,6 +28,11 @@ module Solargraph
28
28
  # @return [::Symbol]
29
29
  attr_accessor :source
30
30
 
31
+ # @type [::Numeric, nil] A priority for determining if pins should be combined or not
32
+ # A nil priority is considered the be the lowest. All code, yard & rbs pins have nil priority
33
+ # Between 2 pins, the one with the higher priority gets chosen. If the priorities are equal, they are combined.
34
+ attr_reader :combine_priority
35
+
31
36
  def presence_certain?
32
37
  true
33
38
  end
@@ -40,7 +45,8 @@ module Solargraph
40
45
  # @param source [Symbol, nil]
41
46
  # @param docstring [YARD::Docstring, nil]
42
47
  # @param directives [::Array<YARD::Tags::Directive>, nil]
43
- def initialize location: nil, type_location: nil, closure: nil, source: nil, name: '', comments: '', docstring: nil, directives: nil
48
+ # @param combine_priority [::Numeric, nil] See attr_reader for combine_priority
49
+ def initialize location: nil, type_location: nil, closure: nil, source: nil, name: '', comments: '', docstring: nil, directives: nil, combine_priority: nil
44
50
  @location = location
45
51
  @type_location = type_location
46
52
  @closure = closure
@@ -50,6 +56,8 @@ module Solargraph
50
56
  @identity = nil
51
57
  @docstring = docstring
52
58
  @directives = directives
59
+ @combine_priority = combine_priority
60
+
53
61
  assert_source_provided
54
62
  assert_location_provided
55
63
  end
@@ -61,12 +69,22 @@ module Solargraph
61
69
  Solargraph.assert_or_log(:best_location, "Neither location nor type_location provided - #{path} #{source} #{self.class}")
62
70
  end
63
71
 
72
+ # @return [Pin::Closure, nil]
73
+ def closure
74
+ Solargraph.assert_or_log(:closure, "Closure not set on #{self.class} #{name.inspect} from #{source.inspect}") unless @closure
75
+ # @type [Pin::Closure, nil]
76
+ @closure
77
+ end
78
+
64
79
  # @param other [self]
65
- # @param attrs [Hash{Symbol => Object}]
80
+ # @param attrs [Hash{::Symbol => Object}]
66
81
  #
67
82
  # @return [self]
68
83
  def combine_with(other, attrs={})
69
84
  raise "tried to combine #{other.class} with #{self.class}" unless other.class == self.class
85
+ priority_choice = choose_priority(other)
86
+ return priority_choice unless priority_choice.nil?
87
+
70
88
  type_location = choose(other, :type_location)
71
89
  location = choose(other, :location)
72
90
  combined_name = combine_name(other)
@@ -79,6 +97,7 @@ module Solargraph
79
97
  source: :combined,
80
98
  docstring: choose(other, :docstring),
81
99
  directives: combine_directives(other),
100
+ combine_priority: combine_priority
82
101
  }.merge(attrs)
83
102
  assert_same_macros(other)
84
103
  logger.debug { "Base#combine_with(path=#{path}) - other.comments=#{other.comments.inspect}, self.comments = #{self.comments}" }
@@ -87,6 +106,25 @@ module Solargraph
87
106
  out
88
107
  end
89
108
 
109
+ # @param other [self]
110
+ # @return [self, nil] Returns either the pin chosen based on priority or nil
111
+ # A nil return means that the combination process must proceed
112
+ def choose_priority(other)
113
+ if combine_priority.nil? && !other.combine_priority.nil?
114
+ return other
115
+ elsif other.combine_priority.nil? && !combine_priority.nil?
116
+ return self
117
+ elsif !combine_priority.nil? && !other.combine_priority.nil?
118
+ if combine_priority > other.combine_priority
119
+ return self
120
+ elsif combine_priority < other.combine_priority
121
+ return other
122
+ end
123
+ end
124
+
125
+ nil
126
+ end
127
+
90
128
  # @param other [self]
91
129
  # @param attr [::Symbol]
92
130
  # @sg-ignore
@@ -98,7 +136,6 @@ module Solargraph
98
136
  val2 = other.send(attr)
99
137
  return val1 if val1 == val2
100
138
  return val2 if val1.nil?
101
- # @sg-ignore
102
139
  val1.length > val2.length ? val1 : val2
103
140
  end
104
141
 
@@ -188,7 +225,7 @@ module Solargraph
188
225
  end
189
226
 
190
227
  # @param other [self]
191
- # @param attr [Symbol]
228
+ # @param attr [::Symbol]
192
229
  # @sg-ignore
193
230
  # @return [undefined]
194
231
  def choose_node(other, attr)
@@ -237,7 +274,6 @@ module Solargraph
237
274
  raise "Expected #{attr} on #{other} to be an Enumerable, got #{arr2.class}" unless arr2.is_a?(::Enumerable)
238
275
  # @type arr2 [::Enumerable]
239
276
 
240
- # @sg-ignore
241
277
  # @type [undefined]
242
278
  values1 = arr1.map(&block)
243
279
  # @type [undefined]
@@ -269,7 +305,8 @@ module Solargraph
269
305
  # @param other [self]
270
306
  # @param attr [::Symbol]
271
307
  #
272
- # @return [Object, nil]
308
+ # @sg-ignore
309
+ # @return [undefined]
273
310
  def assert_same(other, attr)
274
311
  return false if other.nil?
275
312
  val1 = send(attr)
@@ -300,6 +337,8 @@ module Solargraph
300
337
 
301
338
  # @param other [self]
302
339
  # @param attr [::Symbol]
340
+ #
341
+ # @sg-ignore
303
342
  # @return [undefined]
304
343
  def choose_pin_attr(other, attr)
305
344
  # @type [Pin::Base, nil]
@@ -307,11 +346,14 @@ module Solargraph
307
346
  # @type [Pin::Base, nil]
308
347
  val2 = other.send(attr)
309
348
  if val1.class != val2.class
349
+ # :nocov:
310
350
  Solargraph.assert_or_log("combine_with_#{attr}_class".to_sym,
311
351
  "Inconsistent #{attr.inspect} class values between \nself =#{inspect} and \nother=#{other.inspect}:\n\n self.#{attr} = #{val1.inspect}\nother.#{attr} = #{val2.inspect}")
312
352
  return val1
353
+ # :nocov:
313
354
  end
314
355
  # arbitrary way of choosing a pin
356
+ # @sg-ignore Need _1 support
315
357
  [val1, val2].compact.min_by { _1.best_location.to_s }
316
358
  end
317
359
 
@@ -3,8 +3,8 @@
3
3
  module Solargraph
4
4
  module Pin
5
5
  class BaseVariable < Base
6
- include Solargraph::Parser::NodeMethods
7
6
  # include Solargraph::Source::NodeMethods
7
+ include Solargraph::Parser::NodeMethods
8
8
 
9
9
  # @return [Parser::AST::Node, nil]
10
10
  attr_reader :assignment
@@ -43,7 +43,6 @@ module Solargraph
43
43
  @return_type ||= generate_complex_type
44
44
  end
45
45
 
46
- # @sg-ignore
47
46
  def nil_assignment?
48
47
  # this will always be false - should it be return_type ==
49
48
  # ComplexType::NIL or somesuch?
@@ -21,10 +21,13 @@ module Solargraph
21
21
  @parameters = parameters
22
22
  end
23
23
 
24
+ # @return [String]
24
25
  def method_namespace
25
26
  closure.namespace
26
27
  end
27
28
 
29
+ # @param other [self]
30
+ # @return [Pin::Block, nil]
28
31
  def combine_blocks(other)
29
32
  if block.nil?
30
33
  other.block
@@ -57,6 +60,8 @@ module Solargraph
57
60
  []
58
61
  end
59
62
 
63
+ # @param other [self]
64
+ # @return [Array<Pin::Parameter>]
60
65
  def choose_parameters(other)
61
66
  raise "Trying to combine two pins with different arities - \nself =#{inspect}, \nother=#{other.inspect}, \n\n self.arity=#{self.arity}, \nother.arity=#{other.arity}" if other.arity != arity
62
67
  parameters.zip(other.parameters).map do |param, other_param|
@@ -70,6 +75,7 @@ module Solargraph
70
75
  end
71
76
  end
72
77
 
78
+ # @return [Array<Pin::Parameter>]
73
79
  def blockless_parameters
74
80
  if parameters.last&.block?
75
81
  parameters[0..-2]
@@ -78,6 +84,7 @@ module Solargraph
78
84
  end
79
85
  end
80
86
 
87
+ # @return [Array]
81
88
  def arity
82
89
  [generics, blockless_parameters.map(&:arity_decl), block&.arity]
83
90
  end
@@ -125,6 +132,7 @@ module Solargraph
125
132
  end
126
133
  end
127
134
 
135
+ # @return [String]
128
136
  def method_name
129
137
  raise "closure was nil in #{self.inspect}" if closure.nil?
130
138
  @method_name ||= closure.name
@@ -197,6 +205,7 @@ module Solargraph
197
205
  true
198
206
  end
199
207
 
208
+ # @return [Integer]
200
209
  def mandatory_positional_param_count
201
210
  parameters.count(&:arg?)
202
211
  end
@@ -8,6 +8,7 @@ module Solargraph
8
8
 
9
9
  # @param scope [::Symbol] :class or :instance
10
10
  # @param generics [::Array<Pin::Parameter>, nil]
11
+ # @param generic_defaults [Hash{String => ComplexType}]
11
12
  def initialize scope: :class, generics: nil, generic_defaults: {}, **splat
12
13
  super(**splat)
13
14
  @scope = scope
@@ -15,6 +16,7 @@ module Solargraph
15
16
  @generic_defaults = generic_defaults
16
17
  end
17
18
 
19
+ # @return [Hash{String => ComplexType}]
18
20
  def generic_defaults
19
21
  @generic_defaults ||= {}
20
22
  end
@@ -3,12 +3,16 @@
3
3
  module Solargraph
4
4
  module Pin
5
5
  module Common
6
+ # @!method source
7
+ # @abstract
8
+ # @return [Source, nil]
9
+ # @type @closure [Pin::Closure, nil]
10
+
6
11
  # @return [Location]
7
12
  attr_reader :location
8
13
 
14
+ # @sg-ignore Solargraph::Pin::Common#closure return type could not be inferred
9
15
  # @return [Pin::Closure, nil]
10
- attr_reader :closure
11
-
12
16
  def closure
13
17
  Solargraph.assert_or_log(:closure, "Closure not set on #{self.class} #{name.inspect} from #{source.inspect}") unless @closure
14
18
  @closure