ruby-lsp 0.17.5 → 0.17.7
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.
- checksums.yaml +4 -4
 - data/VERSION +1 -1
 - data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +8 -0
 - data/lib/ruby_indexer/lib/ruby_indexer/index.rb +5 -2
 - data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +107 -7
 - data/lib/ruby_indexer/test/index_test.rb +43 -0
 - data/lib/ruby_indexer/test/method_test.rb +37 -24
 - data/lib/ruby_indexer/test/rbs_indexer_test.rb +248 -0
 - data/lib/ruby_lsp/document.rb +14 -24
 - data/lib/ruby_lsp/global_state.rb +8 -4
 - data/lib/ruby_lsp/listeners/completion.rb +27 -0
 - data/lib/ruby_lsp/listeners/definition.rb +27 -3
 - data/lib/ruby_lsp/listeners/hover.rb +38 -11
 - data/lib/ruby_lsp/node_context.rb +65 -5
 - data/lib/ruby_lsp/requests/completion_resolve.rb +2 -0
 - data/lib/ruby_lsp/requests/definition.rb +2 -0
 - data/lib/ruby_lsp/type_inferrer.rb +17 -19
 - metadata +2 -2
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 671bab4fdbd77d1980781f55874d6cd448e1dcd11a6f534a176dfb00b098d2eb
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: bd12fd2ef58588b3b5386fec48c0f561140efff180988f1971b67f635f0e1042
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: f3a2a3115e1745ad7263b7e113ef13795f9a1ed1ee118128a9ab2aaad703b17551acbd929f820700e6650efb76421418a13a78270ac8d3aaff080edc46731aee
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: d29bb4d6c60727eef1a10905762a6d0c8946b7afc8aac6148ef970c8d752365f1577403497702f52a7211689cde7940b3d7cd1e1e0eb03d038e0dc6f7ceed738
         
     | 
    
        data/VERSION
    CHANGED
    
    | 
         @@ -1 +1 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            0.17. 
     | 
| 
      
 1 
     | 
    
         
            +
            0.17.7
         
     | 
| 
         @@ -288,6 +288,14 @@ module RubyIndexer 
     | 
|
| 
       288 
288 
     | 
    
         
             
                class BlockParameter < Parameter
         
     | 
| 
       289 
289 
     | 
    
         
             
                  DEFAULT_NAME = T.let(:"<anonymous block>", Symbol)
         
     | 
| 
       290 
290 
     | 
    
         | 
| 
      
 291 
     | 
    
         
            +
                  class << self
         
     | 
| 
      
 292 
     | 
    
         
            +
                    extend T::Sig
         
     | 
| 
      
 293 
     | 
    
         
            +
                    sig { returns(BlockParameter) }
         
     | 
| 
      
 294 
     | 
    
         
            +
                    def anonymous
         
     | 
| 
      
 295 
     | 
    
         
            +
                      new(name: DEFAULT_NAME)
         
     | 
| 
      
 296 
     | 
    
         
            +
                    end
         
     | 
| 
      
 297 
     | 
    
         
            +
                  end
         
     | 
| 
      
 298 
     | 
    
         
            +
             
     | 
| 
       291 
299 
     | 
    
         
             
                  sig { override.returns(Symbol) }
         
     | 
| 
       292 
300 
     | 
    
         
             
                  def decorated_name
         
     | 
| 
       293 
301 
     | 
    
         
             
                    :"&#{@name}"
         
     | 
| 
         @@ -331,14 +331,17 @@ module RubyIndexer 
     | 
|
| 
       331 
331 
     | 
    
         
             
                  params(
         
     | 
| 
       332 
332 
     | 
    
         
             
                    method_name: String,
         
     | 
| 
       333 
333 
     | 
    
         
             
                    receiver_name: String,
         
     | 
| 
      
 334 
     | 
    
         
            +
                    inherited_only: T::Boolean,
         
     | 
| 
       334 
335 
     | 
    
         
             
                  ).returns(T.nilable(T::Array[T.any(Entry::Member, Entry::MethodAlias)]))
         
     | 
| 
       335 
336 
     | 
    
         
             
                end
         
     | 
| 
       336 
     | 
    
         
            -
                def resolve_method(method_name, receiver_name)
         
     | 
| 
      
 337 
     | 
    
         
            +
                def resolve_method(method_name, receiver_name, inherited_only: false)
         
     | 
| 
       337 
338 
     | 
    
         
             
                  method_entries = self[method_name]
         
     | 
| 
       338 
339 
     | 
    
         
             
                  return unless method_entries
         
     | 
| 
       339 
340 
     | 
    
         | 
| 
       340 
341 
     | 
    
         
             
                  ancestors = linearized_ancestors_of(receiver_name.delete_prefix("::"))
         
     | 
| 
       341 
342 
     | 
    
         
             
                  ancestors.each do |ancestor|
         
     | 
| 
      
 343 
     | 
    
         
            +
                    next if inherited_only && ancestor == receiver_name
         
     | 
| 
      
 344 
     | 
    
         
            +
             
     | 
| 
       342 
345 
     | 
    
         
             
                    found = method_entries.filter_map do |entry|
         
     | 
| 
       343 
346 
     | 
    
         
             
                      case entry
         
     | 
| 
       344 
347 
     | 
    
         
             
                      when Entry::Member, Entry::MethodAlias
         
     | 
| 
         @@ -389,7 +392,7 @@ module RubyIndexer 
     | 
|
| 
       389 
392 
     | 
    
         
             
                  # If we don't have an entry for `name`, raise
         
     | 
| 
       390 
393 
     | 
    
         
             
                  entries = self[fully_qualified_name]
         
     | 
| 
       391 
394 
     | 
    
         | 
| 
       392 
     | 
    
         
            -
                  if singleton_levels > 0 && !entries
         
     | 
| 
      
 395 
     | 
    
         
            +
                  if singleton_levels > 0 && !entries && indexed?(attached_class_name)
         
     | 
| 
       393 
396 
     | 
    
         
             
                    entries = [existing_or_new_singleton_class(attached_class_name)]
         
     | 
| 
       394 
397 
     | 
    
         
             
                  end
         
     | 
| 
       395 
398 
     | 
    
         | 
| 
         @@ -15,20 +15,25 @@ module RubyIndexer 
     | 
|
| 
       15 
15 
     | 
    
         
             
                  loader = RBS::EnvironmentLoader.new
         
     | 
| 
       16 
16 
     | 
    
         
             
                  RBS::Environment.from_loader(loader).resolve_type_names
         
     | 
| 
       17 
17 
     | 
    
         | 
| 
       18 
     | 
    
         
            -
                  loader.each_signature do | 
     | 
