diff options
-rw-r--r-- | crates/ra_hir_expand/src/builtin_macro.rs | 38 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/name.rs | 1 | ||||
-rw-r--r-- | crates/rust-analyzer/tests/heavy_tests/main.rs | 40 |
3 files changed, 60 insertions, 19 deletions
diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs index b50eb347c..631358f41 100644 --- a/crates/ra_hir_expand/src/builtin_macro.rs +++ b/crates/ra_hir_expand/src/builtin_macro.rs | |||
@@ -99,6 +99,7 @@ register_builtin! { | |||
99 | EAGER: | 99 | EAGER: |
100 | (concat, Concat) => concat_expand, | 100 | (concat, Concat) => concat_expand, |
101 | (include, Include) => include_expand, | 101 | (include, Include) => include_expand, |
102 | (include_str, IncludeStr) => include_str_expand, | ||
102 | (env, Env) => env_expand, | 103 | (env, Env) => env_expand, |
103 | (option_env, OptionEnv) => option_env_expand | 104 | (option_env, OptionEnv) => option_env_expand |
104 | } | 105 | } |
@@ -292,11 +293,16 @@ fn concat_expand( | |||
292 | Ok((quote!(#text), FragmentKind::Expr)) | 293 | Ok((quote!(#text), FragmentKind::Expr)) |
293 | } | 294 | } |
294 | 295 | ||
295 | fn relative_file(db: &dyn AstDatabase, call_id: MacroCallId, path: &str) -> Option<FileId> { | 296 | fn relative_file( |
297 | db: &dyn AstDatabase, | ||
298 | call_id: MacroCallId, | ||
299 | path: &str, | ||
300 | allow_recursion: bool, | ||
301 | ) -> Option<FileId> { | ||
296 | let call_site = call_id.as_file().original_file(db); | 302 | let call_site = call_id.as_file().original_file(db); |
297 | let res = db.resolve_path(call_site, path)?; | 303 | let res = db.resolve_path(call_site, path)?; |
298 | // Prevent include itself | 304 | // Prevent include itself |
299 | if res == call_site { | 305 | if res == call_site && !allow_recursion { |
300 | None | 306 | None |
301 | } else { | 307 | } else { |
302 | Some(res) | 308 | Some(res) |
@@ -319,8 +325,8 @@ fn include_expand( | |||
319 | tt: &tt::Subtree, | 325 | tt: &tt::Subtree, |
320 | ) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { | 326 | ) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { |
321 | let path = parse_string(tt)?; | 327 | let path = parse_string(tt)?; |
322 | let file_id = | 328 | let file_id = relative_file(db, arg_id.into(), &path, false) |
323 | relative_file(db, arg_id.into(), &path).ok_or_else(|| mbe::ExpandError::ConversionError)?; | 329 | .ok_or_else(|| mbe::ExpandError::ConversionError)?; |
324 | 330 | ||
325 | // FIXME: | 331 | // FIXME: |
326 | // Handle include as expression | 332 | // Handle include as expression |
@@ -331,6 +337,30 @@ fn include_expand( | |||
331 | Ok((res, FragmentKind::Items)) | 337 | Ok((res, FragmentKind::Items)) |
332 | } | 338 | } |
333 | 339 | ||
340 | fn include_str_expand( | ||
341 | db: &dyn AstDatabase, | ||
342 | arg_id: EagerMacroId, | ||
343 | tt: &tt::Subtree, | ||
344 | ) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { | ||
345 | let path = parse_string(tt)?; | ||
346 | |||
347 | // FIXME: we're not able to read excluded files (which is most of them because | ||
348 | // it's unusual to `include_str!` a Rust file), but we can return an empty string. | ||
349 | // Ideally, we'd be able to offer a precise expansion if the user asks for macro | ||
350 | // expansion. | ||
351 | let file_id = match relative_file(db, arg_id.into(), &path, true) { | ||
352 | Some(file_id) => file_id, | ||
353 | None => { | ||
354 | return Ok((quote!(""), FragmentKind::Expr)); | ||
355 | } | ||
356 | }; | ||
357 | |||
358 | let text = db.file_text(file_id); | ||
359 | let text = &*text; | ||
360 | |||
361 | Ok((quote!(#text), FragmentKind::Expr)) | ||
362 | } | ||
363 | |||
334 | fn get_env_inner(db: &dyn AstDatabase, arg_id: EagerMacroId, key: &str) -> Option<String> { | 364 | fn get_env_inner(db: &dyn AstDatabase, arg_id: EagerMacroId, key: &str) -> Option<String> { |
335 | let krate = db.lookup_intern_eager_expansion(arg_id).krate; | 365 | let krate = db.lookup_intern_eager_expansion(arg_id).krate; |
336 | db.crate_graph()[krate].env.get(key) | 366 | db.crate_graph()[krate].env.get(key) |
diff --git a/crates/ra_hir_expand/src/name.rs b/crates/ra_hir_expand/src/name.rs index 660bdfe33..b475c8cc7 100644 --- a/crates/ra_hir_expand/src/name.rs +++ b/crates/ra_hir_expand/src/name.rs | |||
@@ -191,6 +191,7 @@ pub mod known { | |||
191 | stringify, | 191 | stringify, |
192 | concat, | 192 | concat, |
193 | include, | 193 | include, |
194 | include_str, | ||
194 | format_args, | 195 | format_args, |
195 | format_args_nl, | 196 | format_args_nl, |
196 | env, | 197 | env, |
diff --git a/crates/rust-analyzer/tests/heavy_tests/main.rs b/crates/rust-analyzer/tests/heavy_tests/main.rs index 58839b14a..cc079790e 100644 --- a/crates/rust-analyzer/tests/heavy_tests/main.rs +++ b/crates/rust-analyzer/tests/heavy_tests/main.rs | |||
@@ -494,6 +494,7 @@ fn main() { | |||
494 | } | 494 | } |
495 | //- /src/main.rs | 495 | //- /src/main.rs |
496 | #[rustc_builtin_macro] macro_rules! include {} | 496 | #[rustc_builtin_macro] macro_rules! include {} |
497 | #[rustc_builtin_macro] macro_rules! include_str {} | ||
497 | #[rustc_builtin_macro] macro_rules! concat {} | 498 | #[rustc_builtin_macro] macro_rules! concat {} |
498 | #[rustc_builtin_macro] macro_rules! env {} | 499 | #[rustc_builtin_macro] macro_rules! env {} |
499 | 500 | ||
@@ -512,6 +513,7 @@ fn main() { | |||
512 | let va = A; | 513 | let va = A; |
513 | let vb = B; | 514 | let vb = B; |
514 | let should_be_str = message(); | 515 | let should_be_str = message(); |
516 | let another_str = include_str!("main.rs"); | ||
515 | } | 517 | } |
516 | "###, | 518 | "###, |
517 | ) | 519 | ) |
@@ -523,7 +525,15 @@ fn main() { | |||
523 | let res = server.send_request::<HoverRequest>(HoverParams { | 525 | let res = server.send_request::<HoverRequest>(HoverParams { |
524 | text_document_position_params: TextDocumentPositionParams::new( | 526 | text_document_position_params: TextDocumentPositionParams::new( |
525 | server.doc_id("src/main.rs"), | 527 | server.doc_id("src/main.rs"), |
526 | Position::new(18, 10), | 528 | Position::new(19, 10), |
529 | ), | ||
530 | work_done_progress_params: Default::default(), | ||
531 | }); | ||
532 | assert!(res.to_string().contains("&str")); | ||
533 | let res = server.send_request::<HoverRequest>(HoverParams { | ||
534 | text_document_position_params: TextDocumentPositionParams::new( | ||
535 | server.doc_id("src/main.rs"), | ||
536 | Position::new(20, 10), | ||
527 | ), | 537 | ), |
528 | work_done_progress_params: Default::default(), | 538 | work_done_progress_params: Default::default(), |
529 | }); | 539 | }); |
@@ -532,23 +542,23 @@ fn main() { | |||
532 | GotoDefinitionParams { | 542 | GotoDefinitionParams { |
533 | text_document_position_params: TextDocumentPositionParams::new( | 543 | text_document_position_params: TextDocumentPositionParams::new( |
534 | server.doc_id("src/main.rs"), | 544 | server.doc_id("src/main.rs"), |
535 | Position::new(16, 9), | 545 | Position::new(17, 9), |
536 | ), | 546 | ), |
537 | work_done_progress_params: Default::default(), | 547 | work_done_progress_params: Default::default(), |
538 | partial_result_params: Default::default(), | 548 | partial_result_params: Default::default(), |
539 | }, | 549 | }, |
540 | json!([{ | 550 | json!([{ |
541 | "originSelectionRange": { | 551 | "originSelectionRange": { |
542 | "end": { "character": 10, "line": 16 }, | 552 | "end": { "character": 10, "line": 17 }, |
543 | "start": { "character": 8, "line": 16 } | 553 | "start": { "character": 8, "line": 17 } |
544 | }, | 554 | }, |
545 | "targetRange": { | 555 | "targetRange": { |
546 | "end": { "character": 9, "line": 7 }, | 556 | "end": { "character": 9, "line": 8 }, |
547 | "start": { "character": 0, "line": 6 } | 557 | "start": { "character": 0, "line": 7 } |
548 | }, | 558 | }, |
549 | "targetSelectionRange": { | 559 | "targetSelectionRange": { |
550 | "end": { "character": 8, "line": 7 }, | 560 | "end": { "character": 8, "line": 8 }, |
551 | "start": { "character": 7, "line": 7 } | 561 | "start": { "character": 7, "line": 8 } |
552 | }, | 562 | }, |
553 | "targetUri": "file:///[..]src/main.rs" | 563 | "targetUri": "file:///[..]src/main.rs" |
554 | }]), | 564 | }]), |
@@ -557,23 +567,23 @@ fn main() { | |||
557 | GotoDefinitionParams { | 567 | GotoDefinitionParams { |
558 | text_document_position_params: TextDocumentPositionParams::new( | 568 | text_document_position_params: TextDocumentPositionParams::new( |
559 | server.doc_id("src/main.rs"), | 569 | server.doc_id("src/main.rs"), |
560 | Position::new(17, 9), | 570 | Position::new(18, 9), |
561 | ), | 571 | ), |
562 | work_done_progress_params: Default::default(), | 572 | work_done_progress_params: Default::default(), |
563 | partial_result_params: Default::default(), | 573 | partial_result_params: Default::default(), |
564 | }, | 574 | }, |
565 | json!([{ | 575 | json!([{ |
566 | "originSelectionRange": { | 576 | "originSelectionRange": { |
567 | "end": { "character": 10, "line": 17 }, | 577 | "end": { "character": 10, "line": 18 }, |
568 | "start": { "character": 8, "line": 17 } | 578 | "start": { "character": 8, "line": 18 } |
569 | }, | 579 | }, |
570 | "targetRange": { | 580 | "targetRange": { |
571 | "end": { "character": 9, "line": 11 }, | 581 | "end": { "character": 9, "line": 12 }, |
572 | "start": { "character": 0, "line":10 } | 582 | "start": { "character": 0, "line":11 } |
573 | }, | 583 | }, |
574 | "targetSelectionRange": { | 584 | "targetSelectionRange": { |
575 | "end": { "character": 8, "line": 11 }, | 585 | "end": { "character": 8, "line": 12 }, |
576 | "start": { "character": 7, "line": 11 } | 586 | "start": { "character": 7, "line": 12 } |
577 | }, | 587 | }, |
578 | "targetUri": "file:///[..]src/main.rs" | 588 | "targetUri": "file:///[..]src/main.rs" |
579 | }]), | 589 | }]), |