Unnamed repository; edit this file 'description' to name the repository.
| -rw-r--r-- | crates/hir/src/semantics.rs | 50 | ||||
| -rw-r--r-- | crates/ide/src/expand_macro.rs | 30 |
2 files changed, 75 insertions, 5 deletions
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 2a5112abd8..2618ea3dec 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -19,8 +19,12 @@ use hir_def::{ AsMacroCall, DefWithBodyId, FunctionId, MacroId, TraitId, VariantId, }; use hir_expand::{ - attrs::collect_attrs, db::ExpandDatabase, files::InRealFile, name::AsName, InMacroFile, - MacroCallId, MacroFileId, MacroFileIdExt, + attrs::collect_attrs, + builtin_fn_macro::{BuiltinFnLikeExpander, EagerExpander}, + db::ExpandDatabase, + files::InRealFile, + name::AsName, + InMacroFile, MacroCallId, MacroFileId, MacroFileIdExt, }; use itertools::Itertools; use rustc_hash::{FxHashMap, FxHashSet}; @@ -324,6 +328,48 @@ impl<'db> SemanticsImpl<'db> { Some(node) } + /// Expands the macro if it isn't one of the built-in ones that expand to custom syntax or dummy + /// expansions. + pub fn expand_allowed_builtins(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> { + let sa = self.analyze_no_infer(macro_call.syntax())?; + + let macro_call = InFile::new(sa.file_id, macro_call); + let file_id = if let Some(call) = + <ast::MacroCall as crate::semantics::ToDef>::to_def(self, macro_call) + { + call.as_macro_file() + } else { + sa.expand(self.db, macro_call)? + }; + let macro_call = self.db.lookup_intern_macro_call(file_id.macro_call_id); + + let skip = matches!( + macro_call.def.kind, + hir_expand::MacroDefKind::BuiltIn( + _, + BuiltinFnLikeExpander::Column + | BuiltinFnLikeExpander::File + | BuiltinFnLikeExpander::ModulePath + | BuiltinFnLikeExpander::Asm + | BuiltinFnLikeExpander::LlvmAsm + | BuiltinFnLikeExpander::GlobalAsm + | BuiltinFnLikeExpander::LogSyntax + | BuiltinFnLikeExpander::TraceMacros + | BuiltinFnLikeExpander::FormatArgs + | BuiltinFnLikeExpander::FormatArgsNl + | BuiltinFnLikeExpander::ConstFormatArgs, + ) | hir_expand::MacroDefKind::BuiltInEager(_, EagerExpander::CompileError) + ); + if skip { + // these macros expand to custom builtin syntax and/or dummy things, no point in + // showing these to the user + return None; + } + + let node = self.parse_or_expand(file_id.into()); + Some(node) + } + /// If `item` has an attribute macro attached to it, expands it. pub fn expand_attr_macro(&self, item: &ast::Item) -> Option<SyntaxNode> { let src = self.wrap_node_infile(item.clone()); diff --git a/crates/ide/src/expand_macro.rs b/crates/ide/src/expand_macro.rs index 1ead045788..4b54c057bf 100644 --- a/crates/ide/src/expand_macro.rs +++ b/crates/ide/src/expand_macro.rs @@ -111,9 +111,10 @@ fn expand_macro_recur( macro_call: &ast::Item, ) -> Option<SyntaxNode> { let expanded = match macro_call { - item @ ast::Item::MacroCall(macro_call) => { - sema.expand_attr_macro(item).or_else(|| sema.expand(macro_call))?.clone_for_update() - } + item @ ast::Item::MacroCall(macro_call) => sema + .expand_attr_macro(item) + .or_else(|| sema.expand_allowed_builtins(macro_call))? + .clone_for_update(), item => sema.expand_attr_macro(item)?.clone_for_update(), }; expand(sema, expanded) @@ -229,6 +230,29 @@ mod tests { } #[test] + fn expand_allowed_builtin_macro() { + check( + r#" +//- minicore: concat +$0concat!("test", 10, 'b', true);"#, + expect![[r#" + concat! + "test10btrue""#]], + ); + } + + #[test] + fn do_not_expand_disallowed_macro() { + let (analysis, pos) = fixture::position( + r#" +//- minicore: asm +$0asm!("0x300, x0");"#, + ); + let expansion = analysis.expand_macro(pos).unwrap(); + assert!(expansion.is_none()); + } + + #[test] fn macro_expand_as_keyword() { check( r#" |