From d0e1e5dfa7da13ae8301e1c359af26b0b4733c8f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Jan 2026 21:39:50 +0000 Subject: [PATCH 01/10] Initial plan From 77b780766db5bab9d7a7cacf1914a7f09e842601 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Jan 2026 21:45:59 +0000 Subject: [PATCH 02/10] Fix module and class scope closing by passing false for close_siblings Co-authored-by: kwerle <23320+kwerle@users.noreply.github.com> --- lib/ruby_language_server/scope_parser.rb | 4 +- .../ruby_language_server/scope_parser_spec.rb | 64 +++++++++++++++++++ 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/lib/ruby_language_server/scope_parser.rb b/lib/ruby_language_server/scope_parser.rb index 5ca379b..19342de 100644 --- a/lib/ruby_language_server/scope_parser.rb +++ b/lib/ruby_language_server/scope_parser.rb @@ -41,7 +41,7 @@ def visit_class_node(node) end_line = node.location.end_line column = node.location.start_column - scope = push_scope(ScopeData::Scope::TYPE_CLASS, name, line, column, end_line) + scope = push_scope(ScopeData::Scope::TYPE_CLASS, name, line, column, end_line, false) # Handle superclass if node.superclass @@ -60,7 +60,7 @@ def visit_module_node(node) end_line = node.location.end_line column = node.location.start_column - push_scope(ScopeData::Scope::TYPE_MODULE, name, line, column, end_line) + push_scope(ScopeData::Scope::TYPE_MODULE, name, line, column, end_line, false) super pop_scope end diff --git a/spec/lib/ruby_language_server/scope_parser_spec.rb b/spec/lib/ruby_language_server/scope_parser_spec.rb index f10a778..5729f58 100644 --- a/spec/lib/ruby_language_server/scope_parser_spec.rb +++ b/spec/lib/ruby_language_server/scope_parser_spec.rb @@ -167,5 +167,69 @@ def some_method assert_equal('item', scope_parser.root_scope.self_and_descendants.last.variables.first.name) end end + + describe 'sibling modules' do + let(:sibling_modules_source) do + <<-RUBY + module Foo + module Bar + end + module Baz + end + end + RUBY + end + let(:scope_parser) { RubyLanguageServer::ScopeParser.new(sibling_modules_source) } + + it 'should place sibling modules at the same level' do + foo = scope_parser.root_scope.children.first + assert_equal('Foo', foo.name) + + # Both Bar and Baz should be children of Foo, not Bar containing Baz + children = foo.children + assert_equal(2, children.size, "Foo should have 2 children, but has #{children.size}") + + bar = children.detect { |c| c.name == 'Bar' } + baz = children.detect { |c| c.name == 'Baz' } + + assert_not_nil(bar, "Bar should be a child of Foo") + assert_not_nil(baz, "Baz should be a child of Foo") + + # Verify Baz is not a child of Bar + assert_equal(0, bar.children.size, "Bar should have no children, but has #{bar.children.size}") + end + end + + describe 'sibling classes' do + let(:sibling_classes_source) do + <<-RUBY + module Foo + class Bar + end + class Baz + end + end + RUBY + end + let(:scope_parser) { RubyLanguageServer::ScopeParser.new(sibling_classes_source) } + + it 'should place sibling classes at the same level' do + foo = scope_parser.root_scope.children.first + assert_equal('Foo', foo.name) + + # Both Bar and Baz should be children of Foo, not Bar containing Baz + children = foo.children + assert_equal(2, children.size, "Foo should have 2 children, but has #{children.size}") + + bar = children.detect { |c| c.name == 'Bar' } + baz = children.detect { |c| c.name == 'Baz' } + + assert_not_nil(bar, "Bar should be a child of Foo") + assert_not_nil(baz, "Baz should be a child of Foo") + + # Verify Baz is not a child of Bar + assert_equal(0, bar.children.size, "Bar should have no children, but has #{bar.children.size}") + end + end end end From 747a03929e228ac12f9d53ef5f6a9a4509e4d018 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Jan 2026 21:48:08 +0000 Subject: [PATCH 03/10] Fix trailing whitespace in test cases Co-authored-by: kwerle <23320+kwerle@users.noreply.github.com> --- spec/lib/ruby_language_server/scope_parser_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/lib/ruby_language_server/scope_parser_spec.rb b/spec/lib/ruby_language_server/scope_parser_spec.rb index 5729f58..ff465eb 100644 --- a/spec/lib/ruby_language_server/scope_parser_spec.rb +++ b/spec/lib/ruby_language_server/scope_parser_spec.rb @@ -173,7 +173,7 @@ def some_method <<-RUBY module Foo module Bar - end + end module Baz end end @@ -205,7 +205,7 @@ module Baz <<-RUBY module Foo class Bar - end + end class Baz end end From e7b7e94e3f85718a4172748dcb5f9317bf8c26e1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Jan 2026 22:26:00 +0000 Subject: [PATCH 04/10] Refactor sibling tests into shared examples to reduce duplication Co-authored-by: kwerle <23320+kwerle@users.noreply.github.com> --- .../ruby_language_server/scope_parser_spec.rb | 98 ++++++++----------- 1 file changed, 43 insertions(+), 55 deletions(-) diff --git a/spec/lib/ruby_language_server/scope_parser_spec.rb b/spec/lib/ruby_language_server/scope_parser_spec.rb index ff465eb..b622dae 100644 --- a/spec/lib/ruby_language_server/scope_parser_spec.rb +++ b/spec/lib/ruby_language_server/scope_parser_spec.rb @@ -168,67 +168,55 @@ def some_method end end - describe 'sibling modules' do - let(:sibling_modules_source) do - <<-RUBY - module Foo - module Bar - end - module Baz - end + describe 'siblings' do + shared_examples 'sibling scopes' do |type| + it "should place sibling #{type}s at the same level" do + foo = scope_parser.root_scope.children.first + assert_equal('Foo', foo.name) + + # Both Bar and Baz should be children of Foo, not Bar containing Baz + children = foo.children + assert_equal(2, children.size, "Foo should have 2 children, but has #{children.size}") + + bar = children.detect { |c| c.name == 'Bar' } + baz = children.detect { |c| c.name == 'Baz' } + + assert_not_nil(bar, "Bar should be a child of Foo") + assert_not_nil(baz, "Baz should be a child of Foo") + + # Verify Baz is not a child of Bar + assert_equal(0, bar.children.size, "Bar should have no children, but has #{bar.children.size}") end - RUBY - end - let(:scope_parser) { RubyLanguageServer::ScopeParser.new(sibling_modules_source) } - - it 'should place sibling modules at the same level' do - foo = scope_parser.root_scope.children.first - assert_equal('Foo', foo.name) - - # Both Bar and Baz should be children of Foo, not Bar containing Baz - children = foo.children - assert_equal(2, children.size, "Foo should have 2 children, but has #{children.size}") - - bar = children.detect { |c| c.name == 'Bar' } - baz = children.detect { |c| c.name == 'Baz' } - - assert_not_nil(bar, "Bar should be a child of Foo") - assert_not_nil(baz, "Baz should be a child of Foo") - - # Verify Baz is not a child of Bar - assert_equal(0, bar.children.size, "Bar should have no children, but has #{bar.children.size}") end - end - describe 'sibling classes' do - let(:sibling_classes_source) do - <<-RUBY - module Foo - class Bar + describe 'modules' do + let(:scope_parser) do + RubyLanguageServer::ScopeParser.new(<<-RUBY) + module Foo + module Bar + end + module Baz + end end - class Baz + RUBY + end + + include_examples 'sibling scopes', 'module' + end + + describe 'classes' do + let(:scope_parser) do + RubyLanguageServer::ScopeParser.new(<<-RUBY) + module Foo + class Bar + end + class Baz + end end + RUBY end - RUBY - end - let(:scope_parser) { RubyLanguageServer::ScopeParser.new(sibling_classes_source) } - - it 'should place sibling classes at the same level' do - foo = scope_parser.root_scope.children.first - assert_equal('Foo', foo.name) - - # Both Bar and Baz should be children of Foo, not Bar containing Baz - children = foo.children - assert_equal(2, children.size, "Foo should have 2 children, but has #{children.size}") - - bar = children.detect { |c| c.name == 'Bar' } - baz = children.detect { |c| c.name == 'Baz' } - - assert_not_nil(bar, "Bar should be a child of Foo") - assert_not_nil(baz, "Baz should be a child of Foo") - - # Verify Baz is not a child of Bar - assert_equal(0, bar.children.size, "Bar should have no children, but has #{bar.children.size}") + + include_examples 'sibling scopes', 'class' end end end From ed223c6557bbac7c115909ce1c17b7e43a7b98b4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Jan 2026 22:42:02 +0000 Subject: [PATCH 05/10] Add test case for mixed sibling (class and module) Co-authored-by: kwerle <23320+kwerle@users.noreply.github.com> --- .../ruby_language_server/scope_parser_spec.rb | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/spec/lib/ruby_language_server/scope_parser_spec.rb b/spec/lib/ruby_language_server/scope_parser_spec.rb index b622dae..eccdf84 100644 --- a/spec/lib/ruby_language_server/scope_parser_spec.rb +++ b/spec/lib/ruby_language_server/scope_parser_spec.rb @@ -218,6 +218,41 @@ class Baz include_examples 'sibling scopes', 'class' end + + describe 'mixed (class and module)' do + let(:scope_parser) do + RubyLanguageServer::ScopeParser.new(<<-RUBY) + module Foo + class Bar + end + module Baz + end + end + RUBY + end + + it 'should place sibling class and module at the same level' do + foo = scope_parser.root_scope.children.first + assert_equal('Foo', foo.name) + + # Both Bar (class) and Baz (module) should be children of Foo + children = foo.children + assert_equal(2, children.size, "Foo should have 2 children, but has #{children.size}") + + bar = children.detect { |c| c.name == 'Bar' } + baz = children.detect { |c| c.name == 'Baz' } + + assert_not_nil(bar, "Bar should be a child of Foo") + assert_not_nil(baz, "Baz should be a child of Foo") + + # Verify types are different + assert_equal(:class, bar.type, "Bar should be a class") + assert_equal(:module, baz.type, "Baz should be a module") + + # Verify Baz is not a child of Bar + assert_equal(0, bar.children.size, "Bar should have no children, but has #{bar.children.size}") + end + end end end end From 4d74e6cafb72a99e5fb40c19d3954a5390dc7780 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Jan 2026 23:48:40 +0000 Subject: [PATCH 06/10] Convert tests from RSpec syntax to proper minitest syntax Co-authored-by: kwerle <23320+kwerle@users.noreply.github.com> --- .../ruby_language_server/scope_parser_spec.rb | 118 ++++++++++-------- 1 file changed, 64 insertions(+), 54 deletions(-) diff --git a/spec/lib/ruby_language_server/scope_parser_spec.rb b/spec/lib/ruby_language_server/scope_parser_spec.rb index eccdf84..d2a5554 100644 --- a/spec/lib/ruby_language_server/scope_parser_spec.rb +++ b/spec/lib/ruby_language_server/scope_parser_spec.rb @@ -168,90 +168,100 @@ def some_method end end - describe 'siblings' do - shared_examples 'sibling scopes' do |type| - it "should place sibling #{type}s at the same level" do - foo = scope_parser.root_scope.children.first - assert_equal('Foo', foo.name) - - # Both Bar and Baz should be children of Foo, not Bar containing Baz - children = foo.children - assert_equal(2, children.size, "Foo should have 2 children, but has #{children.size}") - - bar = children.detect { |c| c.name == 'Bar' } - baz = children.detect { |c| c.name == 'Baz' } - - assert_not_nil(bar, "Bar should be a child of Foo") - assert_not_nil(baz, "Baz should be a child of Foo") - - # Verify Baz is not a child of Bar - assert_equal(0, bar.children.size, "Bar should have no children, but has #{bar.children.size}") - end - end - - describe 'modules' do - let(:scope_parser) do - RubyLanguageServer::ScopeParser.new(<<-RUBY) + describe 'sibling modules' do + before do + @parser = RubyLanguageServer::ScopeParser.new(<<-RUBY) module Foo module Bar end module Baz end end - RUBY - end + RUBY + end + + it 'should place sibling modules at the same level' do + foo = @parser.root_scope.children.first + assert_equal('Foo', foo.name) + + # Both Bar and Baz should be children of Foo, not Bar containing Baz + children = foo.children + assert_equal(2, children.size, "Foo should have 2 children, but has #{children.size}") + + bar = children.detect { |c| c.name == 'Bar' } + baz = children.detect { |c| c.name == 'Baz' } + + assert_not_nil(bar, "Bar should be a child of Foo") + assert_not_nil(baz, "Baz should be a child of Foo") - include_examples 'sibling scopes', 'module' + # Verify Baz is not a child of Bar + assert_equal(0, bar.children.size, "Bar should have no children, but has #{bar.children.size}") end + end - describe 'classes' do - let(:scope_parser) do - RubyLanguageServer::ScopeParser.new(<<-RUBY) + describe 'sibling classes' do + before do + @parser = RubyLanguageServer::ScopeParser.new(<<-RUBY) module Foo class Bar end class Baz end end - RUBY - end + RUBY + end + + it 'should place sibling classes at the same level' do + foo = @parser.root_scope.children.first + assert_equal('Foo', foo.name) + + # Both Bar and Baz should be children of Foo, not Bar containing Baz + children = foo.children + assert_equal(2, children.size, "Foo should have 2 children, but has #{children.size}") + + bar = children.detect { |c| c.name == 'Bar' } + baz = children.detect { |c| c.name == 'Baz' } - include_examples 'sibling scopes', 'class' + assert_not_nil(bar, "Bar should be a child of Foo") + assert_not_nil(baz, "Baz should be a child of Foo") + + # Verify Baz is not a child of Bar + assert_equal(0, bar.children.size, "Bar should have no children, but has #{bar.children.size}") end + end - describe 'mixed (class and module)' do - let(:scope_parser) do - RubyLanguageServer::ScopeParser.new(<<-RUBY) + describe 'mixed siblings (class and module)' do + before do + @parser = RubyLanguageServer::ScopeParser.new(<<-RUBY) module Foo class Bar end module Baz end end - RUBY - end + RUBY + end - it 'should place sibling class and module at the same level' do - foo = scope_parser.root_scope.children.first - assert_equal('Foo', foo.name) + it 'should place sibling class and module at the same level' do + foo = @parser.root_scope.children.first + assert_equal('Foo', foo.name) - # Both Bar (class) and Baz (module) should be children of Foo - children = foo.children - assert_equal(2, children.size, "Foo should have 2 children, but has #{children.size}") + # Both Bar (class) and Baz (module) should be children of Foo + children = foo.children + assert_equal(2, children.size, "Foo should have 2 children, but has #{children.size}") - bar = children.detect { |c| c.name == 'Bar' } - baz = children.detect { |c| c.name == 'Baz' } + bar = children.detect { |c| c.name == 'Bar' } + baz = children.detect { |c| c.name == 'Baz' } - assert_not_nil(bar, "Bar should be a child of Foo") - assert_not_nil(baz, "Baz should be a child of Foo") + assert_not_nil(bar, "Bar should be a child of Foo") + assert_not_nil(baz, "Baz should be a child of Foo") - # Verify types are different - assert_equal(:class, bar.type, "Bar should be a class") - assert_equal(:module, baz.type, "Baz should be a module") + # Verify types are different + assert_equal(:class, bar.type, "Bar should be a class") + assert_equal(:module, baz.type, "Baz should be a module") - # Verify Baz is not a child of Bar - assert_equal(0, bar.children.size, "Bar should have no children, but has #{bar.children.size}") - end + # Verify Baz is not a child of Bar + assert_equal(0, bar.children.size, "Bar should have no children, but has #{bar.children.size}") end end end From ce339d22f2d7975b40102511d8c72ca932bec65c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 12 Jan 2026 23:57:49 +0000 Subject: [PATCH 07/10] Refactor sibling tests using helper method to eliminate duplication Co-authored-by: kwerle <23320+kwerle@users.noreply.github.com> --- .../ruby_language_server/scope_parser_spec.rb | 118 +++++++----------- 1 file changed, 46 insertions(+), 72 deletions(-) diff --git a/spec/lib/ruby_language_server/scope_parser_spec.rb b/spec/lib/ruby_language_server/scope_parser_spec.rb index d2a5554..4bcb5a8 100644 --- a/spec/lib/ruby_language_server/scope_parser_spec.rb +++ b/spec/lib/ruby_language_server/scope_parser_spec.rb @@ -168,23 +168,11 @@ def some_method end end - describe 'sibling modules' do - before do - @parser = RubyLanguageServer::ScopeParser.new(<<-RUBY) - module Foo - module Bar - end - module Baz - end - end - RUBY - end - - it 'should place sibling modules at the same level' do + describe 'siblings' do + def assert_siblings(bar_type: nil, baz_type: nil) foo = @parser.root_scope.children.first assert_equal('Foo', foo.name) - # Both Bar and Baz should be children of Foo, not Bar containing Baz children = foo.children assert_equal(2, children.size, "Foo should have 2 children, but has #{children.size}") @@ -193,75 +181,61 @@ module Baz assert_not_nil(bar, "Bar should be a child of Foo") assert_not_nil(baz, "Baz should be a child of Foo") + assert_equal(0, bar.children.size, "Bar should have no children") - # Verify Baz is not a child of Bar - assert_equal(0, bar.children.size, "Bar should have no children, but has #{bar.children.size}") + assert_equal(bar_type, bar.type) if bar_type + assert_equal(baz_type, baz.type) if baz_type end - end - describe 'sibling classes' do - before do - @parser = RubyLanguageServer::ScopeParser.new(<<-RUBY) - module Foo - class Bar - end - class Baz + describe 'modules' do + before do + @parser = RubyLanguageServer::ScopeParser.new(<<-RUBY) + module Foo + module Bar + end + module Baz + end end - end - RUBY - end - - it 'should place sibling classes at the same level' do - foo = @parser.root_scope.children.first - assert_equal('Foo', foo.name) - - # Both Bar and Baz should be children of Foo, not Bar containing Baz - children = foo.children - assert_equal(2, children.size, "Foo should have 2 children, but has #{children.size}") - - bar = children.detect { |c| c.name == 'Bar' } - baz = children.detect { |c| c.name == 'Baz' } - - assert_not_nil(bar, "Bar should be a child of Foo") - assert_not_nil(baz, "Baz should be a child of Foo") + RUBY + end - # Verify Baz is not a child of Bar - assert_equal(0, bar.children.size, "Bar should have no children, but has #{bar.children.size}") + it 'places sibling modules at the same level' do + assert_siblings + end end - end - describe 'mixed siblings (class and module)' do - before do - @parser = RubyLanguageServer::ScopeParser.new(<<-RUBY) - module Foo - class Bar + describe 'classes' do + before do + @parser = RubyLanguageServer::ScopeParser.new(<<-RUBY) + module Foo + class Bar + end + class Baz + end end - module Baz - end - end - RUBY - end - - it 'should place sibling class and module at the same level' do - foo = @parser.root_scope.children.first - assert_equal('Foo', foo.name) - - # Both Bar (class) and Baz (module) should be children of Foo - children = foo.children - assert_equal(2, children.size, "Foo should have 2 children, but has #{children.size}") - - bar = children.detect { |c| c.name == 'Bar' } - baz = children.detect { |c| c.name == 'Baz' } + RUBY + end - assert_not_nil(bar, "Bar should be a child of Foo") - assert_not_nil(baz, "Baz should be a child of Foo") + it 'places sibling classes at the same level' do + assert_siblings + end + end - # Verify types are different - assert_equal(:class, bar.type, "Bar should be a class") - assert_equal(:module, baz.type, "Baz should be a module") + describe 'mixed' do + before do + @parser = RubyLanguageServer::ScopeParser.new(<<-RUBY) + module Foo + class Bar + end + module Baz + end + end + RUBY + end - # Verify Baz is not a child of Bar - assert_equal(0, bar.children.size, "Bar should have no children, but has #{bar.children.size}") + it 'places sibling class and module at the same level' do + assert_siblings(bar_type: :class, baz_type: :module) + end end end end From 9fb60d86acca60551258c3dacae76403249e44ff Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 13 Jan 2026 00:47:51 +0000 Subject: [PATCH 08/10] Fix failing tests by removing helper method and inlining assertions Co-authored-by: kwerle <23320+kwerle@users.noreply.github.com> --- .../ruby_language_server/scope_parser_spec.rb | 115 ++++++++++-------- 1 file changed, 65 insertions(+), 50 deletions(-) diff --git a/spec/lib/ruby_language_server/scope_parser_spec.rb b/spec/lib/ruby_language_server/scope_parser_spec.rb index 4bcb5a8..1958721 100644 --- a/spec/lib/ruby_language_server/scope_parser_spec.rb +++ b/spec/lib/ruby_language_server/scope_parser_spec.rb @@ -168,74 +168,89 @@ def some_method end end - describe 'siblings' do - def assert_siblings(bar_type: nil, baz_type: nil) + describe 'sibling modules' do + before do + @parser = RubyLanguageServer::ScopeParser.new(<<-RUBY) + module Foo + module Bar + end + module Baz + end + end + RUBY + end + + it 'places sibling modules at the same level' do foo = @parser.root_scope.children.first assert_equal('Foo', foo.name) children = foo.children - assert_equal(2, children.size, "Foo should have 2 children, but has #{children.size}") + assert_equal(2, children.size) bar = children.detect { |c| c.name == 'Bar' } baz = children.detect { |c| c.name == 'Baz' } - assert_not_nil(bar, "Bar should be a child of Foo") - assert_not_nil(baz, "Baz should be a child of Foo") - assert_equal(0, bar.children.size, "Bar should have no children") - - assert_equal(bar_type, bar.type) if bar_type - assert_equal(baz_type, baz.type) if baz_type + assert_not_nil(bar) + assert_not_nil(baz) + assert_equal(0, bar.children.size) end + end - describe 'modules' do - before do - @parser = RubyLanguageServer::ScopeParser.new(<<-RUBY) - module Foo - module Bar - end - module Baz - end + describe 'sibling classes' do + before do + @parser = RubyLanguageServer::ScopeParser.new(<<-RUBY) + module Foo + class Bar end - RUBY - end - - it 'places sibling modules at the same level' do - assert_siblings - end + class Baz + end + end + RUBY end - describe 'classes' do - before do - @parser = RubyLanguageServer::ScopeParser.new(<<-RUBY) - module Foo - class Bar - end - class Baz - end - end - RUBY - end + it 'places sibling classes at the same level' do + foo = @parser.root_scope.children.first + assert_equal('Foo', foo.name) - it 'places sibling classes at the same level' do - assert_siblings - end + children = foo.children + assert_equal(2, children.size) + + bar = children.detect { |c| c.name == 'Bar' } + baz = children.detect { |c| c.name == 'Baz' } + + assert_not_nil(bar) + assert_not_nil(baz) + assert_equal(0, bar.children.size) end + end - describe 'mixed' do - before do - @parser = RubyLanguageServer::ScopeParser.new(<<-RUBY) - module Foo - class Bar - end - module Baz - end + describe 'mixed siblings' do + before do + @parser = RubyLanguageServer::ScopeParser.new(<<-RUBY) + module Foo + class Bar end - RUBY - end + module Baz + end + end + RUBY + end - it 'places sibling class and module at the same level' do - assert_siblings(bar_type: :class, baz_type: :module) - end + it 'places sibling class and module at the same level' do + foo = @parser.root_scope.children.first + assert_equal('Foo', foo.name) + + children = foo.children + assert_equal(2, children.size) + + bar = children.detect { |c| c.name == 'Bar' } + baz = children.detect { |c| c.name == 'Baz' } + + assert_not_nil(bar) + assert_not_nil(baz) + assert_equal(:class, bar.type) + assert_equal(:module, baz.type) + assert_equal(0, bar.children.size) end end end From 860df53ccc30dd66a2be24bfa1211c18e5c1c729 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 13 Jan 2026 00:49:25 +0000 Subject: [PATCH 09/10] Add descriptive error messages to test assertions Co-authored-by: kwerle <23320+kwerle@users.noreply.github.com> --- .../ruby_language_server/scope_parser_spec.rb | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/spec/lib/ruby_language_server/scope_parser_spec.rb b/spec/lib/ruby_language_server/scope_parser_spec.rb index 1958721..cdcd1f1 100644 --- a/spec/lib/ruby_language_server/scope_parser_spec.rb +++ b/spec/lib/ruby_language_server/scope_parser_spec.rb @@ -185,14 +185,14 @@ module Baz assert_equal('Foo', foo.name) children = foo.children - assert_equal(2, children.size) + assert_equal(2, children.size, "Foo should have 2 children, but has #{children.size}") bar = children.detect { |c| c.name == 'Bar' } baz = children.detect { |c| c.name == 'Baz' } - assert_not_nil(bar) - assert_not_nil(baz) - assert_equal(0, bar.children.size) + assert_not_nil(bar, "Bar should be a child of Foo") + assert_not_nil(baz, "Baz should be a child of Foo") + assert_equal(0, bar.children.size, "Bar should have no children") end end @@ -213,14 +213,14 @@ class Baz assert_equal('Foo', foo.name) children = foo.children - assert_equal(2, children.size) + assert_equal(2, children.size, "Foo should have 2 children, but has #{children.size}") bar = children.detect { |c| c.name == 'Bar' } baz = children.detect { |c| c.name == 'Baz' } - assert_not_nil(bar) - assert_not_nil(baz) - assert_equal(0, bar.children.size) + assert_not_nil(bar, "Bar should be a child of Foo") + assert_not_nil(baz, "Baz should be a child of Foo") + assert_equal(0, bar.children.size, "Bar should have no children") end end @@ -241,16 +241,16 @@ module Baz assert_equal('Foo', foo.name) children = foo.children - assert_equal(2, children.size) + assert_equal(2, children.size, "Foo should have 2 children, but has #{children.size}") bar = children.detect { |c| c.name == 'Bar' } baz = children.detect { |c| c.name == 'Baz' } - assert_not_nil(bar) - assert_not_nil(baz) - assert_equal(:class, bar.type) - assert_equal(:module, baz.type) - assert_equal(0, bar.children.size) + assert_not_nil(bar, "Bar should be a child of Foo") + assert_not_nil(baz, "Baz should be a child of Foo") + assert_equal(:class, bar.type, "Bar should be a class") + assert_equal(:module, baz.type, "Baz should be a module") + assert_equal(0, bar.children.size, "Bar should have no children") end end end From 7962b7e1668b82540a23d4b0948411a1399bd185 Mon Sep 17 00:00:00 2001 From: Kurt Werle Date: Mon, 12 Jan 2026 18:25:10 -0800 Subject: [PATCH 10/10] It looks like module blocks are failing to close. Fixes #129 --- Gemfile.lock | 4 ++-- lib/ruby_language_server/scope_data/base.rb | 5 ++++- spec/lib/ruby_language_server/scope_parser_spec.rb | 12 ++++++------ 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 26fff2d..57dda9a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - ruby_language_server (0.9.1) + ruby_language_server (0.9.2) activerecord (~> 8.1) amatch bundler @@ -278,7 +278,7 @@ CHECKSUMS rubocop-rake (0.7.1) sha256=3797f2b6810c3e9df7376c26d5f44f3475eda59eb1adc38e6f62ecf027cbae4d rubocop-rspec (3.8.0) sha256=28440dccb3f223a9938ca1f946bd3438275b8c6c156dab909e2cb8bc424cab33 ruby-progressbar (1.13.0) sha256=80fc9c47a9b640d6834e0dc7b3c94c9df37f08cb072b7761e4a71e22cff29b33 - ruby_language_server (0.9.1) + ruby_language_server (0.9.2) securerandom (0.4.1) sha256=cc5193d414a4341b6e225f0cb4446aceca8e50d5e1888743fac16987638ea0b1 shellany (0.0.1) sha256=0e127a9132698766d7e752e82cdac8250b6adbd09e6c0a7fbbb6f61964fedee7 simplecov (0.22.0) sha256=fe2622c7834ff23b98066bb0a854284b2729a569ac659f82621fc22ef36213a5 diff --git a/lib/ruby_language_server/scope_data/base.rb b/lib/ruby_language_server/scope_data/base.rb index 4d3f381..5691228 100644 --- a/lib/ruby_language_server/scope_data/base.rb +++ b/lib/ruby_language_server/scope_data/base.rb @@ -25,7 +25,10 @@ class Base < ActiveRecord::Base TYPE_VARIABLE => '^' }.freeze - attr_accessor :type # Type of this scope (module, class, block) + # Return the class_type as a symbol for easier testing + def type + class_type&.to_sym + end # bar should be closer to Bar than Far. Adding the UPPER version accomplishes this. scope :with_distance_from, lambda { |word| diff --git a/spec/lib/ruby_language_server/scope_parser_spec.rb b/spec/lib/ruby_language_server/scope_parser_spec.rb index cdcd1f1..03553c6 100644 --- a/spec/lib/ruby_language_server/scope_parser_spec.rb +++ b/spec/lib/ruby_language_server/scope_parser_spec.rb @@ -190,8 +190,8 @@ module Baz bar = children.detect { |c| c.name == 'Bar' } baz = children.detect { |c| c.name == 'Baz' } - assert_not_nil(bar, "Bar should be a child of Foo") - assert_not_nil(baz, "Baz should be a child of Foo") + refute_nil(bar, "Bar should be a child of Foo") + refute_nil(baz, "Baz should be a child of Foo") assert_equal(0, bar.children.size, "Bar should have no children") end end @@ -218,8 +218,8 @@ class Baz bar = children.detect { |c| c.name == 'Bar' } baz = children.detect { |c| c.name == 'Baz' } - assert_not_nil(bar, "Bar should be a child of Foo") - assert_not_nil(baz, "Baz should be a child of Foo") + refute_nil(bar, "Bar should be a child of Foo") + refute_nil(baz, "Baz should be a child of Foo") assert_equal(0, bar.children.size, "Bar should have no children") end end @@ -246,8 +246,8 @@ module Baz bar = children.detect { |c| c.name == 'Bar' } baz = children.detect { |c| c.name == 'Baz' } - assert_not_nil(bar, "Bar should be a child of Foo") - assert_not_nil(baz, "Baz should be a child of Foo") + refute_nil(bar, "Bar should be a child of Foo") + refute_nil(baz, "Baz should be a child of Foo") assert_equal(:class, bar.type, "Bar should be a class") assert_equal(:module, baz.type, "Baz should be a module") assert_equal(0, bar.children.size, "Bar should have no children")