aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir_expand/src/builtin_macro.rs59
-rw-r--r--crates/ra_hir_expand/src/name.rs1
2 files changed, 55 insertions, 5 deletions
diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs
index c0e0436c0..d370dfb34 100644
--- a/crates/ra_hir_expand/src/builtin_macro.rs
+++ b/crates/ra_hir_expand/src/builtin_macro.rs
@@ -46,6 +46,7 @@ macro_rules! register_builtin {
46 46
47register_builtin! { 47register_builtin! {
48 (COLUMN_MACRO, Column) => column_expand, 48 (COLUMN_MACRO, Column) => column_expand,
49 (COMPILE_ERROR_MACRO, CompileError) => compile_error_expand,
49 (FILE_MACRO, File) => file_expand, 50 (FILE_MACRO, File) => file_expand,
50 (LINE_MACRO, Line) => line_expand, 51 (LINE_MACRO, Line) => line_expand,
51 (STRINGIFY_MACRO, Stringify) => stringify_expand 52 (STRINGIFY_MACRO, Stringify) => stringify_expand
@@ -57,16 +58,21 @@ fn to_line_number(db: &dyn AstDatabase, file: HirFileId, pos: TextUnit) -> usize
57 let text = db.file_text(file_id); 58 let text = db.file_text(file_id);
58 let mut line_num = 1; 59 let mut line_num = 1;
59 60
61 let pos = pos.to_usize();
62 if pos > text.len() {
63 // FIXME: `pos` at the moment could be an offset inside the "wrong" file
64 // in this case, when we know it's wrong, we return a dummy value
65 return 0;
66 }
60 // Count line end 67 // Count line end
61 for (i, c) in text.chars().enumerate() { 68 for (i, c) in text.chars().enumerate() {
62 if i == pos.to_usize() { 69 if i == pos {
63 break; 70 break;
64 } 71 }
65 if c == '\n' { 72 if c == '\n' {
66 line_num += 1; 73 line_num += 1;
67 } 74 }
68 } 75 }
69
70 line_num 76 line_num
71} 77}
72 78
@@ -118,15 +124,21 @@ fn to_col_number(db: &dyn AstDatabase, file: HirFileId, pos: TextUnit) -> usize
118 // FIXME: Use expansion info 124 // FIXME: Use expansion info
119 let file_id = file.original_file(db); 125 let file_id = file.original_file(db);
120 let text = db.file_text(file_id); 126 let text = db.file_text(file_id);
121 let mut col_num = 1;
122 127
123 for c in text[..pos.to_usize()].chars().rev() { 128 let pos = pos.to_usize();
129 if pos > text.len() {
130 // FIXME: `pos` at the moment could be an offset inside the "wrong" file
131 // in this case we return a dummy value so that we don't `panic!`
132 return 0;
133 }
134
135 let mut col_num = 1;
136 for c in text[..pos].chars().rev() {
124 if c == '\n' { 137 if c == '\n' {
125 break; 138 break;
126 } 139 }
127 col_num = col_num + 1; 140 col_num = col_num + 1;
128 } 141 }
129
130 col_num 142 col_num
131} 143}
132 144
@@ -172,6 +184,26 @@ fn file_expand(
172 Ok(expanded) 184 Ok(expanded)
173} 185}
174 186
187fn compile_error_expand(
188 _db: &dyn AstDatabase,
189 _id: MacroCallId,
190 tt: &tt::Subtree,
191) -> Result<tt::Subtree, mbe::ExpandError> {
192 if tt.count() == 1 {
193 match &tt.token_trees[0] {
194 tt::TokenTree::Leaf(tt::Leaf::Literal(it)) => {
195 let s = it.text.as_str();
196 if s.contains(r#"""#) {
197 return Ok(quote! { loop { #it }});
198 }
199 }
200 _ => {}
201 };
202 }
203
204 Err(mbe::ExpandError::BindingError("Must be a string".into()))
205}
206
175#[cfg(test)] 207#[cfg(test)]
176mod tests { 208mod tests {
177 use super::*; 209 use super::*;
@@ -259,4 +291,21 @@ mod tests {
259 291
260 assert_eq!(expanded, "\"\""); 292 assert_eq!(expanded, "\"\"");
261 } 293 }
294
295 #[test]
296 fn test_compile_error_expand() {
297 let expanded = expand_builtin_macro(
298 r#"
299 #[rustc_builtin_macro]
300 macro_rules! compile_error {
301 ($msg:expr) => ({ /* compiler built-in */ });
302 ($msg:expr,) => ({ /* compiler built-in */ })
303 }
304 compile_error!("error!");
305"#,
306 BuiltinFnLikeExpander::CompileError,
307 );
308
309 assert_eq!(expanded, r#"loop{"error!"}"#);
310 }
262} 311}
diff --git a/crates/ra_hir_expand/src/name.rs b/crates/ra_hir_expand/src/name.rs
index eaea7a6a8..7824489d7 100644
--- a/crates/ra_hir_expand/src/name.rs
+++ b/crates/ra_hir_expand/src/name.rs
@@ -144,5 +144,6 @@ pub const BOX_TYPE: Name = Name::new_inline_ascii(3, b"Box");
144// Builtin Macros 144// Builtin Macros
145pub const FILE_MACRO: Name = Name::new_inline_ascii(4, b"file"); 145pub const FILE_MACRO: Name = Name::new_inline_ascii(4, b"file");
146pub const COLUMN_MACRO: Name = Name::new_inline_ascii(6, b"column"); 146pub const COLUMN_MACRO: Name = Name::new_inline_ascii(6, b"column");
147pub const COMPILE_ERROR_MACRO: Name = Name::new_inline_ascii(13, b"compile_error");
147pub const LINE_MACRO: Name = Name::new_inline_ascii(4, b"line"); 148pub const LINE_MACRO: Name = Name::new_inline_ascii(4, b"line");
148pub const STRINGIFY_MACRO: Name = Name::new_inline_ascii(9, b"stringify"); 149pub const STRINGIFY_MACRO: Name = Name::new_inline_ascii(9, b"stringify");