diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir_expand/src/builtin_macro.rs | 59 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/name.rs | 1 |
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 | ||
47 | register_builtin! { | 47 | register_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 | ||
187 | fn 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)] |
176 | mod tests { | 208 | mod 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 |
145 | pub const FILE_MACRO: Name = Name::new_inline_ascii(4, b"file"); | 145 | pub const FILE_MACRO: Name = Name::new_inline_ascii(4, b"file"); |
146 | pub const COLUMN_MACRO: Name = Name::new_inline_ascii(6, b"column"); | 146 | pub const COLUMN_MACRO: Name = Name::new_inline_ascii(6, b"column"); |
147 | pub const COMPILE_ERROR_MACRO: Name = Name::new_inline_ascii(13, b"compile_error"); | ||
147 | pub const LINE_MACRO: Name = Name::new_inline_ascii(4, b"line"); | 148 | pub const LINE_MACRO: Name = Name::new_inline_ascii(4, b"line"); |
148 | pub const STRINGIFY_MACRO: Name = Name::new_inline_ascii(9, b"stringify"); | 149 | pub const STRINGIFY_MACRO: Name = Name::new_inline_ascii(9, b"stringify"); |