solargraph 0.58.2 → 0.59.0.dev.2

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 (203) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +3 -0
  3. data/.github/workflows/linting.yml +4 -5
  4. data/.github/workflows/plugins.yml +41 -34
  5. data/.github/workflows/rspec.yml +44 -23
  6. data/.github/workflows/typecheck.yml +2 -2
  7. data/.rubocop.yml +32 -5
  8. data/.rubocop_todo.yml +50 -966
  9. data/Gemfile +3 -1
  10. data/README.md +3 -3
  11. data/Rakefile +26 -23
  12. data/bin/solargraph +2 -1
  13. data/lib/solargraph/api_map/cache.rb +3 -3
  14. data/lib/solargraph/api_map/constants.rb +13 -3
  15. data/lib/solargraph/api_map/index.rb +23 -18
  16. data/lib/solargraph/api_map/source_to_yard.rb +22 -9
  17. data/lib/solargraph/api_map/store.rb +33 -28
  18. data/lib/solargraph/api_map.rb +150 -82
  19. data/lib/solargraph/bench.rb +44 -45
  20. data/lib/solargraph/complex_type/conformance.rb +176 -0
  21. data/lib/solargraph/complex_type/type_methods.rb +28 -17
  22. data/lib/solargraph/complex_type/unique_type.rb +218 -57
  23. data/lib/solargraph/complex_type.rb +170 -57
  24. data/lib/solargraph/convention/data_definition/data_assignment_node.rb +61 -61
  25. data/lib/solargraph/convention/data_definition/data_definition_node.rb +7 -5
  26. data/lib/solargraph/convention/data_definition.rb +5 -2
  27. data/lib/solargraph/convention/gemfile.rb +15 -15
  28. data/lib/solargraph/convention/gemspec.rb +23 -23
  29. data/lib/solargraph/convention/rakefile.rb +17 -17
  30. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +2 -1
  31. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +4 -3
  32. data/lib/solargraph/convention/struct_definition.rb +8 -4
  33. data/lib/solargraph/convention.rb +78 -78
  34. data/lib/solargraph/converters/dd.rb +19 -17
  35. data/lib/solargraph/converters/dl.rb +17 -15
  36. data/lib/solargraph/converters/dt.rb +17 -15
  37. data/lib/solargraph/converters/misc.rb +3 -1
  38. data/lib/solargraph/diagnostics/require_not_found.rb +1 -0
  39. data/lib/solargraph/diagnostics/rubocop.rb +11 -10
  40. data/lib/solargraph/diagnostics/rubocop_helpers.rb +5 -3
  41. data/lib/solargraph/diagnostics/type_check.rb +11 -10
  42. data/lib/solargraph/diagnostics/update_errors.rb +37 -41
  43. data/lib/solargraph/doc_map.rb +133 -373
  44. data/lib/solargraph/equality.rb +4 -4
  45. data/lib/solargraph/gem_pins.rb +21 -20
  46. data/lib/solargraph/language_server/error_codes.rb +20 -20
  47. data/lib/solargraph/language_server/host/diagnoser.rb +1 -1
  48. data/lib/solargraph/language_server/host/dispatch.rb +3 -3
  49. data/lib/solargraph/language_server/host/message_worker.rb +4 -3
  50. data/lib/solargraph/language_server/host/sources.rb +2 -1
  51. data/lib/solargraph/language_server/host.rb +30 -22
  52. data/lib/solargraph/language_server/message/base.rb +97 -97
  53. data/lib/solargraph/language_server/message/client/register_capability.rb +13 -15
  54. data/lib/solargraph/language_server/message/completion_item/resolve.rb +58 -60
  55. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +12 -18
  56. data/lib/solargraph/language_server/message/extended/document.rb +1 -0
  57. data/lib/solargraph/language_server/message/extended/document_gems.rb +32 -32
  58. data/lib/solargraph/language_server/message/extended/download_core.rb +20 -19
  59. data/lib/solargraph/language_server/message/extended/search.rb +20 -20
  60. data/lib/solargraph/language_server/message/initialize.rb +197 -191
  61. data/lib/solargraph/language_server/message/text_document/completion.rb +10 -8
  62. data/lib/solargraph/language_server/message/text_document/definition.rb +41 -32
  63. data/lib/solargraph/language_server/message/text_document/document_highlight.rb +23 -16
  64. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +29 -19
  65. data/lib/solargraph/language_server/message/text_document/formatting.rb +8 -6
  66. data/lib/solargraph/language_server/message/text_document/hover.rb +5 -5
  67. data/lib/solargraph/language_server/message/text_document/prepare_rename.rb +18 -11
  68. data/lib/solargraph/language_server/message/text_document/references.rb +23 -16
  69. data/lib/solargraph/language_server/message/text_document/rename.rb +26 -19
  70. data/lib/solargraph/language_server/message/text_document/signature_help.rb +3 -2
  71. data/lib/solargraph/language_server/message/text_document/type_definition.rb +25 -17
  72. data/lib/solargraph/language_server/message/workspace/did_change_configuration.rb +41 -35
  73. data/lib/solargraph/language_server/message/workspace/did_change_watched_files.rb +48 -40
  74. data/lib/solargraph/language_server/message/workspace/did_change_workspace_folders.rb +32 -26
  75. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +27 -17
  76. data/lib/solargraph/language_server/message.rb +94 -94
  77. data/lib/solargraph/language_server/request.rb +29 -27
  78. data/lib/solargraph/language_server/transport/data_reader.rb +72 -74
  79. data/lib/solargraph/language_server/uri_helpers.rb +49 -49
  80. data/lib/solargraph/library.rb +85 -44
  81. data/lib/solargraph/location.rb +17 -14
  82. data/lib/solargraph/logging.rb +24 -4
  83. data/lib/solargraph/page.rb +92 -92
  84. data/lib/solargraph/parser/comment_ripper.rb +19 -4
  85. data/lib/solargraph/parser/flow_sensitive_typing.rb +326 -108
  86. data/lib/solargraph/parser/node_processor/base.rb +34 -4
  87. data/lib/solargraph/parser/node_processor.rb +8 -7
  88. data/lib/solargraph/parser/parser_gem/class_methods.rb +32 -14
  89. data/lib/solargraph/parser/parser_gem/flawed_builder.rb +19 -19
  90. data/lib/solargraph/parser/parser_gem/node_chainer.rb +50 -25
  91. data/lib/solargraph/parser/parser_gem/node_methods.rb +91 -70
  92. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +4 -4
  93. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +13 -11
  94. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +9 -0
  95. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +12 -12
  96. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +10 -3
  97. data/lib/solargraph/parser/parser_gem/node_processors/defs_node.rb +38 -37
  98. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +36 -6
  99. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +5 -3
  100. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +1 -0
  101. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -1
  102. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +3 -3
  103. data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
  104. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -1
  105. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +2 -1
  106. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +4 -5
  107. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +124 -113
  108. data/lib/solargraph/parser/parser_gem/node_processors/until_node.rb +29 -29
  109. data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
  110. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +6 -2
  111. data/lib/solargraph/parser/parser_gem/node_processors.rb +4 -0
  112. data/lib/solargraph/parser/parser_gem.rb +14 -12
  113. data/lib/solargraph/parser/region.rb +9 -3
  114. data/lib/solargraph/parser/snippet.rb +3 -1
  115. data/lib/solargraph/parser.rb +25 -23
  116. data/lib/solargraph/pin/base.rb +126 -80
  117. data/lib/solargraph/pin/base_variable.rb +273 -24
  118. data/lib/solargraph/pin/block.rb +29 -6
  119. data/lib/solargraph/pin/breakable.rb +7 -1
  120. data/lib/solargraph/pin/callable.rb +65 -21
  121. data/lib/solargraph/pin/closure.rb +7 -10
  122. data/lib/solargraph/pin/common.rb +24 -6
  123. data/lib/solargraph/pin/compound_statement.rb +55 -0
  124. data/lib/solargraph/pin/constant.rb +43 -45
  125. data/lib/solargraph/pin/conversions.rb +10 -4
  126. data/lib/solargraph/pin/delegated_method.rb +19 -8
  127. data/lib/solargraph/pin/documenting.rb +4 -2
  128. data/lib/solargraph/pin/instance_variable.rb +5 -1
  129. data/lib/solargraph/pin/keyword.rb +0 -4
  130. data/lib/solargraph/pin/local_variable.rb +15 -59
  131. data/lib/solargraph/pin/method.rb +153 -104
  132. data/lib/solargraph/pin/method_alias.rb +8 -0
  133. data/lib/solargraph/pin/namespace.rb +19 -12
  134. data/lib/solargraph/pin/parameter.rb +100 -36
  135. data/lib/solargraph/pin/proxy_type.rb +4 -1
  136. data/lib/solargraph/pin/reference/override.rb +1 -1
  137. data/lib/solargraph/pin/reference/superclass.rb +2 -0
  138. data/lib/solargraph/pin/reference.rb +19 -0
  139. data/lib/solargraph/pin/search.rb +3 -2
  140. data/lib/solargraph/pin/signature.rb +15 -12
  141. data/lib/solargraph/pin/symbol.rb +2 -1
  142. data/lib/solargraph/pin/until.rb +2 -4
  143. data/lib/solargraph/pin/while.rb +2 -4
  144. data/lib/solargraph/pin.rb +2 -0
  145. data/lib/solargraph/pin_cache.rb +490 -73
  146. data/lib/solargraph/position.rb +14 -10
  147. data/lib/solargraph/range.rb +16 -15
  148. data/lib/solargraph/rbs_map/conversions.rb +343 -214
  149. data/lib/solargraph/rbs_map/core_fills.rb +91 -84
  150. data/lib/solargraph/rbs_map/core_map.rb +24 -17
  151. data/lib/solargraph/rbs_map/stdlib_map.rb +33 -5
  152. data/lib/solargraph/rbs_map.rb +77 -32
  153. data/lib/solargraph/server_methods.rb +16 -16
  154. data/lib/solargraph/shell.rb +128 -73
  155. data/lib/solargraph/source/chain/array.rb +39 -37
  156. data/lib/solargraph/source/chain/call.rb +96 -56
  157. data/lib/solargraph/source/chain/class_variable.rb +13 -13
  158. data/lib/solargraph/source/chain/constant.rb +5 -1
  159. data/lib/solargraph/source/chain/global_variable.rb +13 -13
  160. data/lib/solargraph/source/chain/hash.rb +8 -5
  161. data/lib/solargraph/source/chain/if.rb +12 -10
  162. data/lib/solargraph/source/chain/instance_variable.rb +24 -1
  163. data/lib/solargraph/source/chain/link.rb +99 -109
  164. data/lib/solargraph/source/chain/literal.rb +9 -6
  165. data/lib/solargraph/source/chain/or.rb +10 -4
  166. data/lib/solargraph/source/chain/q_call.rb +13 -11
  167. data/lib/solargraph/source/chain/variable.rb +15 -13
  168. data/lib/solargraph/source/chain/z_super.rb +28 -30
  169. data/lib/solargraph/source/chain.rb +49 -38
  170. data/lib/solargraph/source/change.rb +12 -5
  171. data/lib/solargraph/source/cursor.rb +23 -17
  172. data/lib/solargraph/source/encoding_fixes.rb +6 -7
  173. data/lib/solargraph/source/source_chainer.rb +56 -32
  174. data/lib/solargraph/source/updater.rb +5 -1
  175. data/lib/solargraph/source.rb +59 -35
  176. data/lib/solargraph/source_map/clip.rb +48 -29
  177. data/lib/solargraph/source_map/data.rb +4 -1
  178. data/lib/solargraph/source_map/mapper.rb +71 -42
  179. data/lib/solargraph/source_map.rb +21 -9
  180. data/lib/solargraph/type_checker/problem.rb +3 -1
  181. data/lib/solargraph/type_checker/rules.rb +81 -8
  182. data/lib/solargraph/type_checker.rb +195 -120
  183. data/lib/solargraph/version.rb +1 -1
  184. data/lib/solargraph/workspace/config.rb +13 -10
  185. data/lib/solargraph/workspace/gemspecs.rb +367 -0
  186. data/lib/solargraph/workspace/require_paths.rb +1 -0
  187. data/lib/solargraph/workspace.rb +149 -30
  188. data/lib/solargraph/yard_map/helpers.rb +8 -3
  189. data/lib/solargraph/yard_map/mapper/to_method.rb +13 -7
  190. data/lib/solargraph/yard_map/mapper/to_namespace.rb +2 -1
  191. data/lib/solargraph/yard_map/mapper.rb +13 -8
  192. data/lib/solargraph/yard_tags.rb +20 -20
  193. data/lib/solargraph/yardoc.rb +33 -23
  194. data/lib/solargraph.rb +29 -8
  195. data/rbs/fills/rubygems/0/dependency.rbs +193 -0
  196. data/rbs/fills/tuple/tuple.rbs +28 -0
  197. data/rbs/shims/ast/0/node.rbs +1 -1
  198. data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
  199. data/solargraph.gemspec +36 -34
  200. metadata +38 -33
  201. data/lib/solargraph/type_checker/checks.rb +0 -124
  202. data/lib/solargraph/type_checker/param_def.rb +0 -37
  203. data/lib/solargraph/yard_map/to_method.rb +0 -89
