Skip to content

Commit 24147e8

Browse files
jscharfSeanKG
andauthored
Add support for hover and go to definition when typechecker enabled but typed: false (#1280)
Add support for hover and go to definiton when typechecker enabled but typed: false Co-authored-by: Sean Graves <SeanKGraves@gmail.com>
1 parent 436e3a7 commit 24147e8

File tree

7 files changed

+29
-19
lines changed

7 files changed

+29
-19
lines changed

lib/ruby_lsp/executor.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ def definition(uri, position)
301301
target = parent if target.is_a?(Prism::ConstantReadNode) && parent.is_a?(Prism::ConstantPathNode)
302302

303303
dispatcher = Prism::Dispatcher.new
304-
base_listener = Requests::Definition.new(uri, nesting, @index, dispatcher)
304+
base_listener = Requests::Definition.new(uri, nesting, @index, dispatcher, document.typechecker_enabled?)
305305
dispatcher.dispatch_once(target)
306306
base_listener.response
307307
end
@@ -327,7 +327,7 @@ def hover(uri, position)
327327

328328
# Instantiate all listeners
329329
dispatcher = Prism::Dispatcher.new
330-
hover = Requests::Hover.new(@index, nesting, dispatcher)
330+
hover = Requests::Hover.new(@index, nesting, dispatcher, document.typechecker_enabled?)
331331

332332
# Emit events for all listeners
333333
dispatcher.dispatch_once(target)

lib/ruby_lsp/requests/definition.rb

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,15 @@ class Definition < ExtensibleListener
3737
nesting: T::Array[String],
3838
index: RubyIndexer::Index,
3939
dispatcher: Prism::Dispatcher,
40+
typechecker_enabled: T::Boolean,
4041
).void
4142
end
42-
def initialize(uri, nesting, index, dispatcher)
43+
def initialize(uri, nesting, index, dispatcher, typechecker_enabled)
4344
@uri = uri
4445
@nesting = nesting
4546
@index = index
4647
@_response = T.let(nil, ResponseType)
48+
@typechecker_enabled = typechecker_enabled
4749

4850
super(dispatcher)
4951

@@ -111,7 +113,7 @@ def handle_method_definition(node)
111113

112114
location = target_method.location
113115
file_path = target_method.file_path
114-
return if defined_in_gem?(file_path)
116+
return if @typechecker_enabled && defined_in_gem?(file_path)
115117

116118
@_response = Interface::Location.new(
117119
uri: URI::Generic.from_path(path: file_path).to_s,
@@ -180,7 +182,7 @@ def find_in_index(value)
180182
# additional behavior on top of jumping to RBIs. Sorbet can already handle go to definition for all constants
181183
# in the project, even if the files are typed false
182184
file_path = entry.file_path
183-
next if defined_in_gem?(file_path)
185+
next if DependencyDetector.instance.typechecker && defined_in_gem?(file_path)
184186

185187
Interface::Location.new(
186188
uri: URI::Generic.from_path(path: file_path).to_s,

lib/ruby_lsp/requests/hover.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,14 @@ def provider
4646
index: RubyIndexer::Index,
4747
nesting: T::Array[String],
4848
dispatcher: Prism::Dispatcher,
49+
typechecker_enabled: T::Boolean,
4950
).void
5051
end
51-
def initialize(index, nesting, dispatcher)
52+
def initialize(index, nesting, dispatcher, typechecker_enabled)
5253
@index = index
5354
@nesting = nesting
5455
@_response = T.let(nil, ResponseType)
56+
@typechecker_enabled = typechecker_enabled
5557

5658
super(dispatcher)
5759
dispatcher.register(
@@ -106,7 +108,7 @@ def on_constant_path_node_enter(node)
106108

107109
sig { params(node: Prism::CallNode).void }
108110
def on_call_node_enter(node)
109-
return if DependencyDetector.instance.typechecker
111+
return if @typechecker_enabled
110112
return unless self_receiver?(node)
111113

112114
message = node.message

lib/ruby_lsp/requests/support/common.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@ def create_code_lens(node, title:, command_name:, arguments:, data:)
7171

7272
sig { params(file_path: String).returns(T.nilable(T::Boolean)) }
7373
def defined_in_gem?(file_path)
74-
DependencyDetector.instance.typechecker && BUNDLE_PATH && !file_path.start_with?(T.must(BUNDLE_PATH)) &&
74+
BUNDLE_PATH &&
75+
!file_path.start_with?(T.must(BUNDLE_PATH)) &&
7576
!file_path.start_with?(RbConfig::CONFIG["rubylibdir"])
7677
end
7778

lib/ruby_lsp/requests/workspace_symbol.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def run
3434
# If the project is using Sorbet, we let Sorbet handle symbols defined inside the project itself and RBIs, but
3535
# we still return entries defined in gems to allow developers to jump directly to the source
3636
file_path = entry.file_path
37-
next if defined_in_gem?(file_path)
37+
next if DependencyDetector.instance.typechecker && defined_in_gem?(file_path)
3838

3939
# We should never show private symbols when searching the entire workspace
4040
next if entry.visibility == :private

test/requests/definition_expectations_test.rb

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,8 @@ def test_jumping_to_method_definitions_when_declaration_exists
229229

230230
uri = URI("file:///folder/fake.rb")
231231
source = <<~RUBY
232+
# typed: false
233+
232234
class A
233235
def bar
234236
foo
@@ -246,10 +248,9 @@ def foo; end
246248
RubyIndexer::IndexablePath.new(nil, T.must(uri.to_standardized_path)), source
247249
)
248250

249-
stub_no_typechecker
250251
response = executor.execute({
251252
method: "textDocument/definition",
252-
params: { textDocument: { uri: "file:///folder/fake.rb" }, position: { character: 4, line: 2 } },
253+
params: { textDocument: { uri: "file:///folder/fake.rb" }, position: { character: 4, line: 4 } },
253254
}).response
254255

255256
assert_equal(uri.to_s, response.attributes[:uri])
@@ -263,6 +264,8 @@ def test_jumping_to_method_method_calls_on_explicit_self
263264

264265
uri = URI("file:///folder/fake.rb")
265266
source = <<~RUBY
267+
# typed: false
268+
266269
class A
267270
def bar
268271
self.foo
@@ -280,10 +283,9 @@ def foo; end
280283
RubyIndexer::IndexablePath.new(nil, T.must(uri.to_standardized_path)), source
281284
)
282285

