Skip to content

Commit c205ef7

Browse files
authored
Merge pull request #19880 from Veykril/push-xmpxumsrkymk
fix: Handle included files better in IDE layer
2 parents 035cf40 + 457e84f commit c205ef7

File tree

3 files changed

+97
-31
lines changed

3 files changed

+97
-31
lines changed

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

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -769,6 +769,31 @@ impl<'db> SemanticsImpl<'db> {
769769
})
770770
}
771771

772+
/// Descends the token into the include expansion, if its file is an included file.
773+
pub fn descend_token_into_include_expansion(
774+
&self,
775+
tok: InRealFile<SyntaxToken>,
776+
) -> InFile<SyntaxToken> {
777+
let Some(include) =
778+
self.s2d_cache.borrow_mut().get_or_insert_include_for(self.db, tok.file_id)
779+
else {
780+
return tok.into();
781+
};
782+
let span = self.db.real_span_map(tok.file_id).span_for_range(tok.value.text_range());
783+
let Some(InMacroFile { file_id, value: mut mapped_tokens }) = self.with_ctx(|ctx| {
784+
Some(
785+
ctx.cache
786+
.get_or_insert_expansion(ctx.db, include)
787+
.map_range_down(span)?
788+
.map(SmallVec::<[_; 2]>::from_iter),
789+
)
790+
}) else {
791+
return tok.into();
792+
};
793+
// We should only get one result at most
794+
mapped_tokens.pop().map_or_else(|| tok.into(), |(tok, _)| InFile::new(file_id.into(), tok))
795+
}
796+
772797
/// Maps a node down by mapping its first and last token down.
773798
pub fn descend_node_into_attributes<N: AstNode>(&self, node: N) -> SmallVec<[N; 1]> {
774799
// This might not be the correct way to do this, but it works for now
@@ -1528,11 +1553,9 @@ impl<'db> SemanticsImpl<'db> {
15281553
}
15291554

15301555
pub fn resolve_macro_call2(&self, macro_call: InFile<&ast::MacroCall>) -> Option<Macro> {
1531-
self.with_ctx(|ctx| {
1532-
ctx.macro_call_to_macro_call(macro_call)
1533-
.and_then(|call| macro_call_to_macro_id(ctx, call))
1534-
.map(Into::into)
1535-
})
1556+
self.to_def2(macro_call)
1557+
.and_then(|call| self.with_ctx(|ctx| macro_call_to_macro_id(ctx, call)))
1558+
.map(Into::into)
15361559
}
15371560

15381561
pub fn is_proc_macro_call(&self, macro_call: InFile<&ast::MacroCall>) -> bool {
@@ -1647,6 +1670,10 @@ impl<'db> SemanticsImpl<'db> {
16471670
T::to_def(self, src)
16481671
}
16491672

1673+
pub fn to_def2<T: ToDef>(&self, src: InFile<&T>) -> Option<T::Def> {
1674+
T::to_def(self, src)
1675+
}
1676+
16501677
fn file_to_module_defs(&self, file: FileId) -> impl Iterator<Item = Module> {
16511678
self.with_ctx(|ctx| ctx.file_to_def(file).to_owned()).into_iter().map(Module::from)
16521679
}

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

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -399,19 +399,6 @@ impl SourceToDefCtx<'_, '_> {
399399
Some((container, label?))
400400
}
401401

402-
pub(super) fn item_to_macro_call(&mut self, src: InFile<&ast::Item>) -> Option<MacroCallId> {
403-
let map = self.dyn_map(src)?;
404-
map[keys::ATTR_MACRO_CALL].get(&AstPtr::new(src.value)).copied()
405-
}
406-
407-
pub(super) fn macro_call_to_macro_call(
408-
&mut self,
409-
src: InFile<&ast::MacroCall>,
410-
) -> Option<MacroCallId> {
411-
let map = self.dyn_map(src)?;
412-
map[keys::MACRO_CALL].get(&AstPtr::new(src.value)).copied()
413-
}
414-
415402
/// (AttrId, derive attribute call id, derive call ids)
416403
pub(super) fn attr_to_derive_macro_call(
417404
&mut self,
@@ -449,6 +436,17 @@ impl SourceToDefCtx<'_, '_> {
449436
.or_insert_with(|| container.child_by_source(db, file_id))
450437
}
451438

439+
pub(super) fn item_to_macro_call(&mut self, src: InFile<&ast::Item>) -> Option<MacroCallId> {
440+
self.to_def(src, keys::ATTR_MACRO_CALL)
441+
}
442+
443+
pub(super) fn macro_call_to_macro_call(
444+
&mut self,
445+
src: InFile<&ast::MacroCall>,
446+
) -> Option<MacroCallId> {
447+
self.to_def(src, keys::MACRO_CALL)
448+
}
449+
452450
pub(super) fn type_param_to_def(
453451
&mut self,
454452
src: InFile<&ast::TypeParam>,

src/tools/rust-analyzer/crates/ide/src/expand_macro.rs

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use hir::db::ExpandDatabase;
2-
use hir::{ExpandResult, InFile, Semantics};
2+
use hir::{ExpandResult, InFile, InRealFile, Semantics};
33
use ide_db::{
44
FileId, RootDatabase, base_db::Crate, helpers::pick_best_token,
55
syntax_helpers::prettify_macro_expansion,
66
};
7-
use span::{Edition, SpanMap, SyntaxContext, TextRange, TextSize};
7+
use span::{SpanMap, SyntaxContext, TextRange, TextSize};
88
use stdx::format_to;
99
use syntax::{AstNode, NodeOrToken, SyntaxKind, SyntaxNode, T, ast, ted};
1010

@@ -26,8 +26,9 @@ pub struct ExpandedMacro {
2626
// ![Expand Macro Recursively](https://user-images.githubusercontent.com/48062697/113020648-b3973180-917a-11eb-84a9-ecb921293dc5.gif)
2727
pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<ExpandedMacro> {
2828
let sema = Semantics::new(db);
29-
let file = sema.parse_guess_edition(position.file_id);
30-
let krate = sema.file_to_module_def(position.file_id)?.krate().into();
29+
let file_id = sema.attach_first_edition(position.file_id)?;
30+
let file = sema.parse(file_id);
31+
let krate = sema.file_to_module_def(file_id.file_id(db))?.krate().into();
3132

3233
let tok = pick_best_token(file.syntax().token_at_offset(position.offset), |kind| match kind {
3334
SyntaxKind::IDENT => 1,
@@ -86,7 +87,10 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<
8687
return derive;
8788
}
8889

89-
let mut anc = tok.parent_ancestors();
90+
let mut anc = sema
91+
.descend_token_into_include_expansion(InRealFile::new(file_id, tok))
92+
.value
93+
.parent_ancestors();
9094
let mut span_map = SpanMap::empty();
9195
let mut error = String::new();
9296
let (name, expanded, kind) = loop {
@@ -95,14 +99,7 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<
9599
if let Some(item) = ast::Item::cast(node.clone()) {
96100
if let Some(def) = sema.resolve_attr_macro_call(&item) {
97101
break (
98-
def.name(db)
99-
.display(
100-
db,
101-
sema.attach_first_edition(position.file_id)
102-
.map(|it| it.edition(db))
103-
.unwrap_or(Edition::CURRENT),
104-
)
105-
.to_string(),
102+
def.name(db).display(db, file_id.edition(db)).to_string(),
106103
expand_macro_recur(&sema, &item, &mut error, &mut span_map, TextSize::new(0))?,
107104
SyntaxKind::MACRO_ITEMS,
108105
);
@@ -759,4 +756,48 @@ fn test() {
759756
"<>hi""#]],
760757
);
761758
}
759+
760+
#[test]
761+
fn in_included() {
762+
check(
763+
r#"
764+
//- minicore: include
765+
//- /main.rs crate:main
766+
include!("./included.rs");
767+
//- /included.rs
768+
macro_rules! foo {
769+
() => { fn item() {} };
770+
}
771+
foo$0!();
772+
"#,
773+
expect![[r#"
774+
foo!
775+
fn item(){}"#]],
776+
);
777+
}
778+
779+
#[test]
780+
fn include() {
781+
check(
782+
r#"
783+
//- minicore: include
784+
//- /main.rs crate:main
785+
include$0!("./included.rs");
786+
//- /included.rs
787+
macro_rules! foo {
788+
() => { fn item() {} };
789+
}
790+
foo();
791+
"#,
792+
expect![[r#"
793+
include!
794+
macro_rules! foo {
795+
() => {
796+
fn item(){}
797+
798+
};
799+
}
800+
foo();"#]],
801+
);
802+
}
762803
}

0 commit comments

Comments
 (0)