@@ -3,72 +3,28 @@
3
3
  module Solargraph
4
4
  module Pin
5
5
  class LocalVariable < BaseVariable
6
- # @return [Range]
7
- attr_reader :presence
8
-
9
- def presence_certain?
10
- @presence_certain
11
- end
6
+ # @param api_map [ApiMap]
7
+ # @return [ComplexType, ComplexType::UniqueType]
8
+ def probe api_map
9
+ if presence_certain? && return_type&.defined?
10
+ # flow sensitive typing has already figured out this type
11
+ # has been downcast - use the type it figured out
12
+ # @sg-ignore flow sensitive typing should support ivars
13
+ return adjust_type api_map, return_type.qualify(api_map, *gates)
14
+ end
12
15
 
13
- # @param assignment [AST::Node, nil]
14
- # @param presence [Range, nil]
15
- # @param presence_certain [Boolean]
16
- # @param splat [Hash]
17
- def initialize assignment: nil, presence: nil, presence_certain: false, **splat
18
- super(**splat)
19
- @assignment = assignment
20
- @presence = presence
21
- @presence_certain = presence_certain
16
+ super
22
17
  end
23
18
 
24
- def combine_with(other, attrs={})
25
- new_attrs = {
26
- assignment: assert_same(other, :assignment),
27
- presence_certain: assert_same(other, :presence_certain?),
28
- }.merge(attrs)
29
- new_attrs[:presence] = assert_same(other, :presence) unless attrs.key?(:presence)
19
+ def combine_with other, attrs = {}
20
+ # keep this as a parameter
21
+ return other.combine_with(self, attrs) if other.is_a?(Parameter) && !is_a?(Parameter)
30
22
 
