solargraph 0.58.2 → 0.59.0.dev.1

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 (154) 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 +40 -36
  5. data/.github/workflows/rspec.yml +45 -13
  6. data/.github/workflows/typecheck.yml +2 -2
  7. data/.gitignore +0 -1
  8. data/.rubocop_todo.yml +27 -49
  9. data/CHANGELOG.md +1 -7
  10. data/README.md +3 -3
  11. data/Rakefile +1 -0
  12. data/lib/solargraph/api_map/cache.rb +3 -3
  13. data/lib/solargraph/api_map/constants.rb +13 -3
  14. data/lib/solargraph/api_map/index.rb +22 -11
  15. data/lib/solargraph/api_map/source_to_yard.rb +13 -1
  16. data/lib/solargraph/api_map/store.rb +11 -8
  17. data/lib/solargraph/api_map.rb +105 -50
  18. data/lib/solargraph/complex_type/conformance.rb +176 -0
  19. data/lib/solargraph/complex_type/type_methods.rb +16 -2
  20. data/lib/solargraph/complex_type/unique_type.rb +170 -20
  21. data/lib/solargraph/complex_type.rb +119 -14
  22. data/lib/solargraph/convention/data_definition/data_definition_node.rb +3 -1
  23. data/lib/solargraph/convention/data_definition.rb +4 -1
  24. data/lib/solargraph/convention/struct_definition/struct_assignment_node.rb +1 -0
  25. data/lib/solargraph/convention/struct_definition/struct_definition_node.rb +1 -0
  26. data/lib/solargraph/convention/struct_definition.rb +5 -1
  27. data/lib/solargraph/diagnostics/require_not_found.rb +1 -0
  28. data/lib/solargraph/diagnostics/rubocop.rb +1 -0
  29. data/lib/solargraph/diagnostics/rubocop_helpers.rb +2 -0
  30. data/lib/solargraph/diagnostics/type_check.rb +1 -0
  31. data/lib/solargraph/doc_map.rb +134 -373
  32. data/lib/solargraph/equality.rb +1 -1
  33. data/lib/solargraph/gem_pins.rb +14 -15
  34. data/lib/solargraph/language_server/host/diagnoser.rb +89 -89
  35. data/lib/solargraph/language_server/host/dispatch.rb +1 -0
  36. data/lib/solargraph/language_server/host/message_worker.rb +2 -1
  37. data/lib/solargraph/language_server/host/sources.rb +1 -0
  38. data/lib/solargraph/language_server/host.rb +6 -1
  39. data/lib/solargraph/language_server/message/extended/check_gem_version.rb +2 -7
  40. data/lib/solargraph/language_server/message/extended/document.rb +1 -0
  41. data/lib/solargraph/language_server/message/text_document/completion.rb +2 -0
  42. data/lib/solargraph/language_server/message/text_document/definition.rb +2 -0
  43. data/lib/solargraph/language_server/message/text_document/document_symbol.rb +2 -0
  44. data/lib/solargraph/language_server/message/text_document/formatting.rb +2 -0
  45. data/lib/solargraph/language_server/message/text_document/hover.rb +2 -0
  46. data/lib/solargraph/language_server/message/text_document/signature_help.rb +1 -0
  47. data/lib/solargraph/language_server/message/text_document/type_definition.rb +2 -0
  48. data/lib/solargraph/language_server/message/workspace/workspace_symbol.rb +2 -0
  49. data/lib/solargraph/library.rb +59 -13
  50. data/lib/solargraph/location.rb +9 -4
  51. data/lib/solargraph/logging.rb +21 -1
  52. data/lib/solargraph/parser/comment_ripper.rb +7 -0
  53. data/lib/solargraph/parser/flow_sensitive_typing.rb +330 -102
  54. data/lib/solargraph/parser/node_processor/base.rb +32 -2
  55. data/lib/solargraph/parser/node_processor.rb +7 -6
  56. data/lib/solargraph/parser/parser_gem/class_methods.rb +28 -10
  57. data/lib/solargraph/parser/parser_gem/node_chainer.rb +31 -6
  58. data/lib/solargraph/parser/parser_gem/node_methods.rb +27 -7
  59. data/lib/solargraph/parser/parser_gem/node_processors/and_node.rb +4 -4
  60. data/lib/solargraph/parser/parser_gem/node_processors/args_node.rb +2 -0
  61. data/lib/solargraph/parser/parser_gem/node_processors/begin_node.rb +9 -0
  62. data/lib/solargraph/parser/parser_gem/node_processors/block_node.rb +11 -11
  63. data/lib/solargraph/parser/parser_gem/node_processors/def_node.rb +7 -0
  64. data/lib/solargraph/parser/parser_gem/node_processors/if_node.rb +36 -6
  65. data/lib/solargraph/parser/parser_gem/node_processors/ivasgn_node.rb +3 -2
  66. data/lib/solargraph/parser/parser_gem/node_processors/lvasgn_node.rb +1 -0
  67. data/lib/solargraph/parser/parser_gem/node_processors/masgn_node.rb +3 -1
  68. data/lib/solargraph/parser/parser_gem/node_processors/opasgn_node.rb +2 -2
  69. data/lib/solargraph/parser/parser_gem/node_processors/or_node.rb +22 -0
  70. data/lib/solargraph/parser/parser_gem/node_processors/orasgn_node.rb +1 -1
  71. data/lib/solargraph/parser/parser_gem/node_processors/resbody_node.rb +2 -1
  72. data/lib/solargraph/parser/parser_gem/node_processors/sclass_node.rb +1 -0
  73. data/lib/solargraph/parser/parser_gem/node_processors/send_node.rb +12 -7
  74. data/lib/solargraph/parser/parser_gem/node_processors/when_node.rb +23 -0
  75. data/lib/solargraph/parser/parser_gem/node_processors/while_node.rb +5 -1
  76. data/lib/solargraph/parser/parser_gem/node_processors.rb +4 -0
  77. data/lib/solargraph/parser/region.rb +9 -3
  78. data/lib/solargraph/parser/snippet.rb +1 -1
  79. data/lib/solargraph/pin/base.rb +53 -21
  80. data/lib/solargraph/pin/base_variable.rb +312 -20
  81. data/lib/solargraph/pin/block.rb +26 -4
  82. data/lib/solargraph/pin/breakable.rb +5 -1
  83. data/lib/solargraph/pin/callable.rb +50 -3
  84. data/lib/solargraph/pin/closure.rb +2 -6
  85. data/lib/solargraph/pin/common.rb +20 -5
  86. data/lib/solargraph/pin/compound_statement.rb +55 -0
  87. data/lib/solargraph/pin/conversions.rb +2 -1
  88. data/lib/solargraph/pin/delegated_method.rb +15 -4
  89. data/lib/solargraph/pin/documenting.rb +1 -0
  90. data/lib/solargraph/pin/instance_variable.rb +5 -1
  91. data/lib/solargraph/pin/keyword.rb +0 -4
  92. data/lib/solargraph/pin/local_variable.rb +13 -57
  93. data/lib/solargraph/pin/method.rb +90 -42
  94. data/lib/solargraph/pin/method_alias.rb +8 -0
  95. data/lib/solargraph/pin/namespace.rb +7 -1
  96. data/lib/solargraph/pin/parameter.rb +76 -13
  97. data/lib/solargraph/pin/proxy_type.rb +2 -1
  98. data/lib/solargraph/pin/reference/override.rb +1 -1
  99. data/lib/solargraph/pin/reference/superclass.rb +2 -0
  100. data/lib/solargraph/pin/reference.rb +2 -0
  101. data/lib/solargraph/pin/search.rb +1 -0
  102. data/lib/solargraph/pin/signature.rb +8 -0
  103. data/lib/solargraph/pin/symbol.rb +1 -1
  104. data/lib/solargraph/pin/until.rb +1 -1
  105. data/lib/solargraph/pin/while.rb +1 -1
  106. data/lib/solargraph/pin.rb +2 -0
  107. data/lib/solargraph/pin_cache.rb +477 -57
  108. data/lib/solargraph/position.rb +12 -26
  109. data/lib/solargraph/range.rb +6 -6
  110. data/lib/solargraph/rbs_map/conversions.rb +33 -10
  111. data/lib/solargraph/rbs_map/core_map.rb +24 -17
  112. data/lib/solargraph/rbs_map/stdlib_map.rb +34 -5
  113. data/lib/solargraph/rbs_map.rb +74 -20
  114. data/lib/solargraph/shell.rb +73 -28
  115. data/lib/solargraph/source/chain/call.rb +52 -17
  116. data/lib/solargraph/source/chain/constant.rb +2 -0
  117. data/lib/solargraph/source/chain/hash.rb +1 -0
  118. data/lib/solargraph/source/chain/if.rb +1 -0
  119. data/lib/solargraph/source/chain/instance_variable.rb +22 -1
  120. data/lib/solargraph/source/chain/literal.rb +5 -0
  121. data/lib/solargraph/source/chain/or.rb +9 -1
  122. data/lib/solargraph/source/chain.rb +25 -22
  123. data/lib/solargraph/source/change.rb +9 -2
  124. data/lib/solargraph/source/cursor.rb +7 -1
  125. data/lib/solargraph/source/source_chainer.rb +13 -3
  126. data/lib/solargraph/source/updater.rb +4 -0
  127. data/lib/solargraph/source.rb +33 -7
  128. data/lib/solargraph/source_map/clip.rb +13 -2
  129. data/lib/solargraph/source_map/data.rb +4 -1
  130. data/lib/solargraph/source_map/mapper.rb +24 -1
  131. data/lib/solargraph/source_map.rb +14 -6
  132. data/lib/solargraph/type_checker/problem.rb +3 -1
  133. data/lib/solargraph/type_checker/rules.rb +75 -2
  134. data/lib/solargraph/type_checker.rb +111 -30
  135. data/lib/solargraph/version.rb +1 -1
  136. data/lib/solargraph/workspace/config.rb +3 -1
  137. data/lib/solargraph/workspace/gemspecs.rb +367 -0
  138. data/lib/solargraph/workspace/require_paths.rb +1 -0
  139. data/lib/solargraph/workspace.rb +158 -16
  140. data/lib/solargraph/yard_map/helpers.rb +2 -1
  141. data/lib/solargraph/yard_map/mapper/to_method.rb +5 -1
  142. data/lib/solargraph/yard_map/mapper/to_namespace.rb +1 -0
  143. data/lib/solargraph/yard_map/mapper.rb +5 -0
  144. data/lib/solargraph/yardoc.rb +33 -23
  145. data/lib/solargraph.rb +24 -3
  146. data/rbs/fills/rubygems/0/dependency.rbs +193 -0
  147. data/rbs/fills/tuple/tuple.rbs +28 -0
  148. data/rbs/shims/ast/0/node.rbs +1 -1
  149. data/rbs/shims/diff-lcs/1.5/diff-lcs.rbs +11 -0
  150. data/solargraph.gemspec +2 -1
  151. metadata +12 -7
  152. data/lib/solargraph/type_checker/checks.rb +0 -124
  153. data/lib/solargraph/type_checker/param_def.rb +0 -37
  154. data/lib/solargraph/yard_map/to_method.rb +0 -89
