ruby-lsp 0.21.3 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/VERSION +1 -1
 - data/exe/ruby-lsp +1 -1
 - data/exe/ruby-lsp-launcher +0 -3
 - data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +6 -0
 - data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +136 -58
 - data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +31 -28
 - data/lib/ruby_indexer/lib/ruby_indexer/index.rb +10 -10
 - data/lib/ruby_indexer/test/classes_and_modules_test.rb +2 -2
 - data/lib/ruby_indexer/test/configuration_test.rb +10 -0
 - data/lib/ruby_indexer/test/constant_test.rb +8 -8
 - data/lib/ruby_indexer/test/enhancements_test.rb +134 -38
 - data/lib/ruby_indexer/test/index_test.rb +39 -0
 - data/lib/ruby_indexer/test/method_test.rb +34 -1
 - data/lib/ruby_lsp/global_state.rb +1 -3
 - data/lib/ruby_lsp/internal.rb +1 -0
 - data/lib/ruby_lsp/requests/definition.rb +2 -0
 - data/lib/ruby_lsp/requests/hover.rb +2 -0
 - data/lib/ruby_lsp/requests/support/rubocop_runner.rb +1 -0
 - data/lib/ruby_lsp/server.rb +13 -0
 - data/lib/ruby_lsp/setup_bundler.rb +20 -20
 - metadata +3 -3
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: e48cef95e466e2a75943921fc08ede1a449e07096e44078ca063bdbee6d3c54b
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: c0ce6a0636645674e9e9a87219124b622b1280420c14c4bd12f8f0f0aafc3f32
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 89d02237ecce7e784bb5275ba4d5fc30b64981ea337b078f3117037b98d8f734e0d7e6266078e76023125dd52bbcb6ded8d04fdac1c29eb8292fd29e401cece4
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 7245d82a481bd9e6a56d0cce9ad03796bd1a6d9e770beb5632fcaf7669ab0af9e9c0c95f0b671d844231af718add21b98011665ac3355fab5647ab12378b60bf
         
     | 
    
        data/VERSION
    CHANGED
    
    | 
         @@ -1 +1 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            0. 
     | 
| 
      
 1 
     | 
    
         
            +
            0.22.0
         
     | 
    
        data/exe/ruby-lsp
    CHANGED
    
    | 
         @@ -54,7 +54,7 @@ rescue OptionParser::InvalidOption => e 
     | 
|
| 
       54 
54 
     | 
    
         
             
              exit(1)
         
     | 
| 
       55 
55 
     | 
    
         
             
            end
         
     | 
| 
       56 
56 
     | 
    
         | 
| 
       57 
     | 
    
         
            -
            # When we're running without bundler, then we need to make sure the  
     | 
| 
      
 57 
     | 
    
         
            +
            # When we're running without bundler, then we need to make sure the composed bundle is fully configured and re-execute
         
     | 
| 
       58 
58 
     | 
    
         
             
            # using `BUNDLE_GEMFILE=.ruby-lsp/Gemfile bundle exec ruby-lsp` so that we have access to the gems that are a part of
         
     | 
| 
       59 
59 
     | 
    
         
             
            # the application's bundle
         
     | 
| 
       60 
60 
     | 
    
         
             
            if ENV["BUNDLE_GEMFILE"].nil?
         
     | 
    
        data/exe/ruby-lsp-launcher
    CHANGED
    
    | 
         @@ -74,9 +74,6 @@ rescue StandardError => e 
     | 
|
| 
       74 
74 
     | 
    
         
             
              # If Bundler.setup fails, we need to restore the original $LOAD_PATH so that we can still require the Ruby LSP server
         
     | 
| 
       75 
75 
     | 
    
         
             
              # in degraded mode
         
     | 
| 
       76 
76 
     | 
    
         
             
              $LOAD_PATH.unshift(File.expand_path("../lib", __dir__))
         
     | 
| 
       77 
     | 
    
         
            -
            ensure
         
     | 
| 
       78 
     | 
    
         
            -
              require "fileutils"
         
     | 
| 
       79 
     | 
    
         
            -
              FileUtils.rm(bundle_env_path) if File.exist?(bundle_env_path)
         
     | 
| 
       80 
77 
     | 
    
         
             
            end
         
     | 
| 
       81 
78 
     | 
    
         | 
| 
       82 
79 
     | 
    
         
             
            error_path = File.join(".ruby-lsp", "install_error")
         
     | 
| 
         @@ -109,6 +109,12 @@ module RubyIndexer 
     | 
|
| 
       109 
109 
     | 
    
         | 
| 
       110 
110 
     | 
    
         
             
                  indexables = T.let([], T::Array[IndexablePath])
         
     | 
| 
       111 
111 
     | 
    
         | 
| 
      
 112 
     | 
    
         
            +
                  # Handle top level files separately. The path below is an optimization to prevent descending down directories that
         
     | 
| 
      
 113 
     | 
    
         
            +
                  # are going to be excluded anyway, so we need to handle top level scripts separately
         
     | 
| 
      
 114 
     | 
    
         
            +
                  Dir.glob(File.join(@workspace_path, "*.rb"), flags).each do |path|
         
     | 
| 
      
 115 
     | 
    
         
            +
                    indexables << IndexablePath.new(nil, path)
         
     | 
| 
      
 116 
     | 
    
         
            +
                  end
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
       112 
118 
     | 
    
         
             
                  # Add user specified patterns
         
     | 
| 
       113 
119 
     | 
    
         
             
                  @included_patterns.each do |pattern|
         
     | 
| 
       114 
120 
     | 
    
         
             
                    load_path_entry = T.let(nil, T.nilable(String))
         
     | 
| 
         @@ -18,13 +18,12 @@ module RubyIndexer 
     | 
|
| 
       18 
18 
     | 
    
         
             
                    parse_result: Prism::ParseResult,
         
     | 
| 
       19 
19 
     | 
    
         
             
                    file_path: String,
         
     | 
| 
       20 
20 
     | 
    
         
             
                    collect_comments: T::Boolean,
         
     | 
| 
       21 
     | 
    
         
            -
                    enhancements: T::Array[Enhancement],
         
     | 
| 
       22 
21 
     | 
    
         
             
                  ).void
         
     | 
| 
       23 
22 
     | 
    
         
             
                end
         
     | 
