From 9d02cb379a399c4618f0152e837586427d27f921 Mon Sep 17 00:00:00 2001 From: Thomas Marshall Date: Wed, 9 Oct 2024 18:55:47 +0100 Subject: [PATCH] Fix spec code lens inside classes Minitest specs don't include the class name in the test selector, so we need to strip out the class name (including the module nesting) when we generate the selector. This commit changes `@group_stack` to be a tuple of `[type, value]` so we can distinguish between class/module names and test group/example names. For specs, it removes the class/module names from the stack. --- lib/ruby_lsp/listeners/code_lens.rb | 28 +++++++++++--------- test/requests/code_lens_expectations_test.rb | 4 +-- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/lib/ruby_lsp/listeners/code_lens.rb b/lib/ruby_lsp/listeners/code_lens.rb index 2eb91487e..13153b550 100644 --- a/lib/ruby_lsp/listeners/code_lens.rb +++ b/lib/ruby_lsp/listeners/code_lens.rb @@ -39,7 +39,7 @@ def initialize(response_builder, global_state, uri, dispatcher) @path = T.let(uri.to_standardized_path, T.nilable(String)) # visibility_stack is a stack of [current_visibility, previous_visibility] @visibility_stack = T.let([[:public, :public]], T::Array[T::Array[T.nilable(Symbol)]]) - @group_stack = T.let([], T::Array[String]) + @group_stack = T.let([], T::Array[[Symbol, String]]) @group_id = T.let(1, Integer) @group_id_stack = T.let([], T::Array[Integer]) # We want to avoid adding code lenses for nested definitions @@ -63,15 +63,15 @@ def initialize(response_builder, global_state, uri, dispatcher) def on_class_node_enter(node) @visibility_stack.push([:public, :public]) class_name = node.constant_path.slice - @group_stack.push(class_name) + @group_stack.push([:class, class_name]) if @path && class_name.end_with?("Test") add_test_code_lens( node, name: class_name, - command: generate_test_command(group_stack: @group_stack), + command: generate_test_command(group_stack: @group_stack.map(&:last)), kind: :group, - id: generate_fully_qualified_id(group_stack: @group_stack), + id: generate_fully_qualified_id(group_stack: @group_stack.map(&:last)), ) @group_id_stack.push(@group_id) @@ -96,7 +96,7 @@ def on_def_node_enter(node) @def_depth += 1 return if @def_depth > 1 - class_name = @group_stack.last + class_name = @group_stack.last&.last return unless class_name&.end_with?("Test") visibility, _ = @visibility_stack.last @@ -106,9 +106,9 @@ def on_def_node_enter(node) add_test_code_lens( node, name: method_name, - command: generate_test_command(method_name: method_name, group_stack: @group_stack), + command: generate_test_command(method_name: method_name, group_stack: @group_stack.map(&:last)), kind: :example, - id: generate_fully_qualified_id(group_stack: @group_stack, method_name: method_name), + id: generate_fully_qualified_id(group_stack: @group_stack.map(&:last), method_name: method_name), ) end end @@ -122,9 +122,9 @@ def on_def_node_leave(node) sig { params(node: Prism::ModuleNode).void } def on_module_node_enter(node) if (path = namespace_constant_name(node)) - @group_stack.push(path) + @group_stack.push([:module, path]) else - @group_stack.push(DYNAMIC_REFERENCE_MARKER) + @group_stack.push([:module, DYNAMIC_REFERENCE_MARKER]) end end @@ -293,17 +293,21 @@ def add_spec_code_lens(node, kind:) else # Reset spec_id when entering a new group @spec_id = 0 - @group_stack.push(name) + @group_stack.push([:describe, name]) end if @path + # Remove any class or module names from the group stack. + # Specs don't include the class name in the test selector. + group_stack = @group_stack.filter_map { |type, value| value if type == :describe } + method_name = format("test_%04d_%s", @spec_id, name) if kind == :example add_test_code_lens( node, name: name, - command: generate_test_command(group_stack: @group_stack, spec_name: method_name), + command: generate_test_command(group_stack: group_stack, spec_name: method_name), kind: kind, - id: generate_fully_qualified_id(group_stack: @group_stack, method_name: method_name), + id: generate_fully_qualified_id(group_stack: group_stack, method_name: method_name), ) end end diff --git a/test/requests/code_lens_expectations_test.rb b/test/requests/code_lens_expectations_test.rb index e4541474f..a878a2fb4 100644 --- a/test/requests/code_lens_expectations_test.rb +++ b/test/requests/code_lens_expectations_test.rb @@ -79,12 +79,12 @@ class FooTest < MiniTest::Test ) assert_equal("Run In Terminal", T.must(response[4]).command.title) assert_equal( - "bundle exec ruby -Itest /fake.rb --name \"/^FooTest::a(#|::)/\"", + "bundle exec ruby -Itest /fake.rb --name \"/^a(#|::)/\"", T.must(response[4]).command.arguments[2], ) assert_equal("Run In Terminal", T.must(response[7]).command.title) assert_equal( - "bundle exec ruby -Itest /fake.rb --name \"/^FooTest::a#test_0001_b$/\"", + "bundle exec ruby -Itest /fake.rb --name \"/^a#test_0001_b$/\"", T.must(response[7]).command.arguments[2], ) end