@@ -6,12 +6,24 @@ module Solargraph
6
6
  # @!method source
7
7
  # @abstract
8
8
  # @return [Source, nil]
9
+ # @!method reset_generated!
10
+ # @abstract
11
+ # @return [void]
9
12
  # @type @closure [Pin::Closure, nil]
13
+ # @type @binder [ComplexType, ComplexType::UniqueType, nil]
14
+
15
+ # @todo Missed nil violation
16
+ # @return [Location, nil]
17
+ attr_accessor :location
10
18
 
11
- # @return [Location]
12
- attr_reader :location
19
+ # @param value [Pin::Closure]
20
+ # @return [void]
21
+ def closure=(value)
22
+ @closure = value
23
+ # remove cached values generated from closure
24
+ reset_generated!
25
+ end
13
26
 
14
- # @sg-ignore Solargraph::Pin::Common#closure return type could not be inferred
15
27
  # @return [Pin::Closure, nil]
16
28
  def closure
17
29
  Solargraph.assert_or_log(:closure, "Closure not set on #{self.class} #{name.inspect} from #{source.inspect}") unless @closure
@@ -23,12 +35,13 @@ module Solargraph
23
35
  @name ||= ''
24
36
  end
25
37
 
38
+ # @todo redundant with Base#return_type?
26
39
  # @return [ComplexType]