| 
       24 
     | 
    
         
            -
                def initialize(index, dispatcher, parse_result, file_path, collect_comments: false 
     | 
| 
      
 23 
     | 
    
         
            +
                def initialize(index, dispatcher, parse_result, file_path, collect_comments: false)
         
     | 
| 
       25 
24 
     | 
    
         
             
                  @index = index
         
     | 
| 
       26 
25 
     | 
    
         
             
                  @file_path = file_path
         
     | 
| 
       27 
     | 
    
         
            -
                  @enhancements =  
     | 
| 
      
 26 
     | 
    
         
            +
                  @enhancements = T.let(Enhancement.all(self), T::Array[Enhancement])
         
     | 
| 
       28 
27 
     | 
    
         
             
                  @visibility_stack = T.let([Entry::Visibility::PUBLIC], T::Array[Entry::Visibility])
         
     | 
| 
       29 
28 
     | 
    
         
             
                  @comments_by_line = T.let(
         
     | 
| 
       30 
29 
     | 
    
         
             
                    parse_result.comments.to_h do |c|
         
     | 
| 
         @@ -37,6 +36,7 @@ module RubyIndexer 
     | 
|
| 
       37 
36 
     | 
    
         
             
                    parse_result.code_units_cache(@index.configuration.encoding),
         
     | 
| 
       38 
37 
     | 
    
         
             
                    T.any(T.proc.params(arg0: Integer).returns(Integer), Prism::CodeUnitsCache),
         
     | 
| 
       39 
38 
     | 
    
         
             
                  )
         
     | 
| 
      
 39 
     | 
    
         
            +
                  @source_lines = T.let(parse_result.source.lines, T::Array[String])
         
     | 
| 
       40 
40 
     | 
    
         | 
| 
       41 
41 
     | 
    
         
             
                  # The nesting stack we're currently inside. Used to determine the fully qualified name of constants, but only
         
     | 
| 
       42 
42 
     | 
    
         
             
                  # stored by unresolved aliases which need the original nesting to be lazily resolved
         
     | 
| 
         @@ -85,15 +85,9 @@ module RubyIndexer 
     | 
|
| 
       85 
85 
     | 
    
         | 
| 
       86 
86 
     | 
    
         
             
                sig { params(node: Prism::ClassNode).void }
         
     | 
| 
       87 
87 
     | 
    
         
             
                def on_class_node_enter(node)
         
     | 
| 
       88 
     | 
    
         
            -
                  @visibility_stack.push(Entry::Visibility::PUBLIC)
         
     | 
| 
       89 
88 
     | 
    
         
             
                  constant_path = node.constant_path
         
     | 
| 
       90 
     | 
    
         
            -
                  name = constant_path.slice
         
     | 
| 
       91 
     | 
    
         
            -
             
     | 
| 
       92 
     | 
    
         
            -
                  comments = collect_comments(node)
         
     | 
| 
       93 
     | 
    
         
            -
             
     | 
| 
       94 
89 
     | 
    
         
             
                  superclass = node.superclass
         
     | 
| 
       95 
     | 
    
         
            -
             
     | 
| 
       96 
     | 
    
         
            -
                  nesting = actual_nesting(name)
         
     | 
| 
      
 90 
     | 
    
         
            +
                  nesting = actual_nesting(constant_path.slice)
         
     | 
| 
       97 
91 
     | 
    
         | 
| 
       98 
92 
     | 
    
         
             
                  parent_class = case superclass
         
     | 
| 
       99 
93 
     | 
    
         
             
                  when Prism::ConstantReadNode, Prism::ConstantPathNode
         
     | 
| 
         @@ -112,53 +106,29 @@ module RubyIndexer 
     | 
|
| 
       112 
106 
     | 
    
         
             
                    end
         
     | 
| 
       113 
107 
     | 
    
         
             
                  end
         
     | 
| 
       114 
108 
     | 
    
         | 
| 
       115 
     | 
    
         
            -
                   
     | 
| 
      
 109 
     | 
    
         
            +
                  add_class(
         
     | 
| 
       116 
110 
     | 
    
         
             
                    nesting,
         
     | 
| 
       117 
     | 
    
         
            -
                     
     | 
| 
       118 
     | 
    
         
            -
                     
     | 
| 
       119 
     | 
    
         
            -
                     
     | 
| 
       120 
     | 
    
         
            -
                    comments,
         
     | 
| 
       121 
     | 
    
         
            -
                    parent_class,
         
     | 
| 
      
 111 
     | 
    
         
            +
                    node.location,
         
     | 
| 
      
 112 
     | 
    
         
            +
                    constant_path.location,
         
     | 
| 
      
 113 
     | 
    
         
            +
                    parent_class_name: parent_class,
         
     | 
| 
      
 114 
     | 
    
         
            +
                    comments: collect_comments(node),
         
     | 
| 
       122 
115 
     | 
    
         
             
                  )
         
     | 
| 
       123 
     | 
    
         
            -
             
     | 
| 
       124 
     | 
    
         
            -
                  @owner_stack << entry
         
     | 
| 
       125 
     | 
    
         
            -
                  @index.add(entry)
         
     | 
| 
       126 
     | 
    
         
            -
                  @stack << name
         
     | 
| 
       127 
116 
     | 
    
         
             
                end
         
     | 
| 
       128 
117 
     | 
    
         | 
| 
       129 
118 
     | 
    
         
             
                sig { params(node: Prism::ClassNode).void }
         
     | 
| 
       130 
119 
     | 
    
         
             
                def on_class_node_leave(node)
         
     | 
| 
       131 
     | 
    
         
            -
                   
     | 
| 
       132 
     | 
    
         
            -
                  @owner_stack.pop
         
     | 
| 
       133 
     | 
    
         
            -
                  @visibility_stack.pop
         
     | 
| 
      
 120 
     | 
    
         
            +
                  pop_namespace_stack
         
     | 
| 
       134 
121 
     | 
    
         
             
                end
         
     | 
| 
       135 
122 
     | 
    
         | 
| 
       136 
123 
     | 
    
         
             
                sig { params(node: Prism::ModuleNode).void }
         
     | 
| 
       137 
124 
     | 
    
         
             
                def on_module_node_enter(node)
         
     | 
| 
       138 
     | 
    
         
            -
                  @visibility_stack.push(Entry::Visibility::PUBLIC)
         
     | 
| 
       139 
125 
     | 
    
         
             
                  constant_path = node.constant_path
         
     | 
| 
       140 
     | 
    
         
            -
                   
     | 
| 
       141 
     | 
    
         
            -
             
     | 
| 
       142 
     | 
    
         
            -
                  comments = collect_comments(node)
         
     | 
| 
       143 
     | 
    
         
            -
             
     | 
| 
       144 
     | 
    
         
            -
                  entry = Entry::Module.new(
         
     | 
| 
       145 
     | 
    
         
            -
                    actual_nesting(name),
         
     | 
| 
       146 
     | 
    
         
            -
                    @file_path,
         
     | 
| 
       147 
     | 
    
         
            -
                    Location.from_prism_location(node.location, @code_units_cache),
         
     | 
| 
       148 
     | 
    
         
            -
                    Location.from_prism_location(constant_path.location, @code_units_cache),
         
     | 
| 
       149 
     | 
    
         
            -
                    comments,
         
     | 
| 
       150 
     | 
    
         
            -
                  )
         
     | 
| 
       151 
     | 
    
         
            -
             
     | 
| 
       152 
     | 
    
         
            -
                  @owner_stack << entry
         
     | 
| 
       153 
     | 
    
         
            -
                  @index.add(entry)
         
     | 
| 
       154 
     | 
    
         
            -
                  @stack << name
         
     | 
| 
      
 126 
     | 
    
         
            +
                  add_module(constant_path.slice, node.location, constant_path.location, comments: collect_comments(node))
         
     | 
| 
       155 
127 
     | 
    
         
             
                end
         
     | 
| 
       156 
128 
     | 
    
         | 
| 
       157 
129 
     | 
    
         
             
                sig { params(node: Prism::ModuleNode).void }
         
     | 
| 
       158 
130 
     | 
    
         
             
                def on_module_node_leave(node)
         
     | 
| 
       159 
     | 
    
         
            -
                   
     | 
| 
       160 
     | 
    
         
            -
                  @owner_stack.pop
         
     | 
| 
       161 
     | 
    
         
            -
                  @visibility_stack.pop
         
     | 
| 
      
 131 
     | 
    
         
            +
                  pop_namespace_stack
         
     | 
| 
       162 
132 
     | 
    
         
             
                end
         
     | 
| 
       163 
133 
     | 
    
         | 
| 
       164 
134 
     | 
    
         
             
                sig { params(node: Prism::SingletonClassNode).void }
         
     | 
| 
         @@ -200,9 +170,7 @@ module RubyIndexer 
     | 
|
| 
       200 
170 
     | 
    
         | 
| 
       201 
171 
     | 
    
         
             
                sig { params(node: Prism::SingletonClassNode).void }
         
     | 
| 
       202 
172 
     | 
    
         
             
                def on_singleton_class_node_leave(node)
         
     | 
| 
       203 
     | 
    
         
            -
                   
     | 
| 
       204 
     | 
    
         
            -
                  @owner_stack.pop
         
     | 
| 
       205 
     | 
    
         
            -
                  @visibility_stack.pop
         
     | 
| 
      
 173 
     | 
    
         
            +
                  pop_namespace_stack
         
     | 
| 
       206 
174 
     | 
    
         
             
                end
         
     | 
| 
       207 
175 
     | 
    
         | 
| 
       208 
176 
     | 
    
         
             
                sig { params(node: Prism::MultiWriteNode).void }
         
     | 
| 
         @@ -317,7 +285,7 @@ module RubyIndexer 
     | 
|
| 
       317 
285 
     | 
    
         
             
                  end
         
     | 
| 
       318 
286 
     | 
    
         | 
| 
       319 
287 
     | 
    
         
             
                  @enhancements.each do |enhancement|
         
     | 
| 
       320 
     | 
    
         
            -
                    enhancement.on_call_node_enter( 
     | 
| 
      
 288 
     | 
    
         
            +
                    enhancement.on_call_node_enter(node)
         
     | 
| 
       321 
289 
     | 
    
         
             
                  rescue StandardError => e
         
     | 
| 
       322 
290 
     | 
    
         
             
                    @indexing_errors << <<~MSG
         
     | 
| 
       323 
291 
     | 
    
         
             
                      Indexing error in #{@file_path} with '#{enhancement.class.name}' on call node enter enhancement: #{e.message}
         
     | 
| 
         @@ -338,7 +306,7 @@ module RubyIndexer 
     | 
|
| 
       338 
306 
     | 
    
         
             
                  end
         
     | 
| 
       339 
307 
     | 
    
         | 
| 
       340 
308 
     | 
    
         
             
                  @enhancements.each do |enhancement|
         
     | 
| 
       341 
     | 
    
         
            -
                    enhancement.on_call_node_leave( 
     | 
| 
      
 309 
     | 
    
         
            +
                    enhancement.on_call_node_leave(node)
         
     | 
| 
       342 
310 
     | 
    
         
             
                  rescue StandardError => e
         
     | 
| 
       343 
311 
     | 
    
         
             
                    @indexing_errors << <<~MSG
         
     | 
| 
       344 
312 
     | 
    
         
             
                      Indexing error in #{@file_path} with '#{enhancement.class.name}' on call node leave enhancement: #{e.message}
         
     | 
| 
         @@ -463,6 +431,98 @@ module RubyIndexer 
     | 
|
| 
       463 
431 
     | 
    
         
             
                  )
         
     | 
| 
       464 
432 
     | 
    
         
             
                end
         
     | 
| 
       465 
433 
     | 
    
         | 
| 
      
 434 
     | 
    
         
            +
                sig do
         
     | 
| 
      
 435 
     | 
    
         
            +
                  params(
         
     | 
| 
      
 436 
     | 
    
         
            +
                    name: String,
         
     | 
| 
      
 437 
     | 
    
         
            +
                    node_location: Prism::Location,
         
     | 
| 
      
 438 
     | 
    
         
            +
                    signatures: T::Array[Entry::Signature],
         
     | 
| 
      
 439 
     | 
    
         
            +
                    visibility: Entry::Visibility,
         
     | 
| 
      
 440 
     | 
    
         
            +
                    comments: T.nilable(String),
         
     | 
| 
      
 441 
     | 
    
         
            +
                  ).void
         
     | 
| 
      
 442 
     | 
    
         
            +
                end
         
     | 
| 
      
 443 
     | 
    
         
            +
                def add_method(name, node_location, signatures, visibility: Entry::Visibility::PUBLIC, comments: nil)
         
     | 
| 
      
 444 
     | 
    
         
            +
                  location = Location.from_prism_location(node_location, @code_units_cache)
         
     | 
| 
      
 445 
     | 
    
         
            +
             
     | 
| 
      
 446 
     | 
    
         
            +
                  @index.add(Entry::Method.new(
         
     | 
| 
      
 447 
     | 
    
         
            +
                    name,
         
     | 
| 
      
 448 
     | 
    
         
            +
                    @file_path,
         
     | 
| 
      
 449 
     | 
    
         
            +
                    location,
         
     | 
| 
      
 450 
     | 
    
         
            +
                    location,
         
     | 
| 
      
 451 
     | 
    
         
            +
                    comments,
         
     | 
| 
      
 452 
     | 
    
         
            +
                    signatures,
         
     | 
| 
      
 453 
     | 
    
         
            +
                    visibility,
         
     | 
| 
      
 454 
     | 
    
         
            +
                    @owner_stack.last,
         
     | 
| 
      
 455 
     | 
    
         
            +
                  ))
         
     | 
| 
      
 456 
     | 
    
         
            +
                end
         
     | 
| 
      
 457 
     | 
    
         
            +
             
     | 
| 
      
 458 
     | 
    
         
            +
                sig do
         
     | 
| 
      
 459 
     | 
    
         
            +
                  params(
         
     | 
| 
      
 460 
     | 
    
         
            +
                    name: String,
         
     | 
| 
      
 461 
     | 
    
         
            +
                    full_location: Prism::Location,
         
     | 
| 
      
 462 
     | 
    
         
            +
                    name_location: Prism::Location,
         
     | 
| 
      
 463 
     | 
    
         
            +
                    comments: T.nilable(String),
         
     | 
| 
      
 464 
     | 
    
         
            +
                  ).void
         
     | 
| 
      
 465 
     | 
    
         
            +
                end
         
     | 
| 
      
 466 
     | 
    
         
            +
                def add_module(name, full_location, name_location, comments: nil)
         
     | 
| 
      
 467 
     | 
    
         
            +
                  location = Location.from_prism_location(full_location, @code_units_cache)
         
     | 
| 
      
 468 
     | 
    
         
            +
                  name_loc = Location.from_prism_location(name_location, @code_units_cache)
         
     | 
| 
      
 469 
     | 
    
         
            +
             
     | 
| 
      
 470 
     | 
    
         
            +
                  entry = Entry::Module.new(
         
     | 
| 
      
 471 
     | 
    
         
            +
                    actual_nesting(name),
         
     | 
| 
      
 472 
     | 
    
         
            +
                    @file_path,
         
     | 
| 
      
 473 
     | 
    
         
            +
                    location,
         
     | 
| 
      
 474 
     | 
    
         
            +
                    name_loc,
         
     | 
| 
      
 475 
     | 
    
         
            +
                    comments,
         
     | 
| 
      
 476 
     | 
    
         
            +
                  )
         
     | 
| 
      
 477 
     | 
    
         
            +
             
     | 
| 
      
 478 
     | 
    
         
            +
                  advance_namespace_stack(name, entry)
         
     | 
| 
      
 479 
     | 
    
         
            +
                end
         
     | 
| 
      
 480 
     | 
    
         
            +
             
     | 
| 
      
 481 
     | 
    
         
            +
                sig do
         
     | 
| 
      
 482 
     | 
    
         
            +
                  params(
         
     | 
| 
      
 483 
     | 
    
         
            +
                    name_or_nesting: T.any(String, T::Array[String]),
         
     | 
| 
      
 484 
     | 
    
         
            +
                    full_location: Prism::Location,
         
     | 
| 
      
 485 
     | 
    
         
            +
                    name_location: Prism::Location,
         
     | 
| 
      
 486 
     | 
    
         
            +
                    parent_class_name: T.nilable(String),
         
     | 
| 
      
 487 
     | 
    
         
            +
                    comments: T.nilable(String),
         
     | 
| 
      
 488 
     | 
    
         
            +
                  ).void
         
     | 
| 
      
 489 
     | 
    
         
            +
                end
         
     | 
| 
      
 490 
     | 
    
         
            +
                def add_class(name_or_nesting, full_location, name_location, parent_class_name: nil, comments: nil)
         
     | 
| 
      
 491 
     | 
    
         
            +
                  nesting = name_or_nesting.is_a?(Array) ? name_or_nesting : actual_nesting(name_or_nesting)
         
     | 
| 
      
 492 
     | 
    
         
            +
                  entry = Entry::Class.new(
         
     | 
| 
      
 493 
     | 
    
         
            +
                    nesting,
         
     | 
| 
      
 494 
     | 
    
         
            +
                    @file_path,
         
     | 
| 
      
 495 
     | 
    
         
            +
                    Location.from_prism_location(full_location, @code_units_cache),
         
     | 
| 
      
 496 
     | 
    
         
            +
                    Location.from_prism_location(name_location, @code_units_cache),
         
     | 
| 
      
 497 
     | 
    
         
            +
                    comments,
         
     | 
| 
      
 498 
     | 
    
         
            +
                    parent_class_name,
         
     | 
| 
      
 499 
     | 
    
         
            +
                  )
         
     | 
| 
      
 500 
     | 
    
         
            +
             
     | 
| 
      
 501 
     | 
    
         
            +
                  advance_namespace_stack(T.must(nesting.last), entry)
         
     | 
| 
      
 502 
     | 
    
         
            +
                end
         
     | 
| 
      
 503 
     | 
    
         
            +
             
     | 
| 
      
 504 
     | 
    
         
            +
                sig { params(block: T.proc.params(index: Index, base: Entry::Namespace).void).void }
         
     | 
| 
      
 505 
     | 
    
         
            +
                def register_included_hook(&block)
         
     | 
| 
      
 506 
     | 
    
         
            +
                  owner = @owner_stack.last
         
     | 
| 
      
 507 
     | 
    
         
            +
                  return unless owner
         
     | 
| 
      
 508 
     | 
    
         
            +
             
     | 
| 
      
 509 
     | 
    
         
            +
                  @index.register_included_hook(owner.name) do |index, base|
         
     | 
| 
      
 510 
     | 
    
         
            +
                    block.call(index, base)
         
     | 
| 
      
 511 
     | 
    
         
            +
                  end
         
     | 
| 
      
 512 
     | 
    
         
            +
                end
         
     | 
| 
      
 513 
     | 
    
         
            +
             
     | 
| 
      
 514 
     | 
    
         
            +
                sig { void }
         
     | 
| 
      
 515 
     | 
    
         
            +
                def pop_namespace_stack
         
     | 
| 
      
 516 
     | 
    
         
            +
                  @stack.pop
         
     | 
| 
      
 517 
     | 
    
         
            +
                  @owner_stack.pop
         
     | 
| 
      
 518 
     | 
    
         
            +
                  @visibility_stack.pop
         
     | 
| 
      
 519 
     | 
    
         
            +
                end
         
     | 
| 
      
 520 
     | 
    
         
            +
             
     | 
| 
      
 521 
     | 
    
         
            +
                sig { returns(T.nilable(Entry::Namespace)) }
         
     | 
| 
      
 522 
     | 
    
         
            +
                def current_owner
         
     | 
| 
      
 523 
     | 
    
         
            +
                  @owner_stack.last
         
     | 
| 
      
 524 
     | 
    
         
            +
                end
         
     | 
| 
      
 525 
     | 
    
         
            +
             
     | 
| 
       466 
526 
     | 
    
         
             
                private
         
     | 
| 
       467 
527 
     | 
    
         | 
| 
       468 
528 
     | 
    
         
             
                sig do
         
     | 
| 
         @@ -661,8 +721,7 @@ module RubyIndexer 
     | 
|
| 
       661 
721 
     | 
    
         
             
                  comments = +""
         
     | 
| 
       662 
722 
     | 
    
         | 
| 
       663 
723 
     | 
    
         
             
                  start_line = node.location.start_line - 1
         
     | 
| 
       664 
     | 
    
         
            -
                  start_line -= 1 unless  
     | 
| 
       665 
     | 
    
         
            -
             
     | 
| 
      
 724 
     | 
    
         
            +
                  start_line -= 1 unless comment_exists_at?(start_line)
         
     | 
| 
       666 
725 
     | 
    
         
             
                  start_line.downto(1) do |line|
         
     | 
| 
       667 
726 
     | 
    
         
             
                    comment = @comments_by_line[line]
         
     | 
| 
       668 
727 
     | 
    
         
             
                    break unless comment
         
     | 
| 
         @@ -683,6 +742,11 @@ module RubyIndexer 
     | 
|
| 
       683 
742 
     | 
    
         
             
                  comments
         
     | 
| 
       684 
743 
     | 
    
         
             
                end
         
     | 
| 
       685 
744 
     | 
    
         | 
| 
      
 745 
     | 
    
         
            +
                sig { params(line: Integer).returns(T::Boolean) }
         
     | 
| 
      
 746 
     | 
    
         
            +
                def comment_exists_at?(line)
         
     | 
| 
      
 747 
     | 
    
         
            +
                  @comments_by_line.key?(line) || !@source_lines[line - 1].to_s.strip.empty?
         
     | 
| 
      
 748 
     | 
    
         
            +
                end
         
     | 
| 
      
 749 
     | 
    
         
            +
             
     | 
| 
       686 
750 
     | 
    
         
             
                sig { params(name: String).returns(String) }
         
     | 
| 
       687 
751 
     | 
    
         
             
                def fully_qualify_name(name)
         
     | 
| 
       688 
752 
     | 
    
         
             
                  if @stack.empty? || name.start_with?("::")
         
     | 
| 
         @@ -746,16 +810,22 @@ module RubyIndexer 
     | 
|
| 
       746 
810 
     | 
    
         
             
                  return unless arguments
         
     | 
| 
       747 
811 
     | 
    
         | 
| 
       748 
812 
     | 
    
         
             
                  arguments.each do |node|
         
     | 
| 
       749 
     | 
    
         
            -
                    next unless node.is_a?(Prism::ConstantReadNode) || node.is_a?(Prism::ConstantPathNode)
         
     | 
| 
       750 
     | 
    
         
            -
             
     | 
| 
       751 
     | 
    
         
            -
             
     | 
| 
       752 
     | 
    
         
            -
                     
     | 
| 
       753 
     | 
    
         
            -
                      owner.mixin_operations << Entry::Include.new(node.full_name)
         
     | 
| 
       754 
     | 
    
         
            -
                    when :prepend
         
     | 
| 
       755 
     | 
    
         
            -
                      owner.mixin_operations << Entry::Prepend.new(node.full_name)
         
     | 
| 
       756 
     | 
    
         
            -
                    when :extend
         
     | 
| 
      
 813 
     | 
    
         
            +
                    next unless node.is_a?(Prism::ConstantReadNode) || node.is_a?(Prism::ConstantPathNode) ||
         
     | 
| 
      
 814 
     | 
    
         
            +
                      (node.is_a?(Prism::SelfNode) && operation == :extend)
         
     | 
| 
      
 815 
     | 
    
         
            +
             
     | 
| 
      
 816 
     | 
    
         
            +
                    if node.is_a?(Prism::SelfNode)
         
     | 
| 
       757 
817 
     | 
    
         
             
                      singleton = @index.existing_or_new_singleton_class(owner.name)
         
     | 
| 
       758 
     | 
    
         
            -
                      singleton.mixin_operations << Entry::Include.new( 
     | 
| 
      
 818 
     | 
    
         
            +
                      singleton.mixin_operations << Entry::Include.new(owner.name)
         
     | 
| 
      
 819 
     | 
    
         
            +
                    else
         
     | 
| 
      
 820 
     | 
    
         
            +
                      case operation
         
     | 
| 
      
 821 
     | 
    
         
            +
                      when :include
         
     | 
| 
      
 822 
     | 
    
         
            +
                        owner.mixin_operations << Entry::Include.new(node.full_name)
         
     | 
| 
      
 823 
     | 
    
         
            +
                      when :prepend
         
     | 
| 
      
 824 
     | 
    
         
            +
                        owner.mixin_operations << Entry::Prepend.new(node.full_name)
         
     | 
| 
      
 825 
     | 
    
         
            +
                      when :extend
         
     | 
| 
      
 826 
     | 
    
         
            +
                        singleton = @index.existing_or_new_singleton_class(owner.name)
         
     | 
| 
      
 827 
     | 
    
         
            +
                        singleton.mixin_operations << Entry::Include.new(node.full_name)
         
     | 
| 
      
 828 
     | 
    
         
            +
                      end
         
     | 
| 
       759 
829 
     | 
    
         
             
                    end
         
     | 
| 
       760 
830 
     | 
    
         
             
                  rescue Prism::ConstantPathNode::DynamicPartsInConstantPathError,
         
     | 
| 
       761 
831 
     | 
    
         
             
                         Prism::ConstantPathNode::MissingNodesInConstantPathError
         
     | 
| 
         @@ -910,5 +980,13 @@ module RubyIndexer 
     | 
|
| 
       910 
980 
     | 
    
         | 
| 
       911 
981 
     | 
    
         
             
                  corrected_nesting
         
     | 
| 
       912 
982 
     | 
    
         
             
                end
         
     | 
| 
      
 983 
     | 
    
         
            +
             
     | 
| 
      
 984 
     | 
    
         
            +
                sig { params(short_name: String, entry: Entry::Namespace).void }
         
     | 
| 
      
 985 
     | 
    
         
            +
                def advance_namespace_stack(short_name, entry)
         
     | 
| 
      
 986 
     | 
    
         
            +
                  @visibility_stack.push(Entry::Visibility::PUBLIC)
         
     | 
| 
      
 987 
     | 
    
         
            +
                  @owner_stack << entry
         
     | 
| 
      
 988 
     | 
    
         
            +
                  @index.add(entry)
         
     | 
| 
      
 989 
     | 
    
         
            +
                  @stack << short_name
         
     | 
| 
      
 990 
     | 
    
         
            +
                end
         
     | 
| 
       913 
991 
     | 
    
         
             
              end
         
     | 
| 
       914 
992 
     | 
    
         
             
            end
         
     | 
| 
         @@ -8,38 +8,41 @@ module RubyIndexer 
     | 
|
| 
       8 
8 
     | 
    
         | 
| 
       9 
9 
     | 
    
         
             
                abstract!
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
       11 
     | 
    
         
            -
                 
     | 
| 
       12 
     | 
    
         
            -
             
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
      
 11 
     | 
    
         
            +
                @enhancements = T.let([], T::Array[T::Class[Enhancement]])
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                class << self
         
     | 
| 
      
 14 
     | 
    
         
            +
                  extend T::Sig
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  sig { params(child: T::Class[Enhancement]).void }
         
     | 
| 
      
 17 
     | 
    
         
            +
                  def inherited(child)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    @enhancements << child
         
     | 
| 
      
 19 
     | 
    
         
            +
                    super
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  sig { params(listener: DeclarationListener).returns(T::Array[Enhancement]) }
         
     | 
| 
      
 23 
     | 
    
         
            +
                  def all(listener)
         
     | 
| 
      
 24 
     | 
    
         
            +
                    @enhancements.map { |enhancement| enhancement.new(listener) }
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  # Only available for testing purposes
         
     | 
| 
      
 28 
     | 
    
         
            +
                  sig { void }
         
     | 
| 
      
 29 
     | 
    
         
            +
                  def clear
         
     | 
| 
      
 30 
     | 
    
         
            +
                    @enhancements.clear
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                sig { params(listener: DeclarationListener).void }
         
     | 
| 
      
 35 
     | 
    
         
            +
                def initialize(listener)
         
     | 
| 
      
 36 
     | 
    
         
            +
                  @listener = listener
         
     | 
| 
       14 
37 
     | 
    
         
             
                end
         
     | 
| 
       15 
38 
     | 
    
         | 
| 
       16 
39 
     | 
    
         
             
                # The `on_extend` indexing enhancement is invoked whenever an extend is encountered in the code. It can be used to
         
     | 
| 
       17 
40 
     | 
    
         
             
                # register for an included callback, similar to what `ActiveSupport::Concern` does in order to auto-extend the
         
     | 
| 
       18 
41 
     | 
    
         
             
                # `ClassMethods` modules
         
     | 
| 
       19 
     | 
    
         
            -
                sig  
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
             
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
                    code_units_cache: T.any(
         
     | 
| 
       25 
     | 
    
         
            -
                      T.proc.params(arg0: Integer).returns(Integer),
         
     | 
| 
       26 
     | 
    
         
            -
                      Prism::CodeUnitsCache,
         
     | 
| 
       27 
     | 
    
         
            -
                    ),
         
     | 
| 
       28 
     | 
    
         
            -
                  ).void
         
     | 
| 
       29 
     | 
    
         
            -
                end
         
     | 
| 
       30 
     | 
    
         
            -
                def on_call_node_enter(owner, node, file_path, code_units_cache); end
         
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
     | 
    
         
            -
                sig do
         
     | 
| 
       33 
     | 
    
         
            -
                  overridable.params(
         
     | 
| 
       34 
     | 
    
         
            -
                    owner: T.nilable(Entry::Namespace),
         
     | 
| 
       35 
     | 
    
         
            -
                    node: Prism::CallNode,
         
     | 
| 
       36 
     | 
    
         
            -
                    file_path: String,
         
     | 
| 
       37 
     | 
    
         
            -
                    code_units_cache: T.any(
         
     | 
| 
       38 
     | 
    
         
            -
                      T.proc.params(arg0: Integer).returns(Integer),
         
     | 
| 
       39 
     | 
    
         
            -
                      Prism::CodeUnitsCache,
         
     | 
| 
       40 
     | 
    
         
            -
                    ),
         
     | 
| 
       41 
     | 
    
         
            -
                  ).void
         
     | 
| 
       42 
     | 
    
         
            -
                end
         
     | 
| 
       43 
     | 
    
         
            -
                def on_call_node_leave(owner, node, file_path, code_units_cache); end
         
     | 
| 
      
 42 
     | 
    
         
            +
                sig { overridable.params(node: Prism::CallNode).void }
         
     | 
| 
      
 43 
     | 
    
         
            +
                def on_call_node_enter(node); end # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                sig { overridable.params(node: Prism::CallNode).void }
         
     | 
| 
      
 46 
     | 
    
         
            +
                def on_call_node_leave(node); end # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
         
     | 
| 
       44 
47 
     | 
    
         
             
              end
         
     | 
| 
       45 
48 
     | 
    
         
             
            end
         
     | 
| 
         @@ -7,6 +7,7 @@ module RubyIndexer 
     | 
|
| 
       7 
7 
     | 
    
         | 
| 
       8 
8 
     | 
    
         
             
                class UnresolvableAliasError < StandardError; end
         
     | 
| 
       9 
9 
     | 
    
         
             
                class NonExistingNamespaceError < StandardError; end
         
     | 
| 
      
 10 
     | 
    
         
            +
                class IndexNotEmptyError < StandardError; end
         
     | 
| 
       10 
11 
     | 
    
         | 
| 
       11 
12 
     | 
    
         
             
                # The minimum Jaro-Winkler similarity score for an entry to be considered a match for a given fuzzy search query
         
     | 
| 
       12 
13 
     | 
    
         
             
                ENTRY_SIMILARITY_THRESHOLD = 0.7
         
     | 
| 
         @@ -39,9 +40,6 @@ module RubyIndexer 
     | 
|
| 
       39 
40 
     | 
    
         
             
                  # Holds the linearized ancestors list for every namespace
         
     | 
| 
       40 
41 
     | 
    
         
             
                  @ancestors = T.let({}, T::Hash[String, T::Array[String]])
         
     | 
| 
       41 
42 
     | 
    
         | 
| 
       42 
     | 
    
         
            -
                  # List of classes that are enhancing the index
         
     | 
| 
       43 
     | 
    
         
            -
                  @enhancements = T.let([], T::Array[Enhancement])
         
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
43 
     | 
    
         
             
                  # Map of module name to included hooks that have to be executed when we include the given module
         
     | 
| 
       46 
44 
     | 
    
         
             
                  @included_hooks = T.let(
         
     | 
| 
       47 
45 
     | 
    
         
             
                    {},
         
     | 
| 
         @@ -51,12 +49,6 @@ module RubyIndexer 
     | 
|
| 
       51 
49 
     | 
    
         
             
                  @configuration = T.let(RubyIndexer::Configuration.new, Configuration)
         
     | 
| 
       52 
50 
     | 
    
         
             
                end
         
     | 
| 
       53 
51 
     | 
    
         | 
| 
       54 
     | 
    
         
            -
                # Register an enhancement to the index. Enhancements must conform to the `Enhancement` interface
         
     | 
| 
       55 
     | 
    
         
            -
                sig { params(enhancement: Enhancement).void }
         
     | 
| 
       56 
     | 
    
         
            -
                def register_enhancement(enhancement)
         
     | 
| 
       57 
     | 
    
         
            -
                  @enhancements << enhancement
         
     | 
| 
       58 
     | 
    
         
            -
                end
         
     | 
| 
       59 
     | 
    
         
            -
             
     | 
| 
       60 
52 
     | 
    
         
             
                # Register an included `hook` that will be executed when `module_name` is included into any namespace
         
     | 
| 
       61 
53 
     | 
    
         
             
                sig { params(module_name: String, hook: T.proc.params(index: Index, base: Entry::Namespace).void).void }
         
     | 
| 
       62 
54 
     | 
    
         
             
                def register_included_hook(module_name, &hook)
         
     | 
| 
         @@ -360,6 +352,15 @@ module RubyIndexer 
     | 
|
| 
       360 
352 
     | 
    
         
             
                  ).void
         
     | 
| 
       361 
353 
     | 
    
         
             
                end
         
     | 
| 
       362 
354 
     | 
    
         
             
                def index_all(indexable_paths: @configuration.indexables, &block)
         
     | 
| 
      
 355 
     | 
    
         
            +
                  # When troubleshooting an indexing issue, e.g. through irb, it's not obvious that `index_all` will augment the
         
     | 
| 
      
 356 
     | 
    
         
            +
                  # existing index values, meaning it may contain 'stale' entries. This check ensures that the user is aware of this
         
     | 
| 
      
 357 
     | 
    
         
            +
                  # behavior and can take appropriate action.
         
     | 
| 
      
 358 
     | 
    
         
            +
                  # binding.break
         
     | 
| 
      
 359 
     | 
    
         
            +
                  if @entries.any?
         
     | 
| 
      
 360 
     | 
    
         
            +
                    raise IndexNotEmptyError,
         
     | 
| 
      
 361 
     | 
    
         
            +
                      "The index is not empty. To prevent invalid entries, `index_all` can only be called once."
         
     | 
| 
      
 362 
     | 
    
         
            +
                  end
         
     | 
| 
      
 363 
     | 
    
         
            +
             
     | 
| 
       363 
364 
     | 
    
         
             
                  RBSIndexer.new(self).index_ruby_core
         
     | 
| 
       364 
365 
     | 
    
         
             
                  # Calculate how many paths are worth 1% of progress
         
     | 
| 
       365 
366 
     | 
    
         
             
                  progress_step = (indexable_paths.length / 100.0).ceil
         
     | 
| 
         @@ -386,7 +387,6 @@ module RubyIndexer 
     | 
|
| 
       386 
387 
     | 
    
         
             
                    result,
         
     | 
| 
       387 
388 
     | 
    
         
             
                    indexable_path.full_path,
         
     | 
| 
       388 
389 
     | 
    
         
             
                    collect_comments: collect_comments,
         
     | 
| 
       389 
     | 
    
         
            -
                    enhancements: @enhancements,
         
     | 
| 
       390 
390 
     | 
    
         
             
                  )
         
     | 
| 
       391 
391 
     | 
    
         
             
                  dispatcher.dispatch(result.value)
         
     | 
| 
       392 
392 
     | 
    
         | 
| 
         @@ -302,10 +302,10 @@ module RubyIndexer 
     | 
|
| 
       302 
302 
     | 
    
         
             
                  RUBY
         
     | 
| 
       303 
303 
     | 
    
         | 
| 
       304 
304 
     | 
    
         
             
                  b_const = @index["A::B"].first
         
     | 
| 
       305 
     | 
    
         
            -
                   
     | 
| 
      
 305 
     | 
    
         
            +
                  assert_predicate(b_const, :private?)
         
     | 
| 
       306 
306 
     | 
    
         | 
| 
       307 
307 
     | 
    
         
             
                  c_const = @index["A::C"].first
         
     | 
| 
       308 
     | 
    
         
            -
                   
     | 
| 
      
 308 
     | 
    
         
            +
                  assert_predicate(c_const, :private?)
         
     | 
| 
       309 
309 
     | 
    
         | 
| 
       310 
310 
     | 
    
         
             
                  d_const = @index["A::D"].first
         
     | 
| 
       311 
311 
     | 
    
         
             
                  assert_equal(Entry::Visibility::PUBLIC, d_const.visibility)
         
     | 
| 
         @@ -160,5 +160,15 @@ module RubyIndexer 
     | 
|
| 
       160 
160 
     | 
    
         
             
                    )
         
     | 
