Skip to content

Commit 258afb8

Browse files
bors[bot]Veykril
andauthored
Merge #8138
8138: Set up a search scope when searching for mbe macro references r=Veykril a=Veykril Closes #6184 Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
2 parents 1efd220 + 395183e commit 258afb8

File tree

4 files changed

+147
-80
lines changed

4 files changed

+147
-80
lines changed

crates/hir/src/lib.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,6 +1116,14 @@ impl BuiltinType {
11161116
}
11171117
}
11181118

1119+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1120+
pub enum MacroKind {
1121+
Declarative,
1122+
ProcMacro,
1123+
Derive,
1124+
BuiltIn,
1125+
}
1126+
11191127
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
11201128
pub struct MacroDef {
11211129
pub(crate) id: MacroDefId,
@@ -1140,15 +1148,15 @@ impl MacroDef {
11401148
}
11411149
}
11421150

1143-
/// Indicate it is a proc-macro
1144-
pub fn is_proc_macro(&self) -> bool {
1145-
matches!(self.id.kind, MacroDefKind::ProcMacro(..))
1146-
}
1147-
1148-
/// Indicate it is a derive macro
1149-
pub fn is_derive_macro(&self) -> bool {
1150-
// FIXME: wrong for `ProcMacro`
1151-
matches!(self.id.kind, MacroDefKind::ProcMacro(..) | MacroDefKind::BuiltInDerive(..))
1151+
pub fn kind(&self) -> MacroKind {
1152+
match self.id.kind {
1153+
MacroDefKind::Declarative(_) => MacroKind::Declarative,
1154+
MacroDefKind::BuiltIn(_, _) => MacroKind::BuiltIn,
1155+
MacroDefKind::BuiltInDerive(_, _) => MacroKind::Derive,
1156+
MacroDefKind::BuiltInEager(_, _) => MacroKind::BuiltIn,
1157+
// FIXME might be a derive
1158+
MacroDefKind::ProcMacro(_, _) => MacroKind::ProcMacro,
1159+
}
11521160
}
11531161
}
11541162