| 
       19 
     | 
    
         
            -
                    process_signature( 
     | 
| 
      
 18 
     | 
    
         
            +
                  loader.each_signature do |_source, pathname, _buffer, declarations, _directives|
         
     | 
| 
      
 19 
     | 
    
         
            +
                    process_signature(pathname, declarations)
         
     | 
| 
       20 
20 
     | 
    
         
             
                  end
         
     | 
| 
       21 
21 
     | 
    
         
             
                end
         
     | 
| 
       22 
22 
     | 
    
         | 
| 
       23 
     | 
    
         
            -
                 
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
      
 23 
     | 
    
         
            +
                sig do
         
     | 
| 
      
 24 
     | 
    
         
            +
                  params(
         
     | 
| 
      
 25 
     | 
    
         
            +
                    pathname: Pathname,
         
     | 
| 
      
 26 
     | 
    
         
            +
                    declarations: T::Array[RBS::AST::Declarations::Base],
         
     | 
| 
      
 27 
     | 
    
         
            +
                  ).void
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
                def process_signature(pathname, declarations)
         
     | 
| 
       27 
30 
     | 
    
         
             
                  declarations.each do |declaration|
         
     | 
| 
       28 
31 
     | 
    
         
             
                    process_declaration(declaration, pathname)
         
     | 
| 
       29 
32 
     | 
    
         
             
                  end
         
     | 
| 
       30 
33 
     | 
    
         
             
                end
         
     | 
| 
       31 
34 
     | 
    
         | 
| 
      
 35 
     | 
    
         
            +
                private
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
       32 
37 
     | 
    
         
             
                sig { params(declaration: RBS::AST::Declarations::Base, pathname: Pathname).void }
         
     | 
| 
       33 
38 
     | 
    
         
             
                def process_declaration(declaration, pathname)
         
     | 
| 
       34 
39 
     | 
    
         
             
                  case declaration
         
     | 
| 
         @@ -122,7 +127,102 @@ module RubyIndexer 
     | 
|
| 
       122 
127 
     | 
    
         
             
                  end
         
     | 
| 
       123 
128 
     | 
    
         | 
| 
       124 
129 
     | 
    
         
             
                  real_owner = member.singleton? ? @index.existing_or_new_singleton_class(owner.name) : owner
         
     | 
| 
       125 
     | 
    
         
            -
                   
     | 
| 
      
 130 
     | 
    
         
            +
                  signatures = signatures(member)
         
     | 
| 
      
 131 
     | 
    
         
            +
                  @index.add(Entry::Method.new(name, file_path, location, location, comments, signatures, visibility, real_owner))
         
     | 
| 
      
 132 
     | 
    
         
            +
                end
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
                sig { params(member: RBS::AST::Members::MethodDefinition).returns(T::Array[Entry::Signature]) }
         
     | 
| 
      
 135 
     | 
    
         
            +
                def signatures(member)
         
     | 
| 
      
 136 
     | 
    
         
            +
                  member.overloads.map do |overload|
         
     | 
| 
      
 137 
     | 
    
         
            +
                    parameters = process_overload(overload)
         
     | 
| 
      
 138 
     | 
    
         
            +
                    Entry::Signature.new(parameters)
         
     | 
| 
      
 139 
     | 
    
         
            +
                  end
         
     | 
| 
      
 140 
     | 
    
         
            +
                end
         
     | 
| 
      
 141 
     | 
    
         
            +
             
     | 
| 
      
 142 
     | 
    
         
            +
                sig { params(overload: RBS::AST::Members::MethodDefinition::Overload).returns(T::Array[Entry::Parameter]) }
         
     | 
| 
      
 143 
     | 
    
         
            +
                def process_overload(overload)
         
     | 
| 
      
 144 
     | 
    
         
            +
                  function = T.cast(overload.method_type.type, RBS::Types::Function)
         
     | 
| 
      
 145 
     | 
    
         
            +
                  parameters = parse_arguments(function)
         
     | 
| 
      
 146 
     | 
    
         
            +
             
     | 
| 
      
 147 
     | 
    
         
            +
                  block = overload.method_type.block
         
     | 
| 
      
 148 
     | 
    
         
            +
                  parameters << Entry::BlockParameter.anonymous if block&.required
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
                  parameters
         
     | 
| 
      
 151 
     | 
    
         
            +
                end
         
     | 
| 
      
 152 
     | 
    
         
            +
             
     | 
| 
      
 153 
     | 
    
         
            +
                sig { params(function: RBS::Types::Function).returns(T::Array[Entry::Parameter]) }
         
     | 
| 
      
 154 
     | 
    
         
            +
                def parse_arguments(function)
         
     | 
| 
      
 155 
     | 
    
         
            +
                  parameters = []
         
     | 
| 
      
 156 
     | 
    
         
            +
                  parameters.concat(process_required_and_optional_positionals(function))
         
     | 
| 
      
 157 
     | 
    
         
            +
                  parameters.concat(process_trailing_positionals(function)) if function.trailing_positionals
         
     | 
| 
      
 158 
     | 
    
         
            +
                  parameters << process_rest_positionals(function) if function.rest_positionals
         
     | 
| 
      
 159 
     | 
    
         
            +
                  parameters.concat(process_required_keywords(function)) if function.required_keywords
         
     | 
| 
      
 160 
     | 
    
         
            +
                  parameters.concat(process_optional_keywords(function)) if function.optional_keywords
         
     | 
| 
      
 161 
     | 
    
         
            +
                  parameters << process_rest_keywords(function) if function.rest_keywords
         
     | 
| 
      
 162 
     | 
    
         
            +
                  parameters
         
     | 
| 
      
 163 
     | 
    
         
            +
                end
         
     | 
| 
      
 164 
     | 
    
         
            +
             
     | 
| 
      
 165 
     | 
    
         
            +
                sig { params(function: RBS::Types::Function).returns(T::Array[Entry::RequiredParameter]) }
         
     | 
| 
      
 166 
     | 
    
         
            +
                def process_required_and_optional_positionals(function)
         
     | 
| 
      
 167 
     | 
    
         
            +
                  argument_offset = 0
         
     | 
| 
      
 168 
     | 
    
         
            +
             
     | 
| 
      
 169 
     | 
    
         
            +
                  required = function.required_positionals.map.with_index(argument_offset) do |param, i|
         
     | 
| 
      
 170 
     | 
    
         
            +
                    # Some parameters don't have names, e.g.
         
     | 
| 
      
 171 
     | 
    
         
            +
                    #   def self.try_convert: [U] (untyped) -> ::Array[U]?
         
     | 
| 
      
 172 
     | 
    
         
            +
                    name = param.name || :"arg#{i}"
         
     | 
| 
      
 173 
     | 
    
         
            +
                    argument_offset += 1
         
     | 
| 
      
 174 
     | 
    
         
            +
             
     | 
| 
      
 175 
     | 
    
         
            +
                    Entry::RequiredParameter.new(name: name)
         
     | 
| 
      
 176 
     | 
    
         
            +
                  end
         
     | 
| 
      
 177 
     | 
    
         
            +
             
     | 
| 
      
 178 
     | 
    
         
            +
                  optional = function.optional_positionals.map.with_index(argument_offset) do |param, i|
         
     | 
| 
      
 179 
     | 
    
         
            +
                    # Optional positionals may be unnamed, e.g.
         
     | 
| 
      
 180 
     | 
    
         
            +
                    #  def self.polar: (Numeric, ?Numeric) -> Complex
         
     | 
| 
      
 181 
     | 
    
         
            +
                    name = param.name || :"arg#{i}"
         
     | 
| 
      
 182 
     | 
    
         
            +
             
     | 
| 
      
 183 
     | 
    
         
            +
                    Entry::OptionalParameter.new(name: name)
         
     | 
| 
      
 184 
     | 
    
         
            +
                  end
         
     | 
| 
      
 185 
     | 
    
         
            +
             
     | 
| 
      
 186 
     | 
    
         
            +
                  required + optional
         
     | 
| 
      
 187 
     | 
    
         
            +
                end
         
     | 
| 
      
 188 
     | 
    
         
            +
             
     | 
| 
      
 189 
     | 
    
         
            +
                sig { params(function: RBS::Types::Function).returns(T::Array[Entry::OptionalParameter]) }
         
     | 
| 
      
 190 
     | 
    
         
            +
                def process_trailing_positionals(function)
         
     | 
| 
      
 191 
     | 
    
         
            +
                  function.trailing_positionals.map do |param|
         
     | 
| 
      
 192 
     | 
    
         
            +
                    Entry::OptionalParameter.new(name: param.name)
         
     | 
| 
      
 193 
     | 
    
         
            +
                  end
         
     | 
| 
      
 194 
     | 
    
         
            +
                end
         
     | 
| 
      
 195 
     | 
    
         
            +
             
     | 
| 
      
 196 
     | 
    
         
            +
                sig { params(function: RBS::Types::Function).returns(Entry::RestParameter) }
         
     | 
| 
      
 197 
     | 
    
         
            +
                def process_rest_positionals(function)
         
     | 
| 
      
 198 
     | 
    
         
            +
                  rest = function.rest_positionals
         
     | 
| 
      
 199 
     | 
    
         
            +
             
     | 
| 
      
 200 
     | 
    
         
            +
                  rest_name = rest.name || Entry::RestParameter::DEFAULT_NAME
         
     | 
| 
      
 201 
     | 
    
         
            +
             
     | 
| 
      
 202 
     | 
    
         
            +
                  Entry::RestParameter.new(name: rest_name)
         
     | 
| 
      
 203 
     | 
    
         
            +
                end
         
     | 
| 
      
 204 
     | 
    
         
            +
             
     | 
| 
      
 205 
     | 
    
         
            +
                sig { params(function: RBS::Types::Function).returns(T::Array[Entry::KeywordParameter]) }
         
     | 
| 
      
 206 
     | 
    
         
            +
                def process_required_keywords(function)
         
     | 
| 
      
 207 
     | 
    
         
            +
                  function.required_keywords.map do |name, _param|
         
     | 
| 
      
 208 
     | 
    
         
            +
                    Entry::KeywordParameter.new(name: name)
         
     | 
| 
      
 209 
     | 
    
         
            +
                  end
         
     | 
| 
      
 210 
     | 
    
         
            +
                end
         
     | 
| 
      
 211 
     | 
    
         
            +
             
     | 
| 
      
 212 
     | 
    
         
            +
                sig { params(function: RBS::Types::Function).returns(T::Array[Entry::OptionalKeywordParameter]) }
         
     | 
| 
      
 213 
     | 
    
         
            +
                def process_optional_keywords(function)
         
     | 
| 
      
 214 
     | 
    
         
            +
                  function.optional_keywords.map do |name, _param|
         
     | 
| 
      
 215 
     | 
    
         
            +
                    Entry::OptionalKeywordParameter.new(name: name)
         
     | 
| 
      
 216 
     | 
    
         
            +
                  end
         
     | 
| 
      
 217 
     | 
    
         
            +
                end
         
     | 
| 
      
 218 
     | 
    
         
            +
             
     | 
| 
      
 219 
     | 
    
         
            +
                sig { params(function: RBS::Types::Function).returns(Entry::KeywordRestParameter) }
         
     | 
| 
      
 220 
     | 
    
         
            +
                def process_rest_keywords(function)
         
     | 
| 
      
 221 
     | 
    
         
            +
                  param = function.rest_keywords
         
     | 
| 
      
 222 
     | 
    
         
            +
             
     | 
| 
      
 223 
     | 
    
         
            +
                  name = param.name || Entry::KeywordRestParameter::DEFAULT_NAME
         
     | 
| 
      
 224 
     | 
    
         
            +
             
     | 
| 
      
 225 
     | 
    
         
            +
                  Entry::KeywordRestParameter.new(name: name)
         
     | 
| 
       126 
226 
     | 
    
         
             
                end
         
     | 
| 
       127 
227 
     | 
    
         
             
              end
         
     | 
| 
       128 
228 
     | 
    
         
             
            end
         
     | 
| 
         @@ -285,6 +285,43 @@ module RubyIndexer 
     | 
|
| 
       285 
285 
     | 
    
         
             
                  assert_includes(second_entry.comments, "Hello from second `bar`")
         
     | 
| 
       286 
286 
     | 
    
         
             
                end
         
     | 
| 
       287 
287 
     | 
    
         | 
| 
      
 288 
     | 
    
         
            +
                def test_resolve_method_inherited_only
         
     | 
| 
      
 289 
     | 
    
         
            +
                  index(<<~RUBY)
         
     | 
| 
      
 290 
     | 
    
         
            +
                    class Bar
         
     | 
| 
      
 291 
     | 
    
         
            +
                      def baz; end
         
     | 
| 
      
 292 
     | 
    
         
            +
                    end
         
     | 
| 
      
 293 
     | 
    
         
            +
             
     | 
| 
      
 294 
     | 
    
         
            +
                    class Foo < Bar
         
     | 
| 
      
 295 
     | 
    
         
            +
                      def baz; end
         
     | 
| 
      
 296 
     | 
    
         
            +
                    end
         
     | 
| 
      
 297 
     | 
    
         
            +
                  RUBY
         
     | 
| 
      
 298 
     | 
    
         
            +
             
     | 
| 
      
 299 
     | 
    
         
            +
                  entry = T.must(@index.resolve_method("baz", "Foo", inherited_only: true).first)
         
     | 
| 
      
 300 
     | 
    
         
            +
             
     | 
| 
      
 301 
     | 
    
         
            +
                  assert_equal("Bar", T.must(entry.owner).name)
         
     | 
| 
      
 302 
     | 
    
         
            +
                end
         
     | 
| 
      
 303 
     | 
    
         
            +
             
     | 
| 
      
 304 
     | 
    
         
            +
                def test_resolve_method_inherited_only_for_prepended_module
         
     | 
| 
      
 305 
     | 
    
         
            +
                  index(<<~RUBY)
         
     | 
| 
      
 306 
     | 
    
         
            +
                    module Bar
         
     | 
| 
      
 307 
     | 
    
         
            +
                      def baz
         
     | 
| 
      
 308 
     | 
    
         
            +
                        super
         
     | 
| 
      
 309 
     | 
    
         
            +
                      end
         
     | 
| 
      
 310 
     | 
    
         
            +
                    end
         
     | 
| 
      
 311 
     | 
    
         
            +
             
     | 
| 
      
 312 
     | 
    
         
            +
                    class Foo
         
     | 
| 
      
 313 
     | 
    
         
            +
                      prepend Bar
         
     | 
| 
      
 314 
     | 
    
         
            +
             
     | 
| 
      
 315 
     | 
    
         
            +
                      def baz; end
         
     | 
| 
      
 316 
     | 
    
         
            +
                    end
         
     | 
| 
      
 317 
     | 
    
         
            +
                  RUBY
         
     | 
| 
      
 318 
     | 
    
         
            +
             
     | 
| 
      
 319 
     | 
    
         
            +
                  # This test is just to document the fact that we don't yet support resolving inherited methods for modules that
         
     | 
| 
      
 320 
     | 
    
         
            +
                  # are prepended. The only way to support this is to find all namespaces that have the module a subtype, so that we
         
     | 
| 
      
 321 
     | 
    
         
            +
                  # can show the results for everywhere the module has been prepended.
         
     | 
| 
      
 322 
     | 
    
         
            +
                  assert_nil(@index.resolve_method("baz", "Bar", inherited_only: true))
         
     | 
| 
      
 323 
     | 
    
         
            +
                end
         
     | 
| 
      
 324 
     | 
    
         
            +
             
     | 
| 
       288 
325 
     | 
    
         
             
                def test_prefix_search_for_methods
         
     | 
| 
       289 
326 
     | 
    
         
             
                  index(<<~RUBY)
         
     | 
| 
       290 
327 
     | 
    
         
             
                    module Foo
         
     | 
| 
         @@ -1707,5 +1744,11 @@ module RubyIndexer 
     | 
|
| 
       1707 
1744 
     | 
    
         
             
                    @index.linearized_ancestors_of("A::<Class:A>"),
         
     | 
| 
       1708 
1745 
     | 
    
         
             
                  )
         
     | 
| 
       1709 
1746 
     | 
    
         
             
                end
         
     | 
| 
      
 1747 
     | 
    
         
            +
             
     | 
| 
      
 1748 
     | 
    
         
            +
                def test_linearizing_a_singleton_class_with_no_attached
         
     | 
| 
      
 1749 
     | 
    
         
            +
                  assert_raises(Index::NonExistingNamespaceError) do
         
     | 
| 
      
 1750 
     | 
    
         
            +
                    @index.linearized_ancestors_of("A::<Class:A>")
         
     | 
| 
      
 1751 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1752 
     | 
    
         
            +
                end
         
     | 
| 
       1710 
1753 
     | 
    
         
             
              end
         
     | 
| 
       1711 
1754 
     | 
    
         
             
            end
         
     | 
| 
         @@ -123,8 +123,9 @@ module RubyIndexer 
     | 
|
| 
       123 
123 
     | 
    
         | 
| 
       124 
124 
     | 
    
         
             
                  assert_entry("bar", Entry::Method, "/fake/path/foo.rb:1-2:2-5")
         
     | 
| 
       125 
125 
     | 
    
         
             
                  entry = T.must(@index["bar"].first)
         
     | 
| 
       126 
     | 
    
         
            -
                   
     | 
| 
       127 
     | 
    
         
            -
                   
     | 
| 
      
 126 
     | 
    
         
            +
                  parameters = entry.signatures.first.parameters
         
     | 
| 
      
 127 
     | 
    
         
            +
                  assert_equal(1, parameters.length)
         
     | 
| 
      
 128 
     | 
    
         
            +
                  parameter = parameters.first
         
     | 
| 
       128 
129 
     | 
    
         
             
                  assert_equal(:a, parameter.name)
         
     | 
| 
       129 
130 
     | 
    
         
             
                  assert_instance_of(Entry::RequiredParameter, parameter)
         
     | 
| 
       130 
131 
     | 
    
         
             
                end
         
     | 
| 
         @@ -139,8 +140,9 @@ module RubyIndexer 
     | 
|
| 
       139 
140 
     | 
    
         | 
| 
       140 
141 
     | 
    
         
             
                  assert_entry("bar", Entry::Method, "/fake/path/foo.rb:1-2:2-5")
         
     | 
| 
       141 
142 
     | 
    
         
             
                  entry = T.must(@index["bar"].first)
         
     | 
| 
       142 
     | 
    
         
            -
                   
     | 