27
40
  def return_type
28
41
  @return_type ||= ComplexType::UNDEFINED
29
42
  end
30
43
 
31
- # @return [ComplexType]
44
+ # @return [ComplexType, ComplexType::UniqueType]
32
45
  def context
33
46
  # Get the static context from the nearest namespace
34
47
  @context ||= find_context
@@ -40,7 +53,8 @@ module Solargraph
40
53
  context.namespace.to_s
41
54
  end
42
55
 
43
- # @return [ComplexType]
56
+ # @return [ComplexType, ComplexType::UniqueType]
57
+ # @sg-ignore https://github.com/castwide/solargraph/pull/1100
44
58
  def binder
45
59
  @binder || context
46
60
  end
@@ -70,6 +84,7 @@ module Solargraph
70
84
  elsif here.is_a?(Pin::Method)
71
85
  return here.context
72
86
  end
87
+ # @sg-ignore Need to add nil check here
73
88
  here = here.closure
74
89
  end
75
90
  ComplexType::ROOT
@@ -0,0 +1,55 @@
1
+ module Solargraph
2
+ module Pin
3
+ # A series of statements where if a given statement executes, /all
4
+ # of the previous statements in the sequence must have executed as
5
+ # well/. In other words, the statements are run from the top in
6
+ # sequence, until interrupted by something like a
7
+ # return/break/next/raise/etc.
8
+ #
9
+ # This mix-in is used in flow sensitive typing to determine how
10
+ # far we can assume a given assertion about a type can be trusted
11
+ # to be true.
12
+ #
13
+ # Some examples in Ruby:
14
+ #
15
+ # * Bodies of methods and Ruby blocks
16
+ # * Branches of conditionals and loops - if/elsif/else,
17
+ # unless/else, when, until, ||=, ?:, switch/case/else
18
+ # * The body of begin-end/try/rescue/ensure statements
19
+ #
20
+ # Compare/contrast with:
21
+ #
22
+ # * Scope - a sequence where variables declared are not available
23
+ # after the end of the scope. Note that this is not necessarily
24
+ # true for a compound statement.
25
+ # * Compound statement - synonym
26
+ # * Block - in Ruby this has a special meaning (a closure passed to a method), but
27
+ # in general parlance this is also a synonym.
28
+ # * Closure - a sequence which is also a scope
29
+ # * Namespace - a named sequence which is also a scope and a
30
+ # closure
31
+ #
32
+ # See:
33
+ # https://cse.buffalo.edu/~regan/cse305/RubyBNF.pdf
34
+ # https://ruby-doc.org/docs/ruby-doc-bundle/Manual/man-1.4/syntax.html
35
+ # https://en.wikipedia.org/wiki/Block_(programming)
36
+ #
37
+ # Note:
38
+ #
39
+ # Just because statement #1 in a sequence is executed, it doesn't
40
+ # mean that future ones will. Consider the effect of
41
+ # break/next/return/raise/etc. on control flow.
42
+ class CompoundStatement < Pin::Base
43
+ attr_reader :node
44
+
45
+ # @param receiver [Parser::AST::Node, nil]
46
+ # @param node [Parser::AST::Node, nil]
47
+ # @param context [ComplexType, nil]
48
+ # @param args [::Array<Parameter>]
49
+ def initialize node: nil, **splat
50
+ super(**splat)
51
+ @node = node
52
+ end
53
+ end
54
+ end
55
+ end
@@ -43,6 +43,7 @@ module Solargraph
43
43
  data: {
44
44
  path: path,
45
45
  return_type: return_type.tag,
46
+ # @sg-ignore flow sensitive typing needs to handle attrs
46
47
  location: (location ? location.to_hash : nil),
47
48
  deprecated: deprecated?
48
49
  }