31
- super(other, new_attrs)
32
- end
33
-
34
- # @param other_closure [Pin::Closure]
35
- # @param other_loc [Location]
36
- def visible_at?(other_closure, other_loc)
37
- location.filename == other_loc.filename &&
38
- presence.include?(other_loc.range.start) &&
39
- match_named_closure(other_closure, closure)
23
+ super
40
24
  end
41
25
 
42
26
  def to_rbs
43
- (name || '(anon)') + ' ' + (return_type&.to_rbs || 'untyped')
44
- end
45
-
46
- private
47
-
48
- # @param tag1 [String]
49
- # @param tag2 [String]
50
- # @return [Boolean]
51
- def match_tags tag1, tag2
52
- # @todo This is an unfortunate hack made necessary by a discrepancy in
53
- # how tags indicate the root namespace. The long-term solution is to
54
- # standardize it, whether it's `Class<>`, an empty string, or
55
- # something else.
56
- tag1 == tag2 ||
57
- (['', 'Class<>'].include?(tag1) && ['', 'Class<>'].include?(tag2))
58
- end
59
-
60
- # @param needle [Pin::Base]
61
- # @param haystack [Pin::Base]
62
- # @return [Boolean]
63
- def match_named_closure needle, haystack
64
- return true if needle == haystack || haystack.is_a?(Pin::Block)
65
- cursor = haystack
66
- until cursor.nil?
67
- return true if needle.path == cursor.path
68
- return false if cursor.path && !cursor.path.empty?
69
- cursor = cursor.closure
70
- end
71
- false
27
+ "#{name || '(anon)'} #{return_type&.to_rbs || 'untyped'}"
72
28
  end