| 
       143 
     | 
    
         
            -
                   
     | 
| 
      
 143 
     | 
    
         
            +
                  parameters = entry.signatures.first.parameters
         
     | 
| 
      
 144 
     | 
    
         
            +
                  assert_equal(1, parameters.length)
         
     | 
| 
      
 145 
     | 
    
         
            +
                  parameter = parameters.first
         
     | 
| 
       144 
146 
     | 
    
         
             
                  assert_equal(:"(a, (b, ))", parameter.name)
         
     | 
| 
       145 
147 
     | 
    
         
             
                  assert_instance_of(Entry::RequiredParameter, parameter)
         
     | 
| 
       146 
148 
     | 
    
         
             
                end
         
     | 
| 
         @@ -155,8 +157,9 @@ module RubyIndexer 
     | 
|
| 
       155 
157 
     | 
    
         | 
| 
       156 
158 
     | 
    
         
             
                  assert_entry("bar", Entry::Method, "/fake/path/foo.rb:1-2:2-5")
         
     | 
| 
       157 
159 
     | 
    
         
             
                  entry = T.must(@index["bar"].first)
         
     | 
| 
       158 
     | 
    
         
            -
                   
     | 
| 
       159 
     | 
    
         
            -
                   
     | 
| 
      
 160 
     | 
    
         
            +
                  parameters = entry.signatures.first.parameters
         
     | 
| 
      
 161 
     | 
    
         
            +
                  assert_equal(1, parameters.length)
         
     | 
| 
      
 162 
     | 
    
         
            +
                  parameter = parameters.first
         
     | 
| 
       160 
163 
     | 
    
         
             
                  assert_equal(:a, parameter.name)
         
     | 
| 
       161 
164 
     | 
    
         
             
                  assert_instance_of(Entry::OptionalParameter, parameter)
         
     | 
| 
       162 
165 
     | 
    
         
             
                end
         
     | 
| 
         @@ -171,8 +174,9 @@ module RubyIndexer 
     | 
|
| 
       171 
174 
     | 
    
         | 
| 
       172 
175 
     | 
    
         
             
                  assert_entry("bar", Entry::Method, "/fake/path/foo.rb:1-2:2-5")
         
     | 
| 
       173 
176 
     | 
    
         
             
                  entry = T.must(@index["bar"].first)
         
     | 
| 
       174 
     | 
    
         
            -
                   
     | 
| 
       175 
     | 
    
         
            -
                   
     | 
| 
      
 177 
     | 
    
         
            +
                  parameters = entry.signatures.first.parameters
         
     | 
| 
      
 178 
     | 
    
         
            +
                  assert_equal(2, parameters.length)
         
     | 
| 
      
 179 
     | 
    
         
            +
                  a, b = parameters
         
     | 
| 
       176 
180 
     | 
    
         | 
| 
       177 
181 
     | 
    
         
             
                  assert_equal(:a, a.name)
         
     | 
| 
       178 
182 
     | 
    
         
             
                  assert_instance_of(Entry::KeywordParameter, a)
         
     | 
| 
         @@ -191,8 +195,9 @@ module RubyIndexer 
     | 
|
| 
       191 
195 
     | 
    
         | 
| 
       192 
196 
     | 
    
         
             
                  assert_entry("bar", Entry::Method, "/fake/path/foo.rb:1-2:2-5")
         
     | 
| 
       193 
197 
     | 
    
         
             
                  entry = T.must(@index["bar"].first)
         
     | 
| 
       194 
     | 
    
         
            -
                   
     | 
| 
       195 
     | 
    
         
            -
                   
     | 
| 
      
 198 
     | 
    
         
            +
                  parameters = entry.signatures.first.parameters
         
     | 
| 
      
 199 
     | 
    
         
            +
                  assert_equal(2, parameters.length)
         
     | 
| 
      
 200 
     | 
    
         
            +
                  a, b = parameters
         
     | 
| 
       196 
201 
     | 
    
         | 
| 
       197 
202 
     | 
    
         
             
                  assert_equal(:a, a.name)
         
     | 
| 
       198 
203 
     | 
    
         
             
                  assert_instance_of(Entry::RestParameter, a)
         
     | 
| 
         @@ -216,8 +221,9 @@ module RubyIndexer 
     | 
|
| 
       216 
221 
     | 
    
         | 
| 
       217 
222 
     | 
    
         
             
                  assert_entry("bar", Entry::Method, "/fake/path/foo.rb:1-2:2-5")
         
     | 
| 
       218 
223 
     | 
    
         
             
                  entry = T.must(@index["bar"].first)
         
     | 
| 
       219 
     | 
    
         
            -
                   
     | 
| 
       220 
     | 
    
         
            -
                   
     | 
| 
      
 224 
     | 
    
         
            +
                  parameters = entry.signatures.first.parameters
         
     | 
| 
      
 225 
     | 
    
         
            +
                  assert_equal(2, parameters.length)
         
     | 
| 
      
 226 
     | 
    
         
            +
                  a, b = parameters
         
     | 
| 
       221 
227 
     | 
    
         | 
| 
       222 
228 
     | 
    
         
             
                  assert_equal(:a, a.name)
         
     | 
| 
       223 
229 
     | 
    
         
             
                  assert_instance_of(Entry::RestParameter, a)
         
     | 
| 
         @@ -226,8 +232,9 @@ module RubyIndexer 
     | 
|
| 
       226 
232 
     | 
    
         
             
                  assert_instance_of(Entry::RequiredParameter, b)
         
     | 
| 
       227 
233 
     | 
    
         | 
| 
       228 
234 
     | 
    
         
             
                  entry = T.must(@index["baz"].first)
         
     | 
| 
       229 
     | 
    
         
            -
                   
     | 
| 
       230 
     | 
    
         
            -
                   
     | 
| 
      
 235 
     | 
    
         
            +
                  parameters = entry.signatures.first.parameters
         
     | 
| 
      
 236 
     | 
    
         
            +
                  assert_equal(2, parameters.length)
         
     | 
| 
      
 237 
     | 
    
         
            +
                  a, b = parameters
         
     | 
| 
       231 
238 
     | 
    
         | 
| 
       232 
239 
     | 
    
         
             
                  assert_equal(:a, a.name)
         
     | 
| 
       233 
240 
     | 
    
         
             
                  assert_instance_of(Entry::KeywordRestParameter, a)
         
     | 
| 
         @@ -236,8 +243,9 @@ module RubyIndexer 
     | 
|
| 
       236 
243 
     | 
    
         
             
                  assert_instance_of(Entry::RequiredParameter, b)
         
     | 
| 
       237 
244 
     | 
    
         | 
| 
       238 
245 
     | 
    
         
             
                  entry = T.must(@index["qux"].first)
         
     | 
| 
       239 
     | 
    
         
            -
                   
     | 
| 
       240 
     | 
    
         
            -
                   
     | 
| 
      
 246 
     | 
    
         
            +
                  parameters = entry.signatures.first.parameters
         
     | 
| 
      
 247 
     | 
    
         
            +
                  assert_equal(2, parameters.length)
         
     | 
| 
      
 248 
     | 
    
         
            +
                  _a, second = parameters
         
     | 
| 
       241 
249 
     | 
    
         | 
| 
       242 
250 
     | 
    
         
             
                  assert_equal(:"(b, c)", second.name)
         
     | 
| 
       243 
251 
     | 
    
         
             
                  assert_instance_of(Entry::RequiredParameter, second)
         
     | 
| 
         @@ -253,8 +261,9 @@ module RubyIndexer 
     | 
|
| 
       253 
261 
     | 
    
         | 
| 
       254 
262 
     | 
    
         
             
                  assert_entry("bar", Entry::Method, "/fake/path/foo.rb:1-2:2-5")
         
     | 
| 
       255 
263 
     | 
    
         
             
                  entry = T.must(@index["bar"].first)
         
     | 
| 
       256 
     | 
    
         
            -
                   
     | 
| 
       257 
     | 
    
         
            -
                   
     | 
| 
      
 264 
     | 
    
         
            +
                  parameters = entry.signatures.first.parameters
         
     | 
| 
      
 265 
     | 
    
         
            +
                  assert_equal(1, parameters.length)
         
     | 
| 
      
 266 
     | 
    
         
            +
                  param = parameters.first
         
     | 
| 
       258 
267 
     | 
    
         | 
| 
       259 
268 
     | 
    
         
             
                  assert_equal(:"(a, *b)", param.name)
         
     | 
| 
       260 
269 
     | 
    
         
             
                  assert_instance_of(Entry::RequiredParameter, param)
         
     | 
| 
         @@ -272,14 +281,16 @@ module RubyIndexer 
     | 
|
| 
       272 
281 
     | 
    
         
             
                  RUBY
         
     | 
| 
       273 
282 
     | 
    
         | 
| 
       274 
283 
     | 
    
         
             
                  entry = T.must(@index["bar"].first)
         
     | 
| 
       275 
     | 
    
         
            -
                   
     | 
| 
      
 284 
     | 
    
         
            +
                  parameters = entry.signatures.first.parameters
         
     | 
| 
      
 285 
     | 
    
         
            +
                  param = parameters.first
         
     | 
| 
       276 
286 
     | 
    
         
             
                  assert_equal(:block, param.name)
         
     | 
| 
       277 
287 
     | 
    
         
             
                  assert_instance_of(Entry::BlockParameter, param)
         
     | 
| 
       278 
288 
     | 
    
         | 
| 
       279 
289 
     | 
    
         
             
                  entry = T.must(@index["baz"].first)
         
     | 
| 
       280 
     | 
    
         
            -
                   
     | 
| 
      
 290 
     | 
    
         
            +
                  parameters = entry.signatures.first.parameters
         
     | 
| 
      
 291 
     | 
    
         
            +
                  assert_equal(1, parameters.length)
         
     | 
| 
       281 
292 
     | 
    
         | 
| 
       282 
     | 
    
         
            -
                  param =  
     | 
| 
      
 293 
     | 
    
         
            +
                  param = parameters.first
         
     | 
| 
       283 
294 
     | 
    
         
             
                  assert_equal(Entry::BlockParameter::DEFAULT_NAME, param.name)
         
     | 
| 
       284 
295 
     | 
    
         
             
                  assert_instance_of(Entry::BlockParameter, param)
         
     | 
| 
       285 
296 
     | 
    
         
             
                end
         
     | 
| 
         @@ -294,8 +305,9 @@ module RubyIndexer 
     | 
|
| 
       294 
305 
     | 
    
         | 
| 
       295 
306 
     | 
    
         
             
                  assert_entry("bar", Entry::Method, "/fake/path/foo.rb:1-2:2-5")
         
     | 
| 
       296 
307 
     | 
    
         
             
                  entry = T.must(@index["bar"].first)
         
     | 
| 
       297 
     | 
    
         
            -
                   
     | 
| 
       298 
     | 
    
         
            -
                   
     | 
| 
      
 308 
     | 
    
         
            +
                  parameters = entry.signatures.first.parameters
         
     | 
| 
      
 309 
     | 
    
         
            +
                  assert_equal(2, parameters.length)
         
     | 
| 
      
 310 
     | 
    
         
            +
                  first, second = parameters
         
     | 
| 
       299 
311 
     | 
    
         | 
| 
       300 
312 
     | 
    
         
             
                  assert_equal(Entry::RestParameter::DEFAULT_NAME, first.name)
         
     | 
| 
       301 
313 
     | 
    
         
             
                  assert_instance_of(Entry::RestParameter, first)
         
     | 
| 
         @@ -314,7 +326,8 @@ module RubyIndexer 
     | 
|
| 
       314 
326 
     | 
    
         | 
| 
       315 
327 
     | 
    
         
             
                  assert_entry("bar", Entry::Method, "/fake/path/foo.rb:1-2:2-5")
         
     | 
| 
       316 
328 
     | 
    
         
             
                  entry = T.must(@index["bar"].first)
         
     | 
| 
       317 
     | 
    
         
            -
                   
     | 
| 
      
 329 
     | 
    
         
            +
                  parameters = entry.signatures.first.parameters
         
     | 
| 
      
 330 
     | 
    
         
            +
                  assert_empty(parameters)
         
     | 
| 
       318 
331 
     | 
    
         
             
                end
         
     | 
| 
       319 
332 
     | 
    
         | 
| 
       320 
333 
     | 
    
         
             
                def test_keeps_track_of_method_owner
         
     | 
| 
         @@ -74,5 +74,253 @@ module RubyIndexer 
     | 
|
| 
       74 
74 
     | 
    
         | 
| 
       75 
