Skip to content

Commit 1ebd727

Browse files
committed
Resolve included files to their calling modules in IDE layer
1 parent 9431039 commit 1ebd727

File tree

6 files changed

+93
-56
lines changed

6 files changed

+93
-56
lines changed

src/tools/rust-analyzer/crates/hir-def/src/db.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -240,14 +240,14 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDataba
240240

241241
fn crate_supports_no_std(&self, crate_id: CrateId) -> bool;
242242

243-
fn include_macro_invoc(&self, crate_id: CrateId) -> Vec<(MacroCallId, EditionedFileId)>;
243+
fn include_macro_invoc(&self, crate_id: CrateId) -> Arc<[(MacroCallId, EditionedFileId)]>;
244244
}
245245

246246
// return: macro call id and include file id
247247
fn include_macro_invoc(
248248
db: &dyn DefDatabase,
249249
krate: CrateId,
250-
) -> Vec<(MacroCallId, EditionedFileId)> {
250+
) -> Arc<[(MacroCallId, EditionedFileId)]> {
251251
db.crate_def_map(krate)
252252
.modules
253253
.values()

src/tools/rust-analyzer/crates/hir/src/semantics.rs

+47-44
Original file line numberDiff line numberDiff line change
@@ -770,59 +770,62 @@ impl<'db> SemanticsImpl<'db> {
770770
let file_id = self.find_file(&parent).file_id.file_id()?;
771771

772772
// iterate related crates and find all include! invocations that include_file_id matches
773-
for (invoc, _) in self
773+
for iter in self
774774
.db
775775
.relevant_crates(file_id.file_id())
776776
.iter()
777-
.flat_map(|krate| self.db.include_macro_invoc(*krate))
778-
.filter(|&(_, include_file_id)| include_file_id == file_id)
777+
.map(|krate| self.db.include_macro_invoc(*krate))
779778
{
780-
let macro_file = invoc.as_macro_file();
781-
let expansion_info = {
782-
self.with_ctx(|ctx| {
783-
ctx.cache
784-
.expansion_info_cache
785-
.entry(macro_file)
786-
.or_insert_with(|| {
787-
let exp_info = macro_file.expansion_info(self.db.upcast());
779+
for (invoc, _) in
780+
iter.iter().filter(|&&(_, include_file_id)| include_file_id == file_id)
781+
{
782+
let macro_file = invoc.as_macro_file();
783+
let expansion_info = {
784+
self.with_ctx(|ctx| {
785+
ctx.cache
786+
.expansion_info_cache
787+
.entry(macro_file)
788+
.or_insert_with(|| {
789+
let exp_info = macro_file.expansion_info(self.db.upcast());
788790

789-
let InMacroFile { file_id, value } = exp_info.expanded();
790-
if let InFile { file_id, value: Some(value) } = exp_info.arg() {
791-
self.cache(value.ancestors().last().unwrap(), file_id);
792-
}
793-
self.cache(value, file_id.into());
791+
let InMacroFile { file_id, value } = exp_info.expanded();
792+
if let InFile { file_id, value: Some(value) } = exp_info.arg() {
793+
self.cache(value.ancestors().last().unwrap(), file_id);
794+
}
795+
self.cache(value, file_id.into());
794796

795-
exp_info
796-
})
797-
.clone()
798-
})
799-
};
797+
exp_info
798+
})
799+
.clone()
800+
})
801+
};
800802

801-
// FIXME: uncached parse
802-
// Create the source analyzer for the macro call scope
803-
let Some(sa) = expansion_info
804-
.arg()
805-
.value
806-
.and_then(|it| self.analyze_no_infer(&it.ancestors().last().unwrap()))
807-
else {
808-
continue;
809-
};
803+
// FIXME: uncached parse
804+
// Create the source analyzer for the macro call scope
805+
let Some(sa) = expansion_info
806+
.arg()
807+
.value
808+
.and_then(|it| self.analyze_no_infer(&it.ancestors().last().unwrap()))
809+
else {
810+
continue;
811+
};
810812

811-
// get mapped token in the include! macro file
812-
let span = span::Span {
813-
range: token.text_range(),
814-
anchor: span::SpanAnchor { file_id, ast_id: ROOT_ERASED_FILE_AST_ID },
815-
ctx: SyntaxContextId::ROOT,
816-
};
817-
let Some(InMacroFile { file_id, value: mut mapped_tokens }) =
818-
expansion_info.map_range_down_exact(span)
819-
else {
820-
continue;
821-
};
813+
// get mapped token in the include! macro file
814+
let span = span::Span {
815+
range: token.text_range(),
816+
anchor: span::SpanAnchor { file_id, ast_id: ROOT_ERASED_FILE_AST_ID },
817+
ctx: SyntaxContextId::ROOT,
818+
};
819+
let Some(InMacroFile { file_id, value: mut mapped_tokens }) =
820+
expansion_info.map_range_down_exact(span)
821+
else {
822+
continue;
823+
};
822824

823-
// if we find one, then return
824-
if let Some(t) = mapped_tokens.next() {
825-
return Some((sa, file_id.into(), t, span));
825+
// if we find one, then return
826+
if let Some(t) = mapped_tokens.next() {
827+
return Some((sa, file_id.into(), t, span));
828+
}
826829
}
827830
}
828831

src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs

+25-5
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,9 @@ use hir_def::{
9494
},
9595
hir::{BindingId, LabelId},
9696
AdtId, BlockId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId, ExternCrateId,
97-
FieldId, FunctionId, GenericDefId, GenericParamId, ImplId, LifetimeParamId, MacroId, ModuleId,
98-
StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, TypeParamId, UnionId, UseId, VariantId,
97+
FieldId, FunctionId, GenericDefId, GenericParamId, ImplId, LifetimeParamId, Lookup, MacroId,
98+
ModuleId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId, TypeParamId, UnionId, UseId,
99+
VariantId,
99100
};
100101
use hir_expand::{
101102
attrs::AttrId, name::AsName, ExpansionInfo, HirFileId, HirFileIdExt, MacroCallId,
@@ -131,11 +132,30 @@ impl SourceToDefCtx<'_, '_> {
131132
for &crate_id in self.db.relevant_crates(file).iter() {
132133
// Note: `mod` declarations in block modules cannot be supported here
133134
let crate_def_map = self.db.crate_def_map(crate_id);
134-
mods.extend(
135+
let n_mods = mods.len();
136+
let modules = |file| {
135137
crate_def_map
136138
.modules_for_file(file)
137-
.map(|local_id| crate_def_map.module_id(local_id)),
138-
)
139+
.map(|local_id| crate_def_map.module_id(local_id))
140+
};
141+
mods.extend(modules(file));
142+
if mods.len() == n_mods {
143+
mods.extend(
144+
self.db
145+
.include_macro_invoc(crate_id)
146+
.iter()
147+
.filter(|&&(_, file_id)| file_id == file)
148+
.flat_map(|(call, _)| {
149+
modules(
150+
call.lookup(self.db.upcast())
151+
.kind
152+
.file_id()
153+
.original_file(self.db.upcast())
154+
.file_id(),
155+
)
156+
}),
157+
);
158+
}
139159
}
140160
if mods.is_empty() {
141161
// FIXME: detached file

src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/macro_error.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -273,11 +273,7 @@ fn f() {
273273

274274
#[test]
275275
fn include_does_not_break_diagnostics() {
276-
let mut config = DiagnosticsConfig::test_sample();
277-
config.disabled.insert("inactive-code".to_owned());
278-
config.disabled.insert("unlinked-file".to_owned());
279-
check_diagnostics_with_config(
280-
config,
276+
check_diagnostics(
281277
r#"
282278
//- minicore: include
283279
//- /lib.rs crate:lib

src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/unlinked_file.rs

+12
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,18 @@ $0
499499
mod bar {
500500
mod foo;
501501
}
502+
"#,
503+
);
504+
}
505+
506+
#[test]
507+
fn include_macro_works() {
508+
check_diagnostics(
509+
r#"
510+
//- minicore: include
511+
//- /main.rs
512+
include!("bar/foo/mod.rs");
513+
//- /bar/foo/mod.rs
502514
"#,
503515
);
504516
}

src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs

+6
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,12 @@ pub(crate) fn check_diagnostics_with_config(config: DiagnosticsConfig, ra_fixtur
251251
let mut actual = annotations.remove(&file_id).unwrap_or_default();
252252
let expected = extract_annotations(&db.file_text(file_id));
253253
actual.sort_by_key(|(range, _)| range.start());
254+
// FIXME: We should panic on duplicates instead, but includes currently cause us to report
255+
// diagnostics twice for the calling module when both files are queried.
256+
actual.dedup();
257+
// actual.iter().duplicates().for_each(|(range, msg)| {
258+
// panic!("duplicate diagnostic at {:?}: {msg:?}", line_index.line_col(range.start()))
259+
// });
254260
if expected.is_empty() {
255261
// makes minicore smoke test debuggable
256262
for (e, _) in &actual {

0 commit comments

Comments
 (0)