73
29
  end
74
30
  end
@@ -22,8 +22,10 @@ module Solargraph
22
22
  # @param attribute [Boolean]
23
23
  # @param signatures [::Array<Signature>, nil]
24
24
  # @param anon_splat [Boolean]
25
+ # @param context [ComplexType, ComplexType::UniqueType, nil]
26
+ # @param [Hash{Symbol => Object}] splat
25
27
  def initialize visibility: :public, explicit: true, block: :undefined, node: nil, attribute: false, signatures: nil, anon_splat: false,
26
- **splat
28
+ context: nil, **splat
27
29
  super(**splat)
28
30
  @visibility = visibility
29
31
  @explicit = explicit
@@ -32,31 +34,12 @@ module Solargraph
32
34
  @attribute = attribute
33
35
  @signatures = signatures
34
36
  @anon_splat = anon_splat
35
- end
36
-
37
- # @param signature_pins [Array<Pin::Signature>]
38
- # @return [Array<Pin::Signature>]
39
- def combine_all_signature_pins(*signature_pins)
40
- # @type [Hash{Array => Array<Pin::Signature>}]
41
- by_arity = {}
42
- signature_pins.each do |signature_pin|
43
- by_arity[signature_pin.arity] ||= []
44
- by_arity[signature_pin.arity] << signature_pin
45
- end
46
- by_arity.transform_values! do |same_arity_pins|
47
- # @param memo [Pin::Signature, nil]
48
- # @param signature [Pin::Signature]
49
- same_arity_pins.reduce(nil) do |memo, signature|
50
- next signature if memo.nil?
51
- memo.combine_with(signature)
52
- end
53
- end
54
- by_arity.values.flatten
37
+ @context = context if context
55
38
  end
56
39
 
57
40
  # @param other [Pin::Method]
58
41
  # @return [::Symbol]
59
- def combine_visibility(other)
42
+ def combine_visibility other
60
43
  if dodgy_visibility_source? && !other.dodgy_visibility_source?
61
44
  other.visibility
62
45
  elsif other.dodgy_visibility_source? && !dodgy_visibility_source?
@@ -66,33 +49,18 @@ module Solargraph
66
49
  end
67
50
  end
68
51
 
69
- # @param other [Pin::Method]
70
- # @return [Array<Pin::Signature>]
71
- def combine_signatures(other)
72
- all_undefined = signatures.all? { |sig| sig.return_type.undefined? }
73
- other_all_undefined = other.signatures.all? { |sig| sig.return_type.undefined? }
74
- if all_undefined && !other_all_undefined
75
- other.signatures
76
- elsif other_all_undefined && !all_undefined
77
- signatures
78
- else
79
- combine_all_signature_pins(*signatures, *other.signatures)
80
- end
81
- end
82
-
83
- def combine_with(other, attrs = {})
52
+ def combine_with other, attrs = {}
84
53
  priority_choice = choose_priority(other)
85
54
  return priority_choice unless priority_choice.nil?
86
55
 
87
56
  sigs = combine_signatures(other)
