diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index b4bdd81f64c..17a50cf741d 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs @@ -4876,3 +4876,22 @@ fn main() { "### ); } + +#[test] +fn infer_builtin_macros_column() { + assert_snapshot!( + infer(r#" +#[rustc_builtin_macro] +macro_rules! column {() => {}} + +fn main() { + let x = column!(); +} +"#), + @r###" + ![0; 2) '13': i32 + [66; 92) '{ ...!(); }': () + [76; 77) 'x': i32 + "### + ); +} diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs index d7057e00542..4da56529de3 100644 --- a/crates/ra_hir_expand/src/builtin_macro.rs +++ b/crates/ra_hir_expand/src/builtin_macro.rs @@ -10,6 +10,7 @@ #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum BuiltinExpander { + Column, File, Line, Stringify, @@ -23,6 +24,7 @@ pub fn expand( tt: &tt::Subtree, ) -> Result { match self { + BuiltinExpander::Column => column_expand(db, id, tt), BuiltinExpander::File => file_expand(db, id, tt), BuiltinExpander::Line => line_expand(db, id, tt), BuiltinExpander::Stringify => stringify_expand(db, id, tt), @@ -36,7 +38,9 @@ pub fn find_builtin_macro( ast_id: AstId, ) -> Option { // FIXME: Better registering method - if ident == &name::FILE_MACRO { + if ident == &name::COLUMN_MACRO { + Some(MacroDefId { krate, ast_id, kind: MacroDefKind::BuiltIn(BuiltinExpander::Column) }) + } else 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) }) @@ -110,6 +114,43 @@ fn stringify_expand( Ok(expanded) } +fn to_col_number(db: &dyn AstDatabase, file: HirFileId, pos: TextUnit) -> usize { + // FIXME: Use expansion info + let file_id = file.original_file(db); + let text = db.file_text(file_id); + let mut col_num = 1; + + for c in text[..pos.to_usize()].chars().rev() { + if c == '\n' { + break; + } + col_num = col_num + 1; + } + + col_num +} + +fn column_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 _arg = macro_call.token_tree().ok_or_else(|| mbe::ExpandError::UnexpectedToken)?; + let col_start = macro_call.syntax().text_range().start(); + + let file = id.as_file(MacroFileKind::Expr); + let col_num = to_col_number(db, file, col_start); + + let expanded = quote! { + #col_num + }; + + Ok(expanded) +} + fn file_expand( db: &dyn AstDatabase, id: MacroCallId, @@ -117,6 +158,7 @@ fn file_expand( ) -> 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 diff --git a/crates/ra_hir_expand/src/name.rs b/crates/ra_hir_expand/src/name.rs index 05fe6afd9b8..eaea7a6a86d 100644 --- a/crates/ra_hir_expand/src/name.rs +++ b/crates/ra_hir_expand/src/name.rs @@ -143,5 +143,6 @@ fn as_name(&self) -> Name { // Builtin Macros pub const FILE_MACRO: Name = Name::new_inline_ascii(4, b"file"); +pub const COLUMN_MACRO: Name = Name::new_inline_ascii(6, b"column"); pub const LINE_MACRO: Name = Name::new_inline_ascii(4, b"line"); pub const STRINGIFY_MACRO: Name = Name::new_inline_ascii(9, b"stringify");