diff options
Diffstat (limited to 'crates/hir_expand')
-rw-r--r-- | crates/hir_expand/src/builtin_macro.rs | 129 | ||||
-rw-r--r-- | crates/hir_expand/src/db.rs | 17 | ||||
-rw-r--r-- | crates/hir_expand/src/diagnostics.rs | 9 | ||||
-rw-r--r-- | crates/hir_expand/src/eager.rs | 2 | ||||
-rw-r--r-- | crates/hir_expand/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/hir_expand/src/proc_macro.rs | 2 |
6 files changed, 102 insertions, 59 deletions
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs index aebbfc4df..7f4db106d 100644 --- a/crates/hir_expand/src/builtin_macro.rs +++ b/crates/hir_expand/src/builtin_macro.rs | |||
@@ -6,7 +6,7 @@ use crate::{ | |||
6 | 6 | ||
7 | use base_db::FileId; | 7 | use base_db::FileId; |
8 | use either::Either; | 8 | use either::Either; |
9 | use mbe::parse_to_token_tree; | 9 | use mbe::{parse_to_token_tree, ExpandResult}; |
10 | use parser::FragmentKind; | 10 | use parser::FragmentKind; |
11 | use syntax::ast::{self, AstToken}; | 11 | use syntax::ast::{self, AstToken}; |
12 | 12 | ||
@@ -28,7 +28,7 @@ macro_rules! register_builtin { | |||
28 | db: &dyn AstDatabase, | 28 | db: &dyn AstDatabase, |
29 | id: LazyMacroId, | 29 | id: LazyMacroId, |
30 | tt: &tt::Subtree, | 30 | tt: &tt::Subtree, |
31 | ) -> Result<tt::Subtree, mbe::ExpandError> { | 31 | ) -> ExpandResult<tt::Subtree> { |
32 | let expander = match *self { | 32 | let expander = match *self { |
33 | $( BuiltinFnLikeExpander::$kind => $expand, )* | 33 | $( BuiltinFnLikeExpander::$kind => $expand, )* |
34 | }; | 34 | }; |
@@ -42,7 +42,7 @@ macro_rules! register_builtin { | |||
42 | db: &dyn AstDatabase, | 42 | db: &dyn AstDatabase, |
43 | arg_id: EagerMacroId, | 43 | arg_id: EagerMacroId, |
44 | tt: &tt::Subtree, | 44 | tt: &tt::Subtree, |
45 | ) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { | 45 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { |
46 | let expander = match *self { | 46 | let expander = match *self { |
47 | $( EagerExpander::$e_kind => $e_expand, )* | 47 | $( EagerExpander::$e_kind => $e_expand, )* |
48 | }; | 48 | }; |
@@ -109,25 +109,28 @@ fn line_expand( | |||
109 | _db: &dyn AstDatabase, | 109 | _db: &dyn AstDatabase, |
110 | _id: LazyMacroId, | 110 | _id: LazyMacroId, |
111 | _tt: &tt::Subtree, | 111 | _tt: &tt::Subtree, |
112 | ) -> Result<tt::Subtree, mbe::ExpandError> { | 112 | ) -> ExpandResult<tt::Subtree> { |
113 | // dummy implementation for type-checking purposes | 113 | // dummy implementation for type-checking purposes |
114 | let line_num = 0; | 114 | let line_num = 0; |
115 | let expanded = quote! { | 115 | let expanded = quote! { |
116 | #line_num | 116 | #line_num |
117 | }; | 117 | }; |
118 | 118 | ||
119 | Ok(expanded) | 119 | ExpandResult::ok(expanded) |
120 | } | 120 | } |
121 | 121 | ||
122 | fn stringify_expand( | 122 | fn stringify_expand( |
123 | db: &dyn AstDatabase, | 123 | db: &dyn AstDatabase, |
124 | id: LazyMacroId, | 124 | id: LazyMacroId, |
125 | _tt: &tt::Subtree, | 125 | _tt: &tt::Subtree, |
126 | ) -> Result<tt::Subtree, mbe::ExpandError> { | 126 | ) -> ExpandResult<tt::Subtree> { |
127 | let loc = db.lookup_intern_macro(id); | 127 | let loc = db.lookup_intern_macro(id); |
128 | 128 | ||
129 | let macro_content = { | 129 | let macro_content = { |
130 | let arg = loc.kind.arg(db).ok_or_else(|| mbe::ExpandError::UnexpectedToken)?; | 130 | let arg = match loc.kind.arg(db) { |
131 | Some(arg) => arg, | ||
132 | None => return ExpandResult::only_err(mbe::ExpandError::UnexpectedToken), | ||
133 | }; | ||
131 | let macro_args = arg; | 134 | let macro_args = arg; |
132 | let text = macro_args.text(); | 135 | let text = macro_args.text(); |
133 | let without_parens = TextSize::of('(')..text.len() - TextSize::of(')'); | 136 | let without_parens = TextSize::of('(')..text.len() - TextSize::of(')'); |
@@ -138,28 +141,28 @@ fn stringify_expand( | |||
138 | #macro_content | 141 | #macro_content |
139 | }; | 142 | }; |
140 | 143 | ||
141 | Ok(expanded) | 144 | ExpandResult::ok(expanded) |
142 | } | 145 | } |
143 | 146 | ||
144 | fn column_expand( | 147 | fn column_expand( |
145 | _db: &dyn AstDatabase, | 148 | _db: &dyn AstDatabase, |
146 | _id: LazyMacroId, | 149 | _id: LazyMacroId, |
147 | _tt: &tt::Subtree, | 150 | _tt: &tt::Subtree, |
148 | ) -> Result<tt::Subtree, mbe::ExpandError> { | 151 | ) -> ExpandResult<tt::Subtree> { |
149 | // dummy implementation for type-checking purposes | 152 | // dummy implementation for type-checking purposes |
150 | let col_num = 0; | 153 | let col_num = 0; |
151 | let expanded = quote! { | 154 | let expanded = quote! { |
152 | #col_num | 155 | #col_num |
153 | }; | 156 | }; |
154 | 157 | ||
155 | Ok(expanded) | 158 | ExpandResult::ok(expanded) |
156 | } | 159 | } |
157 | 160 | ||
158 | fn assert_expand( | 161 | fn assert_expand( |
159 | _db: &dyn AstDatabase, | 162 | _db: &dyn AstDatabase, |
160 | _id: LazyMacroId, | 163 | _id: LazyMacroId, |
161 | tt: &tt::Subtree, | 164 | tt: &tt::Subtree, |
162 | ) -> Result<tt::Subtree, mbe::ExpandError> { | 165 | ) -> ExpandResult<tt::Subtree> { |
163 | // A hacky implementation for goto def and hover | 166 | // A hacky implementation for goto def and hover |
164 | // We expand `assert!(cond, arg1, arg2)` to | 167 | // We expand `assert!(cond, arg1, arg2)` to |
165 | // ``` | 168 | // ``` |
@@ -191,14 +194,14 @@ fn assert_expand( | |||
191 | let expanded = quote! { | 194 | let expanded = quote! { |
192 | { { (##arg_tts); } } | 195 | { { (##arg_tts); } } |
193 | }; | 196 | }; |
194 | Ok(expanded) | 197 | ExpandResult::ok(expanded) |
195 | } | 198 | } |
196 | 199 | ||
197 | fn file_expand( | 200 | fn file_expand( |
198 | _db: &dyn AstDatabase, | 201 | _db: &dyn AstDatabase, |
199 | _id: LazyMacroId, | 202 | _id: LazyMacroId, |
200 | _tt: &tt::Subtree, | 203 | _tt: &tt::Subtree, |
201 | ) -> Result<tt::Subtree, mbe::ExpandError> { | 204 | ) -> ExpandResult<tt::Subtree> { |
202 | // FIXME: RA purposefully lacks knowledge of absolute file names | 205 | // FIXME: RA purposefully lacks knowledge of absolute file names |
203 | // so just return "". | 206 | // so just return "". |
204 | let file_name = ""; | 207 | let file_name = ""; |
@@ -207,31 +210,33 @@ fn file_expand( | |||
207 | #file_name | 210 | #file_name |
208 | }; | 211 | }; |
209 | 212 | ||
210 | Ok(expanded) | 213 | ExpandResult::ok(expanded) |
211 | } | 214 | } |
212 | 215 | ||
213 | fn compile_error_expand( | 216 | fn compile_error_expand( |
214 | _db: &dyn AstDatabase, | 217 | _db: &dyn AstDatabase, |
215 | _id: LazyMacroId, | 218 | _id: LazyMacroId, |
216 | tt: &tt::Subtree, | 219 | tt: &tt::Subtree, |
217 | ) -> Result<tt::Subtree, mbe::ExpandError> { | 220 | ) -> ExpandResult<tt::Subtree> { |
218 | if tt.count() == 1 { | 221 | if tt.count() == 1 { |
219 | if let tt::TokenTree::Leaf(tt::Leaf::Literal(it)) = &tt.token_trees[0] { | 222 | if let tt::TokenTree::Leaf(tt::Leaf::Literal(it)) = &tt.token_trees[0] { |
220 | let s = it.text.as_str(); | 223 | let s = it.text.as_str(); |
221 | if s.contains('"') { | 224 | if s.contains('"') { |
222 | return Ok(quote! { loop { #it }}); | 225 | return ExpandResult::ok(quote! { loop { #it }}); |
223 | } | 226 | } |
224 | }; | 227 | }; |
225 | } | 228 | } |
226 | 229 | ||
227 | Err(mbe::ExpandError::BindingError("Must be a string".into())) | 230 | ExpandResult::only_err(mbe::ExpandError::BindingError( |
231 | "`compile_error!` argument be a string".into(), | ||
232 | )) | ||
228 | } | 233 | } |
229 | 234 | ||
230 | fn format_args_expand( | 235 | fn format_args_expand( |
231 | _db: &dyn AstDatabase, | 236 | _db: &dyn AstDatabase, |
232 | _id: LazyMacroId, | 237 | _id: LazyMacroId, |
233 | tt: &tt::Subtree, | 238 | tt: &tt::Subtree, |
234 | ) -> Result<tt::Subtree, mbe::ExpandError> { | 239 | ) -> ExpandResult<tt::Subtree> { |
235 | // We expand `format_args!("", a1, a2)` to | 240 | // We expand `format_args!("", a1, a2)` to |
236 | // ``` | 241 | // ``` |
237 | // std::fmt::Arguments::new_v1(&[], &[ | 242 | // std::fmt::Arguments::new_v1(&[], &[ |
@@ -257,7 +262,7 @@ fn format_args_expand( | |||
257 | args.push(current); | 262 | args.push(current); |
258 | } | 263 | } |
259 | if args.is_empty() { | 264 | if args.is_empty() { |
260 | return Err(mbe::ExpandError::NoMatchingRule); | 265 | return ExpandResult::only_err(mbe::ExpandError::NoMatchingRule); |
261 | } | 266 | } |
262 | let _format_string = args.remove(0); | 267 | let _format_string = args.remove(0); |
263 | let arg_tts = args.into_iter().flat_map(|arg| { | 268 | let arg_tts = args.into_iter().flat_map(|arg| { |
@@ -266,7 +271,7 @@ fn format_args_expand( | |||
266 | let expanded = quote! { | 271 | let expanded = quote! { |
267 | std::fmt::Arguments::new_v1(&[], &[##arg_tts]) | 272 | std::fmt::Arguments::new_v1(&[], &[##arg_tts]) |
268 | }; | 273 | }; |
269 | Ok(expanded) | 274 | ExpandResult::ok(expanded) |
270 | } | 275 | } |
271 | 276 | ||
272 | fn unquote_str(lit: &tt::Literal) -> Option<String> { | 277 | fn unquote_str(lit: &tt::Literal) -> Option<String> { |
@@ -279,19 +284,24 @@ fn concat_expand( | |||
279 | _db: &dyn AstDatabase, | 284 | _db: &dyn AstDatabase, |
280 | _arg_id: EagerMacroId, | 285 | _arg_id: EagerMacroId, |
281 | tt: &tt::Subtree, | 286 | tt: &tt::Subtree, |
282 | ) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { | 287 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { |
283 | let mut text = String::new(); | 288 | let mut text = String::new(); |
284 | for (i, t) in tt.token_trees.iter().enumerate() { | 289 | for (i, t) in tt.token_trees.iter().enumerate() { |
285 | match t { | 290 | match t { |
286 | tt::TokenTree::Leaf(tt::Leaf::Literal(it)) if i % 2 == 0 => { | 291 | tt::TokenTree::Leaf(tt::Leaf::Literal(it)) if i % 2 == 0 => { |
287 | text += &unquote_str(&it).ok_or_else(|| mbe::ExpandError::ConversionError)?; | 292 | text += &match unquote_str(&it) { |
293 | Some(s) => s, | ||
294 | None => { | ||
295 | return ExpandResult::only_err(mbe::ExpandError::ConversionError); | ||
296 | } | ||
297 | }; | ||
288 | } | 298 | } |
289 | tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (), | 299 | tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (), |
290 | _ => return Err(mbe::ExpandError::UnexpectedToken), | 300 | _ => return ExpandResult::only_err(mbe::ExpandError::UnexpectedToken), |
291 | } | 301 | } |
292 | } | 302 | } |
293 | 303 | ||
294 | Ok((quote!(#text), FragmentKind::Expr)) | 304 | ExpandResult::ok(Some((quote!(#text), FragmentKind::Expr))) |
295 | } | 305 | } |
296 | 306 | ||
297 | fn relative_file( | 307 | fn relative_file( |
@@ -324,26 +334,35 @@ fn include_expand( | |||
324 | db: &dyn AstDatabase, | 334 | db: &dyn AstDatabase, |
325 | arg_id: EagerMacroId, | 335 | arg_id: EagerMacroId, |
326 | tt: &tt::Subtree, | 336 | tt: &tt::Subtree, |
327 | ) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { | 337 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { |
328 | let path = parse_string(tt)?; | 338 | let res = (|| { |
329 | let file_id = relative_file(db, arg_id.into(), &path, false) | 339 | let path = parse_string(tt)?; |
330 | .ok_or_else(|| mbe::ExpandError::ConversionError)?; | 340 | let file_id = relative_file(db, arg_id.into(), &path, false) |
331 | 341 | .ok_or_else(|| mbe::ExpandError::ConversionError)?; | |
332 | // FIXME: | 342 | |
333 | // Handle include as expression | 343 | Ok(parse_to_token_tree(&db.file_text(file_id)) |
334 | let res = parse_to_token_tree(&db.file_text(file_id)) | 344 | .ok_or_else(|| mbe::ExpandError::ConversionError)? |
335 | .ok_or_else(|| mbe::ExpandError::ConversionError)? | 345 | .0) |
336 | .0; | 346 | })(); |
337 | 347 | ||
338 | Ok((res, FragmentKind::Items)) | 348 | match res { |
349 | Ok(res) => { | ||
350 | // FIXME: | ||
351 | // Handle include as expression | ||
352 | ExpandResult::ok(Some((res, FragmentKind::Items))) | ||
353 | } | ||
354 | Err(e) => ExpandResult::only_err(e), | ||
355 | } | ||
339 | } | 356 | } |
340 | 357 | ||
341 | fn include_bytes_expand( | 358 | fn include_bytes_expand( |
342 | _db: &dyn AstDatabase, | 359 | _db: &dyn AstDatabase, |
343 | _arg_id: EagerMacroId, | 360 | _arg_id: EagerMacroId, |
344 | tt: &tt::Subtree, | 361 | tt: &tt::Subtree, |
345 | ) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { | 362 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { |
346 | let _path = parse_string(tt)?; | 363 | if let Err(e) = parse_string(tt) { |
364 | return ExpandResult::only_err(e); | ||
365 | } | ||
347 | 366 | ||
348 | // FIXME: actually read the file here if the user asked for macro expansion | 367 | // FIXME: actually read the file here if the user asked for macro expansion |
349 | let res = tt::Subtree { | 368 | let res = tt::Subtree { |
@@ -353,15 +372,18 @@ fn include_bytes_expand( | |||
353 | id: tt::TokenId::unspecified(), | 372 | id: tt::TokenId::unspecified(), |
354 | }))], | 373 | }))], |
355 | }; | 374 | }; |
356 | Ok((res, FragmentKind::Expr)) | 375 | ExpandResult::ok(Some((res, FragmentKind::Expr))) |
357 | } | 376 | } |
358 | 377 | ||
359 | fn include_str_expand( | 378 | fn include_str_expand( |
360 | db: &dyn AstDatabase, | 379 | db: &dyn AstDatabase, |
361 | arg_id: EagerMacroId, | 380 | arg_id: EagerMacroId, |
362 | tt: &tt::Subtree, | 381 | tt: &tt::Subtree, |
363 | ) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { | 382 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { |
364 | let path = parse_string(tt)?; | 383 | let path = match parse_string(tt) { |
384 | Ok(it) => it, | ||
385 | Err(e) => return ExpandResult::only_err(e), | ||
386 | }; | ||
365 | 387 | ||
366 | // FIXME: we're not able to read excluded files (which is most of them because | 388 | // FIXME: we're not able to read excluded files (which is most of them because |
367 | // it's unusual to `include_str!` a Rust file), but we can return an empty string. | 389 | // it's unusual to `include_str!` a Rust file), but we can return an empty string. |
@@ -370,14 +392,14 @@ fn include_str_expand( | |||
370 | let file_id = match relative_file(db, arg_id.into(), &path, true) { | 392 | let file_id = match relative_file(db, arg_id.into(), &path, true) { |
371 | Some(file_id) => file_id, | 393 | Some(file_id) => file_id, |
372 | None => { | 394 | None => { |
373 | return Ok((quote!(""), FragmentKind::Expr)); | 395 | return ExpandResult::ok(Some((quote!(""), FragmentKind::Expr))); |
374 | } | 396 | } |
375 | }; | 397 | }; |
376 | 398 | ||
377 | let text = db.file_text(file_id); | 399 | let text = db.file_text(file_id); |
378 | let text = &*text; | 400 | let text = &*text; |
379 | 401 | ||
380 | Ok((quote!(#text), FragmentKind::Expr)) | 402 | ExpandResult::ok(Some((quote!(#text), FragmentKind::Expr))) |
381 | } | 403 | } |
382 | 404 | ||
383 | fn get_env_inner(db: &dyn AstDatabase, arg_id: EagerMacroId, key: &str) -> Option<String> { | 405 | fn get_env_inner(db: &dyn AstDatabase, arg_id: EagerMacroId, key: &str) -> Option<String> { |
@@ -389,8 +411,11 @@ fn env_expand( | |||
389 | db: &dyn AstDatabase, | 411 | db: &dyn AstDatabase, |
390 | arg_id: EagerMacroId, | 412 | arg_id: EagerMacroId, |
391 | tt: &tt::Subtree, | 413 | tt: &tt::Subtree, |
392 | ) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { | 414 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { |
393 | let key = parse_string(tt)?; | 415 | let key = match parse_string(tt) { |
416 | Ok(it) => it, | ||
417 | Err(e) => return ExpandResult::only_err(e), | ||
418 | }; | ||
394 | 419 | ||
395 | // FIXME: | 420 | // FIXME: |
396 | // If the environment variable is not defined int rustc, then a compilation error will be emitted. | 421 | // If the environment variable is not defined int rustc, then a compilation error will be emitted. |
@@ -402,21 +427,25 @@ fn env_expand( | |||
402 | let s = get_env_inner(db, arg_id, &key).unwrap_or_else(|| "__RA_UNIMPLEMENTED__".to_string()); | 427 | let s = get_env_inner(db, arg_id, &key).unwrap_or_else(|| "__RA_UNIMPLEMENTED__".to_string()); |
403 | let expanded = quote! { #s }; | 428 | let expanded = quote! { #s }; |
404 | 429 | ||
405 | Ok((expanded, FragmentKind::Expr)) | 430 | ExpandResult::ok(Some((expanded, FragmentKind::Expr))) |
406 | } | 431 | } |
407 | 432 | ||
408 | fn option_env_expand( | 433 | fn option_env_expand( |
409 | db: &dyn AstDatabase, | 434 | db: &dyn AstDatabase, |
410 | arg_id: EagerMacroId, | 435 | arg_id: EagerMacroId, |
411 | tt: &tt::Subtree, | 436 | tt: &tt::Subtree, |
412 | ) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { | 437 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { |
413 | let key = parse_string(tt)?; | 438 | let key = match parse_string(tt) { |
439 | Ok(it) => it, | ||
440 | Err(e) => return ExpandResult::only_err(e), | ||
441 | }; | ||
442 | |||
414 | let expanded = match get_env_inner(db, arg_id, &key) { | 443 | let expanded = match get_env_inner(db, arg_id, &key) { |
415 | None => quote! { std::option::Option::None::<&str> }, | 444 | None => quote! { std::option::Option::None::<&str> }, |
416 | Some(s) => quote! { std::option::Some(#s) }, | 445 | Some(s) => quote! { std::option::Some(#s) }, |
417 | }; | 446 | }; |
418 | 447 | ||
419 | Ok((expanded, FragmentKind::Expr)) | 448 | ExpandResult::ok(Some((expanded, FragmentKind::Expr))) |
420 | } | 449 | } |
421 | 450 | ||
422 | #[cfg(test)] | 451 | #[cfg(test)] |
@@ -485,7 +514,7 @@ mod tests { | |||
485 | } | 514 | } |
486 | }); | 515 | }); |
487 | 516 | ||
488 | let (subtree, fragment) = expander.expand(&db, arg_id, &parsed_args).unwrap(); | 517 | let (subtree, fragment) = expander.expand(&db, arg_id, &parsed_args).value.unwrap(); |
489 | let eager = EagerCallLoc { | 518 | let eager = EagerCallLoc { |
490 | def, | 519 | def, |
491 | fragment, | 520 | fragment, |
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs index 46ebdbc74..4fd0ba290 100644 --- a/crates/hir_expand/src/db.rs +++ b/crates/hir_expand/src/db.rs | |||
@@ -3,7 +3,7 @@ | |||
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | 4 | ||
5 | use base_db::{salsa, SourceDatabase}; | 5 | use base_db::{salsa, SourceDatabase}; |
6 | use mbe::{ExpandResult, MacroRules}; | 6 | use mbe::{ExpandError, ExpandResult, MacroRules}; |
7 | use parser::FragmentKind; | 7 | use parser::FragmentKind; |
8 | use syntax::{algo::diff, AstNode, GreenNode, Parse, SyntaxKind::*, SyntaxNode}; | 8 | use syntax::{algo::diff, AstNode, GreenNode, Parse, SyntaxKind::*, SyntaxNode}; |
9 | 9 | ||
@@ -30,8 +30,8 @@ impl TokenExpander { | |||
30 | ) -> mbe::ExpandResult<tt::Subtree> { | 30 | ) -> mbe::ExpandResult<tt::Subtree> { |
31 | match self { | 31 | match self { |
32 | TokenExpander::MacroRules(it) => it.expand(tt), | 32 | TokenExpander::MacroRules(it) => it.expand(tt), |
33 | TokenExpander::Builtin(it) => it.expand(db, id, tt), | ||
33 | // FIXME switch these to ExpandResult as well | 34 | // FIXME switch these to ExpandResult as well |
34 | TokenExpander::Builtin(it) => it.expand(db, id, tt).into(), | ||
35 | TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt).into(), | 35 | TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt).into(), |
36 | TokenExpander::ProcMacro(_) => { | 36 | TokenExpander::ProcMacro(_) => { |
37 | // We store the result in salsa db to prevent non-determinisc behavior in | 37 | // We store the result in salsa db to prevent non-determinisc behavior in |
@@ -81,6 +81,9 @@ pub trait AstDatabase: SourceDatabase { | |||
81 | ) -> ExpandResult<Option<(Parse<SyntaxNode>, Arc<mbe::TokenMap>)>>; | 81 | ) -> ExpandResult<Option<(Parse<SyntaxNode>, Arc<mbe::TokenMap>)>>; |
82 | fn macro_expand(&self, macro_call: MacroCallId) -> ExpandResult<Option<Arc<tt::Subtree>>>; | 82 | fn macro_expand(&self, macro_call: MacroCallId) -> ExpandResult<Option<Arc<tt::Subtree>>>; |
83 | 83 | ||
84 | /// Firewall query that returns the error from the `macro_expand` query. | ||
85 | fn macro_expand_error(&self, macro_call: MacroCallId) -> Option<ExpandError>; | ||
86 | |||
84 | #[salsa::interned] | 87 | #[salsa::interned] |
85 | fn intern_eager_expansion(&self, eager: EagerCallLoc) -> EagerMacroId; | 88 | fn intern_eager_expansion(&self, eager: EagerCallLoc) -> EagerMacroId; |
86 | 89 | ||
@@ -171,6 +174,10 @@ fn macro_expand(db: &dyn AstDatabase, id: MacroCallId) -> ExpandResult<Option<Ar | |||
171 | macro_expand_with_arg(db, id, None) | 174 | macro_expand_with_arg(db, id, None) |
172 | } | 175 | } |
173 | 176 | ||
177 | fn macro_expand_error(db: &dyn AstDatabase, macro_call: MacroCallId) -> Option<ExpandError> { | ||
178 | db.macro_expand(macro_call).err | ||
179 | } | ||
180 | |||
174 | fn expander(db: &dyn AstDatabase, id: MacroCallId) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> { | 181 | fn expander(db: &dyn AstDatabase, id: MacroCallId) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> { |
175 | let lazy_id = match id { | 182 | let lazy_id = match id { |
176 | MacroCallId::LazyMacro(id) => id, | 183 | MacroCallId::LazyMacro(id) => id, |
@@ -189,6 +196,7 @@ fn macro_expand_with_arg( | |||
189 | id: MacroCallId, | 196 | id: MacroCallId, |
190 | arg: Option<Arc<(tt::Subtree, mbe::TokenMap)>>, | 197 | arg: Option<Arc<(tt::Subtree, mbe::TokenMap)>>, |
191 | ) -> ExpandResult<Option<Arc<tt::Subtree>>> { | 198 | ) -> ExpandResult<Option<Arc<tt::Subtree>>> { |
199 | let _p = profile::span("macro_expand"); | ||
192 | let lazy_id = match id { | 200 | let lazy_id = match id { |
193 | MacroCallId::LazyMacro(id) => id, | 201 | MacroCallId::LazyMacro(id) => id, |
194 | MacroCallId::EagerMacro(id) => { | 202 | MacroCallId::EagerMacro(id) => { |
@@ -276,14 +284,15 @@ fn parse_macro_with_arg( | |||
276 | macro_file: MacroFile, | 284 | macro_file: MacroFile, |
277 | arg: Option<Arc<(tt::Subtree, mbe::TokenMap)>>, | 285 | arg: Option<Arc<(tt::Subtree, mbe::TokenMap)>>, |
278 | ) -> ExpandResult<Option<(Parse<SyntaxNode>, Arc<mbe::TokenMap>)>> { | 286 | ) -> ExpandResult<Option<(Parse<SyntaxNode>, Arc<mbe::TokenMap>)>> { |
279 | let _p = profile::span("parse_macro_query"); | ||
280 | |||
281 | let macro_call_id = macro_file.macro_call_id; | 287 | let macro_call_id = macro_file.macro_call_id; |
282 | let result = if let Some(arg) = arg { | 288 | let result = if let Some(arg) = arg { |
283 | macro_expand_with_arg(db, macro_call_id, Some(arg)) | 289 | macro_expand_with_arg(db, macro_call_id, Some(arg)) |
284 | } else { | 290 | } else { |
285 | db.macro_expand(macro_call_id) | 291 | db.macro_expand(macro_call_id) |
286 | }; | 292 | }; |
293 | |||
294 | let _p = profile::span("parse_macro_expansion"); | ||
295 | |||
287 | if let Some(err) = &result.err { | 296 | if let Some(err) = &result.err { |
288 | // Note: | 297 | // Note: |
289 | // The final goal we would like to make all parse_macro success, | 298 | // The final goal we would like to make all parse_macro success, |
diff --git a/crates/hir_expand/src/diagnostics.rs b/crates/hir_expand/src/diagnostics.rs index 1043c6aeb..bf0b85ce9 100644 --- a/crates/hir_expand/src/diagnostics.rs +++ b/crates/hir_expand/src/diagnostics.rs | |||
@@ -5,7 +5,7 @@ | |||
5 | //! | 5 | //! |
6 | //! `DiagnosticSink` struct is used as an emitter for diagnostic. When creating | 6 | //! `DiagnosticSink` struct is used as an emitter for diagnostic. When creating |
7 | //! a `DiagnosticSink`, you supply a callback which can react to a `dyn | 7 | //! a `DiagnosticSink`, you supply a callback which can react to a `dyn |
8 | //! Diagnostic` or to any concrete diagnostic (downcasting is sued internally). | 8 | //! Diagnostic` or to any concrete diagnostic (downcasting is used internally). |
9 | //! | 9 | //! |
10 | //! Because diagnostics store file offsets, it's a bad idea to store them | 10 | //! Because diagnostics store file offsets, it's a bad idea to store them |
11 | //! directly in salsa. For this reason, every hir subsytem defines it's own | 11 | //! directly in salsa. For this reason, every hir subsytem defines it's own |
@@ -32,7 +32,12 @@ impl DiagnosticCode { | |||
32 | pub trait Diagnostic: Any + Send + Sync + fmt::Debug + 'static { | 32 | pub trait Diagnostic: Any + Send + Sync + fmt::Debug + 'static { |
33 | fn code(&self) -> DiagnosticCode; | 33 | fn code(&self) -> DiagnosticCode; |
34 | fn message(&self) -> String; | 34 | fn message(&self) -> String; |
35 | /// Used in highlighting and related purposes | 35 | /// Source element that triggered the diagnostics. |
36 | /// | ||
37 | /// Note that this should reflect "semantics", rather than specific span we | ||
38 | /// want to highlight. When rendering the diagnostics into an error message, | ||
39 | /// the IDE will fetch the `SyntaxNode` and will narrow the span | ||
40 | /// appropriately. | ||
36 | fn display_source(&self) -> InFile<SyntaxNodePtr>; | 41 | fn display_source(&self) -> InFile<SyntaxNodePtr>; |
37 | fn as_any(&self) -> &(dyn Any + Send + 'static); | 42 | fn as_any(&self) -> &(dyn Any + Send + 'static); |
38 | fn is_experimental(&self) -> bool { | 43 | fn is_experimental(&self) -> bool { |
diff --git a/crates/hir_expand/src/eager.rs b/crates/hir_expand/src/eager.rs index 2f37d7189..ab6b4477c 100644 --- a/crates/hir_expand/src/eager.rs +++ b/crates/hir_expand/src/eager.rs | |||
@@ -65,7 +65,7 @@ pub fn expand_eager_macro( | |||
65 | let subtree = to_subtree(&result)?; | 65 | let subtree = to_subtree(&result)?; |
66 | 66 | ||
67 | if let MacroDefKind::BuiltInEager(eager) = def.kind { | 67 | if let MacroDefKind::BuiltInEager(eager) = def.kind { |
68 | let (subtree, fragment) = eager.expand(db, arg_id, &subtree).ok()?; | 68 | let (subtree, fragment) = eager.expand(db, arg_id, &subtree).value?; |
69 | let eager = EagerCallLoc { | 69 | let eager = EagerCallLoc { |
70 | def, | 70 | def, |
71 | fragment, | 71 | fragment, |
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs index d5ba691b7..6dad2507b 100644 --- a/crates/hir_expand/src/lib.rs +++ b/crates/hir_expand/src/lib.rs | |||
@@ -255,7 +255,7 @@ pub enum MacroDefKind { | |||
255 | pub struct MacroCallLoc { | 255 | pub struct MacroCallLoc { |
256 | pub(crate) def: MacroDefId, | 256 | pub(crate) def: MacroDefId, |
257 | pub(crate) krate: CrateId, | 257 | pub(crate) krate: CrateId, |
258 | pub(crate) kind: MacroCallKind, | 258 | pub kind: MacroCallKind, |
259 | } | 259 | } |
260 | 260 | ||
261 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 261 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
diff --git a/crates/hir_expand/src/proc_macro.rs b/crates/hir_expand/src/proc_macro.rs index 7505cb061..97edf0fb6 100644 --- a/crates/hir_expand/src/proc_macro.rs +++ b/crates/hir_expand/src/proc_macro.rs | |||
@@ -50,7 +50,7 @@ impl ProcMacroExpander { | |||
50 | 50 | ||
51 | proc_macro.expander.expand(&tt, None).map_err(mbe::ExpandError::from) | 51 | proc_macro.expander.expand(&tt, None).map_err(mbe::ExpandError::from) |
52 | } | 52 | } |
53 | None => Err(err!("Unresolved proc macro")), | 53 | None => Err(mbe::ExpandError::UnresolvedProcMacro), |
54 | } | 54 | } |
55 | } | 55 | } |
56 | } | 56 | } |