Skip to content

Commit 5b1e851

Browse files
committed
Support AS::TestCase document symbol
1 parent f32f92c commit 5b1e851

File tree

5 files changed

+340
-39
lines changed

5 files changed

+340
-39
lines changed

lib/ruby_lsp/ruby_lsp_rails/addon.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
require_relative "runner_client"
77
require_relative "hover"
88
require_relative "code_lens"
9+
require_relative "document_symbol"
910

1011
module RubyLsp
1112
module Rails
@@ -49,6 +50,16 @@ def create_hover_listener(response_builder, nesting, index, dispatcher)
4950
Hover.new(client, response_builder, nesting, index, dispatcher)
5051
end
5152

53+
sig do
54+
override.params(
55+
response_builder: ResponseBuilders::DocumentSymbol,
56+
dispatcher: Prism::Dispatcher,
57+
).returns(Object)
58+
end
59+
def create_document_symbol_listener(response_builder, dispatcher)
60+
DocumentSymbol.new(response_builder, dispatcher)
61+
end
62+
5263
sig { override.returns(String) }
5364
def name
5465
"Ruby LSP Rails"
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# typed: strict
2+
# frozen_string_literal: true
3+
4+
module RubyLsp
5+
module Rails
6+
# ![Document Symbol demo](../../document_symbol.gif)
7+
#
8+
# The [document symbol](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_documentSymbol)
9+
# request allows users to navigate between ActiveSupport test cases with VS Code's "Go to Symbol" feature.
10+
class DocumentSymbol
11+
extend T::Sig
12+
include Requests::Support::Common
13+
14+
sig do
15+
params(
16+
response_builder: ResponseBuilders::DocumentSymbol,
17+
dispatcher: Prism::Dispatcher,
18+
).void
19+
end
20+
def initialize(response_builder, dispatcher)
21+
@_response = T.let(nil, NilClass)
22+
@response_builder = response_builder
23+
24+
dispatcher.register(self, :on_call_node_enter)
25+
end
26+
27+
sig { params(node: Prism::CallNode).void }
28+
def on_call_node_enter(node)
29+
message_value = node.message
30+
return unless message_value == "test" || message_value == "it"
31+
32+
return unless node.arguments
33+
34+
arguments = node.arguments&.arguments
35+
return unless arguments&.any?
36+
37+
first_argument = arguments.first
38+
39+
content = case first_argument
40+
when Prism::InterpolatedStringNode
41+
parts = first_argument.parts
42+
43+
if parts.all? { |part| part.is_a?(Prism::StringNode) }
44+
T.cast(parts, T::Array[Prism::StringNode]).map(&:content).join
45+
end
46+
when Prism::StringNode
47+
first_argument.content
48+
end
49+
50+
return unless content && !content.empty?
51+
52+
@response_builder.last.children << RubyLsp::Interface::DocumentSymbol.new(
53+
name: content,
54+
kind: LanguageServer::Protocol::Constant::SymbolKind::METHOD,
55+
selection_range: range_from_node(node),
56+
range: range_from_node(node),
57+
)
58+
end
59+
end
60+
end
61+
end

misc/document_symbol.gif

1.53 MB
Loading
Lines changed: 84 additions & 39 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)