| 
       161 
161 
     | 
    
         
             
                  end
         
     | 
| 
       162 
162 
     | 
    
         
             
                end
         
     | 
| 
      
 163 
     | 
    
         
            +
             
     | 
| 
      
 164 
     | 
    
         
            +
                def test_includes_top_level_files
         
     | 
| 
      
 165 
     | 
    
         
            +
                  Dir.mktmpdir do |dir|
         
     | 
| 
      
 166 
     | 
    
         
            +
                    FileUtils.touch(File.join(dir, "find_me.rb"))
         
     | 
| 
      
 167 
     | 
    
         
            +
                    @config.workspace_path = dir
         
     | 
| 
      
 168 
     | 
    
         
            +
             
     | 
| 
      
 169 
     | 
    
         
            +
                    indexables = @config.indexables
         
     | 
| 
      
 170 
     | 
    
         
            +
                    assert(indexables.find { |i| File.basename(i.full_path) == "find_me.rb" })
         
     | 
| 
      
 171 
     | 
    
         
            +
                  end
         
     | 
| 
      
 172 
     | 
    
         
            +
                end
         
     | 
| 
       163 
173 
     | 
    
         
             
              end
         
     | 
| 
       164 
174 
     | 
    
         
             
            end
         
     | 
| 
         @@ -130,13 +130,13 @@ module RubyIndexer 
     | 