75 
     | 
    
         
             
                  assert_same(entry.location, entry.name_location)
         
     | 
| 
       76 
76 
     | 
    
         
             
                end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
                def test_rbs_method_with_required_positionals
         
     | 
| 
      
 79 
     | 
    
         
            +
                  entries = @index["crypt"]
         
     | 
| 
      
 80 
     | 
    
         
            +
                  assert_equal(1, entries.length)
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                  entry = entries.first
         
     | 
| 
      
 83 
     | 
    
         
            +
                  signatures = entry.signatures
         
     | 
| 
      
 84 
     | 
    
         
            +
                  assert_equal(1, signatures.length)
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                  first_signature = signatures.first
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                  # (::string salt_str) -> ::String
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
                  assert_equal(1, first_signature.parameters.length)
         
     | 
| 
      
 91 
     | 
    
         
            +
                  assert_kind_of(Entry::RequiredParameter, first_signature.parameters[0])
         
     | 
| 
      
 92 
     | 
    
         
            +
                  assert_equal(:salt_str, first_signature.parameters[0].name)
         
     | 
| 
      
 93 
     | 
    
         
            +
                end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                def test_rbs_method_with_unnamed_required_positionals
         
     | 
| 
      
 96 
     | 
    
         
            +
                  entries = @index["try_convert"]
         
     | 
| 
      
 97 
     | 
    
         
            +
                  entry = entries.find { |entry| entry.owner.name == "Array::<Class:Array>" }
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                  parameters = entry.signatures[0].parameters
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                  assert_equal([:arg0], parameters.map(&:name))
         
     | 
| 
      
 102 
     | 
    
         
            +
                  assert_kind_of(Entry::RequiredParameter, parameters[0])
         
     | 
| 
      
 103 
     | 
    
         
            +
                end
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                def test_rbs_method_with_optional_positionals
         
     | 
| 
      
 106 
     | 
    
         
            +
                  entries = @index["polar"]
         
     | 
| 
      
 107 
     | 
    
         
            +
                  entry = entries.find { |entry| entry.owner.name == "Complex::<Class:Complex>" }
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                  # def self.polar: (Numeric, ?Numeric) -> Complex
         
     | 
| 
      
 110 
     | 
    
         
            +
             
     | 
| 
      
 111 
     | 
    
         
            +
                  parameters = entry.signatures[0].parameters
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
                  assert_equal([:arg0, :arg1], parameters.map(&:name))
         
     | 
| 
      
 114 
     | 
    
         
            +
                  assert_kind_of(Entry::RequiredParameter, parameters[0])
         
     | 
| 
      
 115 
     | 
    
         
            +
                  assert_kind_of(Entry::OptionalParameter, parameters[1])
         
     | 
| 
      
 116 
     | 
    
         
            +
                end
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
                def test_rbs_method_with_optional_parameter
         
     | 
| 
      
 119 
     | 
    
         
            +
                  entries = @index["chomp"]
         
     | 
| 
      
 120 
     | 
    
         
            +
                  assert_equal(1, entries.length)
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                  entry = entries.first
         
     | 
| 
      
 123 
     | 
    
         
            +
                  signatures = entry.signatures
         
     | 
| 
      
 124 
     | 
    
         
            +
                  assert_equal(1, signatures.length)
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
                  first_signature = signatures.first
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
                  # (?::string? separator) -> ::String
         
     | 
| 
      
 129 
     | 
    
         
            +
             
     | 
| 
      
 130 
     | 
    
         
            +
                  assert_equal(1, first_signature.parameters.length)
         
     | 
| 
      
 131 
     | 
    
         
            +
                  assert_kind_of(Entry::OptionalParameter, first_signature.parameters[0])
         
     | 
| 
      
 132 
     | 
    
         
            +
                  assert_equal(:separator, first_signature.parameters[0].name)
         
     | 
| 
      
 133 
     | 
    
         
            +
                end
         
     | 
| 
      
 134 
     | 
    
         
            +
             
     | 
| 
      
 135 
     | 
    
         
            +
                def test_rbs_method_with_required_and_optional_parameters
         
     | 
| 
      
 136 
     | 
    
         
            +
                  entries = @index["gsub"]
         
     | 
| 
      
 137 
     | 
    
         
            +
                  assert_equal(1, entries.length)
         
     | 
| 
      
 138 
     | 
    
         
            +
             
     | 
| 
      
 139 
     | 
    
         
            +
                  entry = entries.first
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
                  signatures = entry.signatures
         
     | 
| 
      
 142 
     | 
    
         
            +
                  assert_equal(3, signatures.length)
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
                  # (::Regexp | ::string pattern, ::string | ::hash[::String, ::_ToS] replacement) -> ::String
         
     | 
| 
      
 145 
     | 
    
         
            +
                  # | (::Regexp | ::string pattern) -> ::Enumerator[::String, ::String]
         
     | 
| 
      
 146 
     | 
    
         
            +
                  # | (::Regexp | ::string pattern) { (::String match) -> ::_ToS } -> ::String
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
                  parameters = signatures[0].parameters
         
     | 
| 
      
 149 
     | 
    
         
            +
                  assert_equal([:pattern, :replacement], parameters.map(&:name))
         
     | 
| 
      
 150 
     | 
    
         
            +
                  assert_kind_of(Entry::RequiredParameter, parameters[0])
         
     | 
| 
      
 151 
     | 
    
         
            +
                  assert_kind_of(Entry::RequiredParameter, parameters[1])
         
     | 
| 
      
 152 
     | 
    
         
            +
             
     | 
| 
      
 153 
     | 
    
         
            +
                  parameters = signatures[1].parameters
         
     | 
| 
      
 154 
     | 
    
         
            +
                  assert_equal([:pattern], parameters.map(&:name))
         
     | 
| 
      
 155 
     | 
    
         
            +
                  assert_kind_of(Entry::RequiredParameter, parameters[0])
         
     | 
| 
      
 156 
     | 
    
         
            +
             
     | 
| 
      
 157 
     | 
    
         
            +
                  parameters = signatures[2].parameters
         
     | 
| 
      
 158 
     | 
    
         
            +
                  assert_equal([:pattern, :"<anonymous block>"], parameters.map(&:name))
         
     | 
| 
      
 159 
     | 
    
         
            +
                  assert_kind_of(Entry::RequiredParameter, parameters[0])
         
     | 
| 
      
 160 
     | 
    
         
            +
                  assert_kind_of(Entry::BlockParameter, parameters[1])
         
     | 
| 
      
 161 
     | 
    
         
            +
                end
         
     | 
| 
      
 162 
     | 
    
         
            +
             
     | 
| 
      
 163 
     | 
    
         
            +
                def test_rbs_anonymous_block_parameter
         
     | 
| 
      
 164 
     | 
    
         
            +
                  entries = @index["open"]
         
     | 
| 
      
 165 
     | 
    
         
            +
                  entry = entries.find { |entry| entry.owner.name == "File::<Class:File>" }
         
     | 
| 
      
 166 
     | 
    
         
            +
             
     | 
| 
      
 167 
     | 
    
         
            +
                  assert_equal(2, entry.signatures.length)
         
     | 
| 
      
 168 
     | 
    
         
            +
             
     | 
| 
      
 169 
     | 
    
         
            +
                  # (::String name, ?::String mode, ?::Integer perm) -> ::IO?
         
     | 
| 
      
 170 
     | 
    
         
            +
                  # | [T] (::String name, ?::String mode, ?::Integer perm) { (::IO) -> T } -> T
         
     | 
| 
      
 171 
     | 
    
         
            +
             
     | 
| 
      
 172 
     | 
    
         
            +
                  parameters = entry.signatures[0].parameters
         
     | 
| 
      
 173 
     | 
    
         
            +
                  assert_equal([:file_name, :mode, :perm], parameters.map(&:name))
         
     | 
| 
      
 174 
     | 
    
         
            +
                  assert_kind_of(Entry::RequiredParameter, parameters[0])
         
     | 
| 
      
 175 
     | 
    
         
            +
                  assert_kind_of(Entry::OptionalParameter, parameters[1])
         
     | 
| 
      
 176 
     | 
    
         
            +
                  assert_kind_of(Entry::OptionalParameter, parameters[2])
         
     | 
| 
      
 177 
     | 
    
         
            +
             
     | 
| 
      
 178 
     | 
    
         
            +
                  parameters = entry.signatures[1].parameters
         
     | 
| 
      
 179 
     | 
    
         
            +
                  assert_equal([:file_name, :mode, :perm, :"<anonymous block>"], parameters.map(&:name))
         
     | 
| 
      
 180 
     | 
    
         
            +
                  assert_kind_of(Entry::RequiredParameter, parameters[0])
         
     | 
| 
      
 181 
     | 
    
         
            +
                  assert_kind_of(Entry::OptionalParameter, parameters[1])
         
     | 
| 
      
 182 
     | 
    
         
            +
                  assert_kind_of(Entry::OptionalParameter, parameters[2])
         
     | 
| 
      
 183 
     | 
    
         
            +
                  assert_kind_of(Entry::BlockParameter, parameters[3])
         
     | 
| 
      
 184 
     | 
    
         
            +
                end
         
     | 
| 
      
 185 
     | 
    
         
            +
             
     | 
| 
      
 186 
     | 
    
         
            +
                def test_rbs_method_with_rest_positionals
         
     | 
| 
      
 187 
     | 
    
         
            +
                  entries = @index["count"]
         
     | 
| 
      
 188 
     | 
    
         
            +
                  entry = entries.find { |entry| entry.owner.name == "String" }
         
     | 
| 
      
 189 
     | 
    
         
            +
             
     | 
| 
      
 190 
     | 
    
         
            +
                  parameters = entry.signatures.first.parameters
         
     | 
| 
      
 191 
     | 
    
         
            +
                  assert_equal(1, entry.signatures.length)
         
     | 
| 
      
 192 
     | 
    
         
            +
             
     | 
| 
      
 193 
     | 
    
         
            +
                  # (::String::selector selector_0, *::String::selector more_selectors) -> ::Integer
         
     | 
| 
      
 194 
     | 
    
         
            +
             
     | 
| 
      
 195 
     | 
    
         
            +
                  assert_equal([:selector_0, :more_selectors], parameters.map(&:name))
         
     | 
| 
      
 196 
     | 
    
         
            +
                  assert_kind_of(RubyIndexer::Entry::RequiredParameter, parameters[0])
         
     | 
| 
      
 197 
     | 
    
         
            +
                  assert_kind_of(RubyIndexer::Entry::RestParameter, parameters[1])
         
     | 
| 
      
 198 
     | 
    
         
            +
                end
         
     | 
| 
      
 199 
     | 
    
         
            +
             
     | 
| 
      
 200 
     | 
    
         
            +
                def test_rbs_method_with_trailing_positionals
         
     | 
| 
      
 201 
     | 
    
         
            +
                  entries = @index["select"] # https://ruby-doc.org/3.3.3/IO.html#method-c-select
         
     | 
| 
      
 202 
     | 
    
         
            +
                  entry = entries.find { |entry| entry.owner.name == "IO::<Class:IO>" }
         
     | 
| 
      
 203 
     | 
    
         
            +
             
     | 
| 
      
 204 
     | 
    
         
            +
                  signatures = entry.signatures
         
     | 
| 
      
 205 
     | 
    
         
            +
                  assert_equal(2, signatures.length)
         
     | 
| 
      
 206 
     | 
    
         
            +
             
     | 
| 
      
 207 
     | 
    
         
            +
                  # def self.select: [X, Y, Z] (::Array[X & io]? read_array, ?::Array[Y & io]? write_array, ?::Array[Z & io]? error_array) -> [ Array[X], Array[Y], Array[Z] ] # rubocop:disable Layout/LineLength
         
     | 
| 
      
 208 
     | 
    
         
            +
                  #   | [X, Y, Z] (::Array[X & io]? read_array, ?::Array[Y & io]? write_array, ?::Array[Z & io]? error_array, Time::_Timeout? timeout) -> [ Array[X], Array[Y], Array[Z] ]? # rubocop:disable Layout/LineLength
         
     | 
| 
      
 209 
     | 
    
         
            +
             
     | 
| 
      
 210 
     | 
    
         
            +
                  parameters = signatures[0].parameters
         
     | 
| 
      
 211 
     | 
    
         
            +
                  assert_equal([:read_array, :write_array, :error_array], parameters.map(&:name))
         
     | 
| 
      
 212 
     | 
    
         
            +
                  assert_kind_of(Entry::RequiredParameter, parameters[0])
         
     | 
