Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide/src/expand_macro.rs')
| -rw-r--r-- | crates/ide/src/expand_macro.rs | 116 |
1 files changed, 99 insertions, 17 deletions
diff --git a/crates/ide/src/expand_macro.rs b/crates/ide/src/expand_macro.rs index 241a702038..7c396339c1 100644 --- a/crates/ide/src/expand_macro.rs +++ b/crates/ide/src/expand_macro.rs @@ -1,10 +1,10 @@ use hir::db::ExpandDatabase; -use hir::{ExpandResult, InFile, Semantics}; +use hir::{ExpandResult, InFile, InRealFile, Semantics}; use ide_db::{ FileId, RootDatabase, base_db::Crate, helpers::pick_best_token, syntax_helpers::prettify_macro_expansion, }; -use span::{Edition, SpanMap, SyntaxContext, TextRange, TextSize}; +use span::{SpanMap, SyntaxContext, TextRange, TextSize}; use stdx::format_to; use syntax::{AstNode, NodeOrToken, SyntaxKind, SyntaxNode, T, ast, ted}; @@ -26,8 +26,9 @@ pub struct ExpandedMacro { //  pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<ExpandedMacro> { let sema = Semantics::new(db); - let file = sema.parse_guess_edition(position.file_id); - let krate = sema.file_to_module_def(position.file_id)?.krate().into(); + let file_id = sema.attach_first_edition(position.file_id)?; + let file = sema.parse(file_id); + let krate = sema.file_to_module_def(file_id.file_id(db))?.krate().into(); let tok = pick_best_token(file.syntax().token_at_offset(position.offset), |kind| match kind { SyntaxKind::IDENT => 1, @@ -86,7 +87,10 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option< return derive; } - let mut anc = tok.parent_ancestors(); + let mut anc = sema + .descend_token_into_include_expansion(InRealFile::new(file_id, tok)) + .value + .parent_ancestors(); let mut span_map = SpanMap::empty(); let mut error = String::new(); let (name, expanded, kind) = loop { @@ -95,14 +99,7 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option< if let Some(item) = ast::Item::cast(node.clone()) { if let Some(def) = sema.resolve_attr_macro_call(&item) { break ( - def.name(db) - .display( - db, - sema.attach_first_edition(position.file_id) - .map(|it| it.edition(db)) - .unwrap_or(Edition::CURRENT), - ) - .to_string(), + def.name(db).display(db, file_id.edition(db)).to_string(), expand_macro_recur(&sema, &item, &mut error, &mut span_map, TextSize::new(0))?, SyntaxKind::MACRO_ITEMS, ); @@ -146,10 +143,11 @@ fn expand_macro_recur( offset_in_original_node: TextSize, ) -> Option<SyntaxNode> { let ExpandResult { value: expanded, err } = match macro_call { - item @ ast::Item::MacroCall(macro_call) => { - sema.expand_attr_macro(item).or_else(|| sema.expand_allowed_builtins(macro_call))? - } - item => sema.expand_attr_macro(item)?, + item @ ast::Item::MacroCall(macro_call) => sema + .expand_attr_macro(item) + .map(|it| it.map(|it| it.value)) + .or_else(|| sema.expand_allowed_builtins(macro_call))?, + item => sema.expand_attr_macro(item)?.map(|it| it.value), }; let expanded = expanded.clone_for_update(); if let Some(err) = err { @@ -718,4 +716,88 @@ __log!(written:%; "Test"$0); "#]], ); } + + #[test] + fn assoc_call() { + check( + r#" +macro_rules! mac { + () => { fn assoc() {} } +} +impl () { + mac$0!(); +} + "#, + expect![[r#" + mac! + fn assoc(){}"#]], + ); + } + + #[test] + fn eager() { + check( + r#" +//- minicore: concat +macro_rules! my_concat { + ($head:expr, $($tail:tt)*) => { concat!($head, $($tail)*) }; +} + + +fn test() { + _ = my_concat!( + conc$0at!("<", ">"), + "hi", + ); +} + "#, + expect![[r#" + my_concat! + "<>hi""#]], + ); + } + + #[test] + fn in_included() { + check( + r#" +//- minicore: include +//- /main.rs crate:main +include!("./included.rs"); +//- /included.rs +macro_rules! foo { + () => { fn item() {} }; +} +foo$0!(); +"#, + expect![[r#" + foo! + fn item(){}"#]], + ); + } + + #[test] + fn include() { + check( + r#" +//- minicore: include +//- /main.rs crate:main +include$0!("./included.rs"); +//- /included.rs +macro_rules! foo { + () => { fn item() {} }; +} +foo(); +"#, + expect![[r#" + include! + macro_rules! foo { + () => { + fn item(){} + + }; + } + foo();"#]], + ); + } } |