@@ -80,7 +81,7 @@ module Solargraph
80
81
 
81
82
  # Get a markdown-flavored link to a documentation page.
82
83
  #
83
- # @return [String]
84
+ # @return [String, nil]
84
85
  def link_documentation
85
86
  @link_documentation ||= generate_link
86
87
  end
@@ -13,10 +13,11 @@ module Solargraph
13
13
  #
14
14
  # @param method [Method, nil] an already resolved method pin.
15
15
  # @param receiver [Source::Chain, nil] the source code used to resolve the receiver for this delegated method.
16
- # @param name [String]
17
- # @param receiver_method_name [String] the method name that will be called on the receiver (defaults to :name).
16
+ # @param name [String, nil]
17
+ # @param receiver_method_name [String, nil] the method name that will be called on the receiver (defaults to :name).
18
18
  def initialize(method: nil, receiver: nil, name: method&.name, receiver_method_name: name, **splat)
19
19
  raise ArgumentError, 'either :method or :receiver is required' if (method && receiver) || (!method && !receiver)
20
+ # @sg-ignore Need to add nil check here
20
21
  super(name: name, **splat)
21
22
 
22
23
  @receiver_chain = receiver
@@ -69,30 +70,40 @@ module Solargraph
69
70
  #
70
71
  # @param api_map [ApiMap]
