diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 74c12a0a2d..b4bdd81f64 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs @@ -4857,3 +4857,22 @@ fn main() { "### ); } + +#[test] +fn infer_builtin_macros_file() { + assert_snapshot!( + infer(r#" +#[rustc_builtin_macro] +macro_rules! file {() => {}} + +fn main() { + let x = file!(); +} +"#), + @r###" + ![0; 2) '""': &str + [64; 88) '{ ...!(); }': () + [74; 75) 'x': &str + "### + ); +} diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs index 9628666d46..d7057e0054 100644 --- a/crates/ra_hir_expand/src/builtin_macro.rs +++ b/crates/ra_hir_expand/src/builtin_macro.rs @@ -10,6 +10,7 @@ use crate::quote; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum BuiltinExpander { + File, Line, Stringify, } @@ -22,6 +23,7 @@ impl BuiltinExpander { tt: &tt::Subtree, ) -> Result { match self { + BuiltinExpander::File => file_expand(db, id, tt), BuiltinExpander::Line => line_expand(db, id, tt), BuiltinExpander::Stringify => stringify_expand(db, id, tt), } @@ -34,7 +36,9 @@ pub fn find_builtin_macro( ast_id: AstId, ) -> Option { // FIXME: Better registering method - if ident == &name::LINE_MACRO { + if ident == &name::FILE_MACRO { + Some(MacroDefId { krate, ast_id, kind: MacroDefKind::BuiltIn(BuiltinExpander::File) }) + } else if ident == &name::LINE_MACRO { Some(MacroDefId { krate, ast_id, kind: MacroDefKind::BuiltIn(BuiltinExpander::Line) }) } else if ident == &name::STRINGIFY_MACRO { Some(MacroDefId { krate, ast_id, kind: MacroDefKind::BuiltIn(BuiltinExpander::Stringify) }) @@ -105,3 +109,23 @@ fn stringify_expand( Ok(expanded) } + +fn file_expand( + db: &dyn AstDatabase, + id: MacroCallId, + _tt: &tt::Subtree, +) -> Result { + let loc = db.lookup_intern_macro(id); + let macro_call = loc.ast_id.to_node(db); + let _ = macro_call.token_tree().ok_or_else(|| mbe::ExpandError::UnexpectedToken)?; + + // FIXME: RA purposefully lacks knowledge of absolute file names + // so just return "". + let file_name = ""; + + let expanded = quote! { + #file_name + }; + + Ok(expanded) +} diff --git a/crates/ra_hir_expand/src/name.rs b/crates/ra_hir_expand/src/name.rs index c3f7e77a5a..05fe6afd9b 100644 --- a/crates/ra_hir_expand/src/name.rs +++ b/crates/ra_hir_expand/src/name.rs @@ -142,5 +142,6 @@ pub const TARGET_TYPE: Name = Name::new_inline_ascii(6, b"Target"); pub const BOX_TYPE: Name = Name::new_inline_ascii(3, b"Box"); // Builtin Macros +pub const FILE_MACRO: Name = Name::new_inline_ascii(4, b"file"); pub const LINE_MACRO: Name = Name::new_inline_ascii(4, b"line"); pub const STRINGIFY_MACRO: Name = Name::new_inline_ascii(9, b"stringify");