@@ -12,7 +12,7 @@ class Definition
1212 def initialize ( response_builder , global_state , language_id , uri , node_context , dispatcher , sorbet_level ) # rubocop:disable Metrics/ParameterLists
1313 @response_builder = response_builder
1414 @global_state = global_state
15- @index = global_state . index #: RubyIndexer::Index
15+ @graph = global_state . graph #: Rubydex::Graph
1616 @type_inferrer = global_state . type_inferrer #: TypeInferrer
1717 @language_id = language_id
1818 @uri = uri
@@ -109,15 +109,15 @@ def on_constant_path_node_enter(node)
109109 name = RubyIndexer ::Index . constant_name ( node )
110110 return if name . nil?
111111
112- find_in_index ( name )
112+ handle_constant_definition ( name )
113113 end
114114
115115 #: (Prism::ConstantReadNode node) -> void
116116 def on_constant_read_node_enter ( node )
117117 name = RubyIndexer ::Index . constant_name ( node )
118118 return if name . nil?
119119
120- find_in_index ( name )
120+ handle_constant_definition ( name )
121121 end
122122
123123 #: (Prism::GlobalVariableAndWriteNode node) -> void
@@ -152,32 +152,32 @@ def on_global_variable_write_node_enter(node)
152152
153153 #: (Prism::InstanceVariableReadNode node) -> void
154154 def on_instance_variable_read_node_enter ( node )
155- handle_instance_variable_definition ( node . name . to_s )
155+ handle_variable_definition ( node . name . to_s )
156156 end
157157
158158 #: (Prism::InstanceVariableWriteNode node) -> void
159159 def on_instance_variable_write_node_enter ( node )
160- handle_instance_variable_definition ( node . name . to_s )
160+ handle_variable_definition ( node . name . to_s )
161161 end
162162
163163 #: (Prism::InstanceVariableAndWriteNode node) -> void
164164 def on_instance_variable_and_write_node_enter ( node )
165- handle_instance_variable_definition ( node . name . to_s )
165+ handle_variable_definition ( node . name . to_s )
166166 end
167167
168168 #: (Prism::InstanceVariableOperatorWriteNode node) -> void
169169 def on_instance_variable_operator_write_node_enter ( node )
170- handle_instance_variable_definition ( node . name . to_s )
170+ handle_variable_definition ( node . name . to_s )
171171 end
172172
173173 #: (Prism::InstanceVariableOrWriteNode node) -> void
174174 def on_instance_variable_or_write_node_enter ( node )
175- handle_instance_variable_definition ( node . name . to_s )
175+ handle_variable_definition ( node . name . to_s )
176176 end
177177
178178 #: (Prism::InstanceVariableTargetNode node) -> void
179179 def on_instance_variable_target_node_enter ( node )
180- handle_instance_variable_definition ( node . name . to_s )
180+ handle_variable_definition ( node . name . to_s )
181181 end
182182
183183 #: (Prism::SuperNode node) -> void
@@ -192,32 +192,32 @@ def on_forwarding_super_node_enter(node)
192192
193193 #: (Prism::ClassVariableAndWriteNode node) -> void
194194 def on_class_variable_and_write_node_enter ( node )
195- handle_class_variable_definition ( node . name . to_s )
195+ handle_variable_definition ( node . name . to_s )
196196 end
197197
198198 #: (Prism::ClassVariableOperatorWriteNode node) -> void
199199 def on_class_variable_operator_write_node_enter ( node )
200- handle_class_variable_definition ( node . name . to_s )
200+ handle_variable_definition ( node . name . to_s )
201201 end
202202
203203 #: (Prism::ClassVariableOrWriteNode node) -> void
204204 def on_class_variable_or_write_node_enter ( node )
205- handle_class_variable_definition ( node . name . to_s )
205+ handle_variable_definition ( node . name . to_s )
206206 end
207207
208208 #: (Prism::ClassVariableTargetNode node) -> void
209209 def on_class_variable_target_node_enter ( node )
210- handle_class_variable_definition ( node . name . to_s )
210+ handle_variable_definition ( node . name . to_s )
211211 end
212212
213213 #: (Prism::ClassVariableReadNode node) -> void
214214 def on_class_variable_read_node_enter ( node )
215- handle_class_variable_definition ( node . name . to_s )
215+ handle_variable_definition ( node . name . to_s )
216216 end
217217
218218 #: (Prism::ClassVariableWriteNode node) -> void
219219 def on_class_variable_write_node_enter ( node )
220- handle_class_variable_definition ( node . name . to_s )
220+ handle_variable_definition ( node . name . to_s )
221221 end
222222
223223 private
@@ -257,106 +257,74 @@ def handle_super_node_definition
257257
258258 #: (String name) -> void
259259 def handle_global_variable_definition ( name )
260- entries = @index [ name ]
260+ declaration = @graph [ name ]
261+ return unless declaration
261262
262- return unless entries
263-
264- entries . each do |entry |
265- location = entry . location
266-
267- @response_builder << Interface ::Location . new (
268- uri : entry . uri . to_s ,
269- range : Interface ::Range . new (
270- start : Interface ::Position . new ( line : location . start_line - 1 , character : location . start_column ) ,
271- end : Interface ::Position . new ( line : location . end_line - 1 , character : location . end_column ) ,
272- ) ,
273- )
274- end
275- end
276-
277- #: (String name) -> void
278- def handle_class_variable_definition ( name )
279- type = @type_inferrer . infer_receiver_type ( @node_context )
280- return unless type
281-
282- entries = @index . resolve_class_variable ( name , type . name )
283- return unless entries
284-
285- entries . each do |entry |
286- @response_builder << Interface ::Location . new (
287- uri : entry . uri . to_s ,
288- range : range_from_location ( entry . location ) ,
289- )
290- end
291- rescue RubyIndexer ::Index ::NonExistingNamespaceError
292- # If by any chance we haven't indexed the owner, then there's no way to find the right declaration
263+ declaration . definitions . each { |definition | @response_builder << definition . to_lsp_selection_location }
293264 end
294265
266+ # Handle class or instance variables. We collect all definitions across the ancestors of the type
267+ #
295268 #: (String name) -> void
296- def handle_instance_variable_definition ( name )
297- # Sorbet enforces that all instance variables be declared on typed strict or higher, which means it will be able
298- # to provide all features for them
269+ def handle_variable_definition ( name )
270+ # Sorbet enforces that all variables be declared on typed strict or higher, which means it will be able to
271+ # provide all features for them
299272 return if @sorbet_level . strict?
300273
301274 type = @type_inferrer . infer_receiver_type ( @node_context )
302275 return unless type
303276
304- entries = @index . resolve_instance_variable ( name , type . name )
305- return unless entries
277+ owner = @graph [ type . name ]
278+ return unless owner . is_a? ( Rubydex :: Namespace )
306279
307- entries . each do |entry |
308- location = entry . location
280+ owner . ancestors . each do |ancestor |
281+ member = ancestor . member ( name )
282+ next unless member
309283
310- @response_builder << Interface ::Location . new (
311- uri : entry . uri . to_s ,
312- range : Interface ::Range . new (
313- start : Interface ::Position . new ( line : location . start_line - 1 , character : location . start_column ) ,
314- end : Interface ::Position . new ( line : location . end_line - 1 , character : location . end_column ) ,
315- ) ,
316- )
284+ member . definitions . each { |definition | @response_builder << definition . to_lsp_selection_location }
317285 end
318- rescue RubyIndexer ::Index ::NonExistingNamespaceError
319- # If by any chance we haven't indexed the owner, then there's no way to find the right declaration
320286 end
321287
322288 #: (String message, TypeInferrer::Type? receiver_type, ?inherited_only: bool) -> void
323289 def handle_method_definition ( message , receiver_type , inherited_only : false )
324- methods = if receiver_type
325- @index . resolve_method ( message , receiver_type . name , inherited_only : inherited_only )
290+ declaration = if receiver_type
291+ owner = @graph [ receiver_type . name ]
292+ owner . find_member ( "#{ message } ()" , only_inherited : inherited_only ) if owner . is_a? ( Rubydex ::Namespace )
326293 end
327294
328- # If the method doesn't have a receiver, or the guessed receiver doesn't have any matched candidates,
329- # then we provide a few candidates to jump to
330- # But we don't want to provide too many candidates, as it can be overwhelming
331- if receiver_type . nil? || ( receiver_type . is_a? ( TypeInferrer ::GuessedType ) && methods . nil? )
332- methods = @index [ message ] & .take ( MAX_NUMBER_OF_DEFINITION_CANDIDATES_WITHOUT_RECEIVER )
295+ # If the method doesn't have a receiver, or the guessed receiver doesn't have any matched candidates, then we
296+ # provide a few candidates to jump to. However, we don't want to provide too many candidates, as it can be
297+ # overwhelming
298+ if receiver_type . nil? || ( receiver_type . is_a? ( TypeInferrer ::GuessedType ) && declaration . nil? )
299+ declaration = @graph . search ( "# #{ message } ()" ) . take ( MAX_NUMBER_OF_DEFINITION_CANDIDATES_WITHOUT_RECEIVER )
333300 end
334301
335- return unless methods
302+ return unless declaration
336303
337- methods . each do |target_method |
338- uri = target_method . uri
339- full_path = uri . full_path
340- next if @sorbet_level . true_or_higher? && ( !full_path || not_in_dependencies? ( full_path ) )
304+ Array ( declaration ) . each do |decl |
305+ decl . definitions . each do |definition |
306+ location = definition . location
307+ uri = URI ( location . uri )
308+ full_path = uri . full_path
309+ next if @sorbet_level . true_or_higher? && ( !full_path || not_in_dependencies? ( full_path ) )
341310
342- @response_builder << Interface ::LocationLink . new (
343- target_uri : uri . to_s ,
344- target_range : range_from_location ( target_method . location ) ,
345- target_selection_range : range_from_location ( target_method . name_location ) ,
346- )
311+ @response_builder << Interface ::LocationLink . new (
312+ target_uri : uri . to_s ,
313+ target_range : definition . to_lsp_selection_range ,
314+ target_selection_range : definition . to_lsp_name_range || definition . to_lsp_selection_range ,
315+ )
316+ end
347317 end
348318 end
349319
350320 #: (Prism::StringNode node, Symbol message) -> void
351321 def handle_require_definition ( node , message )
352322 case message
353323 when :require
354- entry = @index . search_require_paths ( node . content ) . find do |uri |
355- uri . require_path == node . content
356- end
324+ document = @graph . resolve_require_path ( node . content , $LOAD_PATH)
357325
358- if entry
359- candidate = entry . full_path
326+ if document
327+ candidate = URI ( document . uri ) . full_path
360328
361329 if candidate
362330 @response_builder << Interface ::Location . new (
@@ -392,35 +360,33 @@ def handle_autoload_definition(node)
392360 constant_name = argument . value
393361 return unless constant_name
394362
395- find_in_index ( constant_name )
363+ handle_constant_definition ( constant_name )
396364 end
397365
398366 #: (String value) -> void
399- def find_in_index ( value )
400- entries = @index . resolve ( value , @node_context . nesting )
401- return unless entries
367+ def handle_constant_definition ( value )
368+ declaration = @graph . resolve_constant ( value , @node_context . nesting )
369+ return unless declaration
402370
371+ # [RUBYDEX] TODO: temporarily commented out until we have the visibility API
372+ #
403373 # We should only allow jumping to the definition of private constants if the constant is defined in the same
404374 # namespace as the reference
405- first_entry = entries . first #: as !nil
406- return if first_entry . private? && first_entry . name != "#{ @node_context . fully_qualified_name } ::#{ value } "
375+ #
376+ # return if declaration .private? && declaration .name != "#{@node_context.fully_qualified_name}::#{value}"
407377
408- entries . each do |entry |
378+ declaration . definitions . each do |definition |
409379 # If the project has Sorbet, then we only want to handle go to definition for constants defined in gems, as an
410380 # additional behavior on top of jumping to RBIs. The only sigil where Sorbet cannot handle constants is typed
411381 # ignore
412- uri = entry . uri
382+ uri = URI ( definition . location . uri )
413383 full_path = uri . full_path
414384
415385 if !@sorbet_level . ignore? && ( !full_path || not_in_dependencies? ( full_path ) )
416386 next
417387 end
418388
419- @response_builder << Interface ::LocationLink . new (
420- target_uri : uri . to_s ,
421- target_range : range_from_location ( entry . location ) ,
422- target_selection_range : range_from_location ( entry . name_location ) ,
423- )
389+ @response_builder << definition . to_lsp_location_link
424390 end
425391 end
426392 end
0 commit comments