|
| 
       130 
130 
     | 
    
         
             
                  RUBY
         
     | 
| 
       131 
131 
     | 
    
         | 
| 
       132 
132 
     | 
    
         
             
                  b_const = @index["A::B"].first
         
     | 
| 
       133 
     | 
    
         
            -
                   
     | 
| 
      
 133 
     | 
    
         
            +
                  assert_predicate(b_const, :private?)
         
     | 
| 
       134 
134 
     | 
    
         | 
| 
       135 
135 
     | 
    
         
             
                  c_const = @index["A::C"].first
         
     | 
| 
       136 
     | 
    
         
            -
                   
     | 
| 
      
 136 
     | 
    
         
            +
                  assert_predicate(c_const, :private?)
         
     | 
| 
       137 
137 
     | 
    
         | 
| 
       138 
138 
     | 
    
         
             
                  d_const = @index["A::D"].first
         
     | 
| 
       139 
     | 
    
         
            -
                   
     | 
| 
      
 139 
     | 
    
         
            +
                  assert_predicate(d_const, :public?)
         
     | 
| 
       140 
140 
     | 
    
         
             
                end
         
     | 
| 
       141 
141 
     | 
    
         | 
| 
       142 
142 
     | 
    
         
             
                def test_marking_constants_as_private_reopening_namespaces
         
     | 
| 
         @@ -163,13 +163,13 @@ module RubyIndexer 
     | 
|
| 
       163 
163 
     | 
    
         
             
                  RUBY
         
     | 
| 
       164 
164 
     | 
    
         | 
| 
       165 
165 
     | 
    
         
             
                  a_const = @index["A::B::CONST_A"].first
         
     | 
| 
       166 
     | 
    
         
            -
                   
     | 
| 
      
 166 
     | 
    
         
            +
                  assert_predicate(a_const, :private?)
         
     | 
| 
       167 
167 
     | 
    
         | 
| 
       168 
168 
     | 
    
         
             
                  b_const = @index["A::B::CONST_B"].first
         
     | 
| 
       169 
     | 
    
         
            -
                   
     | 
| 
      
 169 
     | 
    
         
            +
                  assert_predicate(b_const, :private?)
         
     | 
| 
       170 
170 
     | 
    
         | 
| 
       171 
171 
     | 
    
         
             
                  c_const = @index["A::B::CONST_C"].first
         
     | 
| 
       172 
     | 
    
         
            -
                   
     | 
| 
      
 172 
     | 
    
         
            +
                  assert_predicate(c_const, :private?)
         
     | 
| 
       173 
173 
     | 
    
         
             
                end
         
     | 
| 
       174 
174 
     | 
    
         | 
| 
       175 
175 
     | 
    
         
             
                def test_marking_constants_as_private_with_receiver
         
     | 
| 
         @@ -187,10 +187,10 @@ module RubyIndexer 
     | 
|
| 
       187 
187 
     | 
    
         
             
                  RUBY
         
     | 
| 
       188 
188 
     | 
    
         | 
| 
       189 
189 
     | 
    
         
             
                  a_const = @index["A::B::CONST_A"].first
         
     | 
| 
       190 
     | 
    
         
            -
                   
     | 
| 
      
 190 
     | 
    
         
            +
                  assert_predicate(a_const, :private?)
         
     | 
| 
       191 
191 
     | 
    
         | 
| 
       192 
192 
     | 
    
         
             
                  b_const = @index["A::B::CONST_B"].first
         
     | 
| 
       193 
     | 
    
         
            -
                   
     | 
| 
      
 193 
     | 
    
         
            +
                  assert_predicate(b_const, :private?)
         
     | 
| 
       194 
194 
     | 
    
         
             
                end
         
     | 
| 
       195 
195 
     | 
    
         | 
| 
       196 
196 
     | 
    
         
             
                def test_indexing_constant_aliases
         
     | 
| 
         @@ -5,24 +5,28 @@ require_relative "test_case" 
     | 
|
| 
       5 
5 
     | 
    
         | 
| 
       6 
6 
     | 
    
         
             
            module RubyIndexer
         
     | 
| 
       7 
7 
     | 
    
         
             
              class EnhancementTest < TestCase
         
     | 
| 
      
 8 
     | 
    
         
            +
                def teardown
         
     | 
| 
      
 9 
     | 
    
         
            +
                  super
         
     | 
| 
      
 10 
     | 
    
         
            +
                  Enhancement.clear
         
     | 
| 
      
 11 
     | 
    
         
            +
                end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
       8 
13 
     | 
    
         
             
                def test_enhancing_indexing_included_hook
         
     | 
| 
       9 
     | 
    
         
            -
                   
     | 
