aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir_expand/src/builtin_macro.rs38
-rw-r--r--crates/ra_hir_expand/src/name.rs1
-rw-r--r--crates/rust-analyzer/tests/heavy_tests/main.rs40
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
295fn relative_file(db: &dyn AstDatabase, call_id: MacroCallId, path: &str) -> Option<FileId> { 296fn 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
340fn 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
334fn get_env_inner(db: &dyn AstDatabase, arg_id: EagerMacroId, key: &str) -> Option<String> { 364fn 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 }]),