| 
      
 213 
     | 
    
         
            +
                  assert_kind_of(Entry::OptionalParameter, parameters[1])
         
     | 
| 
      
 214 
     | 
    
         
            +
                  assert_kind_of(Entry::OptionalParameter, parameters[2])
         
     | 
| 
      
 215 
     | 
    
         
            +
             
     | 
| 
      
 216 
     | 
    
         
            +
                  parameters = signatures[1].parameters
         
     | 
| 
      
 217 
     | 
    
         
            +
                  assert_equal([:read_array, :write_array, :error_array, :timeout], parameters.map(&:name))
         
     | 
| 
      
 218 
     | 
    
         
            +
                  assert_kind_of(Entry::RequiredParameter, parameters[0])
         
     | 
| 
      
 219 
     | 
    
         
            +
                  assert_kind_of(Entry::OptionalParameter, parameters[1])
         
     | 
| 
      
 220 
     | 
    
         
            +
                  assert_kind_of(Entry::OptionalParameter, parameters[2])
         
     | 
| 
      
 221 
     | 
    
         
            +
                  assert_kind_of(Entry::OptionalParameter, parameters[3])
         
     | 
| 
      
 222 
     | 
    
         
            +
                end
         
     | 
| 
      
 223 
     | 
    
         
            +
             
     | 
| 
      
 224 
     | 
    
         
            +
                def test_rbs_method_with_optional_keywords
         
     | 
| 
      
 225 
     | 
    
         
            +
                  entries = @index["step"]
         
     | 
| 
      
 226 
     | 
    
         
            +
                  entry = entries.find { |entry| entry.owner.name == "Numeric" }
         
     | 
| 
      
 227 
     | 
    
         
            +
             
     | 
| 
      
 228 
     | 
    
         
            +
                  signatures = entry.signatures
         
     | 
| 
      
 229 
     | 
    
         
            +
                  assert_equal(4, signatures.length)
         
     | 
| 
      
 230 
     | 
    
         
            +
             
     | 
| 
      
 231 
     | 
    
         
            +
                  # (?::Numeric limit, ?::Numeric step) { (::Numeric) -> void } -> self
         
     | 
| 
      
 232 
     | 
    
         
            +
                  # | (?::Numeric limit, ?::Numeric step) -> ::Enumerator[::Numeric, self]
         
     | 
| 
      
 233 
     | 
    
         
            +
                  # | (?by: ::Numeric, ?to: ::Numeric) { (::Numeric) -> void } -> self
         
     | 
| 
      
 234 
     | 
    
         
            +
                  # | (?by: ::Numeric, ?to: ::Numeric) -> ::Enumerator[::Numeric, self]
         
     | 
| 
      
 235 
     | 
    
         
            +
             
     | 
| 
      
 236 
     | 
    
         
            +
                  parameters = signatures[0].parameters
         
     | 
| 
      
 237 
     | 
    
         
            +
                  assert_equal([:limit, :step, :"<anonymous block>"], parameters.map(&:name))
         
     | 
| 
      
 238 
     | 
    
         
            +
                  assert_kind_of(Entry::OptionalParameter, parameters[0])
         
     | 
| 
      
 239 
     | 
    
         
            +
                  assert_kind_of(Entry::OptionalParameter, parameters[1])
         
     | 
| 
      
 240 
     | 
    
         
            +
                  assert_kind_of(Entry::BlockParameter, parameters[2])
         
     | 
| 
      
 241 
     | 
    
         
            +
             
     | 
| 
      
 242 
     | 
    
         
            +
                  parameters = signatures[1].parameters
         
     | 
| 
      
 243 
     | 
    
         
            +
                  assert_equal([:limit, :step], parameters.map(&:name))
         
     | 
| 
      
 244 
     | 
    
         
            +
                  assert_kind_of(Entry::OptionalParameter, parameters[0])
         
     | 
| 
      
 245 
     | 
    
         
            +
                  assert_kind_of(Entry::OptionalParameter, parameters[1])
         
     | 
| 
      
 246 
     | 
    
         
            +
             
     | 
| 
      
 247 
     | 
    
         
            +
                  parameters = signatures[2].parameters
         
     | 
| 
      
 248 
     | 
    
         
            +
                  assert_equal([:by, :to, :"<anonymous block>"], parameters.map(&:name))
         
     | 
| 
      
 249 
     | 
    
         
            +
                  assert_kind_of(Entry::OptionalKeywordParameter, parameters[0])
         
     | 
| 
      
 250 
     | 
    
         
            +
                  assert_kind_of(Entry::OptionalKeywordParameter, parameters[1])
         
     | 
| 
      
 251 
     | 
    
         
            +
                  assert_kind_of(Entry::BlockParameter, parameters[2])
         
     | 
| 
      
 252 
     | 
    
         
            +
             
     | 
| 
      
 253 
     | 
    
         
            +
                  parameters = signatures[3].parameters
         
     | 
| 
      
 254 
     | 
    
         
            +
                  assert_equal([:by, :to], parameters.map(&:name))
         
     | 
| 
      
 255 
     | 
    
         
            +
                  assert_kind_of(Entry::OptionalKeywordParameter, parameters[0])
         
     | 
| 
      
 256 
     | 
    
         
            +
                  assert_kind_of(Entry::OptionalKeywordParameter, parameters[1])
         
     | 
| 
      
 257 
     | 
    
         
            +
                end
         
     | 
| 
      
 258 
     | 
    
         
            +
             
     | 
| 
      
 259 
     | 
    
         
            +
                def test_rbs_method_with_required_keywords
         
     | 
| 
      
 260 
     | 
    
         
            +
                  # There are no methods in Core that have required keyword arguments,
         
     | 
| 
      
 261 
     | 
    
         
            +
                  # so we test against RBS directly
         
     | 
| 
      
 262 
     | 
    
         
            +
             
     | 
| 
      
 263 
     | 
    
         
            +
                  rbs = <<~RBS
         
     | 
| 
      
 264 
     | 
    
         
            +
                    class File
         
     | 
| 
      
 265 
     | 
    
         
            +
                      def foo: (a: ::Numeric sz, b: ::Numeric) -> void
         
     | 
| 
      
 266 
     | 
    
         
            +
                    end
         
     | 
| 
      
 267 
     | 
    
         
            +
                  RBS
         
     | 
| 
      
 268 
     | 
    
         
            +
                  signatures = parse_rbs_methods(rbs, "foo")
         
     | 
| 
      
 269 
     | 
    
         
            +
                  parameters = signatures[0].parameters
         
     | 
| 
      
 270 
     | 
    
         
            +
                  assert_equal([:a, :b], parameters.map(&:name))
         
     | 
| 
      
 271 
     | 
    
         
            +
                  assert_kind_of(Entry::KeywordParameter, parameters[0])
         
     | 
| 
      
 272 
     | 
    
         
            +
                  assert_kind_of(Entry::KeywordParameter, parameters[1])
         
     | 
| 
      
 273 
     | 
    
         
            +
                end
         
     | 
| 
      
 274 
     | 
    
         
            +
             
     | 
| 
      
 275 
     | 
    
         
            +
                def test_rbs_method_with_rest_keywords
         
     | 
| 
      
 276 
     | 
    
         
            +
                  entries = @index["method_missing"]
         
     | 
| 
      
 277 
     | 
    
         
            +
                  entry = entries.find { |entry| entry.owner.name == "BasicObject" }
         
     | 
| 
      
 278 
     | 
    
         
            +
                  signatures = entry.signatures
         
     | 
| 
      
 279 
     | 
    
         
            +
                  assert_equal(1, signatures.length)
         
     | 
| 
      
 280 
     | 
    
         
            +
             
     | 
| 
      
 281 
     | 
    
         
            +
                  # (Symbol, *untyped, **untyped) ?{ (*untyped, **untyped) -> untyped } -> untyped
         
     | 
| 
      
 282 
     | 
    
         
            +
             
     | 
| 
      
 283 
     | 
    
         
            +
                  parameters = signatures[0].parameters
         
     | 
| 
      
 284 
     | 
    
         
            +
                  assert_equal([:arg0, :"<anonymous splat>", :"<anonymous keyword splat>"], parameters.map(&:name))
         
     | 
| 
      
 285 
     | 
    
         
            +
                  assert_kind_of(Entry::RequiredParameter, parameters[0])
         
     | 
| 
      
 286 
     | 
    
         
            +
                  assert_kind_of(Entry::RestParameter, parameters[1])
         
     | 
| 
      
 287 
     | 
    
         
            +
                  assert_kind_of(Entry::KeywordRestParameter, parameters[2])
         
     | 
| 
      
 288 
     | 
    
         
            +
                end
         
     | 
| 
      
 289 
     | 
    
         
            +
             
     | 
| 
      
 290 
     | 
    
         
            +
                def test_parse_simple_rbs
         
     | 
| 
      
 291 
     | 
    
         
            +
                  rbs = <<~RBS
         
     | 
| 
      
 292 
     | 
    
         
            +
                    class File
         
     | 
| 
      
 293 
     | 
    
         
            +
                      def self?.open: (String name, ?String mode, ?Integer perm) -> IO?
         
     | 
| 
      
 294 
     | 
    
         
            +
                          | [T] (String name, ?String mode, ?Integer perm) { (IO) -> T } -> T
         
     | 
| 
      
 295 
     | 
    
         
            +
                    end
         
     | 
| 
      
 296 
     | 
    
         
            +
                  RBS
         
     | 
| 
      
 297 
     | 
    
         
            +
                  signatures = parse_rbs_methods(rbs, "open")
         
     | 
| 
      
 298 
     | 
    
         
            +
                  assert_equal(2, signatures.length)
         
     | 
| 
      
 299 
     | 
    
         
            +
                  parameters = signatures[0].parameters
         
     | 
| 
      
 300 
     | 
    
         
            +
                  assert_equal([:name, :mode, :perm], parameters.map(&:name))
         
     | 
| 
      
 301 
     | 
    
         
            +
                  assert_kind_of(Entry::RequiredParameter, parameters[0])
         
     | 
| 
      
 302 
     | 
    
         
            +
                  assert_kind_of(Entry::OptionalParameter, parameters[1])
         
     | 
| 
      
 303 
     | 
    
         
            +
                  assert_kind_of(Entry::OptionalParameter, parameters[2])
         
     | 
| 
      
 304 
     | 
    
         
            +
             
     | 
| 
      
 305 
     | 
    
         
            +
                  parameters = signatures[1].parameters
         
     | 
| 
      
 306 
     | 
    
         
            +
                  assert_equal([:name, :mode, :perm, :"<anonymous block>"], parameters.map(&:name))
         
     | 
| 
      
 307 
     | 
    
         
            +
                  assert_kind_of(Entry::RequiredParameter, parameters[0])
         
     | 
| 
      
 308 
     | 
    
         
            +
                  assert_kind_of(Entry::OptionalParameter, parameters[1])
         
     | 
| 
      
 309 
     | 
    
         
            +
                  assert_kind_of(Entry::OptionalParameter, parameters[2])
         
     | 
| 
      
 310 
     | 
    
         
            +
                  assert_kind_of(Entry::BlockParameter, parameters[3])
         
     | 
| 
      
 311 
     | 
    
         
            +
                end
         
     | 
| 
      
 312 
     | 
    
         
            +
             
     | 
| 
      
 313 
     | 
    
         
            +
                private
         
     | 
| 
      
 314 
     | 
    
         
            +
             
     | 
| 
      
 315 
     | 
    
         
            +
                def parse_rbs_methods(rbs, method_name)
         
     | 
| 
      
 316 
     | 
    
         
            +
                  buffer = RBS::Buffer.new(content: rbs, name: "")
         
     | 
| 
      
 317 
     | 
    
         
            +
                  _, _, declarations = RBS::Parser.parse_signature(buffer)
         
     | 
| 
      
 318 
     | 
    
         
            +
                  index = RubyIndexer::Index.new
         
     | 
| 
      
 319 
     | 
    
         
            +
                  indexer = RubyIndexer::RBSIndexer.new(index)
         
     | 
| 
      
 320 
     | 
    
         
            +
                  pathname = Pathname.new("file.rbs")
         
     | 
| 
      
 321 
     | 
    
         
            +
                  indexer.process_signature(pathname, declarations)
         
     | 
| 
      
 322 
     | 
    
         
            +
                  entry = T.must(index[method_name]).first
         
     | 
| 
      
 323 
     | 
    
         
            +
                  T.cast(entry, Entry::Method).signatures
         
     | 
| 
      
 324 
     | 
    
         
            +
                end
         
     | 
| 
       77 