crates/ide/src/references.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1294,4 +1294,34 @@ pub use level1::Foo;
12941294
"#]],
12951295
);
12961296
}
1297+
1298+
#[test]
1299+
fn test_decl_macro_references() {
1300+
check(
1301+
r#"
1302+
//- /lib.rs crate:lib
1303+
#[macro_use]
1304+
mod qux;
1305+
mod bar;
1306+
1307+
pub use self::foo;
1308+
//- /qux.rs
1309+
#[macro_export]
1310+
macro_rules! foo$0 {
1311+
() => {struct Foo;};
1312+
}
1313+
//- /bar.rs
1314+
foo!();
1315+
//- /other.rs crate:other deps:lib new_source_root:
1316+
lib::foo!();
1317+
"#,
1318+
expect![[r#"
1319+
foo Macro FileId(1) 0..61 29..32
1320+
1321+
FileId(0) 46..49
1322+
FileId(2) 0..3
1323+
FileId(3) 5..8
1324+
"#]],
1325+
);
1326+
}
12971327
}

crates/ide_completion/src/completions/attribute.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,8 @@ fn get_derive_names_in_scope(ctx: &CompletionContext) -> FxHashSet<String> {
246246
let mut result = FxHashSet::default();
247247
ctx.scope.process_all_names(&mut |name, scope_def| {
248248
if let hir::ScopeDef::MacroDef(mac) = scope_def {
249-
if mac.is_derive_macro() {
249+
// FIXME kind() doesn't check whether proc-macro is a derive
250+
if mac.kind() == hir::MacroKind::Derive || mac.kind() == hir::MacroKind::ProcMacro {
250251
result.insert(name.to_string());
251252
}
252253
}

crates/ide_db/src/search.rs

Lines changed: 98 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use std::{convert::TryInto, mem};
88

99
use base_db::{FileId, FileRange, SourceDatabase, SourceDatabaseExt};
10-
use hir::{DefWithBody, HasSource, Module, ModuleSource, Semantics, Visibility};
10+
use hir::{DefWithBody, HasAttrs, HasSource, InFile, ModuleSource, Semantics, Visibility};
1111
use once_cell::unsync::Lazy;
1212
use rustc_hash::FxHashMap;
1313
use syntax::{ast, match_ast, AstNode, TextRange, TextSize};
@@ -78,6 +78,76 @@ impl SearchScope {
7878
SearchScope { entries }
7979
}
8080

81+
fn crate_graph(db: &RootDatabase) -> SearchScope {
82+
let mut entries = FxHashMap::default();
83+
84+
let graph = db.crate_graph();
85+
for krate in graph.iter() {
86+
let root_file = graph[krate].root_file_id;
87+
let source_root_id = db.file_source_root(root_file);
88+
let source_root = db.source_root(source_root_id);
89+
entries.extend(source_root.iter().map(|id| (id, None)));
90+
}
91+
SearchScope { entries }
92+
}
93+
94+
fn reverse_dependencies(db: &RootDatabase, of: hir::Crate) -> SearchScope {
95+
let mut entries = FxHashMap::default();
96+
for rev_dep in of.transitive_reverse_dependencies(db) {
97+
let root_file = rev_dep.root_file(db);
98+
let source_root_id = db.file_source_root(root_file);
99+
let source_root = db.source_root(source_root_id);
100+
entries.extend(source_root.iter().map(|id| (id, None)));
101+
}
102+
SearchScope { entries }
103+
}
104+
105+
fn krate(db: &RootDatabase, of: hir::Crate) -> SearchScope {
106+
let root_file = of.root_file(db);
107+
let source_root_id = db.file_source_root(root_file);
108+
let source_root = db.source_root(source_root_id);
109+
SearchScope {
110+
entries: source_root.iter().map(|id| (id, None)).collect::<FxHashMap<_, _>>(),
111+
}
112+
}
113+
114+
fn module(db: &RootDatabase, module: hir::Module) -> SearchScope {
115+
let mut entries = FxHashMap::default();
116+
117+
let mut to_visit = vec![module];
118+
let mut is_first = true;
119+
while let Some(module) = to_visit.pop() {
120+
let src = module.definition_source(db);
121+
let file_id = src.file_id.original_file(db);
122+
match src.value {
123+
ModuleSource::Module(m) => {
124+
if is_first {
125+
let range = Some(m.syntax().text_range());
126+
entries.insert(file_id, range);
127+
} else {
128+
// We have already added the enclosing file to the search scope,
129+
// so do nothing.
130+
}
131+
}
132+
ModuleSource::BlockExpr(b) => {
133+
if is_first {
134+
let range = Some(b.syntax().text_range());
135+
entries.insert(file_id, range);
136+
} else {
137+
// We have already added the enclosing file to the search scope,
138+
// so do nothing.
139+
}
140+
}
141+
ModuleSource::SourceFile(_) => {
142+
entries.insert(file_id, None);
143+
}
144+
};
145+
is_first = false;
146+
to_visit.extend(module.children(db));
147+
}
148+
SearchScope { entries }
149+
}
150+
81151
pub fn empty() -> SearchScope {
82152
SearchScope::new(FxHashMap::default())
83153
}
@@ -140,34 +210,26 @@ impl Definition {
140210
let _p = profile::span("search_scope");
141211

142212
if let Definition::ModuleDef(hir::ModuleDef::BuiltinType(_)) = self {
143-
let mut res = FxHashMap::default();
144-
145-
let graph = db.crate_graph();
146-
for krate in graph.iter() {
147-
let root_file = graph[krate].root_file_id;
148-
let source_root_id = db.file_source_root(root_file);
149-
let source_root = db.source_root(source_root_id);
150-
res.extend(source_root.iter().map(|id| (id, None)));
151-
}
152-
return SearchScope::new(res);
213+
return SearchScope::crate_graph(db);
153214
}
154215

155216
let module = match self.module(db) {
156217
Some(it) => it,
157218
None => return SearchScope::empty(),
158219
};
159-
let module_src = module.definition_source(db);
160-
let file_id = module_src.file_id.original_file(db);
220+
let InFile { file_id, value: module_source } = module.definition_source(db);
221+
let file_id = file_id.original_file(db);
161222

162223
if let Definition::Local(var) = self {
163224
let range = match var.parent(db) {
164225
DefWithBody::Function(f) => f.source(db).map(|src| src.value.syntax().text_range()),
165226
DefWithBody::Const(c) => c.source(db).map(|src| src.value.syntax().text_range()),
166227
DefWithBody::Static(s) => s.source(db).map(|src| src.value.syntax().text_range()),
167228
};
168-
let mut res = FxHashMap::default();
169-
res.insert(file_id, range);
170-
return SearchScope::new(res);
229+
return match range {
230+
Some(range) => SearchScope::file_range(FileRange { file_id, range }),
231+
None => SearchScope::single_file(file_id),
232+
};
171233
}
172234

173235
if let Definition::GenericParam(hir::GenericParam::LifetimeParam(param)) = self {
@@ -198,73 +260,39 @@ impl Definition {
198260
it.source(db).map(|src| src.value.syntax().text_range())
199261
}
200262
};
201-
let mut res = FxHashMap::default();
202-
res.insert(file_id, range);
203-
return SearchScope::new(res);
263+
return match range {
264+
Some(range) => SearchScope::file_range(FileRange { file_id, range }),
265+
None => SearchScope::single_file(file_id),
266+
};
204267
}
205268

206-
let vis = self.visibility(db);
207-
208-
if let Some(Visibility::Module(module)) = vis.and_then(|it| it.into()) {
209-
let module: Module = module.into();
210-
let mut res = FxHashMap::default();
211-
212-
let mut to_visit = vec![module];
213-
let mut is_first = true;
214-
while let Some(module) = to_visit.pop() {
215-
let src = module.definition_source(db);
216-
let file_id = src.file_id.original_file(db);
217-
match src.value {
218-
ModuleSource::Module(m) => {
219-
if is_first {
220-
let range = Some(m.syntax().text_range());
221-
res.insert(file_id, range);
222-
} else {
223-
// We have already added the enclosing file to the search scope,
224-
// so do nothing.
225-
}
226-
}
227-
ModuleSource::BlockExpr(b) => {
228-
if is_first {
229-
let range = Some(b.syntax().text_range());
230-
res.insert(file_id, range);
231-
} else {
232-
// We have already added the enclosing file to the search scope,
233-
// so do nothing.
234-
}
235-
}
236-
ModuleSource::SourceFile(_) => {
237-
res.insert(file_id, None);
238-
}
269+
if let Definition::Macro(macro_def) = self {
270+
if macro_def.kind() == hir::MacroKind::Declarative {
271+
return if macro_def.attrs(db).by_key("macro_export").exists() {
272+
SearchScope::reverse_dependencies(db, module.krate())
273+
} else {
274+
SearchScope::krate(db, module.krate())
239275
};
240-
is_first = false;
241-
to_visit.extend(module.children(db));
242276
}
243-
244-
return SearchScope::new(res);
245277
}
246278

279+
let vis = self.visibility(db);
247280
if let Some(Visibility::Public) = vis {
248-
let mut res = FxHashMap::default();
249-
250-
let krate = module.krate();
251-
for rev_dep in krate.transitive_reverse_dependencies(db) {
252-
let root_file = rev_dep.root_file(db);
253-
let source_root_id = db.file_source_root(root_file);
254-
let source_root = db.source_root(source_root_id);
255-
res.extend(source_root.iter().map(|id| (id, None)));
256-
}
257-
return SearchScope::new(res);
281+
return SearchScope::reverse_dependencies(db, module.krate());
282+
}
283+
if let Some(Visibility::Module(module)) = vis {
284+
return SearchScope::module(db, module.into());
258285
}
259286

260-
let mut res = FxHashMap::default();
261-
let range = match module_src.value {
287+
let range = match module_source {
262288
ModuleSource::Module(m) => Some(m.syntax().text_range()),
263289
ModuleSource::BlockExpr(b) => Some(b.syntax().text_range()),
264290
ModuleSource::SourceFile(_) => None,
265291
};
266-
res.insert(file_id, range);
267-
SearchScope::new(res)
292+
match range {
293+
Some(range) => SearchScope::file_range(FileRange { file_id, range }),
294+
None => SearchScope::single_file(file_id),
295+
}
268296
}
269297

270298
pub fn usages<'a>(&'a self, sema: &'a Semantics<RootDatabase>) -> FindUsages<'a> {

0 commit comments

Comments
 (0)