Skip to content

Commit 3a0e038

Browse files
authored
Merge pull request #253 from Shopify/as/refactor-response
Update Hover and CodeLens as per refactored responses in Ruby LSP
2 parents 088312d + 41c8c29 commit 3a0e038

File tree

7 files changed

+729
-622
lines changed

7 files changed

+729
-622
lines changed

Gemfile.lock

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ PATH
55
actionpack (>= 6.0)
66
activerecord (>= 6.0)
77
railties (>= 6.0)
8-
ruby-lsp (>= 0.13.0, < 0.14.0)
8+
ruby-lsp (>= 0.14.0, < 0.15.0)
99
sorbet-runtime (>= 0.5.9897)
1010

1111
GEM
@@ -221,9 +221,9 @@ GEM
221221
rubocop (~> 1.51)
222222
rubocop-sorbet (0.7.6)
223223
rubocop (>= 0.90.0)
224-
ruby-lsp (0.13.4)
224+
ruby-lsp (0.14.0)
225225
language_server-protocol (~> 3.17.0)
226-
prism (>= 0.19.0, < 0.20)
226+
prism (>= 0.19.0, < 0.22)
227227
sorbet-runtime (>= 0.5.10782)
228228
ruby-progressbar (1.13.0)
229229
ruby2_keywords (0.0.5)

lib/ruby_lsp/ruby_lsp_rails/addon.rb

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,23 +28,25 @@ def deactivate; end
2828
# Creates a new CodeLens listener. This method is invoked on every CodeLens request
2929
sig do
3030
override.params(
31+
response_builder: ResponseBuilders::CollectionResponseBuilder[Interface::CodeLens],
3132
uri: URI::Generic,
3233
dispatcher: Prism::Dispatcher,
33-
).returns(T.nilable(Listener[T::Array[Interface::CodeLens]]))
34+
).void
3435
end
35-
def create_code_lens_listener(uri, dispatcher)
36-
CodeLens.new(uri, dispatcher)
36+
def create_code_lens_listener(response_builder, uri, dispatcher)
37+
CodeLens.new(response_builder, uri, dispatcher)
3738
end
3839

3940
sig do
4041
override.params(
42+
response_builder: ResponseBuilders::Hover,
4143
nesting: T::Array[String],
4244
index: RubyIndexer::Index,
4345
dispatcher: Prism::Dispatcher,
44-
).returns(T.nilable(Listener[T.nilable(Interface::Hover)]))
46+
).void
4547
end
46-
def create_hover_listener(nesting, index, dispatcher)
47-
Hover.new(client, nesting, index, dispatcher)
48+
def create_hover_listener(response_builder, nesting, index, dispatcher)
49+
Hover.new(client, response_builder, nesting, index, dispatcher)
4850
end
4951

5052
sig { override.returns(String) }

lib/ruby_lsp/ruby_lsp_rails/code_lens.rb

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,26 +32,26 @@ module Rails
3232
# ````
3333
#
3434
# The code lenses will be displayed above the class and above each test method.
35-
class CodeLens < ::RubyLsp::Listener
35+
class CodeLens
3636
extend T::Sig
37-
extend T::Generic
37+
include Requests::Support::Common
3838

39-
ResponseType = type_member { { fixed: T::Array[::RubyLsp::Interface::CodeLens] } }
4039
BASE_COMMAND = "bin/rails test"
4140

42-
sig { override.returns(ResponseType) }
43-
attr_reader :_response
44-
45-
sig { params(uri: URI::Generic, dispatcher: Prism::Dispatcher).void }
46-
def initialize(uri, dispatcher)
47-
@_response = T.let([], ResponseType)
41+
sig do
42+
params(
43+
response_builder: ResponseBuilders::CollectionResponseBuilder[Interface::CodeLens],
44+
uri: URI::Generic,
45+
dispatcher: Prism::Dispatcher,
46+
).void
47+
end
48+
def initialize(response_builder, uri, dispatcher)
49+
@response_builder = response_builder
4850
@path = T.let(uri.to_standardized_path, T.nilable(String))
4951
@group_id = T.let(1, Integer)
5052
@group_id_stack = T.let([], T::Array[Integer])
5153

5254
dispatcher.register(self, :on_call_node_enter, :on_class_node_enter, :on_def_node_enter, :on_class_node_leave)
53-
54-
super(dispatcher)
5555
end
5656

5757
sig { params(node: Prism::CallNode).void }
@@ -131,23 +131,23 @@ def add_test_code_lens(node, name:, command:, kind:)
131131
grouping_data = { group_id: @group_id_stack.last, kind: kind }
132132
grouping_data[:id] = @group_id if kind == :group
133133

