From bad4e48672f928644457cece3b7e21dd78ea1e9b Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Sun, 21 Mar 2021 20:08:08 +0100 Subject: Set up a search scope when searching for mbe macro references --- crates/hir/src/lib.rs | 5 +++++ crates/ide/src/references.rs | 30 ++++++++++++++++++++++++++++++ crates/ide_db/src/search.rs | 25 +++++++++++++++++++++---- 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 68f4551c0..ea0a60961 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -1150,6 +1150,11 @@ impl MacroDef { // FIXME: wrong for `ProcMacro` matches!(self.id.kind, MacroDefKind::ProcMacro(..) | MacroDefKind::BuiltInDerive(..)) } + + /// Indicate it is a declarative macro + pub fn is_declarative(&self) -> bool { + matches!(self.id.kind, MacroDefKind::Declarative(..)) + } } /// Invariant: `inner.as_assoc_item(db).is_some()` diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs index 379674530..95ed8a045 100644 --- a/crates/ide/src/references.rs +++ b/crates/ide/src/references.rs @@ -1294,4 +1294,34 @@ pub use level1::Foo; "#]], ); } + + #[test] + fn test_decl_macro_references() { + check( + r#" +//- /lib.rs crate:lib +#[macro_use] +mod qux; +mod bar; + +pub use self::foo; +//- /qux.rs +#[macro_export] +macro_rules! foo$0 { + () => {struct Foo;}; +} +//- /bar.rs +foo!(); +//- /other.rs crate:other deps:lib new_source_root: +lib::foo!(); +"#, + expect![[r#" + foo Macro FileId(1) 0..61 29..32 + + FileId(0) 46..49 + FileId(2) 0..3 + FileId(3) 5..8 + "#]], + ); + } } diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs index 8e93de277..5fdcb13cf 100644 --- a/crates/ide_db/src/search.rs +++ b/crates/ide_db/src/search.rs @@ -7,7 +7,7 @@ use std::{convert::TryInto, mem}; use base_db::{FileId, FileRange, SourceDatabase, SourceDatabaseExt}; -use hir::{DefWithBody, HasSource, Module, ModuleSource, Semantics, Visibility}; +use hir::{DefWithBody, HasAttrs, HasSource, Module, ModuleSource, Semantics, Visibility}; use once_cell::unsync::Lazy; use rustc_hash::FxHashMap; use syntax::{ast, match_ast, AstNode, TextRange, TextSize}; @@ -244,9 +244,8 @@ impl Definition { return SearchScope::new(res); } - if let Some(Visibility::Public) = vis { + let rev_dep_scope = || { let mut res = FxHashMap::default(); - let krate = module.krate(); for rev_dep in krate.transitive_reverse_dependencies(db) { let root_file = rev_dep.root_file(db); @@ -254,7 +253,25 @@ impl Definition { let source_root = db.source_root(source_root_id); res.extend(source_root.iter().map(|id| (id, None))); } - return SearchScope::new(res); + SearchScope::new(res) + }; + + if let Definition::Macro(macro_def) = self { + if macro_def.is_declarative() { + return if macro_def.attrs(db).by_key("macro_export").exists() { + rev_dep_scope() + } else { + let source_root_id = db.file_source_root(file_id); + let source_root = db.source_root(source_root_id); + SearchScope::new( + source_root.iter().map(|id| (id, None)).collect::>(), + ) + }; + } + } + + if let Some(Visibility::Public) = vis { + return rev_dep_scope(); } let mut res = FxHashMap::default(); -- cgit v1.2.3 From 7c4eb66c1acf10216fa866e05d646bdaea229ded Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 22 Mar 2021 15:56:59 +0100 Subject: Merge hir::MacroDef::is_* into hir::MacroDef::kind --- crates/hir/src/lib.rs | 31 ++++++++++++---------- crates/ide_completion/src/completions/attribute.rs | 3 ++- crates/ide_db/src/search.rs | 2 +- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index ea0a60961..5da6a0340 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -1116,6 +1116,14 @@ impl BuiltinType { } } +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum MacroKind { + Declarative, + ProcMacro, + Derive, + BuiltIn, +} + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct MacroDef { pub(crate) id: MacroDefId, @@ -1140,20 +1148,15 @@ impl MacroDef { } } - /// Indicate it is a proc-macro - pub fn is_proc_macro(&self) -> bool { - matches!(self.id.kind, MacroDefKind::ProcMacro(..)) - } - - /// Indicate it is a derive macro - pub fn is_derive_macro(&self) -> bool { - // FIXME: wrong for `ProcMacro` - matches!(self.id.kind, MacroDefKind::ProcMacro(..) | MacroDefKind::BuiltInDerive(..)) - } - - /// Indicate it is a declarative macro - pub fn is_declarative(&self) -> bool { - matches!(self.id.kind, MacroDefKind::Declarative(..)) + pub fn kind(&self) -> MacroKind { + match self.id.kind { + MacroDefKind::Declarative(_) => MacroKind::Declarative, + MacroDefKind::BuiltIn(_, _) => MacroKind::BuiltIn, + MacroDefKind::BuiltInDerive(_, _) => MacroKind::Derive, + MacroDefKind::BuiltInEager(_, _) => MacroKind::BuiltIn, + // FIXME might be a derive + MacroDefKind::ProcMacro(_, _) => MacroKind::ProcMacro, + } } } diff --git a/crates/ide_completion/src/completions/attribute.rs b/crates/ide_completion/src/completions/attribute.rs index e846678b4..b1505c74b 100644 --- a/crates/ide_completion/src/completions/attribute.rs +++ b/crates/ide_completion/src/completions/attribute.rs @@ -246,7 +246,8 @@ fn get_derive_names_in_scope(ctx: &CompletionContext) -> FxHashSet { let mut result = FxHashSet::default(); ctx.scope.process_all_names(&mut |name, scope_def| { if let hir::ScopeDef::MacroDef(mac) = scope_def { - if mac.is_derive_macro() { + // FIXME kind() doesn't check whether proc-macro is a derive + if mac.kind() == hir::MacroKind::Derive || mac.kind() == hir::MacroKind::ProcMacro { result.insert(name.to_string()); } } diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs index 5fdcb13cf..ff958c757 100644 --- a/crates/ide_db/src/search.rs +++ b/crates/ide_db/src/search.rs @@ -257,7 +257,7 @@ impl Definition { }; if let Definition::Macro(macro_def) = self { - if macro_def.is_declarative() { + if macro_def.kind() == hir::MacroKind::Declarative { return if macro_def.attrs(db).by_key("macro_export").exists() { rev_dep_scope() } else { -- cgit v1.2.3 From 395183e0b7609dfb0d21f135879dc8f3d8e97e41 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 22 Mar 2021 17:11:33 +0100 Subject: Cleanup Definition::search_scope --- crates/ide_db/src/search.rs | 177 +++++++++++++++++++++++--------------------- 1 file changed, 94 insertions(+), 83 deletions(-) diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs index ff958c757..3634b2b26 100644 --- a/crates/ide_db/src/search.rs +++ b/crates/ide_db/src/search.rs @@ -7,7 +7,7 @@ use std::{convert::TryInto, mem}; use base_db::{FileId, FileRange, SourceDatabase, SourceDatabaseExt}; -use hir::{DefWithBody, HasAttrs, HasSource, Module, ModuleSource, Semantics, Visibility}; +use hir::{DefWithBody, HasAttrs, HasSource, InFile, ModuleSource, Semantics, Visibility}; use once_cell::unsync::Lazy; use rustc_hash::FxHashMap; use syntax::{ast, match_ast, AstNode, TextRange, TextSize}; @@ -78,6 +78,76 @@ impl SearchScope { SearchScope { entries } } + fn crate_graph(db: &RootDatabase) -> SearchScope { + let mut entries = FxHashMap::default(); + + let graph = db.crate_graph(); + for krate in graph.iter() { + let root_file = graph[krate].root_file_id; + let source_root_id = db.file_source_root(root_file); + let source_root = db.source_root(source_root_id); + entries.extend(source_root.iter().map(|id| (id, None))); + } + SearchScope { entries } + } + + fn reverse_dependencies(db: &RootDatabase, of: hir::Crate) -> SearchScope { + let mut entries = FxHashMap::default(); + for rev_dep in of.transitive_reverse_dependencies(db) { + let root_file = rev_dep.root_file(db); + let source_root_id = db.file_source_root(root_file); + let source_root = db.source_root(source_root_id); + entries.extend(source_root.iter().map(|id| (id, None))); + } + SearchScope { entries } + } + + fn krate(db: &RootDatabase, of: hir::Crate) -> SearchScope { + let root_file = of.root_file(db); + let source_root_id = db.file_source_root(root_file); + let source_root = db.source_root(source_root_id); + SearchScope { + entries: source_root.iter().map(|id| (id, None)).collect::>(), + } + } + + fn module(db: &RootDatabase, module: hir::Module) -> SearchScope { + let mut entries = FxHashMap::default(); + + let mut to_visit = vec![module]; + let mut is_first = true; + while let Some(module) = to_visit.pop() { + let src = module.definition_source(db); + let file_id = src.file_id.original_file(db); + match src.value { + ModuleSource::Module(m) => { + if is_first { + let range = Some(m.syntax().text_range()); + entries.insert(file_id, range); + } else { + // We have already added the enclosing file to the search scope, + // so do nothing. + } + } + ModuleSource::BlockExpr(b) => { + if is_first { + let range = Some(b.syntax().text_range()); + entries.insert(file_id, range); + } else { + // We have already added the enclosing file to the search scope, + // so do nothing. + } + } + ModuleSource::SourceFile(_) => { + entries.insert(file_id, None); + } + }; + is_first = false; + to_visit.extend(module.children(db)); + } + SearchScope { entries } + } + pub fn empty() -> SearchScope { SearchScope::new(FxHashMap::default()) } @@ -140,24 +210,15 @@ impl Definition { let _p = profile::span("search_scope"); if let Definition::ModuleDef(hir::ModuleDef::BuiltinType(_)) = self { - let mut res = FxHashMap::default(); - - let graph = db.crate_graph(); - for krate in graph.iter() { - let root_file = graph[krate].root_file_id; - let source_root_id = db.file_source_root(root_file); - let source_root = db.source_root(source_root_id); - res.extend(source_root.iter().map(|id| (id, None))); - } - return SearchScope::new(res); + return SearchScope::crate_graph(db); } let module = match self.module(db) { Some(it) => it, None => return SearchScope::empty(), }; - let module_src = module.definition_source(db); - let file_id = module_src.file_id.original_file(db); + let InFile { file_id, value: module_source } = module.definition_source(db); + let file_id = file_id.original_file(db); if let Definition::Local(var) = self { let range = match var.parent(db) { @@ -165,9 +226,10 @@ impl Definition { DefWithBody::Const(c) => c.source(db).map(|src| src.value.syntax().text_range()), DefWithBody::Static(s) => s.source(db).map(|src| src.value.syntax().text_range()), }; - let mut res = FxHashMap::default(); - res.insert(file_id, range); - return SearchScope::new(res); + return match range { + Some(range) => SearchScope::file_range(FileRange { file_id, range }), + None => SearchScope::single_file(file_id), + }; } if let Definition::GenericParam(hir::GenericParam::LifetimeParam(param)) = self { @@ -198,90 +260,39 @@ impl Definition { it.source(db).map(|src| src.value.syntax().text_range()) } }; - let mut res = FxHashMap::default(); - res.insert(file_id, range); - return SearchScope::new(res); - } - - let vis = self.visibility(db); - - if let Some(Visibility::Module(module)) = vis.and_then(|it| it.into()) { - let module: Module = module.into(); - let mut res = FxHashMap::default(); - - let mut to_visit = vec![module]; - let mut is_first = true; - while let Some(module) = to_visit.pop() { - let src = module.definition_source(db); - let file_id = src.file_id.original_file(db); - match src.value { - ModuleSource::Module(m) => { - if is_first { - let range = Some(m.syntax().text_range()); - res.insert(file_id, range); - } else { - // We have already added the enclosing file to the search scope, - // so do nothing. - } - } - ModuleSource::BlockExpr(b) => { - if is_first { - let range = Some(b.syntax().text_range()); - res.insert(file_id, range); - } else { - // We have already added the enclosing file to the search scope, - // so do nothing. - } - } - ModuleSource::SourceFile(_) => { - res.insert(file_id, None); - } - }; - is_first = false; - to_visit.extend(module.children(db)); - } - - return SearchScope::new(res); + return match range { + Some(range) => SearchScope::file_range(FileRange { file_id, range }), + None => SearchScope::single_file(file_id), + }; } - let rev_dep_scope = || { - let mut res = FxHashMap::default(); - let krate = module.krate(); - for rev_dep in krate.transitive_reverse_dependencies(db) { - let root_file = rev_dep.root_file(db); - let source_root_id = db.file_source_root(root_file); - let source_root = db.source_root(source_root_id); - res.extend(source_root.iter().map(|id| (id, None))); - } - SearchScope::new(res) - }; - if let Definition::Macro(macro_def) = self { if macro_def.kind() == hir::MacroKind::Declarative { return if macro_def.attrs(db).by_key("macro_export").exists() { - rev_dep_scope() + SearchScope::reverse_dependencies(db, module.krate()) } else { - let source_root_id = db.file_source_root(file_id); - let source_root = db.source_root(source_root_id); - SearchScope::new( - source_root.iter().map(|id| (id, None)).collect::>(), - ) + SearchScope::krate(db, module.krate()) }; } } + let vis = self.visibility(db); if let Some(Visibility::Public) = vis { - return rev_dep_scope(); + return SearchScope::reverse_dependencies(db, module.krate()); + } + if let Some(Visibility::Module(module)) = vis { + return SearchScope::module(db, module.into()); } - let mut res = FxHashMap::default(); - let range = match module_src.value { + let range = match module_source { ModuleSource::Module(m) => Some(m.syntax().text_range()), ModuleSource::BlockExpr(b) => Some(b.syntax().text_range()), ModuleSource::SourceFile(_) => None, }; - res.insert(file_id, range); - SearchScope::new(res) + match range { + Some(range) => SearchScope::file_range(FileRange { file_id, range }), + None => SearchScope::single_file(file_id), + } } pub fn usages<'a>(&'a self, sema: &'a Semantics) -> FindUsages<'a> { -- cgit v1.2.3