| 
       10 
     | 
    
         
            -
                    def on_call_node_enter( 
     | 
| 
      
 14 
     | 
    
         
            +
                  Class.new(Enhancement) do
         
     | 
| 
      
 15 
     | 
    
         
            +
                    def on_call_node_enter(call_node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
         
     | 
| 
      
 16 
     | 
    
         
            +
                      owner = @listener.current_owner
         
     | 
| 
       11 
17 
     | 
    
         
             
                      return unless owner
         
     | 
| 
       12 
     | 
    
         
            -
                      return unless  
     | 
| 
      
 18 
     | 
    
         
            +
                      return unless call_node.name == :extend
         
     | 
| 
       13 
19 
     | 
    
         | 
| 
       14 
     | 
    
         
            -
                      arguments =  
     | 
| 
      
 20 
     | 
    
         
            +
                      arguments = call_node.arguments&.arguments
         
     | 
| 
       15 
21 
     | 
    
         
             
                      return unless arguments
         
     | 
| 
       16 
22 
     | 
    
         | 
| 
       17 
     | 
    
         
            -
                      location = Location.from_prism_location(node.location, code_units_cache)
         
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
23 
     | 
    
         
             
                      arguments.each do |node|
         
     | 
| 
       20 
24 
     | 
    
         
             
                        next unless node.is_a?(Prism::ConstantReadNode) || node.is_a?(Prism::ConstantPathNode)
         
     | 
| 
       21 
25 
     | 
    
         | 
| 
       22 
26 
     | 
    
         
             
                        module_name = node.full_name
         
     | 
| 
       23 
27 
     | 
    
         
             
                        next unless module_name == "ActiveSupport::Concern"
         
     | 
| 
       24 
28 
     | 
    
         | 
| 
       25 
     | 
    
         
            -
                        @ 
     | 
| 
      
 29 
     | 
    
         
            +
                        @listener.register_included_hook do |index, base|
         
     | 
| 
       26 
30 
     | 
    
         
             
                          class_methods_name = "#{owner.name}::ClassMethods"
         
     | 
| 
       27 
31 
     | 
    
         | 
| 
       28 
32 
     | 
    
         
             
                          if index.indexed?(class_methods_name)
         
     | 
| 
         @@ -31,16 +35,11 @@ module RubyIndexer 
     | 
|
| 
       31 
35 
     | 
    
         
             
                          end
         
     | 
| 
       32 
36 
     | 
    
         
             
                        end
         
     | 
| 
       33 
37 
     | 
    
         | 
| 
       34 
     | 
    
         
            -
                        @ 
     | 
| 
      
 38 
     | 
    
         
            +
                        @listener.add_method(
         
     | 
| 
       35 
39 
     | 
    
         
             
                          "new_method",
         
     | 
| 
       36 
     | 
    
         
            -
                           
     | 
| 
       37 
     | 
    
         
            -
                          location,
         
     | 
| 
       38 
     | 
    
         
            -
                          location,
         
     | 
| 
       39 
     | 
    
         
            -
                          nil,
         
     | 
| 
      
 40 
     | 
    
         
            +
                          call_node.location,
         
     | 
| 
       40 
41 
     | 
    
         
             
                          [Entry::Signature.new([Entry::RequiredParameter.new(name: :a)])],
         
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
       42 
     | 
    
         
            -
                          owner,
         
     | 
| 
       43 
     | 
    
         
            -
                        ))
         
     | 
| 
      
 42 
     | 
    
         
            +
                        )
         
     | 
| 
       44 
43 
     | 
    
         
             
                      rescue Prism::ConstantPathNode::DynamicPartsInConstantPathError,
         
     | 
| 
       45 
44 
     | 
    
         
             
                             Prism::ConstantPathNode::MissingNodesInConstantPathError
         
     | 
| 
       46 
45 
     | 
    
         
             
                        # Do nothing
         
     | 
| 
         @@ -48,7 +47,6 @@ module RubyIndexer 
     | 
|
| 
       48 
47 
     | 
    
         
             
                    end
         
     | 
| 
       49 
48 
     | 
    
         
             
                  end
         
     | 
| 
       50 
49 
     | 
    
         | 
| 
       51 
     | 
    
         
            -
                  @index.register_enhancement(enhancement_class.new(@index))
         
     | 
| 
       52 
50 
     | 
    
         
             
                  index(<<~RUBY)
         
     | 
| 
       53 
51 
     | 
    
         
             
                    module ActiveSupport
         
     | 
| 
       54 
52 
     | 
    
         
             
                      module Concern
         
     | 
| 
         @@ -96,9 +94,9 @@ module RubyIndexer 
     | 
|
| 
       96 
94 
     | 
    
         
             
                end
         
     | 
| 
       97 
95 
     | 
    
         | 
| 
       98 
96 
     | 
    
         
             
                def test_enhancing_indexing_configuration_dsl
         
     | 
| 
       99 
     | 
    
         
            -
                   
     | 