71
72
  # @return [Pin::Method, nil]
73
+ # @sg-ignore Declared return type ::Solargraph::Pin::Method, nil
74
+ # does not match inferred type nil, false for
75
+ # Solargraph::Pin::DelegatedMethod#resolve_method
72
76
  def resolve_method api_map
73
77
  return if @resolved_method
74
78
 
79
+ # @sg-ignore Need to add nil check here
75
80
  resolver = @receiver_chain.define(api_map, self, []).first
76
81
 
77
82
  unless resolver
78
- Solargraph.logger.warn \
79
- "Delegated receiver for #{path} was resolved to nil from `#{print_chain(@receiver_chain)}'"
83
+ # @sg-ignore Need to add nil check here
84
+ Solargraph.logger.warn "Delegated receiver for #{path} was resolved to nil from `#{print_chain(@receiver_chain)}'"
80
85
  return
81
86
  end
82
87
 
88
+ # @sg-ignore Need to add nil check here
83
89
  receiver_type = resolver.return_type
84
90
 
91
+ # @sg-ignore Need to add nil check here
85
92
  return if receiver_type.undefined?
86
93
 
87
94
  receiver_path, method_scope =
95
+ # @sg-ignore Need to add nil check here
88
96
  if @receiver_chain.constant?
89
97
  # HACK: the `return_type` of a constant is Class<Whatever>, but looking up a method expects
90
98
  # the arguments `"Whatever"` and `scope: :class`.
99
+ # @sg-ignore Need to add nil check here
91
100
  [receiver_type.to_s.sub(/^Class<(.+)>$/, '\1'), :class]
92
101
  else
102
+ # @sg-ignore Need to add nil check here
93
103
  [receiver_type.to_s, :instance]
94
104
  end
95
105
 
106
+ # @sg-ignore Need to add nil check here
96
107
  method_stack = api_map.get_method_stack(receiver_path, @receiver_method_name, scope: method_scope)
97
108
  @resolved_method = method_stack.first
98
109
  end
@@ -104,6 +104,7 @@ module Solargraph
104
104
  left = text.lines.map do |line|
105
105
  match = line.match(/^ +/)
106
106
  next 0 unless match
107
+ # @sg-ignore Need to add nil check here
107
108
  match[0].length
108
109
  end.min
109
110
  return text if left.nil? || left.zero?
@@ -3,13 +3,17 @@
3
3
  module Solargraph
4
4
  module Pin
5
5
  class InstanceVariable < BaseVariable
6
- # @return [ComplexType]
6
+ # @sg-ignore Need to add nil check here
7
+ # @return [ComplexType, ComplexType::UniqueType]
7
8
  def binder
9
+ # @sg-ignore Need to add nil check here
8
10
  closure.binder
9
11
  end
10
12
 
13
+ # @sg-ignore Need to add nil check here
11
14
  # @return [::Symbol]
12
15
  def scope
16
+ # @sg-ignore Need to add nil check here
13
17
  closure.binder.scope
14
18
  end
15
19
 
@@ -11,10 +11,6 @@ module Solargraph
11
11
  def closure
12
12
  @closure ||= Pin::ROOT_PIN
13
13
  end
14
-
15
- def name
16
- @name
17
- end
18
14
  end
19
15
  end
20
16
  end
@@ -3,73 +3,29 @@
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 && 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
19
  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)
20
+ # keep this as a parameter
21
+ return other.combine_with(self, attrs) if other.is_a?(Parameter) && !self.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
27
  (name || '(anon)') + ' ' + (return_type&.to_rbs || 'untyped')
44
28
  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
72
- end
73
29
  end
74
30
  end
75
31
  end
@@ -22,8 +22,9 @@ 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]
25
26
  def initialize visibility: :public, explicit: true, block: :undefined, node: nil, attribute: false, signatures: nil, anon_splat: false,