325 
     | 
    
         
             
              end
         
     | 
| 
       78 
326 
     | 
    
         
             
            end
         
     | 
    
        data/lib/ruby_lsp/document.rb
    CHANGED
    
    | 
         @@ -127,8 +127,18 @@ module RubyLsp 
     | 
|
| 
       127 
127 
     | 
    
         
             
                  parent = T.let(nil, T.nilable(Prism::Node))
         
     | 
| 
       128 
128 
     | 
    
         
             
                  nesting_nodes = T.let(
         
     | 
| 
       129 
129 
     | 
    
         
             
                    [],
         
     | 
| 
       130 
     | 
    
         
            -
                    T::Array[T.any( 
     | 
| 
      
 130 
     | 
    
         
            +
                    T::Array[T.any(
         
     | 
| 
      
 131 
     | 
    
         
            +
                      Prism::ClassNode,
         
     | 
| 
      
 132 
     | 
    
         
            +
                      Prism::ModuleNode,
         
     | 
| 
      
 133 
     | 
    
         
            +
                      Prism::SingletonClassNode,
         
     | 
| 
      
 134 
     | 
    
         
            +
                      Prism::DefNode,
         
     | 
| 
      
 135 
     | 
    
         
            +
                      Prism::BlockNode,
         
     | 
| 
      
 136 
     | 
    
         
            +
                      Prism::LambdaNode,
         
     | 
| 
      
 137 
     | 
    
         
            +
                      Prism::ProgramNode,
         
     | 
| 
      
 138 
     | 
    
         
            +
                    )],
         
     | 
| 
       131 
139 
     | 
    
         
             
                  )
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
                  nesting_nodes << node if node.is_a?(Prism::ProgramNode)
         
     | 
| 
       132 
142 
     | 
    
         
             
                  call_node = T.let(nil, T.nilable(Prism::CallNode))
         
     | 
| 
       133 
143 
     | 
    
         | 
| 
       134 
144 
     | 
    
         
             
                  until queue.empty?
         
     | 
| 
         @@ -158,11 +168,8 @@ module RubyLsp 
     | 
|
| 
       158 
168 
     | 
    
         
             
                    # Keep track of the nesting where we found the target. This is used to determine the fully qualified name of the
         
     | 
| 
       159 
169 
     | 
    
         
             
                    # target when it is a constant
         
     | 
| 
       160 
170 
     | 
    
         
             
                    case candidate
         
     | 
| 
       161 
     | 
    
         
            -
                    when Prism::ClassNode, Prism::ModuleNode
         
     | 
| 
       162 
     | 
    
         
            -
                       
     | 
| 
       163 
     | 
    
         
            -
                    when Prism::SingletonClassNode
         
     | 
| 
       164 
     | 
    
         
            -
                      nesting_nodes << candidate
         
     | 
| 
       165 
     | 
    
         
            -
                    when Prism::DefNode
         
     | 
| 
      
 171 
     | 
    
         
            +
                    when Prism::ClassNode, Prism::ModuleNode, Prism::SingletonClassNode, Prism::DefNode, Prism::BlockNode,
         
     | 
| 
      
 172 
     | 
    
         
            +
                      Prism::LambdaNode
         
     | 
| 
       166 
173 
     | 
    
         
             
                      nesting_nodes << candidate
         
     | 
| 
       167 
174 
     | 
    
         
             
                    end
         
     | 
| 
       168 
175 
     | 
    
         | 
| 
         @@ -203,24 +210,7 @@ module RubyLsp 
     | 
|
| 
       203 
210 
     | 
    
         
             
                    end
         
     | 
| 
       204 
211 
     | 
    
         
             
                  end
         
     | 
| 
       205 
212 
     | 
    
         | 
| 
       206 
     | 
    
         
            -
                   
     | 
| 
       207 
     | 
    
         
            -
                  surrounding_method = T.let(nil, T.nilable(String))
         
     | 
| 
       208 
     | 
    
         
            -
             
     | 
| 
       209 
     | 
    
         
            -
                  nesting_nodes.each do |node|
         
     | 
| 
       210 
     | 
    
         
            -
                    case node
         
     | 
| 
       211 
     | 
    
         
            -
                    when Prism::ClassNode, Prism::ModuleNode
         
     | 
| 
       212 
     | 
    
         
            -
                      nesting << node.constant_path.slice
         
     | 
| 
       213 
     | 
    
         
            -
                    when Prism::SingletonClassNode
         
     | 
| 
       214 
     | 
    
         
            -
                      nesting << "<Class:#{nesting.last}>"
         
     | 
| 
       215 
     | 
    
         
            -
                    when Prism::DefNode
         
     | 
| 
       216 
     | 
    
         
            -
                      surrounding_method = node.name.to_s
         
     | 
| 
       217 
     | 
    
         
            -
                      next unless node.receiver.is_a?(Prism::SelfNode)
         
     | 
| 
       218 
     | 
    
         
            -
             
     | 
| 
       219 
     | 
    
         
            -
                      nesting << "<Class:#{nesting.last}>"
         
     | 
| 
       220 
     | 
    
         
            -
                    end
         
     | 
| 
       221 
     | 
    
         
            -
                  end
         
     | 
| 
       222 
     | 
    
         
            -
             
     | 
| 
       223 
     | 
    
         
            -
                  NodeContext.new(closest, parent, nesting, call_node, surrounding_method)
         
     | 
| 
      
 213 
     | 
    
         
            +
                  NodeContext.new(closest, parent, nesting_nodes, call_node)
         
     | 
| 
       224 
214 
     | 
    
         
             
                end
         
     | 
| 
       225 
215 
     | 
    
         | 
| 
       226 
216 
     | 
    
         
             
                sig { returns(T::Boolean) }
         
     | 
| 
         @@ -69,7 +69,7 @@ module RubyLsp 
     | 
|
| 
       69 
69 
     | 
    
         
             
                  @formatter = detect_formatter(direct_dependencies, all_dependencies) if @formatter == "auto"
         
     | 
| 
       70 
70 
     | 
    
         | 
| 
       71 
71 
     | 
    
         
             
                  specified_linters = options.dig(:initializationOptions, :linters)
         
     | 
| 
       72 
     | 
    
         
            -
                  @linters = specified_linters || detect_linters(direct_dependencies)
         
     | 
| 
      
 72 
     | 
    
         
            +
                  @linters = specified_linters || detect_linters(direct_dependencies, all_dependencies)
         
     | 
| 
       73 
73 
     | 
    
         
             
                  @test_library = detect_test_library(direct_dependencies)
         
     | 
| 
       74 
74 
     | 
    
         
             
                  @has_type_checker = detect_typechecker(direct_dependencies)
         
     | 
| 
       75 
75 
     | 
    
         | 
| 
         @@ -127,10 +127,14 @@ module RubyLsp 
     | 
|
| 
       127 
127 
     | 
    
         | 
| 
       128 
128 
     | 
    
         
             
                # Try to detect if there are linters in the project's dependencies. For auto-detection, we always only consider a
         
     | 
| 
       129 
129 
     | 
    
         
             
                # single linter. To have multiple linters running, the user must configure them manually
         
     | 
| 
       130 
     | 
    
         
            -
                sig { params(dependencies: T::Array[String]).returns(T::Array[String]) }
         
     | 
| 
       131 
     | 
    
         
            -
                def detect_linters(dependencies)
         
     | 
| 
      
 130 
     | 
    
         
            +
                sig { params(dependencies: T::Array[String], all_dependencies: T::Array[String]).returns(T::Array[String]) }
         
     | 
| 
      
 131 
     | 
    
         
            +
                def detect_linters(dependencies, all_dependencies)
         
     | 
| 
       132 
132 
     | 
    
         
             
                  linters = []
         
     | 
| 
       133 
     | 
    
         
            -
             
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
                  if dependencies.any?(/^rubocop/) || (all_dependencies.include?("rubocop") && dot_rubocop_yml_present)
         
     | 
| 
      
 135 
     | 
    
         
            +
                    linters << "rubocop"
         
     | 
| 
      
 136 
     | 
    
         
            +
                  end
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
       134 
138 
     | 
    
         
             
                  linters
         
     | 
| 
       135 
139 
     | 
    
         
             
                end
         
     | 
| 
       136 
140 
     | 
    
         | 
| 
         @@ -277,6 +277,8 @@ module RubyLsp 
     | 
|
| 
       277 
277 
     | 
    
         | 
| 
       278 
278 
     | 
    
         
             
                  sig { params(node: Prism::CallNode, name: String).void }
         
     | 
| 
       279 
279 
     | 
    
         
             
                  def complete_methods(node, name)
         
     | 
| 
      
 280 
     | 
    
         
            +
                    add_local_completions(node, name)
         
     | 
| 
      
 281 
     | 
    
         
            +
             
     | 
| 
       280 
282 
     | 
    
         
             
                    type = @type_inferrer.infer_receiver_type(@node_context)
         
     | 
| 
       281 
283 
     | 
    
         
             
                    return unless type
         
     | 
| 
       282 
284 
     | 
    
         | 
| 
         @@ -322,6 +324,31 @@ module RubyLsp 
     | 
|
| 
       322 
324 
     | 
    
         
             
                    # We have not indexed this namespace, so we can't provide any completions
         
     | 
| 
       323 
325 
     | 
    
         
             
                  end
         
     | 
| 
       324 
326 
     | 
    
         | 
| 
      
 327 
     | 
    
         
            +
                  sig { params(node: Prism::CallNode, name: String).void }
         
     | 
| 
      
 328 
     | 
    
         
            +
                  def add_local_completions(node, name)
         
     | 
| 
      
 329 
     | 
    
         
            +
                    return if @global_state.has_type_checker
         
     | 
| 
      
 330 
     | 
    
         
            +
             
     | 
| 
      
 331 
     | 
    
         
            +
                    # If the call node has a receiver, then it cannot possibly be a local variable
         
     | 
| 
      
 332 
     | 
    
         
            +
                    return if node.receiver
         
     | 
| 
      
 333 
     | 
    
         
            +
             
     | 
| 
      
 334 
     | 
    
         
            +
                    range = range_from_location(T.must(node.message_loc))
         
     | 
| 
      
 335 
     | 
    
         
            +
             
     | 
| 
      
 336 
     | 
    
         
            +
                    @node_context.locals_for_scope.each do |local|
         
     | 
| 
      
 337 
     | 
    
         
            +
                      local_name = local.to_s
         
     | 
| 
      
 338 
     | 
    
         
            +
                      next unless local_name.start_with?(name)
         
     | 
| 
      
 339 
     | 
    
         
            +
             
     | 
| 
      
 340 
     | 
    
         
            +
                      @response_builder << Interface::CompletionItem.new(
         
     | 
| 
      
 341 
     | 
    
         
            +
                        label: local_name,
         
     | 
| 
      
 342 
     | 
    
         
            +
                        filter_text: local_name,
         
     | 
| 
      
 343 
     | 
    
         
            +
                        text_edit: Interface::TextEdit.new(range: range, new_text: local_name),
         
     | 
| 
      
 344 
     | 
    
         
            +
                        kind: Constant::CompletionItemKind::VARIABLE,
         
     | 
| 
      
 345 
     | 
    
         
            +
                        data: {
         
     | 
| 
      
 346 
     | 
    
         
            +
                          skip_resolve: true,
         
     | 
| 
      
 347 
     | 
    
         
            +
                        },
         
     | 
| 
      
 348 
     | 
    
         
            +
                      )
         
     | 
| 
      
 349 
     | 
    
         
            +
                    end
         
     | 
| 
      
 350 
     | 
    
         
            +
                  end
         
     | 
| 
      
 351 
     | 
    
         
            +
             
     | 
| 
       325 
352 
     | 
    
         
             
                  sig { params(label: String, node: Prism::StringNode).returns(Interface::CompletionItem) }
         
     | 
| 
       326 
353 
     | 
    
         
             
                  def build_completion(label, node)
         
     | 
| 
       327 
354 
     | 
    
         
             
                    # We should use the content location as we only replace the content and not the delimiters of the string
         
     | 
| 
         @@ -46,6 +46,8 @@ module RubyLsp 
     | 
|
| 
       46 
46 
     | 
    
         
             
                      :on_instance_variable_or_write_node_enter,
         
     | 
| 
       47 
47 
     | 
    
         
             
                      :on_instance_variable_target_node_enter,
         
     | 
| 
       48 
48 
     | 
    
         
             
                      :on_string_node_enter,
         
     | 
| 
      
 49 
     | 
    
         
            +
                      :on_super_node_enter,
         
     | 
| 
      
 50 
     | 
    
         
            +
                      :on_forwarding_super_node_enter,
         
     | 
| 
       49 
51 
     | 
    
         
             
                    )
         
     | 
| 
       50 
52 
     | 
    
         
             
                  end
         
     | 
| 
       51 
53 
     | 
    
         | 
| 
         @@ -133,8 +135,30 @@ module RubyLsp 
     | 
|
| 
       133 
135 
     | 
    
         
             
                    handle_instance_variable_definition(node.name.to_s)
         
     | 
| 
       134 
136 
     | 
    
         
             
                  end
         
     | 
| 
       135 
137 
     | 
    
         | 
| 
      
 138 
     | 
    
         
            +
                  sig { params(node: Prism::SuperNode).void }
         
     | 
| 
      
 139 
     | 
    
         
            +
                  def on_super_node_enter(node)
         
     | 
| 
      
 140 
     | 
    
         
            +
                    handle_super_node_definition
         
     | 
| 
      
 141 
     | 
    
         
            +
                  end
         
     | 
| 
      
 142 
     | 
    
         
            +
             
     | 
| 
      
 143 
     | 
    
         
            +
                  sig { params(node: Prism::ForwardingSuperNode).void }
         
     | 
| 
      
 144 
     | 
    
         
            +
                  def on_forwarding_super_node_enter(node)
         
     | 
| 
      
 145 
     | 
    
         
            +
                    handle_super_node_definition
         
     | 
| 
      
 146 
     | 
    
         
            +
                  end
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
       136 
148 
     | 
    
         
             
                  private
         
     | 
| 
       137 
149 
     | 
    
         | 
| 
      
 150 
     | 
    
         
            +
                  sig { void }
         
     | 
| 
      
 151 
     | 
    
         
            +
                  def handle_super_node_definition
         
     | 
| 
      
 152 
     | 
    
         
            +
                    surrounding_method = @node_context.surrounding_method
         
     | 
| 
      
 153 
     | 
    
         
            +
                    return unless surrounding_method
         
     | 
| 
      
 154 
     | 
    
         
            +
             
     | 
| 
      
 155 
     | 
    
         
            +
                    handle_method_definition(
         
     | 
| 
      
 156 
     | 
    
         
            +
                      surrounding_method,
         
     | 
| 
      
 157 
     | 
    
         
            +
                      @type_inferrer.infer_receiver_type(@node_context),
         
     | 
| 
      
 158 
     | 
    
         
            +
                      inherited_only: true,
         
     | 
| 
      
 159 
     | 
    
         
            +
                    )
         
     | 
| 
      
 160 
     | 
    
         
            +
                  end
         
     | 
| 
      
 161 
     | 
    
         
            +
             
     | 
| 
       138 
162 
     | 
    
         
             
                  sig { params(name: String).void }
         
     | 
| 
       139 
163 
     | 
    
         
             
                  def handle_instance_variable_definition(name)
         
     | 
| 
       140 
164 
     | 
    
         
             
                    type = @type_inferrer.infer_receiver_type(@node_context)
         
     | 
| 
         @@ -158,10 +182,10 @@ module RubyLsp 
     | 
|
| 
       158 
182 
     | 
    
         
             
                    # If by any chance we haven't indexed the owner, then there's no way to find the right declaration
         
     | 
| 
       159 
183 
     | 
    
         
             
                  end
         
     | 
| 
       160 
184 
     | 
    
         | 
| 
       161 
     | 
    
         
            -
                  sig { params(message: String, receiver_type: T.nilable(String)).void }
         
     | 
| 
       162 
     | 
    
         
            -
                  def handle_method_definition(message, receiver_type)
         
     | 
| 
      
 185 
     | 
    
         
            +
                  sig { params(message: String, receiver_type: T.nilable(String), inherited_only: T::Boolean).void }
         
     | 
| 
      
 186 
     | 
    
         
            +
                  def handle_method_definition(message, receiver_type, inherited_only: false)
         
     | 
| 
       163 
187 
     | 
    
         
             
                    methods = if receiver_type
         
     | 
| 
       164 
     | 
    
         
            -
                      @index.resolve_method(message, receiver_type)
         
     | 
| 
      
 188 
     | 
    
         
            +
                      @index.resolve_method(message, receiver_type, inherited_only: inherited_only)
         
     | 
| 
       165 
189 
     | 
    
         
             
                    else
         
     | 
| 
       166 
190 
     | 
    
         
             
                      # If the method doesn't have a receiver, then we provide a few candidates to jump to
         
     | 
| 
       167 
191 
     | 
    
         
             
                      # But we don't want to provide too many candidates, as it can be overwhelming
         
     | 
| 
         @@ -21,6 +21,8 @@ module RubyLsp 
     | 
|
| 
       21 
21 
     | 
    
         
             
                      Prism::InstanceVariableWriteNode,
         
     | 
| 
       22 
22 
     | 
    
         
             
                      Prism::SymbolNode,
         
     | 
| 
       23 
23 
     | 
    
         
             
                      Prism::StringNode,
         
     | 
| 
      
 24 
     | 
    
         
            +
                      Prism::SuperNode,
         
     | 
| 
      
 25 
     | 
    
         
            +
                      Prism::ForwardingSuperNode,
         
     | 
| 
       24 
26 
     | 
    
         
             
                    ],
         
     | 
