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
1220use hir:: { PathResolution , Semantics } ;
1321use ide_db:: {
@@ -28,27 +36,76 @@ use syntax::{
2836
2937use crate :: { FilePosition , HighlightedRange , NavigationTarget , TryToNav , highlight_related} ;
3038
39+ /// Result of a reference search operation.
3140#[ derive( Debug , Clone ) ]
3241pub 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 ) ]
3857pub 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// 
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.
52109pub ( 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.
223292fn 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.
260339fn 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.
287368fn 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.
293379fn is_lit_name_ref ( name_ref : & ast:: NameRef ) -> bool {
294380 name_ref. syntax ( ) . ancestors ( ) . find_map ( |ancestor| {
295381 match_ast ! {
0 commit comments