88
- parameters = if sigs.length > 0
89
- [].freeze
90
- else
91
- choose(other, :parameters).clone.freeze
92
- end
57
+ parameters = if sigs.length.positive?
58
+ [].freeze
59
+ else
60
+ choose(other, :parameters).clone.freeze
61
+ end
93
62
  new_attrs = {
94
63
  visibility: combine_visibility(other),
95
- # @sg-ignore https://github.com/castwide/solargraph/pull/1050
96
64
  explicit: explicit? || other.explicit?,
97
65
  block: combine_blocks(other),
98
66
  node: choose_node(other, :node),
@@ -110,7 +78,7 @@ module Solargraph
110
78
  super && other.node == node
111
79
  end
112
80
 
113
- def transform_types(&transform)
81
+ def transform_types &transform
114
82
  # @todo 'super' alone should work here I think, but doesn't typecheck at level typed
115
83
  m = super(&transform)
116
84
  m.signatures = m.signatures.map do |sig|
@@ -125,14 +93,12 @@ module Solargraph
125
93
  def reset_generated!
126
94
  super
127
95
  unless signatures.empty?
128
- return_type = nil
129
96
  @block = :undefined
130
- parameters = []
97
+ []
131
98
  end
132
99
  block&.reset_generated!
133
100
  @signatures&.each(&:reset_generated!)
134
- signature_help = nil
135
- documentation = nil
101
+ nil
136
102
  end
137
103
 
138
104
  def all_rooted?
@@ -141,7 +107,7 @@ module Solargraph
141
107
 
142
108
  # @param signature [Pin::Signature]
143
109
  # @return [Pin::Method]
144
- def with_single_signature(signature)
110
+ def with_single_signature signature
145
111
  m = proxy signature.return_type
146
112
  m.reset_generated!
147
113
  # @todo populating the single parameters/return_type/block
@@ -160,6 +126,8 @@ module Solargraph
160
126
  !block.nil?
161
127
  end
162
128
 
129
+ # @sg-ignore flow sensitive typing needs to remove literal with
130
+ # this unless block
163
131
  # @return [Pin::Signature, nil]
164
132
  def block
165
133
  return @block unless @block == :undefined
@@ -179,9 +147,10 @@ module Solargraph
179
147
  end
180
148
 
181
149
  # @param parameters [::Array<Parameter>]
182
- # @param return_type [ComplexType]
150
+ # @param return_type [ComplexType, nil]
183
151
  # @return [Signature]
184
- def generate_signature(parameters, return_type)
152
+ def generate_signature parameters, return_type
153
+ # @type [Pin::Signature, nil]
185
154
  block = nil
186
155
  yieldparam_tags = docstring.tags(:yieldparam)
187
156
  yieldreturn_tags = docstring.tags(:yieldreturn)
@@ -202,7 +171,7 @@ module Solargraph
202
171
  comments: p.text,
203
172
  name: name,
204
173
  decl: decl,
205
- presence: location ? location.range : nil,
174
+ presence: location&.range,
206
175
  return_type: ComplexType.try_parse(*p.types),
207
176
  source: source
208
177
  )
@@ -223,7 +192,11 @@ module Solargraph
223
192
  top_type = generate_complex_type
224
193
  result = []
225
194
  result.push generate_signature(parameters, top_type) if top_type.defined?
226
- result.concat(overloads.map { |meth| generate_signature(meth.parameters, meth.return_type) }) unless overloads.empty?
195
+ unless overloads.empty?
196
+ result.concat(overloads.map do |meth|
197
+ generate_signature(meth.parameters, meth.return_type)
198
+ end)
199
+ end
227
200
  result.push generate_signature(parameters, @return_type || ComplexType::UNDEFINED) if result.empty?
228
201
  result
229
202
  end
@@ -243,11 +216,18 @@ module Solargraph
243
216
  # change when pins get proxied.
244
217
  detail = String.new
245
218
  detail += if signatures.length > 1
246
- "(*) "
247
- else
248
- "(#{signatures.first.parameters.map(&:full).join(', ')}) " unless signatures.first.parameters.empty?
249
- end.to_s
250
- detail += "=#{probed? ? '~' : (proxied? ? '^' : '>')} #{return_type.to_s}" unless return_type.undefined?
219
+ '(*) '
220
+ else
221
+ "(#{signatures.first.parameters.map(&:full).join(', ')}) " unless signatures.first.parameters.empty?
222
+ end.to_s
223
+ # @sg-ignore Need to add nil check here
224
+ unless return_type.undefined?
225
+ detail += "=#{if probed?
226
+ '~'
227
+ else
228
+ (proxied? ? '^' : '>')
229
+ end} #{return_type}"
230
+ end
251
231
  detail.strip!
252
232
  return nil if detail.empty?
253
233
  detail
@@ -257,7 +237,7 @@ module Solargraph
257
237
  def signature_help
258
238
  @signature_help ||= signatures.map do |sig|
259
239
  {
260
- label: name + '(' + sig.parameters.map(&:full).join(', ') + ')',
240
+ label: "#{name}(#{sig.parameters.map(&:full).join(', ')})",
261
241
  documentation: documentation
262
242
  }
263
243
  end
@@ -276,6 +256,7 @@ module Solargraph
276
256
  return nil if signatures.empty?
277
257
 
278
258
  rbs = "def #{name}: #{signatures.first.to_rbs}"
259
+ # @sg-ignore Need to add nil check here
279
260
  signatures[1..].each do |sig|
280
261
  rbs += "\n"
281
262
  rbs += (' ' * (4 + name.length))
@@ -285,7 +266,7 @@ module Solargraph
285
266
  end
286
267
 
287
268
  def path
288
- @path ||= "#{namespace}#{(scope == :instance ? '#' : '.')}#{name}"
269
+ @path ||= "#{namespace}#{scope == :instance ? '#' : '.'}#{name}"
289
270
  end
290
271
 
291
272
  # @return [String]
@@ -294,15 +275,21 @@ module Solargraph
294
275
  end
295
276
 
296
277
  def typify api_map
297
- logger.debug { "Method#typify(self=#{self}, binder=#{binder}, closure=#{closure}, context=#{context.rooted_tags}, return_type=#{return_type.rooted_tags}) - starting" }
278
+ logger.debug do
279
+ # @sg-ignore Need to add nil check here
280
+ "Method#typify(self=#{self}, binder=#{binder}, closure=#{closure}, context=#{context.rooted_tags}, return_type=#{return_type.rooted_tags}) - starting"
281
+ end
298
282
  decl = super
299
283
  unless decl.undefined?
300
- logger.debug { "Method#typify(self=#{self}, binder=#{binder}, closure=#{closure}, context=#{context}) => #{decl.rooted_tags.inspect} - decl found" }
284
+ logger.debug do
285
+ "Method#typify(self=#{self}, binder=#{binder}, closure=#{closure}, context=#{context}) => #{decl.rooted_tags.inspect} - decl found"
286
+ end
301
287
  return decl
