diff --git a/crates/ide/src/annotations.rs b/crates/ide/src/annotations.rs index 210c5c7facd2..ba4c330bf3d5 100644 --- a/crates/ide/src/annotations.rs +++ b/crates/ide/src/annotations.rs @@ -158,6 +158,7 @@ pub(crate) fn resolve_annotation(db: &RootDatabase, mut annotation: Annotation) &Semantics::new(db), FilePosition { file_id, offset: annotation.range.start() }, None, + false, ) .map(|result| { result diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index 0552330814aa..065b48378b88 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -425,8 +425,11 @@ impl Analysis { &self, position: FilePosition, search_scope: Option, + exclude_imports: bool, ) -> Cancellable>> { - self.with_db(|db| references::find_all_refs(&Semantics::new(db), position, search_scope)) + self.with_db(|db| { + references::find_all_refs(&Semantics::new(db), position, search_scope, exclude_imports) + }) } /// Finds all methods and free functions for the file. Does not return tests! diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs index 99614b645e48..5b410c454d9d 100644 --- a/crates/ide/src/references.rs +++ b/crates/ide/src/references.rs @@ -54,6 +54,7 @@ pub(crate) fn find_all_refs( sema: &Semantics<'_, RootDatabase>, position: FilePosition, search_scope: Option, + exclude_imports: bool, ) -> Option> { let _p = profile::span("find_all_refs"); let syntax = sema.parse(position.file_id).syntax().clone(); @@ -79,6 +80,10 @@ pub(crate) fn find_all_refs( retain_adt_literal_usages(&mut usages, def, sema); } + if exclude_imports { + filter_import_references(&mut usages); + } + let references = usages .into_iter() .map(|(file_id, refs)| { @@ -112,6 +117,17 @@ pub(crate) fn find_all_refs( } } +fn filter_import_references(usages: &mut UsageSearchResult) { + for (_file_id, refs) in &mut usages.references { + refs.retain(|it| match it.name.as_name_ref() { + Some(name_ref) => { + !name_ref.syntax().ancestors().any(|it_ref| matches!(it_ref.kind(), USE)) + } + None => true, + }); + } +} + pub(crate) fn find_defs<'a>( sema: &'a Semantics<'_, RootDatabase>, syntax: &SyntaxNode, @@ -1094,7 +1110,7 @@ impl Foo { fn check_with_scope(ra_fixture: &str, search_scope: Option, expect: Expect) { let (analysis, pos) = fixture::position(ra_fixture); - let refs = analysis.find_all_refs(pos, search_scope).unwrap().unwrap(); + let refs = analysis.find_all_refs(pos, search_scope, false).unwrap().unwrap(); let mut actual = String::new(); for refs in refs { diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 6d1bf08124fa..e0384e67d466 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -219,7 +219,6 @@ config_data! { files_excludeDirs: Vec = "[]", /// Controls file watching implementation. files_watcher: FilesWatcherDef = "\"client\"", - /// Enables highlighting of related references while the cursor is on `break`, `loop`, `while`, or `for` keywords. highlightRelated_breakPoints_enable: bool = "true", /// Enables highlighting of all exit points while the cursor is on any `return`, `?`, `fn`, or return type arrow (`->`). @@ -361,6 +360,9 @@ config_data! { /// this is rust-analyzer itself, but we override this in tests). procMacro_server: Option = "null", + /// Exclude imports from find-all-references. + references_excludeImports: bool = "false", + /// Command to be executed instead of 'cargo' for runnables. runnables_command: Option = "null", /// Additional arguments to be passed to cargo for runnables such as @@ -1151,6 +1153,10 @@ impl Config { } } + pub fn find_all_refs_exclude_imports(&self) -> bool { + self.data.references_excludeImports + } + pub fn snippet_cap(&self) -> bool { self.experimental("snippetTextEdit") } diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index e79cf3d3fd6e..7b486744da52 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs @@ -1012,7 +1012,9 @@ pub(crate) fn handle_references( let _p = profile::span("handle_references"); let position = from_proto::file_position(&snap, params.text_document_position)?; - let refs = match snap.analysis.find_all_refs(position, None)? { + let exclude_imports = snap.config.find_all_refs_exclude_imports(); + + let refs = match snap.analysis.find_all_refs(position, None, exclude_imports)? { None => return Ok(None), Some(refs) => refs, }; @@ -1652,7 +1654,9 @@ fn show_ref_command_link( position: &FilePosition, ) -> Option { if snap.config.hover_actions().references && snap.config.client_commands().show_reference { - if let Some(ref_search_res) = snap.analysis.find_all_refs(*position, None).unwrap_or(None) { + if let Some(ref_search_res) = + snap.analysis.find_all_refs(*position, None, false).unwrap_or(None) + { let uri = to_proto::url(snap, position.file_id); let line_index = snap.file_line_index(position.file_id).ok()?; let position = to_proto::position(&line_index, position.offset); diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc index 6757624aea6a..2b02c64b66f0 100644 --- a/docs/user/generated_config.adoc +++ b/docs/user/generated_config.adoc @@ -551,6 +551,11 @@ This config takes a map of crate names with the exported proc-macro names to ign Internal config, path to proc-macro server executable (typically, this is rust-analyzer itself, but we override this in tests). -- +[[rust-analyzer.references.excludeImports]]rust-analyzer.references.excludeImports (default: `false`):: ++ +-- +Exclude imports from find-all-references. +-- [[rust-analyzer.runnables.command]]rust-analyzer.runnables.command (default: `null`):: + -- diff --git a/editors/code/package.json b/editors/code/package.json index 7e91d989f156..2ffed7595afa 100644 --- a/editors/code/package.json +++ b/editors/code/package.json @@ -1041,6 +1041,11 @@ "string" ] }, + "rust-analyzer.references.excludeImports": { + "markdownDescription": "Exclude imports from find-all-references.", + "default": false, + "type": "boolean" + }, "rust-analyzer.runnables.command": { "markdownDescription": "Command to be executed instead of 'cargo' for runnables.", "default": null,