Skip to content

Commit 91435dd

Browse files
committed
[ty] de-dupe ref matching
1 parent 4027b37 commit 91435dd

1 file changed

Lines changed: 76 additions & 53 deletions

File tree

crates/ty_ide/src/references.rs

Lines changed: 76 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -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.
279322
fn 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

696726
impl 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

Comments
 (0)