diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs index 7deffe8e0f6..6f885fba783 100644 --- a/crates/ide-db/src/search.rs +++ b/crates/ide-db/src/search.rs @@ -9,6 +9,7 @@ use base_db::{FileId, FileRange, SourceDatabase, SourceDatabaseExt}; use hir::{DefWithBody, HasAttrs, HasSource, InFile, ModuleSource, Semantics, Visibility}; use once_cell::unsync::Lazy; +use parser::SyntaxKind; use stdx::hash::NoHashHashMap; use syntax::{ast, match_ast, AstNode, TextRange, TextSize}; @@ -67,6 +68,7 @@ pub enum ReferenceCategory { // Create Write, Read, + Import, // FIXME: Some day should be able to search in doc comments. Would probably // need to switch from enum to bitflags then? // DocComment @@ -577,7 +579,7 @@ fn found_self_module_name_ref( let reference = FileReference { range, name: ast::NameLike::NameRef(name_ref.clone()), - category: None, + category: is_name_ref_in_import(name_ref).then(|| ReferenceCategory::Import), }; sink(file_id, reference) } @@ -756,7 +758,7 @@ impl ReferenceCategory { fn new(def: &Definition, r: &ast::NameRef) -> Option { // Only Locals and Fields have accesses for now. if !matches!(def, Definition::Local(_) | Definition::Field(_)) { - return None; + return is_name_ref_in_import(r).then(|| ReferenceCategory::Import); } let mode = r.syntax().ancestors().find_map(|node| { @@ -783,3 +785,12 @@ fn new(def: &Definition, r: &ast::NameRef) -> Option { mode.or(Some(ReferenceCategory::Read)) } } + +fn is_name_ref_in_import(name_ref: &ast::NameRef) -> bool { + name_ref + .syntax() + .parent() + .and_then(ast::PathSegment::cast) + .and_then(|it| it.parent_path().top_path().syntax().parent()) + .map_or(false, |it| it.kind() == SyntaxKind::USE_TREE) +} diff --git a/crates/ide/src/annotations.rs b/crates/ide/src/annotations.rs index ba4c330bf3d..210c5c7facd 100644 --- a/crates/ide/src/annotations.rs +++ b/crates/ide/src/annotations.rs @@ -158,7 +158,6 @@ 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/highlight_related.rs b/crates/ide/src/highlight_related.rs index f190da326e4..1bdd626f1e8 100644 --- a/crates/ide/src/highlight_related.rs +++ b/crates/ide/src/highlight_related.rs @@ -377,6 +377,7 @@ fn check_with_config(ra_fixture: &str, config: HighlightRelatedConfig) { match it { ReferenceCategory::Read => "read", ReferenceCategory::Write => "write", + ReferenceCategory::Import => "import", } .to_string() }), @@ -423,12 +424,12 @@ fn test_hl_self_in_crate_root() { check( r#" use crate$0; - //^^^^^ + //^^^^^ import use self; - //^^^^ + //^^^^ import mod __ { use super; - //^^^^^ + //^^^^^ import } "#, ); @@ -436,7 +437,7 @@ mod __ { r#" //- /main.rs crate:main deps:lib use lib$0; - //^^^ + //^^^ import //- /lib.rs crate:lib "#, ); @@ -450,7 +451,7 @@ fn test_hl_self_in_module() { mod foo; //- /foo.rs use self$0; - // ^^^^ + // ^^^^ import "#, ); } diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index 065b48378b8..0552330814a 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs @@ -425,11 +425,8 @@ pub fn find_all_refs( &self, position: FilePosition, search_scope: Option, - exclude_imports: bool, ) -> Cancellable>> { - self.with_db(|db| { - references::find_all_refs(&Semantics::new(db), position, search_scope, exclude_imports) - }) + self.with_db(|db| references::find_all_refs(&Semantics::new(db), position, search_scope)) } /// 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 5b410c454d9..e942413c110 100644 --- a/crates/ide/src/references.rs +++ b/crates/ide/src/references.rs @@ -54,7 +54,6 @@ 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(); @@ -80,10 +79,6 @@ 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)| { @@ -117,17 +112,6 @@ 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, @@ -758,7 +742,7 @@ pub struct Foo { expect![[r#" foo Module FileId(0) 0..8 4..7 - FileId(0) 14..17 + FileId(0) 14..17 Import "#]], ); } @@ -776,7 +760,7 @@ fn test_find_all_refs_decl_module_on_self() { expect![[r#" foo Module FileId(0) 0..8 4..7 - FileId(1) 4..8 + FileId(1) 4..8 Import "#]], ); } @@ -791,7 +775,7 @@ fn test_find_all_refs_decl_module_on_self_crate_root() { expect![[r#" Module FileId(0) 0..10 - FileId(0) 4..8 + FileId(0) 4..8 Import "#]], ); } @@ -819,7 +803,7 @@ pub(super) struct Foo$0 { expect![[r#" Foo Struct FileId(2) 0..41 18..21 - FileId(1) 20..23 + FileId(1) 20..23 Import FileId(1) 47..50 "#]], ); @@ -982,7 +966,7 @@ fn f$0() {} expect![[r#" f Function FileId(0) 22..31 25..26 - FileId(1) 11..12 + FileId(1) 11..12 Import FileId(1) 24..25 "#]], ); @@ -1110,7 +1094,7 @@ fn check(ra_fixture: &str, expect: Expect) { 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, false).unwrap().unwrap(); + let refs = analysis.find_all_refs(pos, search_scope).unwrap().unwrap(); let mut actual = String::new(); for refs in refs { @@ -1440,9 +1424,9 @@ fn test_transitive() { expect![[r#" Foo Struct FileId(0) 0..15 11..14 - FileId(1) 16..19 - FileId(2) 16..19 - FileId(3) 16..19 + FileId(1) 16..19 Import + FileId(2) 16..19 Import + FileId(3) 16..19 Import "#]], ); } @@ -1470,7 +1454,7 @@ macro_rules! foo$0 { expect![[r#" foo Macro FileId(1) 0..61 29..32 - FileId(0) 46..49 + FileId(0) 46..49 Import FileId(2) 0..3 FileId(3) 5..8 "#]], @@ -1633,7 +1617,7 @@ fn derive() { expect![[r#" derive_identity Derive FileId(2) 1..107 45..60 - FileId(0) 17..31 + FileId(0) 17..31 Import FileId(0) 56..70 "#]], ); diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index 7b486744da5..baf6dd7488b 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs @@ -10,8 +10,8 @@ use anyhow::Context; use ide::{ AnnotationConfig, AssistKind, AssistResolveStrategy, FileId, FilePosition, FileRange, - HoverAction, HoverGotoTypeData, Query, RangeInfo, Runnable, RunnableKind, SingleResolve, - SourceChange, TextEdit, + HoverAction, HoverGotoTypeData, Query, RangeInfo, ReferenceCategory, Runnable, RunnableKind, + SingleResolve, SourceChange, TextEdit, }; use ide_db::SymbolKind; use lsp_server::ErrorCode; @@ -1014,7 +1014,7 @@ pub(crate) fn handle_references( let exclude_imports = snap.config.find_all_refs_exclude_imports(); - let refs = match snap.analysis.find_all_refs(position, None, exclude_imports)? { + let refs = match snap.analysis.find_all_refs(position, None)? { None => return Ok(None), Some(refs) => refs, }; @@ -1034,7 +1034,11 @@ pub(crate) fn handle_references( refs.references .into_iter() .flat_map(|(file_id, refs)| { - refs.into_iter().map(move |(range, _)| FileRange { file_id, range }) + refs.into_iter() + .filter(|&(_, category)| { + !exclude_imports || category != Some(ReferenceCategory::Import) + }) + .map(move |(range, _)| FileRange { file_id, range }) }) .chain(decl) }) @@ -1285,7 +1289,7 @@ pub(crate) fn handle_document_highlight( .into_iter() .map(|ide::HighlightedRange { range, category }| lsp_types::DocumentHighlight { range: to_proto::range(&line_index, range), - kind: category.map(to_proto::document_highlight_kind), + kind: category.and_then(to_proto::document_highlight_kind), }) .collect(); Ok(Some(res)) @@ -1654,9 +1658,7 @@ 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, false).unwrap_or(None) - { + if let Some(ref_search_res) = snap.analysis.find_all_refs(*position, None).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/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index e083b9d0e33..1de801e23e5 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs @@ -83,10 +83,11 @@ pub(crate) fn structure_node_kind(kind: StructureNodeKind) -> lsp_types::SymbolK pub(crate) fn document_highlight_kind( category: ReferenceCategory, -) -> lsp_types::DocumentHighlightKind { +) -> Option { match category { - ReferenceCategory::Read => lsp_types::DocumentHighlightKind::READ, - ReferenceCategory::Write => lsp_types::DocumentHighlightKind::WRITE, + ReferenceCategory::Read => Some(lsp_types::DocumentHighlightKind::READ), + ReferenceCategory::Write => Some(lsp_types::DocumentHighlightKind::WRITE), + ReferenceCategory::Import => None, } }