| 
       25 
27 
     | 
    
         
             
                    T::Array[T.class_of(Prism::Node)],
         
     | 
| 
       26 
28 
     | 
    
         
             
                  )
         
     | 
| 
         @@ -64,6 +66,8 @@ module RubyLsp 
     | 
|
| 
       64 
66 
     | 
    
         
             
                      :on_instance_variable_operator_write_node_enter,
         
     | 
| 
       65 
67 
     | 
    
         
             
                      :on_instance_variable_or_write_node_enter,
         
     | 
| 
       66 
68 
     | 
    
         
             
                      :on_instance_variable_target_node_enter,
         
     | 
| 
      
 69 
     | 
    
         
            +
                      :on_super_node_enter,
         
     | 
| 
      
 70 
     | 
    
         
            +
                      :on_forwarding_super_node_enter,
         
     | 
| 
       67 
71 
     | 
    
         
             
                    )
         
     | 
| 
       68 
72 
     | 
    
         
             
                  end
         
     | 
| 
       69 
73 
     | 
    
         | 
| 
         @@ -106,17 +110,7 @@ module RubyLsp 
     | 
|
| 
       106 
110 
     | 
    
         
             
                    message = node.message
         
     | 
| 
       107 
111 
     | 
    
         
             
                    return unless message
         
     | 
| 
       108 
112 
     | 
    
         | 
| 
       109 
     | 
    
         
            -
                     
     | 
| 
       110 
     | 
    
         
            -
                    return unless type
         
     | 
| 
       111 
     | 
    
         
            -
             
     | 
| 
       112 
     | 
    
         
            -
                    methods = @index.resolve_method(message, type)
         
     | 
| 
       113 
     | 
    
         
            -
                    return unless methods
         
     | 
| 
       114 
     | 
    
         
            -
             
     | 
| 
       115 
     | 
    
         
            -
                    title = "#{message}#{T.must(methods.first).decorated_parameters}"
         
     | 
| 
       116 
     | 
    
         
            -
             
     | 
| 
       117 
     | 
    
         
            -
                    categorized_markdown_from_index_entries(title, methods).each do |category, content|
         
     | 
| 
       118 
     | 
    
         
            -
                      @response_builder.push(content, category: category)
         
     | 
| 
       119 
     | 
    
         
            -
                    end
         
     | 
| 
      
 113 
     | 
    
         
            +
                    handle_method_hover(message)
         
     | 
| 
       120 
114 
     | 
    
         
             
                  end
         
     | 
| 
       121 
115 
     | 
    
         | 
| 
       122 
116 
     | 
    
         
             
                  sig { params(node: Prism::InstanceVariableReadNode).void }
         
     | 
| 
         @@ -149,8 +143,41 @@ module RubyLsp 
     | 
|
| 
       149 
143 
     | 
    
         
             
                    handle_instance_variable_hover(node.name.to_s)
         
     | 
| 
       150 
144 
     | 
    
         
             
                  end
         
     | 
| 
       151 
145 
     | 
    
         | 
| 
      
 146 
     | 
    
         
            +
                  sig { params(node: Prism::SuperNode).void }
         
     | 
| 
      
 147 
     | 
    
         
            +
                  def on_super_node_enter(node)
         
     | 
| 
      
 148 
     | 
    
         
            +
                    handle_super_node_hover
         
     | 
| 
      
 149 
     | 
    
         
            +
                  end
         
     | 
| 
      
 150 
     | 
    
         
            +
             
     | 
| 
      
 151 
     | 
    
         
            +
                  sig { params(node: Prism::ForwardingSuperNode).void }
         
     | 
| 
      
 152 
     | 
    
         
            +
                  def on_forwarding_super_node_enter(node)
         
     | 
| 
      
 153 
     | 
    
         
            +
                    handle_super_node_hover
         
     | 
| 
      
 154 
     | 
    
         
            +
                  end
         
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
       152 
156 
     | 
    
         
             
                  private
         
     | 
| 
       153 
157 
     | 
    
         | 
| 
      
 158 
     | 
    
         
            +
                  sig { void }
         
     | 
| 
      
 159 
     | 
    
         
            +
                  def handle_super_node_hover
         
     | 
| 
      
 160 
     | 
    
         
            +
                    surrounding_method = @node_context.surrounding_method
         
     | 
| 
      
 161 
     | 
    
         
            +
                    return unless surrounding_method
         
     | 
| 
      
 162 
     | 
    
         
            +
             
     | 
| 
      
 163 
     | 
    
         
            +
                    handle_method_hover(surrounding_method, inherited_only: true)
         
     | 
| 
      
 164 
     | 
    
         
            +
                  end
         
     | 
| 
      
 165 
     | 
    
         
            +
             
     | 
| 
      
 166 
     | 
    
         
            +
                  sig { params(message: String, inherited_only: T::Boolean).void }
         
     | 
| 
      
 167 
     | 
    
         
            +
                  def handle_method_hover(message, inherited_only: false)
         
     | 
| 
      
 168 
     | 
    
         
            +
                    type = @type_inferrer.infer_receiver_type(@node_context)
         
     | 
| 
      
 169 
     | 
    
         
            +
                    return unless type
         
     | 
| 
      
 170 
     | 
    
         
            +
             
     | 
| 
      
 171 
     | 
    
         
            +
                    methods = @index.resolve_method(message, type, inherited_only: inherited_only)
         
     | 
| 
      
 172 
     | 
    
         
            +
                    return unless methods
         
     | 
| 
      
 173 
     | 
    
         
            +
             
     | 
| 
      
 174 
     | 
    
         
            +
                    title = "#{message}#{T.must(methods.first).decorated_parameters}"
         
     | 
| 
      
 175 
     | 
    
         
            +
             
     | 
| 
      
 176 
     | 
    
         
            +
                    categorized_markdown_from_index_entries(title, methods).each do |category, content|
         
     | 
| 
      
 177 
     | 
    
         
            +
                      @response_builder.push(content, category: category)
         
     | 
| 
      
 178 
     | 
    
         
            +
                    end
         
     | 
| 
      
 179 
     | 
    
         
            +
                  end
         
     | 
| 
      
 180 
     | 
    
         
            +
             
     | 
| 
       154 
181 
     | 
    
         
             
                  sig { params(name: String).void }
         
     | 
| 
       155 
182 
     | 
    
         
             
                  def handle_instance_variable_hover(name)
         
     | 
| 
       156 
183 
     | 
    
         
             
                    type = @type_inferrer.infer_receiver_type(@node_context)
         
     | 
| 
         @@ -23,22 +23,82 @@ module RubyLsp 
     | 
|
| 
       23 
23 
     | 
    
         
             
                  params(
         
     | 
| 
       24 
24 
     | 
    
         
             
                    node: T.nilable(Prism::Node),
         
     | 
| 
       25 
25 
     | 
    
         
             
                    parent: T.nilable(Prism::Node),
         
     | 
| 
       26 
     | 
    
         
            -
                     
     | 
| 
      
 26 
     | 
    
         
            +
                    nesting_nodes: T::Array[T.any(
         
     | 
| 
      
 27 
     | 
    
         
            +
                      Prism::ClassNode,
         
     | 
| 
      
 28 
     | 
    
         
            +
                      Prism::ModuleNode,
         
     | 
| 
      
 29 
     | 
    
         
            +
                      Prism::SingletonClassNode,
         
     | 
| 
      
 30 
     | 
    
         
            +
                      Prism::DefNode,
         
     | 
| 
      
 31 
     | 
    
         
            +
                      Prism::BlockNode,
         
     | 
| 
      
 32 
     | 
    
         
            +
                      Prism::LambdaNode,
         
     | 
| 
      
 33 
     | 
    
         
            +
                      Prism::ProgramNode,
         
     | 
| 
      
 34 
     | 
    
         
            +
                    )],
         
     | 
| 
       27 
35 
     | 
    
         
             
                    call_node: T.nilable(Prism::CallNode),
         
     | 
| 
       28 
     | 
    
         
            -
                    surrounding_method: T.nilable(String),
         
     | 
| 
       29 
36 
     | 
    
         
             
                  ).void
         
     | 