| 
       100 
     | 
    
         
            -
                    def on_call_node_enter( 
     | 
| 
       101 
     | 
    
         
            -
                      return unless  
     | 
| 
      
 97 
     | 
    
         
            +
                  Class.new(Enhancement) do
         
     | 
| 
      
 98 
     | 
    
         
            +
                    def on_call_node_enter(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
         
     | 
| 
      
 99 
     | 
    
         
            +
                      return unless @listener.current_owner
         
     | 
| 
       102 
100 
     | 
    
         | 
| 
       103 
101 
     | 
    
         
             
                      name = node.name
         
     | 
| 
       104 
102 
     | 
    
         
             
                      return unless name == :has_many
         
     | 
| 
         @@ -109,22 +107,14 @@ module RubyIndexer 
     | 
|
| 
       109 
107 
     | 
    
         
             
                      association_name = arguments.first
         
     | 
| 
       110 
108 
     | 
    
         
             
                      return unless association_name.is_a?(Prism::SymbolNode)
         
     | 
| 
       111 
109 
     | 
    
         | 
| 
       112 
     | 
    
         
            -
                       
     | 
| 
       113 
     | 
    
         
            -
             
     | 
| 
       114 
     | 
    
         
            -
                      @index.add(Entry::Method.new(
         
     | 
| 
      
 110 
     | 
    
         
            +
                      @listener.add_method(
         
     | 
| 
       115 
111 
     | 
    
         
             
                        T.must(association_name.value),
         
     | 
| 
       116 
     | 
    
         
            -
                         
     | 
| 
       117 
     | 
    
         
            -
                        location,
         
     | 
| 
       118 
     | 
    
         
            -
                        location,
         
     | 
| 
       119 
     | 
    
         
            -
                        nil,
         
     | 
| 
      
 112 
     | 
    
         
            +
                        association_name.location,
         
     | 
| 
       120 
113 
     | 
    
         
             
                        [],
         
     | 
| 
       121 
     | 
    
         
            -
             
     | 
| 
       122 
     | 
    
         
            -
                        owner,
         
     | 
| 
       123 
     | 
    
         
            -
                      ))
         
     | 
| 
      
 114 
     | 
    
         
            +
                      )
         
     | 
| 
       124 
115 
     | 
    
         
             
                    end
         
     | 
| 
       125 
116 
     | 
    
         
             
                  end
         
     | 
| 
       126 
117 
     | 
    
         | 
| 
       127 
     | 
    
         
            -
                  @index.register_enhancement(enhancement_class.new(@index))
         
     | 
| 
       128 
118 
     | 
    
         
             
                  index(<<~RUBY)
         
     | 
| 
       129 
119 
     | 
    
         
             
                    module ActiveSupport
         
     | 
| 
       130 
120 
     | 
    
         
             
                      module Concern
         
     | 
| 
         @@ -157,8 +147,8 @@ module RubyIndexer 
     | 
|
| 
       157 
147 
     | 
    
         
             
                end
         
     | 
| 
       158 
148 
     | 
    
         | 
| 
       159 
149 
     | 
    
         
             
                def test_error_handling_in_on_call_node_enter_enhancement
         
     | 
| 
       160 
     | 
    
         
            -
                   
     | 
| 
       161 
     | 
    
         
            -
                    def on_call_node_enter( 
     | 
| 
      
 150 
     | 
    
         
            +
                  Class.new(Enhancement) do
         
     | 
| 
      
 151 
     | 
    
         
            +
                    def on_call_node_enter(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
         
     | 
| 
       162 
152 
     | 
    
         
             
                      raise "Error"
         
     | 
| 
       163 
153 
     | 
    
         
             
                    end
         
     | 
| 
       164 
154 
     | 
    
         | 
| 
         @@ -169,8 +159,6 @@ module RubyIndexer 
     | 
|
| 
       169 
159 
     | 
    
         
             
                    end
         
     | 
| 
       170 
160 
     | 
    
         
             
                  end
         
     | 
| 
       171 
161 
     | 
    
         | 
| 
       172 
     | 
    
         
            -
                  @index.register_enhancement(enhancement_class.new(@index))
         
     | 
| 
       173 
     | 
    
         
            -
             
     | 
| 
       174 
162 
     | 
    
         
             
                  _stdout, stderr = capture_io do
         
     | 
| 
       175 
163 
     | 
    
         
             
                    index(<<~RUBY)
         
     | 
| 
       176 
164 
     | 
    
         
             
                      module ActiveSupport
         
     | 
| 
         @@ -192,8 +180,8 @@ module RubyIndexer 
     | 
|
| 
       192 
180 
     | 
    
         
             
                end
         
     | 
| 
       193 
181 
     | 
    
         | 
| 
       194 
182 
     | 
    
         
             
                def test_error_handling_in_on_call_node_leave_enhancement
         
     | 
| 
       195 
     | 
    
         
            -
                   
     | 
| 
       196 
     | 
    
         
            -
                    def on_call_node_leave( 
     | 
| 
      
 183 
     | 
    
         
            +
                  Class.new(Enhancement) do
         
     | 
| 
      
 184 
     | 
    
         
            +
                    def on_call_node_leave(node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
         
     | 
| 
       197 
185 
     | 
    
         
             
                      raise "Error"
         
     | 
| 
       198 
186 
     | 
    
         
             
                    end
         
     | 
| 
       199 
187 
     | 
    
         | 
| 
         @@ -204,8 +192,6 @@ module RubyIndexer 
     | 
|
| 
       204 
192 
     | 
    
         
             
                    end
         
     | 
| 
       205 
193 
     | 
    
         
             
                  end
         
     | 
| 
       206 
194 
     | 
    
         | 
| 
       207 
     | 
    
         
            -
                  @index.register_enhancement(enhancement_class.new(@index))
         
     | 
| 
       208 
     | 
    
         
            -
             
     | 
| 
       209 
195 
     | 
    
         
             
                  _stdout, stderr = capture_io do
         
     | 
| 
       210 
196 
     | 
    
         
             
                    index(<<~RUBY)
         
     | 
| 
       211 
197 
     | 
    
         
             
                      module ActiveSupport
         
     | 
| 
         @@ -225,5 +211,115 @@ module RubyIndexer 
     | 
|
| 
       225 
211 
     | 
    
         
             
                  # The module should still be indexed
         
     | 
| 
       226 
212 
     | 
    
         
             
                  assert_entry("ActiveSupport::Concern", Entry::Module, "/fake/path/foo.rb:1-2:5-5")
         
     | 
| 
       227 
213 
     | 
    
         
             
                end
         
     | 
| 
      
 214 
     | 
    
         
            +
             
     | 
| 
      
 215 
     | 
    
         
            +
                def test_advancing_namespace_stack_from_enhancement
         
     | 
| 
      
 216 
     | 
    
         
            +
                  Class.new(Enhancement) do
         
     | 
| 
      
 217 
     | 
    
         
            +
                    def on_call_node_enter(call_node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
         
     | 
| 
      
 218 
     | 
    
         
            +
                      owner = @listener.current_owner
         
     | 
| 
      
 219 
     | 
    
         
            +
                      return unless owner
         
     | 
| 
      
 220 
     | 
    
         
            +
             
     | 
| 
      
 221 
     | 
    
         
            +
                      case call_node.name
         
     | 
| 
      
 222 
     | 
    
         
            +
                      when :class_methods
         
     | 
| 
      
 223 
     | 
    
         
            +
                        @listener.add_module("ClassMethods", call_node.location, call_node.location)
         
     | 
| 
      
 224 
     | 
    
         
            +
                      when :extend
         
     | 
| 
      
 225 
     | 
    
         
            +
                        arguments = call_node.arguments&.arguments
         
     | 
| 
      
 226 
     | 
    
         
            +
                        return unless arguments
         
     | 
| 
      
 227 
     | 
    
         
            +
             
     | 
| 
      
 228 
     | 
    
         
            +
                        arguments.each do |node|
         
     | 
| 
      
 229 
     | 
    
         
            +
                          next unless node.is_a?(Prism::ConstantReadNode) || node.is_a?(Prism::ConstantPathNode)
         
     | 
| 
      
 230 
     | 
    
         
            +
             
     | 
| 
      
 231 
     | 
    
         
            +
                          module_name = node.full_name
         
     | 
| 
      
 232 
     | 
    
         
            +
                          next unless module_name == "ActiveSupport::Concern"
         
     | 
| 
      
 233 
     | 
    
         
            +
             
     | 
| 
      
 234 
     | 
    
         
            +
                          @listener.register_included_hook do |index, base|
         
     | 
| 
      
 235 
     | 
    
         
            +
                            class_methods_name = "#{owner.name}::ClassMethods"
         
     | 
| 
      
 236 
     | 
    
         
            +
             
     | 
| 
      
 237 
     | 
    
         
            +
                            if index.indexed?(class_methods_name)
         
     | 
| 
      
 238 
     | 
    
         
            +
                              singleton = index.existing_or_new_singleton_class(base.name)
         
     | 
| 
      
 239 
     | 
    
         
            +
                              singleton.mixin_operations << Entry::Include.new(class_methods_name)
         
     | 
| 
      
 240 
     | 
    
         
            +
                            end
         
     | 
| 
      
 241 
     | 
    
         
            +
                          end
         
     | 
| 
      
 242 
     | 
    
         
            +
                        end
         
     | 
| 
      
 243 
     | 
    
         
            +
                      end
         
     | 
| 
      
 244 
     | 
    
         
            +
                    end
         
     | 
| 
      
 245 
     | 
    
         
            +
             
     | 
| 
      
 246 
     | 
    
         
            +
                    def on_call_node_leave(call_node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
         
     | 
| 
      
 247 
     | 
    
         
            +
                      return unless call_node.name == :class_methods
         
     | 
| 
      
 248 
     | 
    
         
            +
             
     | 
| 
      
 249 
     | 
    
         
            +
                      @listener.pop_namespace_stack
         
     | 
| 
      
 250 
     | 
    
         
            +
                    end
         
     | 
| 
      
 251 
     | 
    
         
            +
                  end
         
     | 
| 
      
 252 
     | 
    
         
            +
             
     | 
| 
      
 253 
     | 
    
         
            +
                  index(<<~RUBY)
         
     | 
| 
      
 254 
     | 
    
         
            +
                    module ActiveSupport
         
     | 
| 
      
 255 
     | 
    
         
            +
                      module Concern
         
     | 
| 
      
 256 
     | 
    
         
            +
                      end
         
     | 
| 
      
 257 
     | 
    
         
            +
                    end
         
     | 
| 
      
 258 
     | 
    
         
            +
             
     | 
| 
      
 259 
     | 
    
         
            +
                    module MyConcern
         
     | 
| 
      
 260 
     | 
    
         
            +
                      extend ActiveSupport::Concern
         
     | 
| 
      
 261 
     | 
    
         
            +
             
     | 
| 
      
 262 
     | 
    
         
            +
                      class_methods do
         
     | 
| 
      
 263 
     | 
    
         
            +
                        def foo; end
         
     | 
| 
      
 264 
     | 
    
         
            +
                      end
         
     | 
| 
      
 265 
     | 
    
         
            +
                    end
         
     | 
| 
      
 266 
     | 
    
         
            +
             
     | 
| 
      
 267 
     | 
    
         
            +
                    class User
         
     | 
| 
      
 268 
     | 
    
         
            +
                      include MyConcern
         
     | 
| 
      
 269 
     | 
    
         
            +
                    end
         
     | 
| 
      
 270 
     | 
    
         
            +
                  RUBY
         
     | 
| 
      
 271 
     | 
    
         
            +
             
     | 
| 
      
 272 
     | 
    
         
            +
                  assert_equal(
         
     | 
| 
      
 273 
     | 
    
         
            +
                    [
         
     | 
| 
      
 274 
     | 
    
         
            +
                      "User::<Class:User>",
         
     | 
| 
      
 275 
     | 
    
         
            +
                      "MyConcern::ClassMethods",
         
     | 
| 
      
 276 
     | 
    
         
            +
                      "Object::<Class:Object>",
         
     | 
| 
      
 277 
     | 
    
         
            +
                      "BasicObject::<Class:BasicObject>",
         
     | 
| 
      
 278 
     | 
    
         
            +
                      "Class",
         
     | 
| 
      
 279 
     | 
    
         
            +
                      "Module",
         
     | 
| 
      
 280 
     | 
    
         
            +
                      "Object",
         
     | 
| 
      
 281 
     | 
    
         
            +
                      "Kernel",
         
     | 
| 
      
 282 
     | 
    
         
            +
                      "BasicObject",
         
     | 
| 
      
 283 
     | 
    
         
            +
                    ],
         
     | 
| 
      
 284 
     | 
    
         
            +
                    @index.linearized_ancestors_of("User::<Class:User>"),
         
     | 
| 
      
 285 
     | 
    
         
            +
                  )
         
     | 
| 
      
 286 
     | 
    
         
            +
             
     | 
| 
      
 287 
     | 
    
         
            +
                  refute_nil(@index.resolve_method("foo", "User::<Class:User>"))
         
     | 
| 
      
 288 
     | 
    
         
            +
                end
         
     | 
| 
      
 289 
     | 
    
         
            +
             
     | 
| 
      
 290 
     | 
    
         
            +
                def test_creating_anonymous_classes_from_enhancement
         
     | 
| 
      
 291 
     | 
    
         
            +
                  Class.new(Enhancement) do
         
     | 
| 
      
 292 
     | 
    
         
            +
                    def on_call_node_enter(call_node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
         
     | 
| 
      
 293 
     | 
    
         
            +
                      case call_node.name
         
     | 
| 
      
 294 
     | 
    
         
            +
                      when :context
         
     | 
| 
      
 295 
     | 
    
         
            +
                        arguments = call_node.arguments&.arguments
         
     | 
| 
      
 296 
     | 
    
         
            +
                        first_argument = arguments&.first
         
     | 
| 
      
 297 
     | 
    
         
            +
                        return unless first_argument.is_a?(Prism::StringNode)
         
     | 
| 
      
 298 
     | 
    
         
            +
             
     | 
| 
      
 299 
     | 
    
         
            +
                        @listener.add_class(
         
     | 
| 
      
 300 
     | 
    
         
            +
                          "<RSpec:#{first_argument.content}>",
         
     | 
| 
      
 301 
     | 
    
         
            +
                          call_node.location,
         
     | 
| 
      
 302 
     | 
    
         
            +
                          first_argument.location,
         
     | 
| 
      
 303 
     | 
    
         
            +
                        )
         
     | 
| 
      
 304 
     | 
    
         
            +
                      when :subject
         
     | 
| 
      
 305 
     | 
    
         
            +
                        @listener.add_method("subject", call_node.location, [])
         
     | 
| 
      
 306 
     | 
    
         
            +
                      end
         
     | 
| 
      
 307 
     | 
    
         
            +
                    end
         
     | 
| 
      
 308 
     | 
    
         
            +
             
     | 
| 
      
 309 
     | 
    
         
            +
                    def on_call_node_leave(call_node) # rubocop:disable RubyLsp/UseRegisterWithHandlerMethod
         
     | 
| 
      
 310 
     | 
    
         
            +
                      return unless call_node.name == :context
         
     | 
| 
      
 311 
     | 
    
         
            +
             
     | 
| 
      
 312 
     | 
    
         
            +
                      @listener.pop_namespace_stack
         
     | 
| 
      
 313 
     | 
    
         
            +
                    end
         
     | 
| 
      
 314 
     | 
    
         
            +
                  end
         
     | 
| 
      
 315 
     | 
    
         
            +
             
     | 
| 
      
 316 
     | 
    
         
            +
                  index(<<~RUBY)
         
     | 
| 
      
 317 
     | 
    
         
            +
                    context "does something" do
         
     | 
| 
      
 318 
     | 
    
         
            +
                      subject { call_whatever }
         
     | 
| 
      
 319 
     | 
    
         
            +
                    end
         
     | 
| 
      
 320 
     | 
    
         
            +
                  RUBY
         
     | 
| 
      
 321 
     | 
    
         
            +
             
     | 
| 
      
 322 
     | 
    
         
            +
                  refute_nil(@index.resolve_method("subject", "<RSpec:does something>"))
         
     | 
| 
      
 323 
     | 
    
         
            +
                end
         
     | 
| 
       228 
324 
     | 
    
         
             
              end
         
     | 
| 
       229 
325 
     | 
    
         
             
            end
         
     | 
| 
         @@ -1672,6 +1672,38 @@ module RubyIndexer 
     | 
|
| 
       1672 
1672 
     | 
    
         
             
                  )
         
     | 
| 
       1673 
1673 
     | 
    
         
             
                end
         
     | 
| 
       1674 
1674 
     | 
    
         | 
| 
      
 1675 
     | 
    
         
            +
                def test_extend_self
         
     | 
| 
      
 1676 
     | 
    
         
            +
                  @index.index_single(IndexablePath.new(nil, "/fake/path/foo.rb"), <<~RUBY)
         
     | 
| 
      
 1677 
     | 
    
         
            +
                    module Foo
         
     | 
| 
      
 1678 
     | 
    
         
            +
                      def bar
         
     | 
| 
      
 1679 
     | 
    
         
            +
                      end
         
     | 
| 
      
 1680 
     | 
    
         
            +
             
     | 
| 
      
 1681 
     | 
    
         
            +
                      extend self
         
     | 
| 
      
 1682 
     | 
    
         
            +
             
     | 
| 
      
 1683 
     | 
    
         
            +
                      def baz
         
     | 
| 
      
 1684 
     | 
    
         
            +
                      end
         
     | 
| 
      
 1685 
     | 
    
         
            +
                    end
         
     | 
| 
      
 1686 
     | 
    
         
            +
                  RUBY
         
     | 
| 
      
 1687 
     | 
    
         
            +
             
     | 
| 
      
 1688 
     | 
    
         
            +
                  ["bar", "baz"].product(["Foo", "Foo::<Class:Foo>"]).each do |method, receiver|
         
     | 
| 
      
 1689 
     | 
    
         
            +
                    entry = @index.resolve_method(method, receiver)&.first
         
     | 
| 
      
 1690 
     | 
    
         
            +
                    refute_nil(entry)
         
     | 
| 
      
 1691 
     | 
    
         
            +
                    assert_equal(method, T.must(entry).name)
         
     | 
| 
      
 1692 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1693 
     | 
    
         
            +
             
     | 
| 
      
 1694 
     | 
    
         
            +
                  assert_equal(
         
     | 
| 
      
 1695 
     | 
    
         
            +
                    [
         
     | 
| 
      
 1696 
     | 
    
         
            +
                      "Foo::<Class:Foo>",
         
     | 
| 
      
 1697 
     | 
    
         
            +
                      "Foo",
         
     | 
| 
      
 1698 
     | 
    
         
            +
                      "Module",
         
     | 
| 
      
 1699 
     | 
    
         
            +
                      "Object",
         
     | 
| 
      
 1700 
     | 
    
         
            +
                      "Kernel",
         
     | 
| 
      
 1701 
     | 
    
         
            +
                      "BasicObject",
         
     | 
| 
      
 1702 
     | 
    
         
            +
                    ],
         
     | 
| 
      
 1703 
     | 
    
         
            +
                    @index.linearized_ancestors_of("Foo::<Class:Foo>"),
         
     | 
| 
      
 1704 
     | 
    
         
            +
                  )
         
     | 
| 
      
 1705 
     | 
    
         
            +
                end
         
     | 
| 
      
 1706 
     | 
    
         
            +
             
     | 
| 
       1675 
1707 
     | 
    
         
             
                def test_linearizing_singleton_ancestors
         
     | 
| 
       1676 
1708 
     | 
    
         
             
                  @index.index_single(IndexablePath.new(nil, "/fake/path/foo.rb"), <<~RUBY)
         
     | 
| 
       1677 
1709 
     | 
    
         
             
                    module First
         
     | 
| 
         @@ -2023,5 +2055,12 @@ module RubyIndexer 
     | 
|
| 
       2023 
2055 
     | 
    
         
             
                    ),
         
     | 
| 
       2024 
2056 
     | 
    
         
             
                  )
         
     | 
| 
       2025 
2057 
     | 
    
         
             
                end
         
     | 
| 
      
 2058 
     | 
    
         
            +
             
     | 
| 
      
 2059 
     | 
    
         
            +
                def test_prevents_multiple_calls_to_index_all
         
     | 
| 
      
 2060 
     | 
    
         
            +
                  # For this test class, `index_all` is already called once in `setup`.
         
     | 
| 
      
 2061 
     | 
    
         
            +
                  assert_raises(Index::IndexNotEmptyError) do
         
     | 
| 
      
 2062 
     | 
    
         
            +
                    @index.index_all
         
     | 
| 
      
 2063 
     | 
    
         
            +
                  end
         
     | 
| 
      
 2064 
     | 
    
         
            +
                end
         
     | 
| 
       2026 
2065 
     | 
    
         
             
              end
         
     | 
| 
       2027 
2066 
     | 
    
         
             
            end
         
     | 
| 
         @@ -141,7 +141,7 @@ module RubyIndexer 
     | 
|
| 
       141 
141 
     | 
    
         
             
                    # The first entry points to the location of the module_function call
         
     | 
| 
       142 
142 
     | 
    
         
             
                    assert_equal("Test", first_entry.owner.name)
         
     | 
| 
       143 
143 
     | 
    
         
             
                    assert_instance_of(Entry::Module, first_entry.owner)
         
     | 
| 
       144 
     | 
    
         
            -
                     
     | 
| 
      
 144 
     | 
    
         
            +
                    assert_predicate(first_entry, :private?)
         
     | 
| 
       145 
145 
     | 
    
         
             
                    # The second entry points to the public singleton method
         
     | 
| 
       146 
146 
     | 
    
         
             
                    assert_equal("Test::<Class:Test>", second_entry.owner.name)
         
     | 
| 
       147 
147 
     | 
    
         
             
                    assert_instance_of(Entry::SingletonClass, second_entry.owner)
         
     | 
| 
         @@ -149,6 +149,39 @@ module RubyIndexer 
     | 
|
| 
       149 
149 
     | 
    
         
             
                  end
         
     | 
| 
       150 
150 
     | 
    
         
             
                end
         
     | 
| 
       151 
151 
     | 
    
         | 
| 
      
 152 
     | 
    
         
            +
                def test_comments_documentation
         
     | 
| 
      
 153 
     | 
    
         
            +
                  index(<<~RUBY)
         
     | 
| 
      
 154 
     | 
    
         
            +
                    # Documentation for Foo
         
     | 
| 
      
 155 
     | 
    
         
            +
             
     | 
| 
      
 156 
     | 
    
         
            +
                    class Foo
         
     | 
| 
      
 157 
     | 
    
         
            +
                      # ####################
         
     | 
| 
      
 158 
     | 
    
         
            +
                      # Documentation for bar
         
     | 
| 
      
 159 
     | 
    
         
            +
                      # ####################
         
     | 
| 
      
 160 
     | 
    
         
            +
                      #
         
     | 
| 
      
 161 
     | 
    
         
            +
                      def bar
         
     | 
| 
      
 162 
     | 
    
         
            +
                      end
         
     | 
| 
      
 163 
     | 
    
         
            +
             
     | 
| 
      
 164 
     | 
    
         
            +
                      # test
         
     | 
| 
      
 165 
     | 
    
         
            +
             
     | 
| 
      
 166 
     | 
    
         
            +
                      # Documentation for baz
         
     | 
| 
      
 167 
     | 
    
         
            +
                      def baz; end
         
     | 
| 
      
 168 
     | 
    
         
            +
                      def ban; end
         
     | 
| 
      
 169 
     | 
    
         
            +
                    end
         
     | 
| 
      
 170 
     | 
    
         
            +
                  RUBY
         
     | 
| 
      
 171 
     | 
    
         
            +
             
     | 
| 
      
 172 
     | 
    
         
            +
                  foo_comment = @index["Foo"].first.comments
         
     | 
| 
      
 173 
     | 
    
         
            +
                  assert_equal("Documentation for Foo", foo_comment)
         
     | 
| 
      
 174 
     | 
    
         
            +
             
     | 
| 
      
 175 
     | 
    
         
            +
                  bar_comment = @index["bar"].first.comments
         
     | 
| 
      
 176 
     | 
    
         
            +
                  assert_equal("####################\nDocumentation for bar\n####################\n", bar_comment)
         
     | 
| 
      
 177 
     | 
    
         
            +
             
     | 
| 
      
 178 
     | 
    
         
            +
                  baz_comment = @index["baz"].first.comments
         
     | 
| 
      
 179 
     | 
    
         
            +
                  assert_equal("Documentation for baz", baz_comment)
         
     | 
| 
      
 180 
     | 
    
         
            +
             
     | 
| 
      
 181 
     | 
    
         
            +
                  ban_comment = @index["ban"].first.comments
         
     | 
| 
      
 182 
     | 
    
         
            +
                  assert_empty(ban_comment)
         
     | 
| 
      
 183 
     | 
    
         
            +
                end
         
     | 
| 
      
 184 
     | 
    
         
            +
             
     | 
| 
       152 
185 
     | 
    
         
             
                def test_method_with_parameters
         
     | 
| 
       153 
186 
     | 
    
         
             
                  index(<<~RUBY)
         
     | 
| 
       154 
187 
     | 
    
         
             
                    class Foo
         
     | 
| 
         @@ -21,7 +21,7 @@ module RubyLsp 
     | 
|
| 
       21 
21 
     | 
    
         
             
                attr_reader :encoding
         
     | 
| 
       22 
22 
     | 
    
         | 
| 
       23 
23 
     | 
    
         
             
                sig { returns(T::Boolean) }
         
     | 
| 
       24 
     | 
    
         
            -
                attr_reader : 
     | 
| 
      
 24 
     | 
    
         
            +
                attr_reader :top_level_bundle
         
     | 
| 
       25 
25 
     | 
    
         | 
| 
       26 
26 
     | 
    
         
             
                sig { returns(TypeInferrer) }
         
     | 
| 
       27 
27 
     | 
    
         
             
                attr_reader :type_inferrer
         
     | 
| 
         @@ -40,7 +40,6 @@ module RubyLsp 
     | 
|
| 
       40 
40 
     | 
    
         
             
                  @has_type_checker = T.let(true, T::Boolean)
         
     | 
| 
       41 
41 
     | 
    
         
             
                  @index = T.let(RubyIndexer::Index.new, RubyIndexer::Index)
         
     | 
| 
       42 
42 
     | 
    
         
             
                  @supported_formatters = T.let({}, T::Hash[String, Requests::Support::Formatter])
         
     | 
| 
       43 
     | 
    
         
            -
                  @experimental_features = T.let(false, T::Boolean)
         
     | 
| 
       44 
43 
     | 
    
         
             
                  @type_inferrer = T.let(TypeInferrer.new(@index), TypeInferrer)
         
     | 
| 
       45 
44 
     | 
    
         
             
                  @addon_settings = T.let({}, T::Hash[String, T.untyped])
         
     | 
| 
       46 
45 
     | 
    
         
             
                  @top_level_bundle = T.let(
         
     | 
| 
         @@ -131,7 +130,6 @@ module RubyLsp 
     | 
|
| 
       131 
130 
     | 
    
         
             
                  end
         
     | 
| 
       132 
131 
     | 
    
         
             
                  @index.configuration.encoding = @encoding
         
     | 
| 
       133 
132 
     | 
    
         | 
| 
       134 
     | 
    
         
            -
                  @experimental_features = options.dig(:initializationOptions, :experimentalFeaturesEnabled) || false
         
     | 
| 
       135 
133 
     | 
    
         
             
                  @client_capabilities.apply_client_capabilities(options[:capabilities]) if options[:capabilities]
         
     | 
| 
       136 
134 
     | 
    
         | 
| 
       137 
135 
     | 
    
         
             
                  addon_settings = options.dig(:initializationOptions, :addonSettings)
         
     | 
    
        data/lib/ruby_lsp/internal.rb
    CHANGED
    
    
    
        data/lib/ruby_lsp/server.rb
    CHANGED
    
    | 
         @@ -216,6 +216,13 @@ module RubyLsp 
     | 
|
| 
       216 
216 
     | 
    
         
             
                    Hash.new(true)
         
     | 
| 
       217 
217 
     | 
    
         
             
                  end
         
     | 
| 
       218 
218 
     | 
    
         | 
| 
      
 219 
     | 
    
         
            +
                  bundle_env_path = File.join(".ruby-lsp", "bundle_env")
         
     | 
| 
      
 220 
     | 
    
         
            +
                  bundle_env = if File.exist?(bundle_env_path)
         
     | 
| 
      
 221 
     | 
    
         
            +
                    env = File.readlines(bundle_env_path).to_h { |line| T.cast(line.chomp.split("=", 2), [String, String]) }
         
     | 
| 
      
 222 
     | 
    
         
            +
                    FileUtils.rm(bundle_env_path)
         
     | 
| 
      
 223 
     | 
    
         
            +
                    env
         
     | 
| 
      
 224 
     | 
    
         
            +
                  end
         
     | 
| 
      
 225 
     | 
    
         
            +
             
     | 
| 
       219 
226 
     | 
    
         
             
                  document_symbol_provider = Requests::DocumentSymbol.provider if enabled_features["documentSymbols"]
         
     | 
| 
       220 
227 
     | 
    
         
             
                  document_link_provider = Requests::DocumentLink.provider if enabled_features["documentLink"]
         
     | 
| 
       221 
228 
     | 
    
         
             
                  code_lens_provider = Requests::CodeLens.provider if enabled_features["codeLens"]
         
     | 
| 
         @@ -269,6 +276,7 @@ module RubyLsp 
     | 
|
| 
       269 
276 
     | 
    
         
             
                    },
         
     | 
| 
       270 
277 
     | 
    
         
             
                    formatter: @global_state.formatter,
         
     | 
| 
       271 
278 
     | 
    
         
             
                    degraded_mode: !!(@install_error || @setup_error),
         
     | 
| 
      
 279 
     | 
    
         
            +
                    bundle_env: bundle_env,
         
     | 
| 
       272 
280 
     | 
    
         
             
                  }
         
     | 
| 
       273 
281 
     | 
    
         | 
| 
       274 
282 
     | 
    
         
             
                  send_message(Result.new(id: message[:id], response: response))
         
     | 
| 
         @@ -604,6 +612,11 @@ module RubyLsp 
     | 
|
| 
       604 
612 
     | 
    
         
             
                  # don't want to format it
         
     | 
| 
       605 
613 
     | 
    
         
             
                  path = uri.to_standardized_path
         
     | 
| 
       606 
614 
     | 
    
         
             
                  unless path.nil? || path.start_with?(@global_state.workspace_path)
         
     | 
| 
      
 615 
     | 
    
         
            +
                    send_log_message(<<~MESSAGE)
         
     | 
| 
      
 616 
     | 
    
         
            +
                      Ignoring formatting request for file outside of the workspace.
         
     | 
| 
      
 617 
     | 
    
         
            +
                      Workspace path was set by editor as #{@global_state.workspace_path}.
         
     | 
| 
      
 618 
     | 
    
         
            +
                      File path requested for formatting was #{path}
         
     | 
| 
      
 619 
     | 
    
         
            +
                    MESSAGE
         
     | 
| 
       607 
620 
     | 
    
         
             
                    send_empty_response(message[:id])
         
     | 
| 
       608 
621 
     | 
    
         
             
                    return
         
     | 
| 
       609 
622 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -12,7 +12,7 @@ require "digest" 
     | 
|
| 
       12 
12 
     | 
    
         
             
            require "time"
         
     | 
| 
       13 
13 
     | 
    
         
             
            require "uri"
         
     | 
| 
       14 
14 
     | 
    
         | 
| 
       15 
     | 
    
         
            -
            # This file is a script that will configure a  
     | 
| 
      
 15 
     | 
    
         
            +
            # This file is a script that will configure a composed bundle for the Ruby LSP. The composed bundle allows developers to use
         
     | 
| 
       16 
16 
     | 
    
         
             
            # the Ruby LSP without including the gem in their application's Gemfile while at the same time giving us access to the
         
     | 
| 
       17 
17 
     | 
    
         
             
            # exact locked versions of dependencies.
         
     | 
| 
       18 
18 
     | 
    
         | 
| 
         @@ -62,7 +62,7 @@ module RubyLsp 
     | 
|
| 
       62 
62 
     | 
    
         
             
                  @retry = T.let(false, T::Boolean)
         
     | 
| 
       63 
63 
     | 
    
         
             
                end
         
     | 
| 
       64 
64 
     | 
    
         | 
| 
       65 
     | 
    
         
            -
                # Sets up the  
     | 
| 
      
 65 
     | 
    
         
            +
                # Sets up the composed bundle and returns the `BUNDLE_GEMFILE`, `BUNDLE_PATH` and `BUNDLE_APP_CONFIG` that should be
         
     | 
| 
       66 
66 
     | 
    
         
             
                # used for running the server
         
     | 
| 
       67 
67 
     | 
    
         
             
                sig { returns(T::Hash[String, String]) }
         
     | 
| 
       68 
68 
     | 
    
         
             
                def setup!
         
     | 
| 
         @@ -73,12 +73,12 @@ module RubyLsp 
     | 
|
| 
       73 
73 
     | 
    
         
             
                  ignore_file = @custom_dir + ".gitignore"
         
     | 
| 
       74 
74 
     | 
    
         
             
                  ignore_file.write("*") unless ignore_file.exist?
         
     | 
| 
       75 
75 
     | 
    
         | 
| 
       76 
     | 
    
         
            -
                  # Do not set up a  
     | 
| 
      
 76 
     | 
    
         
            +
                  # Do not set up a composed bundle if LSP dependencies are already in the Gemfile
         
     | 
| 
       77 
77 
     | 
    
         
             
                  if @dependencies["ruby-lsp"] &&
         
     | 
| 
       78 
78 
     | 
    
         
             
                      @dependencies["debug"] &&
         
     | 
| 
       79 
79 
     | 
    
         
             
                      (@rails_app ? @dependencies["ruby-lsp-rails"] : true)
         
     | 
| 
       80 
80 
     | 
    
         
             
                    $stderr.puts(
         
     | 
| 
       81 
     | 
    
         
            -
                      "Ruby LSP> Skipping  
     | 
| 
      
 81 
     | 
    
         
            +
                      "Ruby LSP> Skipping composed bundle setup since LSP dependencies are already in #{@gemfile}",
         
     | 
| 
       82 
82 
     | 
    
         
             
                    )
         
     | 
| 
       83 
83 
     | 
    
         | 
| 
       84 
84 
     | 
    
         
             
                    return run_bundle_install
         
     | 
| 
         @@ -96,7 +96,7 @@ module RubyLsp 
     | 
|
| 
       96 
96 
     | 
    
         | 
| 
       97 
97 
     | 
    
         
             
                  if @custom_lockfile.exist? && @lockfile_hash_path.exist? && @lockfile_hash_path.read == current_lockfile_hash
         
     | 
| 
       98 
98 
     | 
    
         
             
                    $stderr.puts(
         
     | 
| 
       99 
     | 
    
         
            -
                      "Ruby LSP> Skipping  
     | 
| 
      
 99 
     | 
    
         
            +
                      "Ruby LSP> Skipping composed bundle setup since #{@custom_lockfile} already exists and is up to date",
         
     | 
| 
       100 
100 
     | 
    
         
             
                    )
         
     | 
| 
       101 
101 
     | 
    
         
             
                    return run_bundle_install(@custom_gemfile)
         
     | 
| 
       102 
102 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -110,8 +110,8 @@ module RubyLsp 
     | 
|
| 
       110 
110 
     | 
    
         
             
                private
         
     | 
| 
       111 
111 
     | 
    
         | 
| 
       112 
112 
     | 
    
         
             
                sig { returns(T::Hash[String, T.untyped]) }
         
     | 
| 
       113 
     | 
    
         
            -
                def  
     | 
| 
       114 
     | 
    
         
            -
                  @ 
     | 
| 
      
 113 
     | 
    
         
            +
                def composed_bundle_dependencies
         
     | 
| 
      
 114 
     | 
    
         
            +
                  @composed_bundle_dependencies ||= T.let(
         
     | 
| 
       115 
115 
     | 
    
         
             
                    begin
         
     | 
| 
       116 
116 
     | 
    
         
             
                      original_bundle_gemfile = ENV["BUNDLE_GEMFILE"]
         
     | 
| 
       117 
117 
     | 
    
         | 
| 
         @@ -136,8 +136,8 @@ module RubyLsp 
     | 
|
| 
       136 
136 
     | 
    
         
             
                    "",
         
     | 
| 
       137 
137 
     | 
    
         
             
                  ]
         
     | 
| 
       138 
138 
     | 
    
         | 
| 
       139 
     | 
    
         
            -
                  # If there's a top level Gemfile, we want to evaluate from the  
     | 
| 
       140 
     | 
    
         
            -
                  # Gemfile, so if there isn't one we need to add a default source
         
     | 
| 
      
 139 
     | 
    
         
            +
                  # If there's a top level Gemfile, we want to evaluate from the composed bundle. We get the source from the top
         
     | 
| 
      
 140 
     | 
    
         
            +
                  # level Gemfile, so if there isn't one we need to add a default source
         
     | 
| 
       141 
141 
     | 
    
         
             
                  if @gemfile&.exist? && @lockfile&.exist?
         
     | 
| 
       142 
142 
     | 
    
         
             
                    parts << "eval_gemfile(File.expand_path(\"../#{@gemfile_name}\", __dir__))"
         
     | 
| 
       143 
143 
     | 
    
         
             
                  else
         
     | 
| 
         @@ -187,7 +187,7 @@ module RubyLsp 
     | 
|
| 
       187 
187 
     | 
    
         
             
                  env = bundler_settings_as_env
         
     | 
| 
       188 
188 
     | 
    
         
             
                  env["BUNDLE_GEMFILE"] = bundle_gemfile.to_s
         
     | 
| 
       189 
189 
     | 
    
         | 
| 
       190 
     | 
    
         
            -
                  # If the user has a  
     | 
| 
      
 190 
     | 
    
         
            +
                  # If the user has a composed bundle path configured, we need to ensure that we will use the absolute and not
         
     | 
| 
       191 
191 
     | 
    
         
             
                  # relative version of it when running `bundle install`. This is necessary to avoid installing the gems under the
         
     | 
| 
       192 
192 
     | 
    
         
             
                  # `.ruby-lsp` folder, which is not the user's intention. For example, if the path is configured as `vendor`, we
         
     | 
| 
       193 
193 
     | 
    
         
             
                  # want to install it in the top level `vendor` and not `.ruby-lsp/vendor`
         
     | 
| 
         @@ -244,7 +244,7 @@ module RubyLsp 
     | 
|
| 
       244 
244 
     | 
    
         
             
                  base_bundle = base_bundle_command(env)
         
     | 
| 
       245 
245 
     | 
    
         | 
| 
       246 
246 
     | 
    
         
             
                  # If `ruby-lsp` and `debug` (and potentially `ruby-lsp-rails`) are already in the Gemfile, then we shouldn't try
         
     | 
| 
       247 
     | 
    
         
            -
                  # to upgrade them or else we'll produce undesired source control changes. If the  
     | 
| 
      
 247 
     | 
    
         
            +
                  # to upgrade them or else we'll produce undesired source control changes. If the composed bundle was just created
         
     | 
| 
       248 
248 
     | 
    
         
             
                  # and any of `ruby-lsp`, `ruby-lsp-rails` or `debug` weren't a part of the Gemfile, then we need to run `bundle
         
     | 
| 
       249 
249 
     | 
    
         
             
                  # install` for the first time to generate the Gemfile.lock with them included or else Bundler will complain that
         
     | 
| 
       250 
250 
     | 
    
         
             
                  # they're missing. We can only update if the custom `.ruby-lsp/Gemfile.lock` already exists and includes all gems
         
     | 
| 
         @@ -274,16 +274,16 @@ module RubyLsp 
     | 
|
| 
       274 
274 
     | 
    
         
             
                  command << "1>&2"
         
     | 
| 
       275 
275 
     | 
    
         | 
| 
       276 
276 
     | 
    
         
             
                  # Add bundle update
         
     | 
| 
       277 
     | 
    
         
            -
                  $stderr.puts("Ruby LSP> Running bundle install for the  
     | 
| 
      
 277 
     | 
    
         
            +
                  $stderr.puts("Ruby LSP> Running bundle install for the composed bundle. This may take a while...")
         
     | 
| 
       278 
278 
     | 
    
         
             
                  $stderr.puts("Ruby LSP> Command: #{command}")
         
     | 
| 
       279 
279 
     | 
    
         | 
| 
       280 
     | 
    
         
            -
                  # Try to run the bundle install or update command. If that fails, it normally means that the  
     | 
| 
       281 
     | 
    
         
            -
                  # a bad state that no longer reflects the top level one. In that case, we can remove the whole directory, try
         
     | 
| 
      
 280 
     | 
    
         
            +
                  # Try to run the bundle install or update command. If that fails, it normally means that the composed lockfile is
         
     | 
| 
      
 281 
     | 
    
         
            +
                  # in a bad state that no longer reflects the top level one. In that case, we can remove the whole directory, try
         
     | 
| 
       282 
282 
     | 
    
         
             
                  # another time and give up if it fails again
         
     | 
| 
       283 
283 
     | 
    
         
             
                  if !system(env, command) && !@retry && @custom_gemfile.exist?
         
     | 
| 
       284 
284 
     | 
    
         
             
                    @retry = true
         
     | 
| 
       285 
285 
     | 
    
         
             
                    @custom_dir.rmtree
         
     | 
| 
       286 
     | 
    
         
            -
                    $stderr.puts("Ruby LSP> Running bundle install failed. Trying to re-generate the  
     | 
| 
      
 286 
     | 
    
         
            +
                    $stderr.puts("Ruby LSP> Running bundle install failed. Trying to re-generate the composed bundle from scratch")
         
     | 
| 
       287 
287 
     | 
    
         
             
                    return setup!
         
     | 
| 
       288 
288 
     | 
    
         
             
                  end
         
     | 
| 
       289 
289 
     | 
    
         | 
| 
         @@ -330,14 +330,14 @@ module RubyLsp 
     | 
|
| 
       330 
330 
     | 
    
         
             
                  if @rails_app
         
     | 
| 
       331 
331 
     | 
    
         
             
                    return false if @dependencies.values_at("ruby-lsp", "ruby-lsp-rails", "debug").all?
         
     | 
| 
       332 
332 
     | 
    
         | 
| 
       333 
     | 
    
         
            -
                    # If the  
     | 
| 
       334 
     | 
    
         
            -
                    # before updating
         
     | 
| 
       335 
     | 
    
         
            -
                    return false if  
     | 
| 
      
 333 
     | 
    
         
            +
                    # If the composed lockfile doesn't include `ruby-lsp`, `ruby-lsp-rails` or `debug`, we need to run bundle
         
     | 
| 
      
 334 
     | 
    
         
            +
                    # install before updating
         
     | 
| 
      
 335 
     | 
    
         
            +
                    return false if composed_bundle_dependencies.values_at("ruby-lsp", "debug", "ruby-lsp-rails").any?(&:nil?)
         
     | 
| 
       336 
336 
     | 
    
         
             
                  else
         
     | 
| 
       337 
337 
     | 
    
         
             
                    return false if @dependencies.values_at("ruby-lsp", "debug").all?
         
     | 
| 
       338 
338 
     | 
    
         | 
| 
       339 
     | 
    
         
            -
                    # If the  
     | 
| 
       340 
     | 
    
         
            -
                    return false if  
     | 
| 
      
 339 
     | 
    
         
            +
                    # If the composed lockfile doesn't include `ruby-lsp` or `debug`, we need to run bundle install before updating
         
     | 
| 
      
 340 
     | 
    
         
            +
                    return false if composed_bundle_dependencies.values_at("ruby-lsp", "debug").any?(&:nil?)
         
     | 
| 
       341 
341 
     | 
    
         
             
                  end
         
     | 
| 
       342 
342 
     | 
    
         | 
| 
       343 
343 
     | 
    
         
             
                  # If the last updated file doesn't exist or was updated more than 4 hours ago, we should update
         
     | 
    
        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. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.22.0
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Shopify
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire:
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: exe
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date: 2024-11- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2024-11-20 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: language_server-protocol
         
     | 
| 
         @@ -217,7 +217,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement 
     | 
|
| 
       217 
217 
     | 
    
         
             
                - !ruby/object:Gem::Version
         
     | 
| 
       218 
218 
     | 
    
         
             
                  version: '0'
         
     | 
| 
       219 
219 
     | 
    
         
             
            requirements: []
         
     | 
| 
       220 
     | 
    
         
            -
            rubygems_version: 3.5. 
     | 
| 
      
 220 
     | 
    
         
            +
            rubygems_version: 3.5.23
         
     | 
| 
       221 
221 
     | 
    
         
             
            signing_key:
         
     | 
| 
       222 
222 
     | 
    
         
             
            specification_version: 4
         
     | 
| 
       223 
223 
     | 
    
         
             
            summary: An opinionated language server for Ruby
         
     |