302
288
  end
303
289
  type = see_reference(api_map) || typify_from_super(api_map)
304
290
  logger.debug { "Method#typify(self=#{self}) - type=#{type&.rooted_tags.inspect}" }
305
291
  unless type.nil?
292
+ # @sg-ignore Need to add nil check here
306
293
  qualified = type.qualify(api_map, *closure.gates)
307
294
  logger.debug { "Method#typify(self=#{self}) => #{qualified.rooted_tags.inspect}" }
308
295
  return qualified
@@ -314,26 +301,26 @@ module Solargraph
314
301
  if @documentation.nil?
315
302
  method_docs ||= super || ''
316
303
  param_tags = docstring.tags(:param)
317
- unless param_tags.nil? or param_tags.empty?
304
+ unless param_tags.nil? || param_tags.empty?
318
305
  method_docs += "\n\n" unless method_docs.empty?
319
306
  method_docs += "Params:\n"
320
307
  lines = []
321
308
  param_tags.each do |p|
322
309
  l = "* #{p.name}"
323
- l += " [#{escape_brackets(p.types.join(', '))}]" unless p.types.nil? or p.types.empty?
310
+ l += " [#{escape_brackets(p.types.join(', '))}]" unless p.types.nil? || p.types.empty?
324
311
  l += " #{p.text}"
325
312
  lines.push l
326
313
  end
327
314
  method_docs += lines.join("\n")
328
315
  end
329
316
  yieldparam_tags = docstring.tags(:yieldparam)
330
- unless yieldparam_tags.nil? or yieldparam_tags.empty?
317
+ unless yieldparam_tags.nil? || yieldparam_tags.empty?
331
318
  method_docs += "\n\n" unless method_docs.empty?
332
319
  method_docs += "Block Params:\n"
333
320
  lines = []
334
321
  yieldparam_tags.each do |p|
335
322
  l = "* #{p.name}"
336
- l += " [#{escape_brackets(p.types.join(', '))}]" unless p.types.nil? or p.types.empty?
323
+ l += " [#{escape_brackets(p.types.join(', '))}]" unless p.types.nil? || p.types.empty?
337
324
  l += " #{p.text}"
338
325
  lines.push l
339
326
  end
@@ -345,8 +332,8 @@ module Solargraph
345
332
  method_docs += "Block Returns:\n"
346
333
  lines = []
347
334
  yieldreturn_tags.each do |r|
348
- l = "*"
349
- l += " [#{escape_brackets(r.types.join(', '))}]" unless r.types.nil? or r.types.empty?
335
+ l = '*'
336
+ l += " [#{escape_brackets(r.types.join(', '))}]" unless r.types.nil? || r.types.empty?
350
337
  l += " #{r.text}"
351
338
  lines.push l
352
339
  end
@@ -358,8 +345,8 @@ module Solargraph
358
345
  method_docs += "Returns:\n"
359
346
  lines = []
360
347
  return_tags.each do |r|
361
- l = "*"
362
- l += " [#{escape_brackets(r.types.join(', '))}]" unless r.types.nil? or r.types.empty?
348
+ l = '*'
349
+ l += " [#{escape_brackets(r.types.join(', '))}]" unless r.types.nil? || r.types.empty?
363
350
  l += " #{r.text}"
364
351
  lines.push l
365
352
  end
@@ -396,7 +383,7 @@ module Solargraph
396
383
  attribute? ? infer_from_iv(api_map) : infer_from_return_nodes(api_map)
397
384
  end
398
385
 
399
- # @return [::Array<Pin::Method>]
386
+ # @return [::Array<Pin::Signature>]
400
387
  def overloads
401
388
  # Ignore overload tags with nil parameters. If it's not an array, the
402
389
  # tag's source is likely malformed.
@@ -414,14 +401,14 @@ module Solargraph
414
401
  comments: tag.docstring.all.to_s,
415
402
  name: name,
416
403
  decl: decl,
417
- presence: location ? location.range : nil,
404
+ presence: location&.range,
418
405
  return_type: param_type_from_name(tag, src.first),
419
406
  source: :overloads
420
407
  )
421
408
  end,
422
409
  closure: self,
423
410
  return_type: ComplexType.try_parse(*tag.docstring.tags(:return).flat_map(&:types)),
424
- source: :overloads,
411
+ source: :overloads
425
412
  )
426
413
  end
427
414
  @overloads
@@ -440,13 +427,13 @@ module Solargraph
440
427
  return self unless docstring.ref_tags.any?
441
428
  docstring.ref_tags.each do |tag|