26
- **splat
27
+ context: nil, **splat
27
28
  super(**splat)
28
29
  @visibility = visibility
29
30
  @explicit = explicit
@@ -32,26 +33,7 @@ module Solargraph
32
33
  @attribute = attribute
33
34
  @signatures = signatures
34
35
  @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
36
+ @context = context if context
55
37
  end
56
38
 
57
39
  # @param other [Pin::Method]
@@ -66,20 +48,6 @@ module Solargraph
66
48
  end
67
49
  end
68
50
 
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
51
  def combine_with(other, attrs = {})
84
52
  priority_choice = choose_priority(other)
85
53
  return priority_choice unless priority_choice.nil?
@@ -92,7 +60,6 @@ module Solargraph
92
60
  end
93
61
  new_attrs = {
94
62
  visibility: combine_visibility(other),
95
- # @sg-ignore https://github.com/castwide/solargraph/pull/1050
96
63
  explicit: explicit? || other.explicit?,
97
64
  block: combine_blocks(other),
98
65
  node: choose_node(other, :node),
@@ -160,6 +127,8 @@ module Solargraph
160
127
  !block.nil?
161
128
  end
162
129
 
130
+ # @sg-ignore flow sensitive typing needs to remove literal with
131
+ # this unless block
163
132
  # @return [Pin::Signature, nil]
164
133
  def block
165
134
  return @block unless @block == :undefined
@@ -179,9 +148,10 @@ module Solargraph
179
148
  end
180
149
 
181
150
  # @param parameters [::Array<Parameter>]
182
- # @param return_type [ComplexType]
151
+ # @param return_type [ComplexType, nil]
183
152
  # @return [Signature]
184
153
  def generate_signature(parameters, return_type)
154
+ # @type [Pin::Signature, nil]
185
155
  block = nil
186
156
  yieldparam_tags = docstring.tags(:yieldparam)
187
157
  yieldreturn_tags = docstring.tags(:yieldreturn)
@@ -202,6 +172,7 @@ module Solargraph
202
172
  comments: p.text,
203
173
  name: name,
204
174
  decl: decl,
175
+ # @sg-ignore flow sensitive typing needs to handle attrs
205
176
  presence: location ? location.range : nil,
206
177
  return_type: ComplexType.try_parse(*p.types),
207
178
  source: source
@@ -247,6 +218,7 @@ module Solargraph
247
218
  else
248
219
  "(#{signatures.first.parameters.map(&:full).join(', ')}) " unless signatures.first.parameters.empty?
249
220
  end.to_s
221
+ # @sg-ignore Need to add nil check here
250
222
  detail += "=#{probed? ? '~' : (proxied? ? '^' : '>')} #{return_type.to_s}" unless return_type.undefined?
251
223
  detail.strip!
252
224
  return nil if detail.empty?
@@ -276,6 +248,7 @@ module Solargraph
276
248
  return nil if signatures.empty?
277
249
 
278
250
  rbs = "def #{name}: #{signatures.first.to_rbs}"
251
+ # @sg-ignore Need to add nil check here
279
252
  signatures[1..].each do |sig|
280
253
  rbs += "\n"
281
254
  rbs += (' ' * (4 + name.length))
@@ -294,6 +267,7 @@ module Solargraph
294
267
  end
295
268
 
296
269
  def typify api_map
270
+ # @sg-ignore Need to add nil check here
297
271
  logger.debug { "Method#typify(self=#{self}, binder=#{binder}, closure=#{closure}, context=#{context.rooted_tags}, return_type=#{return_type.rooted_tags}) - starting" }
298
272
  decl = super
299
273
  unless decl.undefined?
@@ -303,6 +277,7 @@ module Solargraph
303
277
  type = see_reference(api_map) || typify_from_super(api_map)
304
278
  logger.debug { "Method#typify(self=#{self}) - type=#{type&.rooted_tags.inspect}" }
305
279
  unless type.nil?
280
+ # @sg-ignore Need to add nil check here
306
281
  qualified = type.qualify(api_map, *closure.gates)
307
282
  logger.debug { "Method#typify(self=#{self}) => #{qualified.rooted_tags.inspect}" }
308
283
  return qualified
@@ -396,7 +371,7 @@ module Solargraph
396
371
  attribute? ? infer_from_iv(api_map) : infer_from_return_nodes(api_map)
397
372
  end
398
373
 
399
- # @return [::Array<Pin::Method>]
374
+ # @return [::Array<Pin::Signature>]
400
375
  def overloads
401
376
  # Ignore overload tags with nil parameters. If it's not an array, the
402
377
  # tag's source is likely malformed.
@@ -414,6 +389,7 @@ module Solargraph
414
389
  comments: tag.docstring.all.to_s,
415
390
  name: name,
416
391
  decl: decl,
392
+ # @sg-ignore flow sensitive typing needs to handle attrs
417
393
  presence: location ? location.range : nil,
418
394
  return_type: param_type_from_name(tag, src.first),
419
395
  source: :overloads
@@ -468,10 +444,12 @@ module Solargraph
468
444
 
469
445
  attr_writer :documentation
470
446
 
447
+ # @sg-ignore Need to add nil check here
471
448
  def dodgy_visibility_source?
472
449
  # as of 2025-03-12, the RBS generator used for
473
450
  # e.g. activesupport did not understand 'private' markings
474
451
  # inside 'class << self' blocks, but YARD did OK at it
452
+ # @sg-ignore Need to add nil check here
475
453
  source == :rbs && scope == :class && type_location&.filename&.include?('generated') && return_type.undefined? ||
476
454
  # YARD's RBS generator seems to miss a lot of should-be protected instance methods
477
455
  source == :rbs && scope == :instance && namespace.start_with?('YARD::') ||
@@ -485,6 +463,71 @@ module Solargraph
485
463
 
486
464
  private
487
465
 
466
+ # @param other [Pin::Method]
467
+ # @return [Array<Pin::Signature>]
468
+ def combine_signatures(other)
469
+ all_undefined = signatures.all? { |sig| !sig.return_type&.defined? }
470
+ other_all_undefined = other.signatures.all? { |sig| !sig.return_type&.defined? }
471
+ if all_undefined && !other_all_undefined
472
+ other.signatures
473
+ elsif other_all_undefined && !all_undefined
474
+ signatures
475
+ else
476
+ combine_signatures_by_type_arity(*signatures, *other.signatures)
477
+ end
478
+ end
479
+
480
+ # @param signature_pins [Array<Pin::Signature>]
481
+ #
482
+ # @return [Array<Pin::Signature>]
483
+ def combine_signatures_by_type_arity(*signature_pins)
484
+ # @type [Hash{Array => Array<Pin::Signature>}]
485
+ by_type_arity = {}
486
+ signature_pins.each do |signature_pin|
487
+ by_type_arity[signature_pin.type_arity] ||= []
488
+ by_type_arity[signature_pin.type_arity] << signature_pin
489
+ end
490
+
491
+ by_type_arity.transform_values! do |same_type_arity_signatures|
492
+ combine_same_type_arity_signatures same_type_arity_signatures
493
+ end
494
+ by_type_arity.values.flatten
495
+ end
496
+
497
+ # @param same_type_arity_signatures [Array<Pin::Signature>]
498
+ #
499
+ # @return [Array<Pin::Signature>]
500
+ def combine_same_type_arity_signatures(same_type_arity_signatures)
501
+ # This is an O(n^2) operation, so bail out if n is not small
502
+ return same_type_arity_signatures if same_type_arity_signatures.length > 10
503
+
504
+ # @param old_signatures [Array<Pin::Signature>]
505
+ # @param new_signature [Pin::Signature]
506
+ same_type_arity_signatures.reduce([]) do |old_signatures, new_signature|
507
+ next [new_signature] if old_signatures.empty?
508
+
509
+ found_merge = false
510
+ old_signatures.flat_map do |old_signature|
511
+ potential_new_signature = old_signature.combine_with(new_signature)
512
+
513
+ if potential_new_signature.type_arity == old_signature.type_arity
514
+ # the number of types in each parameter and return type
515
+ # match, so we found compatible signatures to merge. If
516
+ # we increased the number of types, we'd potentially
517
+ # have taken away the ability to use parameter types to
518
+ # choose the correct return type (while Ruby doesn't
519
+ # dispatch based on type, RBS does distinguish overloads
520
+ # based on types, not just arity, allowing for type
521
+ # information describing how methods behave based on
522
+ # their input types)
523
+ old_signatures - [old_signature] + [potential_new_signature]
524
+ else
525
+ old_signatures + [new_signature]
526
+ end
527
+ end
528
+ end
529
+ end
530
+
488
531
  # @param name [String]
489
532
  # @param asgn [Boolean]
490
533
  #
@@ -532,19 +575,20 @@ module Solargraph
532
575
  end
533
576
 
534
577
  # @param api_map [ApiMap]
535
- # @return [ComplexType, nil]
578
+ # @return [ComplexType, ComplexType::UniqueType, nil]
536
579
  def see_reference api_map
537
580
  # This should actually be an intersection type
538
- # @param ref [YARD::Tags::Tag, Solargraph::Yard::Tags::RefTag]
581
+ # @param ref [YARD::Tags::Tag, YARD::Tags::RefTag]
539
582
  docstring.ref_tags.each do |ref|
540
583
  # @sg-ignore ref should actually be an intersection type
541
584
  next unless ref.tag_name == 'return' && ref.owner
542
- # @sg-ignore ref should actually be an intersection type
585
+ # @sg-ignore should actually be an intersection type
543
586
  result = resolve_reference(ref.owner.to_s, api_map)
544
587
  return result unless result.nil?
545
588
  end
546
589
  match = comments.match(/^[ \t]*\(see (.*)\)/m)
547
590
  return nil if match.nil?
591
+ # @sg-ignore Need to add nil check here
548
592
  resolve_reference match[1], api_map
549
593
  end
550
594
 
@@ -559,6 +603,7 @@ module Solargraph
559
603
  stack = rest_of_stack api_map
560
604
  return nil if stack.empty?
561
605
  stack.each do |pin|
606
+ # @sg-ignore Need to add nil check here
562
607
  return pin.return_type unless pin.return_type.undefined?
563
608
  end
564
609
  nil
@@ -566,7 +611,7 @@ module Solargraph
566
611
 
567
612
  # @param ref [String]
568
613
  # @param api_map [ApiMap]
569
- # @return [ComplexType, nil]
614
+ # @return [ComplexType, ComplexType::UniqueType, nil]
570
615
  def resolve_reference ref, api_map
571
616
  parts = ref.split(/[.#]/)
572
617
  if parts.first.empty? || parts.one?
@@ -574,6 +619,7 @@ module Solargraph
574
619
  else
575
620
  fqns = api_map.qualify(parts.first, *gates)
576
621
  return ComplexType::UNDEFINED if fqns.nil?
622
+ # @sg-ignore Need to add nil check here
577
623
  path = fqns + ref[parts.first.length] + parts.last
578
624
  end
579
625
  pins = api_map.get_path_pins(path)
@@ -609,9 +655,11 @@ module Solargraph
609
655
  rng = Range.from_node(n)
610
656
  next unless rng
611
657
  clip = api_map.clip_at(
658
+ # @sg-ignore Need to add nil check here
612
659
  location.filename,
613
660
  rng.ending
614
661
  )
662
+ # @sg-ignore Need to add nil check here
615
663
  chain = Solargraph::Parser.chain(n, location.filename)
616
664
  type = chain.infer(api_map, self, clip.locals)
617
665
  result.push type unless type.undefined?
@@ -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
@@ -26,7 +26,6 @@ module Solargraph
26
26
  @type = type
27
27
  @visibility = visibility
28
28
  if name.start_with?('::')
29
- # @type [String]
30
29
  name = name[2..-1] || ''
31
30
  @closure = Solargraph::Pin::ROOT_PIN
32
31
  end
@@ -39,6 +38,7 @@ module Solargraph
39
38
  closure_name = if [Solargraph::Pin::ROOT_PIN, nil].include?(closure)
40
39
  ''
41
40
  else
41
+ # @sg-ignore Need to add nil check here
42
42
  closure.full_context.namespace + '::'
43
43
  end
44
44
  closure_name += parts.join('::')
@@ -48,6 +48,12 @@ module Solargraph
48
48
  @name = name
49
49
  end
50
50
 
51
+ def reset_generated!
52
+ @return_type = nil
53
+ @full_context = nil
54
+ @path = nil
55
+ end
56
+
51
57
  def to_rbs
52
58
  "#{@type.to_s} #{return_type.all_params.first.to_rbs}#{rbs_generics}".strip
53
59
  end