| 
       30 
37 
     | 
    
         
             
                end
         
     | 
| 
       31 
     | 
    
         
            -
                def initialize(node, parent,  
     | 
| 
      
 38 
     | 
    
         
            +
                def initialize(node, parent, nesting_nodes, call_node)
         
     | 
| 
       32 
39 
     | 
    
         
             
                  @node = node
         
     | 
| 
       33 
40 
     | 
    
         
             
                  @parent = parent
         
     | 
| 
       34 
     | 
    
         
            -
                  @ 
     | 
| 
      
 41 
     | 
    
         
            +
                  @nesting_nodes = nesting_nodes
         
     | 
| 
       35 
42 
     | 
    
         
             
                  @call_node = call_node
         
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                  nesting, surrounding_method = handle_nesting_nodes(nesting_nodes)
         
     | 
| 
      
 45 
     | 
    
         
            +
                  @nesting = T.let(nesting, T::Array[String])
         
     | 
| 
      
 46 
     | 
    
         
            +
                  @surrounding_method = T.let(surrounding_method, T.nilable(String))
         
     | 
| 
       37 
47 
     | 
    
         
             
                end
         
     | 
| 
       38 
48 
     | 
    
         | 
| 
       39 
49 
     | 
    
         
             
                sig { returns(String) }
         
     | 
| 
       40 
50 
     | 
    
         
             
                def fully_qualified_name
         
     | 
| 
       41 
51 
     | 
    
         
             
                  @fully_qualified_name ||= T.let(@nesting.join("::"), T.nilable(String))
         
     | 
| 
       42 
52 
     | 
    
         
             
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                sig { returns(T::Array[Symbol]) }
         
     | 
| 
      
 55 
     | 
    
         
            +
                def locals_for_scope
         
     | 
| 
      
 56 
     | 
    
         
            +
                  locals = []
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                  @nesting_nodes.each do |node|
         
     | 
| 
      
 59 
     | 
    
         
            +
                    if node.is_a?(Prism::ClassNode) || node.is_a?(Prism::ModuleNode) || node.is_a?(Prism::SingletonClassNode) ||
         
     | 
| 
      
 60 
     | 
    
         
            +
                        node.is_a?(Prism::DefNode)
         
     | 
| 
      
 61 
     | 
    
         
            +
                      locals.clear
         
     | 
| 
      
 62 
     | 
    
         
            +
                    end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                    locals.concat(node.locals)
         
     | 
| 
      
 65 
     | 
    
         
            +
                  end
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
                  locals
         
     | 
| 
      
 68 
     | 
    
         
            +
                end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                private
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                sig do
         
     | 
| 
      
 73 
     | 
    
         
            +
                  params(nodes: T::Array[T.any(
         
     | 
| 
      
 74 
     | 
    
         
            +
                    Prism::ClassNode,
         
     | 
| 
      
 75 
     | 
    
         
            +
                    Prism::ModuleNode,
         
     | 
| 
      
 76 
     | 
    
         
            +
                    Prism::SingletonClassNode,
         
     | 
| 
      
 77 
     | 
    
         
            +
                    Prism::DefNode,
         
     | 
| 
      
 78 
     | 
    
         
            +
                    Prism::BlockNode,
         
     | 
| 
      
 79 
     | 
    
         
            +
                    Prism::LambdaNode,
         
     | 
| 
      
 80 
     | 
    
         
            +
                    Prism::ProgramNode,
         
     | 
| 
      
 81 
     | 
    
         
            +
                  )]).returns([T::Array[String], T.nilable(String)])
         
     | 
| 
      
 82 
     | 
    
         
            +
                end
         
     | 
| 
      
 83 
     | 
    
         
            +
                def handle_nesting_nodes(nodes)
         
     | 
| 
      
 84 
     | 
    
         
            +
                  nesting = []
         
     | 
| 
      
 85 
     | 
    
         
            +
                  surrounding_method = T.let(nil, T.nilable(String))
         
     | 
| 
      
 86 
     | 
    
         
            +
             
     | 
| 
      
 87 
     | 
    
         
            +
                  @nesting_nodes.each do |node|
         
     | 
| 
      
 88 
     | 
    
         
            +
                    case node
         
     | 
| 
      
 89 
     | 
    
         
            +
                    when Prism::ClassNode, Prism::ModuleNode
         
     | 
| 
      
 90 
     | 
    
         
            +
                      nesting << node.constant_path.slice
         
     | 
| 
      
 91 
     | 
    
         
            +
                    when Prism::SingletonClassNode
         
     | 
| 
      
 92 
     | 
    
         
            +
                      nesting << "<Class:#{nesting.last}>"
         
     | 
| 
      
 93 
     | 
    
         
            +
                    when Prism::DefNode
         
     | 
| 
      
 94 
     | 
    
         
            +
                      surrounding_method = node.name.to_s
         
     | 
| 
      
 95 
     | 
    
         
            +
                      next unless node.receiver.is_a?(Prism::SelfNode)
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                      nesting << "<Class:#{nesting.last}>"
         
     | 
| 
      
 98 
     | 
    
         
            +
                    end
         
     | 
| 
      
 99 
     | 
    
         
            +
                  end
         
     | 
| 
      
 100 
     | 
    
         
            +
             
     | 
| 
      
 101 
     | 
    
         
            +
                  [nesting, surrounding_method]
         
     | 
| 
      
 102 
     | 
    
         
            +
                end
         
     | 
| 
       43 
103 
     | 
    
         
             
              end
         
     | 
| 
       44 
104 
     | 
    
         
             
            end
         
     | 
| 
         @@ -38,6 +38,8 @@ module RubyLsp 
     | 
|
| 
       38 
38 
     | 
    
         | 
| 
       39 
39 
     | 
    
         
             
                  sig { override.returns(T::Hash[Symbol, T.untyped]) }
         
     | 
| 
       40 
40 
     | 
    
         
             
                  def perform
         
     | 
| 
      
 41 
     | 
    
         
            +
                    return @item if @item.dig(:data, :skip_resolve)
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
       41 
43 
     | 
    
         
             
                    # Based on the spec https://microsoft.github.io/language-server-protocol/specification#textDocument_completion,
         
     | 
| 
       42 
44 
     | 
    
         
             
                    # a completion resolve request must always return the original completion item without modifying ANY fields
         
     | 
| 
       43 
45 
     | 
    
         
             
                    # other than detail and documentation (NOT labelDetails). If we modify anything, the completion behaviour might
         
     | 
| 
         @@ -20,16 +20,9 @@ module RubyLsp 
     | 
|
| 
       20 
20 
     | 
    
         
             
                  when Prism::CallNode
         
     | 
| 
       21 
21 
     | 
    
         
             
                    infer_receiver_for_call_node(node, node_context)
         
     | 
| 
       22 
22 
     | 
    
         
             
                  when Prism::InstanceVariableReadNode, Prism::InstanceVariableAndWriteNode, Prism::InstanceVariableWriteNode,
         
     | 
| 
       23 
     | 
    
         
            -
                    Prism::InstanceVariableOperatorWriteNode, Prism::InstanceVariableOrWriteNode, Prism::InstanceVariableTargetNode
         
     | 
| 
       24 
     | 
    
         
            -
                     
     | 
| 
       25 
     | 
    
         
            -
                     
     | 
| 
       26 
     | 
    
         
            -
                    # inherits from Object
         
     | 
| 
       27 
     | 
    
         
            -
                    return "Object" if nesting.empty?
         
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
       29 
     | 
    
         
            -
                    fully_qualified_name = node_context.fully_qualified_name
         
     | 
| 
       30 
     | 
    
         
            -
                    return fully_qualified_name if node_context.surrounding_method
         
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
     | 
    
         
            -
                    "#{fully_qualified_name}::<Class:#{nesting.last}>"
         
     | 
| 
      
 23 
     | 
    
         
            +
                    Prism::InstanceVariableOperatorWriteNode, Prism::InstanceVariableOrWriteNode, Prism::InstanceVariableTargetNode,
         
     | 
| 
      
 24 
     | 
    
         
            +
                    Prism::SuperNode, Prism::ForwardingSuperNode
         
     | 
| 
      
 25 
     | 
    
         
            +
                    self_receiver_handling(node_context)
         
     | 
| 
       33 
26 
     | 
    
         
             
                  end
         
     | 
| 
       34 
27 
     | 
    
         
             
                end
         
     | 
| 
       35 
28 
     | 
    
         | 
| 
         @@ -41,15 +34,7 @@ module RubyLsp 
     | 
|
| 
       41 
34 
     | 
    
         | 
| 
       42 
35 
     | 
    
         
             
                  case receiver
         
     | 
| 
       43 
36 
     | 
    
         
             
                  when Prism::SelfNode, nil
         
     | 
| 
       44 
     | 
    
         
            -
                     
     | 
| 
       45 
     | 
    
         
            -
                    # If we're at the top level, then the invocation is happening on `<main>`, which is a special singleton that
         
     | 
| 
       46 
     | 
    
         
            -
                    # inherits from Object
         
     | 
| 
       47 
     | 
    
         
            -
                    return "Object" if nesting.empty?
         
     | 
| 
       48 
     | 
    
         
            -
                    return node_context.fully_qualified_name if node_context.surrounding_method
         
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
     | 
    
         
            -
                    # If we're not inside a method, then we're inside the body of a class or module, which is a singleton
         
     | 
| 
       51 
     | 
    
         
            -
                    # context
         
     | 
| 
       52 
     | 
    
         
            -
                    "#{nesting.join("::")}::<Class:#{nesting.last}>"
         
     | 
| 
      
 37 
     | 
    
         
            +
                    self_receiver_handling(node_context)
         
     | 
| 
       53 
38 
     | 
    
         
             
                  when Prism::ConstantPathNode, Prism::ConstantReadNode
         
     | 
| 
       54 
39 
     | 
    
         
             
                    # When the receiver is a constant reference, we have to try to resolve it to figure out the right
         
     | 
| 
       55 
40 
     | 
    
         
             
                    # receiver. But since the invocation is directly on the constant, that's the singleton context of that
         
     | 
| 
         @@ -68,6 +53,19 @@ module RubyLsp 
     | 
|
| 
       68 
53 
     | 
    
         
             
                  end
         
     | 
| 
       69 
54 
     | 
    
         
             
                end
         
     | 
| 
       70 
55 
     | 
    
         | 
| 
      
 56 
     | 
    
         
            +
                sig { params(node_context: NodeContext).returns(String) }
         
     | 
| 
      
 57 
     | 
    
         
            +
                def self_receiver_handling(node_context)
         
     | 
| 
      
 58 
     | 
    
         
            +
                  nesting = node_context.nesting
         
     | 
| 
      
 59 
     | 
    
         
            +
                  # If we're at the top level, then the invocation is happening on `<main>`, which is a special singleton that
         
     | 
| 
      
 60 
     | 
    
         
            +
                  # inherits from Object
         
     | 
| 
      
 61 
     | 
    
         
            +
                  return "Object" if nesting.empty?
         
     | 
| 
      
 62 
     | 
    
         
            +
                  return node_context.fully_qualified_name if node_context.surrounding_method
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                  # If we're not inside a method, then we're inside the body of a class or module, which is a singleton
         
     | 
| 
      
 65 
     | 
    
         
            +
                  # context
         
     | 
| 
      
 66 
     | 
    
         
            +
                  "#{nesting.join("::")}::<Class:#{nesting.last}>"
         
     | 
| 
      
 67 
     | 
    
         
            +
                end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
       71 
69 
     | 
    
         
             
                sig do
         
     | 
| 
       72 
70 
     | 
    
         
             
                  params(
         
     | 
| 
       73 
71 
     | 
    
         
             
                    node: T.any(
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: ruby-lsp
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0.17. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.17.7
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Shopify
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire:
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: exe
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date: 2024-07- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2024-07-11 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: language_server-protocol
         
     |