@@ -274,6 +274,49 @@ fn navigation_targets_intersect(
274274 } )
275275}
276276
277+ fn covering_node_for_identifier < ' a > (
278+ target_text : & str ,
279+ ancestors : & [ AnyNodeRef < ' a > ] ,
280+ identifier : & ' a ast:: Identifier ,
281+ ) -> Option < CoveringNode < ' a > > {
282+ // Quick text-based check first
283+ if identifier. id != target_text {
284+ return None ;
285+ }
286+
287+ let mut ancestors_with_identifier = ancestors. to_vec ( ) ;
288+ ancestors_with_identifier. push ( AnyNodeRef :: from ( identifier) ) ;
289+ Some ( CoveringNode :: from_ancestors ( ancestors_with_identifier) )
290+ }
291+
292+ fn covering_node_matches_target_definitions (
293+ model : & SemanticModel < ' _ > ,
294+ tokens : & Tokens ,
295+ mode : ReferencesMode ,
296+ target_definitions : & NavigationTargets ,
297+ covering_node : & CoveringNode < ' _ > ,
298+ ) -> bool {
299+ // Use the start of the covering node as the offset. Any offset within
300+ // the node is fine here. Offsets matter only for import statements
301+ // where the identifier might be a multi-part module name.
302+ let offset = covering_node. node ( ) . start ( ) ;
303+ let Some ( goto_target) = GotoTarget :: from_covering_node ( model, covering_node, offset, tokens)
304+ else {
305+ return false ;
306+ } ;
307+
308+ // Get the definitions for this goto target
309+ let Some ( current_definitions) = goto_target
310+ . get_definition_targets ( model, mode. to_import_alias_resolution ( ) )
311+ . and_then ( |definitions| definitions. declaration_targets ( model. db ( ) ) )
312+ else {
313+ return false ;
314+ } ;
315+
316+ // Check if any of the current definitions match our target definitions
317+ navigation_targets_intersect ( target_definitions, & current_definitions)
318+ }
319+
277320/// Find all references to a local symbol within the current file.
278321/// The behavior depends on the provided mode.
279322fn references_for_file (
@@ -553,41 +596,28 @@ impl LocalReferencesFinder<'_> {
553596
554597 /// Helper method to check identifier references for declarations
555598 fn check_identifier_reference ( & mut self , identifier : & ast:: Identifier ) {
556- // Quick text-based check first
557- if identifier. id != self . target_text {
558- return ;
599+ if let Some ( covering_node) =
600+ covering_node_for_identifier ( self . target_text , & self . ancestors , identifier)
601+ {
602+ self . check_reference_from_covering_node ( & covering_node) ;
559603 }
560-
561- let mut ancestors_with_identifier = self . ancestors . clone ( ) ;
562- ancestors_with_identifier. push ( AnyNodeRef :: from ( identifier) ) ;
563- let covering_node = CoveringNode :: from_ancestors ( ancestors_with_identifier) ;
564- self . check_reference_from_covering_node ( & covering_node) ;
565604 }
566605
567606 /// Determines whether the given covering node is a reference to
568607 /// the symbol we are searching for
569608 fn check_reference_from_covering_node ( & mut self , covering_node : & CoveringNode < ' _ > ) {
570- // Use the start of the covering node as the offset. Any offset within
571- // the node is fine here. Offsets matter only for import statements
572- // where the identifier might be a multi-part module name.
573- let offset = covering_node. node ( ) . start ( ) ;
574- if let Some ( goto_target) =
575- GotoTarget :: from_covering_node ( self . model , covering_node, offset, self . tokens )
576- {
577- // Get the definitions for this goto target
578- if let Some ( current_definitions) = goto_target
579- . get_definition_targets ( self . model , self . mode . to_import_alias_resolution ( ) )
580- . and_then ( |definitions| definitions. declaration_targets ( self . model . db ( ) ) )
581- {
582- // Check if any of the current definitions match our target definitions
583- if navigation_targets_intersect ( self . target_definitions , & current_definitions) {
584- // Determine if this is a read or write reference
585- let kind = self . determine_reference_kind ( covering_node) ;
586- let target =
587- ReferenceTarget :: new ( self . model . file ( ) , covering_node. node ( ) . range ( ) , kind) ;
588- self . references . push ( target) ;
589- }
590- }
609+ if covering_node_matches_target_definitions (
610+ self . model ,
611+ self . tokens ,
612+ self . mode ,
613+ self . target_definitions ,
614+ covering_node,
615+ ) {
616+ // Determine if this is a read or write reference
617+ let kind = self . determine_reference_kind ( covering_node) ;
618+ let target =
619+ ReferenceTarget :: new ( self . model . file ( ) , covering_node. node ( ) . range ( ) , kind) ;
620+ self . references . push ( target) ;
591621 }
592622 }
593623
@@ -695,34 +725,27 @@ impl LocalReferencesFinder<'_> {
695725
696726impl KeywordArgumentReferencesFinder < ' _ > {
697727 fn check_identifier_reference ( & mut self , identifier : & ast:: Identifier ) {
698- if identifier. id != self . target_text {
699- return ;
728+ if let Some ( covering_node) =
729+ covering_node_for_identifier ( self . target_text , & self . ancestors , identifier)
730+ {
731+ self . check_reference_from_covering_node ( & covering_node) ;
700732 }
701-
702- let mut ancestors_with_identifier = self . ancestors . clone ( ) ;
703- ancestors_with_identifier. push ( AnyNodeRef :: from ( identifier) ) ;
704- let covering_node = CoveringNode :: from_ancestors ( ancestors_with_identifier) ;
705- self . check_reference_from_covering_node ( & covering_node) ;
706733 }
707734
708735 fn check_reference_from_covering_node ( & mut self , covering_node : & CoveringNode < ' _ > ) {
709- let offset = covering_node. node ( ) . start ( ) ;
710- if let Some ( goto_target) =
711- GotoTarget :: from_covering_node ( self . model , covering_node, offset, self . tokens )
712- {
713- if let Some ( current_definitions) = goto_target
714- . get_definition_targets ( self . model , self . mode . to_import_alias_resolution ( ) )
715- . and_then ( |definitions| definitions. declaration_targets ( self . model . db ( ) ) )
716- {
717- if navigation_targets_intersect ( self . target_definitions , & current_definitions) {
718- let target = ReferenceTarget :: new (
719- self . model . file ( ) ,
720- covering_node. node ( ) . range ( ) ,
721- ReferenceKind :: Other ,
722- ) ;
723- self . references . push ( target) ;
724- }
725- }
736+ if covering_node_matches_target_definitions (
737+ self . model ,
738+ self . tokens ,
739+ self . mode ,
740+ self . target_definitions ,
741+ covering_node,
742+ ) {
743+ let target = ReferenceTarget :: new (
744+ self . model . file ( ) ,
745+ covering_node. node ( ) . range ( ) ,
746+ ReferenceKind :: Other ,
747+ ) ;
748+ self . references . push ( target) ;
726749 }
727750 }
728751}
0 commit comments