442
429
  ref = if tag.owner.to_s.start_with?(/[#.]/)
443
- api_map.get_methods(namespace)
444
- .select { |pin| pin.path.end_with?(tag.owner.to_s) }
445
- .first
446
- else
447
- # @todo Resolve relative namespaces
448
- api_map.get_path_pins(tag.owner.to_s).first
449
- end
430
+ api_map.get_methods(namespace)
431
+ .select { |pin| pin.path.end_with?(tag.owner.to_s) }
432
+ .first
433
+ else
434
+ # @todo Resolve relative namespaces
435
+ api_map.get_path_pins(tag.owner.to_s).first
436
+ end
450
437
  next unless ref
451
438
 
452
439
  docstring.add_tag(*ref.docstring.tags(:param))
@@ -462,29 +449,90 @@ module Solargraph
462
449
 
463
450
  protected
464
451
 
465
- attr_writer :block
466
-
467
- attr_writer :signature_help
468
-
469
- attr_writer :documentation
452
+ attr_writer :block, :signature_help, :documentation, :return_type
470
453
 
454
+ # @sg-ignore Need to add nil check here
471
455
  def dodgy_visibility_source?
472
456
  # as of 2025-03-12, the RBS generator used for
473
457
  # e.g. activesupport did not understand 'private' markings
474
458
  # inside 'class << self' blocks, but YARD did OK at it
475
- source == :rbs && scope == :class && type_location&.filename&.include?('generated') && return_type.undefined? ||
459
+ # @sg-ignore Need to add nil check here
460
+ (source == :rbs && scope == :class && type_location&.filename&.include?('generated') && return_type.undefined?) ||
476
461
  # YARD's RBS generator seems to miss a lot of should-be protected instance methods
477
- source == :rbs && scope == :instance && namespace.start_with?('YARD::') ||
462
+ (source == :rbs && scope == :instance && namespace.start_with?('YARD::')) ||
478
463
  # private on attr_readers seems to be broken in Prism's auto-generator script
479
- source == :rbs && scope == :instance && namespace.start_with?('Prism::') ||
464
+ (source == :rbs && scope == :instance && namespace.start_with?('Prism::')) ||
480
465
  # The RBS for the RBS gem itself seems to use private as a
481
466
  # 'is this a public API' concept, more aggressively than the
482
467
  # actual code. Let's respect that and ignore the actual .rb file.
483
- source == :yardoc && scope == :instance && namespace.start_with?('RBS::')
468
+ (source == :yardoc && scope == :instance && namespace.start_with?('RBS::'))
484
469
  end
485
470
 
486
471
  private
487
472
 
473
+ # @param other [Pin::Method]
474
+ # @return [Array<Pin::Signature>]
475
+ def combine_signatures other
476
+ all_undefined = signatures.all? { |sig| !sig.return_type&.defined? }
477
+ other_all_undefined = other.signatures.all? { |sig| !sig.return_type&.defined? }
478
+ if all_undefined && !other_all_undefined
479
+ other.signatures
480
+ elsif other_all_undefined && !all_undefined
481
+ signatures
482
+ else
483
+ combine_signatures_by_type_arity(*signatures, *other.signatures)
484
+ end
485
+ end
486
+
487
+ # @param signature_pins [Array<Pin::Signature>]
488
+ #
489
+ # @return [Array<Pin::Signature>]
490
+ def combine_signatures_by_type_arity(*signature_pins)
491
+ # @type [Hash{Array => Array<Pin::Signature>}]
492
+ by_type_arity = {}
493
+ signature_pins.each do |signature_pin|
494
+ by_type_arity[signature_pin.type_arity] ||= []
495
+ by_type_arity[signature_pin.type_arity] << signature_pin
496
+ end
497
+
498
+ by_type_arity.transform_values! do |same_type_arity_signatures|
499
+ combine_same_type_arity_signatures same_type_arity_signatures
500
+ end
501
+ by_type_arity.values.flatten
502
+ end
503
+
504
+ # @param same_type_arity_signatures [Array<Pin::Signature>]
505
+ #
506
+ # @return [Array<Pin::Signature>]
507
+ def combine_same_type_arity_signatures same_type_arity_signatures
508
+ # This is an O(n^2) operation, so bail out if n is not small
509
+ return same_type_arity_signatures if same_type_arity_signatures.length > 10
510
+
511
+ # @param old_signatures [Array<Pin::Signature>]
512
+ # @param new_signature [Pin::Signature]
513
+ same_type_arity_signatures.reduce([]) do |old_signatures, new_signature|
514
+ next old_signatures + [new_signature] if old_signatures.empty?
515
+ old_signatures.flat_map do |old_signature|
516
+ potential_new_signature = old_signature.combine_with(new_signature)
517
+
518
+ if potential_new_signature.type_arity == old_signature.type_arity
519
+ # the number of types in each parameter and return type
520
+ # match, so we found compatible signatures to merge. If
521
+ # we increased the number of types, we'd potentially
522
+ # have taken away the ability to use parameter types to
523
+ # choose the correct return type (while Ruby doesn't
524
+ # dispatch based on type, RBS does distinguish overloads
525
+ # based on types, not just arity, allowing for type
526
+ # information describing how methods behave based on
527
+ # their input types)
528
+ old_signatures - [old_signature] + [potential_new_signature]
529
+ else
530
+ old_signatures + [new_signature]
531
+ end
532
+ end
533
+ end
534
+ end
535
+
488
536
  # @param name [String]
489
537
  # @param asgn [Boolean]
490
538
  #
@@ -517,7 +565,7 @@ module Solargraph
517
565
  # @param name [String]
518
566
  #
519
567
  # @return [ComplexType]
520
- def param_type_from_name(tag, name)
568
+ def param_type_from_name tag, name
521
569
  # @param t [YARD::Tags::Tag]
522
570
  param = tag.tags(:param).select { |t| t.name == name }.first
523
571
  return ComplexType::UNDEFINED unless param
@@ -528,23 +576,24 @@ module Solargraph
528
576
  def generate_complex_type
529
577
  tags = docstring.tags(:return).map(&:types).flatten.compact
530
578
  return ComplexType::UNDEFINED if tags.empty?
531
- ComplexType.try_parse *tags
579
+ ComplexType.try_parse(*tags)
532
580
  end
533
581
 
534
582
  # @param api_map [ApiMap]
535
- # @return [ComplexType, nil]
583
+ # @return [ComplexType, ComplexType::UniqueType, nil]
536
584
  def see_reference api_map
537
585
  # This should actually be an intersection type
538
- # @param ref [YARD::Tags::Tag, Solargraph::Yard::Tags::RefTag]
586
+ # @param ref [YARD::Tags::Tag, YARD::Tags::RefTag]
539
587
  docstring.ref_tags.each do |ref|
540
588
  # @sg-ignore ref should actually be an intersection type
541
589
  next unless ref.tag_name == 'return' && ref.owner
542
- # @sg-ignore ref should actually be an intersection type
590
+ # @sg-ignore should actually be an intersection type
543
591
  result = resolve_reference(ref.owner.to_s, api_map)
544
592
  return result unless result.nil?
545
593
  end
546
594
  match = comments.match(/^[ \t]*\(see (.*)\)/m)
547
595
  return nil if match.nil?
596
+ # @sg-ignore Need to add nil check here
548
597
  resolve_reference match[1], api_map
549
598
  end
550
599
 
@@ -559,6 +608,7 @@ module Solargraph
559
608
  stack = rest_of_stack api_map
560
609
  return nil if stack.empty?
561
610
  stack.each do |pin|
611
+ # @sg-ignore Need to add nil check here
562
612
  return pin.return_type unless pin.return_type.undefined?
563
613
  end
564
614
  nil
@@ -566,7 +616,7 @@ module Solargraph
566
616
 
567
617
  # @param ref [String]
568
618
  # @param api_map [ApiMap]
569
- # @return [ComplexType, nil]
619
+ # @return [ComplexType, ComplexType::UniqueType, nil]
570
620
  def resolve_reference ref, api_map
571
621
  parts = ref.split(/[.#]/)
572
622
  if parts.first.empty? || parts.one?
@@ -574,6 +624,7 @@ module Solargraph
574
624
  else
575
625
  fqns = api_map.qualify(parts.first, *gates)
576
626
  return ComplexType::UNDEFINED if fqns.nil?
627
+ # @sg-ignore Need to add nil check here
577
628
  path = fqns + ref[parts.first.length] + parts.last
578
629
  end
579
630
  pins = api_map.get_path_pins(path)
@@ -589,7 +640,7 @@ module Solargraph
589
640
  return nil if node.nil?
590
641
  return node.children[1].children.last if node.type == :DEFN
591
642
  return node.children[2].children.last if node.type == :DEFS
592
- return node.children[2] if node.type == :def || node.type == :DEFS
643
+ return node.children[2] if %i[def DEFS].include?(node.type)
593
644
  return node.children[3] if node.type == :defs
594
645
  nil
595
646
  end
@@ -602,16 +653,18 @@ module Solargraph
602
653
  has_nil = false
603
654
  return ComplexType::NIL if method_body_node.nil?
604
655
  returns_from_method_body(method_body_node).each do |n|
605
- if n.nil? || [:NIL, :nil].include?(n.type)
656
+ if n.nil? || %i[NIL nil].include?(n.type)
606
657
  has_nil = true
607
658
  next
608
659
  end
609
660
  rng = Range.from_node(n)
610
661
  next unless rng
611
662
  clip = api_map.clip_at(
663
+ # @sg-ignore Need to add nil check here
612
664
  location.filename,
613
665
  rng.ending
614
666
  )
667
+ # @sg-ignore Need to add nil check here
615
668
  chain = Solargraph::Parser.chain(n, location.filename)
616
669
  type = chain.infer(api_map, self, clip.locals)
617
670
  result.push type unless type.undefined?
@@ -640,12 +693,12 @@ module Solargraph
640
693
  #
641
694
  # @param name [String]
642
695
  # @return [::Array(String, ::Symbol)]
643
- def parse_overload_param(name)
696
+ def parse_overload_param name
644
697
  # @todo this needs to handle mandatory vs not args, kwargs, blocks, etc
645
698
  if name.start_with?('**')
646
- [name[2..-1], :kwrestarg]
699
+ [name[2..], :kwrestarg]
647
700
  elsif name.start_with?('*')
648
- [name[1..-1], :restarg]
701
+ [name[1..], :restarg]
649
702
  else
650
703
  [name, :arg]
651
704
  end
@@ -663,10 +716,6 @@ module Solargraph
663
716
  .join("\n")
664
717
  .concat("```\n")
665
718
  end
666
-
667
- protected
668
-
669
- attr_writer :return_type
670
719
  end
671
720
  end
672
721
  end
@@ -26,6 +26,14 @@ module Solargraph
26
26
  :public
27
27
  end
28
28
 
29
+ def to_rbs
30
+ if scope == :class
31
+ "alias self.#{name} self.#{original}"
32
+ else
33
+ "alias #{name} #{original}"
34
+ end
35
+ end
36
+
29
37
  def path
30
38
  @path ||= namespace + (scope == :instance ? '#' : '.') + name
31
39
  end