Repository: Shopify/ruby-lsp (Ruby)

Issue:
Document Symbol request doesn't list shorthand assignments for instance variables
```ruby
@foo = 1
@bar += 2
```
Go To Symbol lists `@foo`, but not `@bar`.


Discussion:

Patch:
diff --git a/lib/ruby_lsp/listeners/document_symbol.rb b/lib/ruby_lsp/listeners/document_symbol.rb
index 8288117374..fa590de15e 100644
--- a/lib/ruby_lsp/listeners/document_symbol.rb
+++ b/lib/ruby_lsp/listeners/document_symbol.rb
@@ -41,6 +41,9 @@ def initialize(response_builder, uri, dispatcher)
           :on_module_node_enter,
           :on_module_node_leave,
           :on_instance_variable_write_node_enter,
+          :on_instance_variable_operator_write_node_enter,
+          :on_instance_variable_or_write_node_enter,
+          :on_instance_variable_and_write_node_enter,
           :on_class_variable_write_node_enter,
           :on_singleton_class_node_enter,
           :on_singleton_class_node_leave,
@@ -249,6 +252,16 @@ def on_module_node_leave(node)
         @response_builder.pop
       end
 
+      sig { params(node: Prism::ClassVariableWriteNode).void }
+      def on_class_variable_write_node_enter(node)
+        create_document_symbol(
+          name: node.name.to_s,
+          kind: Constant::SymbolKind::VARIABLE,
+          range_location: node.name_loc,
+          selection_range_location: node.name_loc,
+        )
+      end
+
       sig { params(node: Prism::InstanceVariableWriteNode).void }
       def on_instance_variable_write_node_enter(node)
         create_document_symbol(
@@ -259,8 +272,28 @@ def on_instance_variable_write_node_enter(node)
         )
       end
 
-      sig { params(node: Prism::ClassVariableWriteNode).void }
-      def on_class_variable_write_node_enter(node)
+      sig { params(node: Prism::InstanceVariableOperatorWriteNode).void }
+      def on_instance_variable_operator_write_node_enter(node)
+        create_document_symbol(
+          name: node.name.to_s,
+          kind: Constant::SymbolKind::VARIABLE,
+          range_location: node.name_loc,
+          selection_range_location: node.name_loc,
+        )
+      end
+
+      sig { params(node: Prism::InstanceVariableOrWriteNode).void }
+      def on_instance_variable_or_write_node_enter(node)
+        create_document_symbol(
+          name: node.name.to_s,
+          kind: Constant::SymbolKind::VARIABLE,
+          range_location: node.name_loc,
+          selection_range_location: node.name_loc,
+        )
+      end
+
+      sig { params(node: Prism::InstanceVariableAndWriteNode).void }
+      def on_instance_variable_and_write_node_enter(node)
         create_document_symbol(
           name: node.name.to_s,
           kind: Constant::SymbolKind::VARIABLE,


Test patch:
diff --git a/test/requests/document_symbol_expectations_test.rb b/test/requests/document_symbol_expectations_test.rb
index 14abd09557..e96c2523a3 100644
--- a/test/requests/document_symbol_expectations_test.rb
+++ b/test/requests/document_symbol_expectations_test.rb
@@ -7,6 +7,32 @@
 class DocumentSymbolExpectationsTest < ExpectationsTestRunner
   expectations_tests RubyLsp::Requests::DocumentSymbol, "document_symbol"
 
+  def test_instance_variable_with_shorthand_assignment
+    source = <<~RUBY
+      @foo = 1
+      @bar += 2
+      @baz -= 3
+      @qux ||= 4
+      @quux &&= 5
+    RUBY
+    uri = URI("file:///fake.rb")
+
+    document = RubyLsp::RubyDocument.new(source: source, version: 1, uri: uri)
+
+    dispatcher = Prism::Dispatcher.new
+    listener = RubyLsp::Requests::DocumentSymbol.new(uri, dispatcher)
+    dispatcher.dispatch(document.parse_result.value)
+    response = listener.perform
+
+    assert_equal(5, response.size)
+
+    assert_equal("@foo", T.must(response[0]).name)
+    assert_equal("@bar", T.must(response[1]).name)
+    assert_equal("@baz", T.must(response[2]).name)
+    assert_equal("@qux", T.must(response[3]).name)
+    assert_equal("@quux", T.must(response[4]).name)
+  end
+
   def test_labels_blank_names
     source = <<~RUBY
       def