134-
@_response << create_code_lens(
134+
@response_builder << create_code_lens(
135135
node,
136136
title: "Run",
137137
command_name: "rubyLsp.runTest",
138138
arguments: arguments,
139139
data: { type: "test", **grouping_data },
140140
)
141141

142-
@_response << create_code_lens(
142+
@response_builder << create_code_lens(
143143
node,
144144
title: "Run In Terminal",
145145
command_name: "rubyLsp.runTestInTerminal",
146146
arguments: arguments,
147147
data: { type: "test_in_terminal", **grouping_data },
148148
)
149149

150-
@_response << create_code_lens(
150+
@response_builder << create_code_lens(
151151
node,
152152
title: "Debug",
153153
command_name: "rubyLsp.debugTest",

lib/ruby_lsp/ruby_lsp_rails/hover.rb

Lines changed: 24 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -16,28 +16,22 @@ module Rails
1616
# User.all
1717
# # ^ hovering here will show information about the User model
1818
# ```
19-
class Hover < ::RubyLsp::Listener
19+
class Hover
2020
extend T::Sig
21-
extend T::Generic
22-
23-
ResponseType = type_member { { fixed: T.nilable(::RubyLsp::Interface::Hover) } }
24-
25-
sig { override.returns(ResponseType) }
26-
attr_reader :_response
21+
include Requests::Support::Common
2722

2823
sig do
2924
params(
3025
client: RailsClient,
26+
response_builder: ResponseBuilders::Hover,
3127
nesting: T::Array[String],
3228
index: RubyIndexer::Index,
3329
dispatcher: Prism::Dispatcher,
3430
).void
3531
end
36-
def initialize(client, nesting, index, dispatcher)
37-
super(dispatcher)
38-
39-
@_response = T.let(nil, ResponseType)
32+
def initialize(client, response_builder, nesting, index, dispatcher)
4033
@client = client
34+
@response_builder = response_builder
4135
@nesting = nesting
4236
@index = index
4337
dispatcher.register(self, :on_constant_path_node_enter, :on_constant_read_node_enter, :on_call_node_enter)
@@ -49,28 +43,18 @@ def on_constant_path_node_enter(node)
4943
return unless entries
5044

5145
name = T.must(entries.first).name
52-
content = +""
53-
column_info = generate_column_content(name)
54-
content << column_info if column_info
5546

56-
urls = Support::RailsDocumentClient.generate_rails_document_urls(name)
57-
content << urls.join("\n\n") unless urls.empty?
58-
return if content.empty?
47+
generate_column_content(name)
5948

60-
contents = RubyLsp::Interface::MarkupContent.new(kind: "markdown", value: content)
61-
@_response = RubyLsp::Interface::Hover.new(range: range_from_location(node.location), contents: contents)
49+
generate_rails_document_link_hover(name, node.location)
6250
end
6351

6452
sig { params(node: Prism::ConstantReadNode).void }
6553
def on_constant_read_node_enter(node)
6654
entries = @index.resolve(node.name.to_s, @nesting)
6755
return unless entries
6856

69-
content = generate_column_content(T.must(entries.first).name)
70-
return unless content
71-
72-
contents = RubyLsp::Interface::MarkupContent.new(kind: "markdown", value: content)
73-
@_response = RubyLsp::Interface::Hover.new(range: range_from_location(node.location), contents: contents)
57+
generate_column_content(T.must(entries.first).name)
7458
end
7559

7660
sig { params(node: Prism::CallNode).void }
@@ -80,30 +64,37 @@ def on_call_node_enter(node)
8064

8165
return unless message_value && message_loc
8266

83-
@_response = generate_rails_document_link_hover(message_value, message_loc)
67+
generate_rails_document_link_hover(message_value, message_loc)
8468
end
8569

8670
private
8771

88-
sig { params(name: String).returns(T.nilable(String)) }
72+
sig { params(name: String).void }
8973
def generate_column_content(name)
9074
model = @client.model(name)
9175
return if model.nil?
9276

9377
schema_file = model[:schema_file]
94-
content = +""
95-
content << "[Schema](#{URI::Generic.build(scheme: "file", path: schema_file)})\n\n" if schema_file
96-
content << model[:columns].map { |name, type| "**#{name}**: #{type}\n" }.join("\n")
97-
content
78+
79+
@response_builder.push(
80+
"[Schema](#{URI::Generic.build(scheme: "file", path: schema_file)})",
81+
category: :links,
82+
) if schema_file
83+
84+
@response_builder.push(
85+
model[:columns].map do |name, type|
86+
"**#{name}**: #{type}\n"
87+
end.join("\n"),
88+
category: :documentation,
89+
)
9890
end
9991

100-
sig { params(name: String, location: Prism::Location).returns(T.nilable(Interface::Hover)) }
92+
sig { params(name: String, location: Prism::Location).void }
10193
def generate_rails_document_link_hover(name, location)
10294
urls = Support::RailsDocumentClient.generate_rails_document_urls(name)
10395
return if urls.empty?
10496

105-
contents = RubyLsp::Interface::MarkupContent.new(kind: "markdown", value: urls.join("\n\n"))
106-
RubyLsp::Interface::Hover.new(range: range_from_location(location), contents: contents)
97+
@response_builder.push(urls.join("\n\n"), category: :links)
10798
end
10899
end
109100
end

ruby-lsp-rails.gemspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@ Gem::Specification.new do |spec|
2424
spec.add_dependency("actionpack", ">= 6.0")
2525
spec.add_dependency("activerecord", ">= 6.0")
2626
spec.add_dependency("railties", ">= 6.0")
27-
spec.add_dependency("ruby-lsp", ">= 0.13.0", "< 0.14.0")
27+
spec.add_dependency("ruby-lsp", ">= 0.14.0", "< 0.15.0")
2828
spec.add_dependency("sorbet-runtime", ">= 0.5.9897")
2929
end

0 commit comments

Comments
 (0)