Skip to content

Commit 8d958aa

Browse files
authored
Merge pull request #19861 from vremyavnikuda/docs/find-all-refs-constructor-search
docs: add documentation for find_all_refs constructor search
2 parents 23738b5 + 430f75a commit 8d958aa

File tree

2 files changed

+88
-3
lines changed

2 files changed

+88
-3
lines changed

src/tools/rust-analyzer/crates/ide/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,6 @@ impl Analysis {
514514
self.with_db(|db| goto_type_definition::goto_type_definition(db, position))
515515
}
516516

517-
/// Finds all usages of the reference at point.
518517
pub fn find_all_refs(
519518
&self,
520519
position: FilePosition,

src/tools/rust-analyzer/crates/ide/src/references.rs

Lines changed: 88 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@
88
//! for text occurrences of the identifier. If there's an `ast::NameRef`
99
//! at the index that the match starts at and its tree parent is
1010
//! resolved to the search element definition, we get a reference.
11+
//!
12+
//! Special handling for constructors/initializations:
13+
//! When searching for references to a struct/enum/variant, if the cursor is positioned on:
14+
//! - `{` after a struct/enum/variant definition
15+
//! - `(` for tuple structs/variants
16+
//! - `;` for unit structs
17+
//! - The type name in a struct/enum/variant definition
18+
//! Then only constructor/initialization usages will be shown, filtering out other references.
1119
1220
use hir::{PathResolution, Semantics};
1321
use ide_db::{
@@ -28,27 +36,76 @@ use syntax::{
2836

2937
use crate::{FilePosition, HighlightedRange, NavigationTarget, TryToNav, highlight_related};
3038

39+
/// Result of a reference search operation.
3140
#[derive(Debug, Clone)]
3241
pub struct ReferenceSearchResult {
42+
/// Information about the declaration site of the searched item.
43+
/// For ADTs (structs/enums), this points to the type definition.
44+
/// May be None for primitives or items without clear declaration sites.
3345
pub declaration: Option<Declaration>,
46+
/// All references found, grouped by file.
47+
/// For ADTs when searching from a constructor position (e.g. on '{', '(', ';'),
48+
/// this only includes constructor/initialization usages.
49+
/// The map key is the file ID, and the value is a vector of (range, category) pairs.
50+
/// - range: The text range of the reference in the file
51+
/// - category: Metadata about how the reference is used (read/write/etc)
3452
pub references: IntMap<FileId, Vec<(TextRange, ReferenceCategory)>>,
3553
}
3654

55+
/// Information about the declaration site of a searched item.
3756
#[derive(Debug, Clone)]
3857
pub struct Declaration {
58+
/// Navigation information to jump to the declaration
3959
pub nav: NavigationTarget,
60+
/// Whether the declared item is mutable (relevant for variables)
4061
pub is_mut: bool,
4162
}
4263

4364
// Feature: Find All References
4465
//
45-
// Shows all references of the item at the cursor location
66+
// Shows all references of the item at the cursor location. This includes:
67+
// - Direct references to variables, functions, types, etc.
68+
// - Constructor/initialization references when cursor is on struct/enum definition tokens
69+
// - References in patterns and type contexts
70+
// - References through dereferencing and borrowing
71+
// - References in macro expansions
72+
//
73+
// Special handling for constructors:
74+
// - When the cursor is on `{`, `(`, or `;` in a struct/enum definition
75+
// - When the cursor is on the type name in a struct/enum definition
76+
// These cases will show only constructor/initialization usages of the type
4677
//
4778
// | Editor | Shortcut |
4879
// |---------|----------|
4980
// | VS Code | <kbd>Shift+Alt+F12</kbd> |
5081
//
5182
// ![Find All References](https://user-images.githubusercontent.com/48062697/113020670-b7c34f00-917a-11eb-8003-370ac5f2b3cb.gif)
83+
84+
/// Find all references to the item at the given position.
85+
///
86+
/// # Arguments
87+
/// * `sema` - Semantic analysis context
88+
/// * `position` - Position in the file where to look for the item
89+
/// * `search_scope` - Optional scope to limit the search (e.g. current crate only)
90+
///
91+
/// # Returns
92+
/// Returns `None` if no valid item is found at the position.
93+
/// Otherwise returns a vector of `ReferenceSearchResult`, usually with one element.
94+
/// Multiple results can occur in case of ambiguity or when searching for trait items.
95+
///
96+
/// # Special cases
97+
/// - Control flow keywords (break, continue, etc): Shows all related jump points
98+
/// - Constructor search: When on struct/enum definition tokens (`{`, `(`, `;`), shows only initialization sites
99+
/// - Format string arguments: Shows template parameter usages
100+
/// - Lifetime parameters: Shows lifetime constraint usages
101+
///
102+
/// # Constructor search
103+
/// When the cursor is on specific tokens in a struct/enum definition:
104+
/// - `{` after struct/enum/variant: Shows record literal initializations
105+
/// - `(` after tuple struct/variant: Shows tuple literal initializations
106+
/// - `;` after unit struct: Shows unit literal initializations
107+
/// - Type name in definition: Shows all initialization usages
108+
/// In these cases, other kinds of references (like type references) are filtered out.
52109
pub(crate) fn find_all_refs(
53110
sema: &Semantics<'_, RootDatabase>,
54111
position: FilePosition,
@@ -219,7 +276,19 @@ fn retain_adt_literal_usages(
219276
}
220277
}
221278

222-
/// Returns `Some` if the cursor is at a position for an item to search for all its constructor/literal usages
279+
/// Returns `Some` if the cursor is at a position where we should search for constructor/initialization usages.
280+
/// This is used to implement the special constructor search behavior when the cursor is on specific tokens
281+
/// in a struct/enum/variant definition.
282+
///
283+
/// # Returns
284+
/// - `Some(name)` if the cursor is on:
285+
/// - `{` after a struct/enum/variant definition
286+
/// - `(` for tuple structs/variants
287+
/// - `;` for unit structs
288+
/// - The type name in a struct/enum/variant definition
289+
/// - `None` otherwise
290+
///
291+
/// The returned name is the name of the type whose constructor usages should be searched for.
223292
fn name_for_constructor_search(syntax: &SyntaxNode, position: FilePosition) -> Option<ast::Name> {
224293
let token = syntax.token_at_offset(position.offset).right_biased()?;
225294
let token_parent = token.parent()?;
@@ -257,6 +326,16 @@ fn name_for_constructor_search(syntax: &SyntaxNode, position: FilePosition) -> O
257326
}
258327
}
259328

329+
/// Checks if a name reference is part of an enum variant literal expression.
330+
/// Used to filter references when searching for enum variant constructors.
331+
///
332+
/// # Arguments
333+
/// * `sema` - Semantic analysis context
334+
/// * `enum_` - The enum type to check against
335+
/// * `name_ref` - The name reference to check
336+
///
337+
/// # Returns
338+
/// `true` if the name reference is used as part of constructing a variant of the given enum.
260339
fn is_enum_lit_name_ref(
261340
sema: &Semantics<'_, RootDatabase>,
262341
enum_: hir::Enum,
@@ -284,12 +363,19 @@ fn is_enum_lit_name_ref(
284363
.unwrap_or(false)
285364
}
286365

366+
/// Checks if a path ends with the given name reference.
367+
/// Helper function for checking constructor usage patterns.
287368
fn path_ends_with(path: Option<ast::Path>, name_ref: &ast::NameRef) -> bool {
288369
path.and_then(|path| path.segment())
289370
.and_then(|segment| segment.name_ref())
290371
.map_or(false, |segment| segment == *name_ref)
291372
}
292373

374+
/// Checks if a name reference is used in a literal (constructor) context.
375+
/// Used to filter references when searching for struct/variant constructors.
376+
///
377+
/// # Returns
378+
/// `true` if the name reference is used as part of a struct/variant literal expression.
293379
fn is_lit_name_ref(name_ref: &ast::NameRef) -> bool {
294380
name_ref.syntax().ancestors().find_map(|ancestor| {
295381
match_ast! {

0 commit comments

Comments
 (0)