283-
stub_no_typechecker
284286
response = executor.execute({
285287
method: "textDocument/definition",
286-
params: { textDocument: { uri: "file:///folder/fake.rb" }, position: { character: 9, line: 2 } },
288+
params: { textDocument: { uri: "file:///folder/fake.rb" }, position: { character: 9, line: 4 } },
287289
}).response
288290

289291
assert_equal(uri.to_s, response.attributes[:uri])
@@ -297,6 +299,8 @@ def test_jumping_to_method_definitions_when_declaration_does_not_exist
297299

298300
uri = URI("file:///folder/fake.rb")
299301
source = <<~RUBY
302+
# typed: false
303+
300304
class A
301305
def bar
302306
foo
@@ -312,10 +316,9 @@ def bar
312316
RubyIndexer::IndexablePath.new(nil, T.must(uri.to_standardized_path)), source
313317
)
314318

315-
stub_no_typechecker
316319
response = executor.execute({
317320
method: "textDocument/definition",
318-
params: { textDocument: { uri: "file:///folder/fake.rb" }, position: { character: 4, line: 2 } },
321+
params: { textDocument: { uri: "file:///folder/fake.rb" }, position: { character: 4, line: 4 } },
319322
}).response
320323

321324
assert_nil(response)

test/requests/hover_expectations_test.rb

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ def test_hovering_methods_invoked_on_implicit_self
6767

6868
uri = URI("file:///fake.rb")
6969
source = <<~RUBY
70+
# typed: false
71+
7072
class A
7173
# Hello from `foo`
7274
def foo; end
@@ -82,10 +84,9 @@ def bar
8284
index = executor.instance_variable_get(:@index)
8385
index.index_single(RubyIndexer::IndexablePath.new(nil, T.must(uri.to_standardized_path)), source)
8486

85-
stub_no_typechecker
8687
response = executor.execute({
8788
method: "textDocument/hover",
88-
params: { textDocument: { uri: uri }, position: { character: 4, line: 5 } },
89+
params: { textDocument: { uri: uri }, position: { character: 4, line: 7 } },
8990
}).response
9091

9192
assert_match("Hello from `foo`", response.contents.value)
@@ -99,6 +100,8 @@ def test_hovering_methods_invoked_on_explicit_self
99100

100101
uri = URI("file:///fake.rb")
101102
source = <<~RUBY
103+
# typed: false
104+
102105
class A
103106
# Hello from `foo`
104107
def foo; end
@@ -114,10 +117,9 @@ def bar
114117
index = executor.instance_variable_get(:@index)
115118
index.index_single(RubyIndexer::IndexablePath.new(nil, T.must(uri.to_standardized_path)), source)
116119

117-
stub_no_typechecker
118120
response = executor.execute({
119121
method: "textDocument/hover",
120-
params: { textDocument: { uri: uri }, position: { character: 9, line: 5 } },
122+
params: { textDocument: { uri: uri }, position: { character: 9, line: 7 } },
121123
}).response
122124

123125
assert_match("Hello from `foo`", response.contents.value)

0 commit comments

Comments
 (0)