Skip to content

Commit aa82b59

Browse files
Merge #3494
3494: Implement include macro r=matklad a=edwin0cheng This PR implement builtin `include` macro. * It does not support include as expression yet. * It doesn't consider `env!("OUT_DIR")` yet. Co-authored-by: Edwin Cheng <[email protected]>
2 parents 4173645 + 0a06c7e commit aa82b59

File tree

4 files changed

+107
-19
lines changed

4 files changed

+107
-19
lines changed

crates/ra_hir_expand/src/builtin_macro.rs

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ use crate::{
55
name, AstId, CrateId, MacroDefId, MacroDefKind, TextUnit,
66
};
77

8-
use crate::{quote, LazyMacroId};
8+
use crate::{quote, EagerMacroId, LazyMacroId, MacroCallId};
99
use either::Either;
10+
use ra_db::{FileId, RelativePath};
1011
use ra_parser::FragmentKind;
1112

1213
macro_rules! register_builtin {
@@ -38,12 +39,14 @@ macro_rules! register_builtin {
3839
impl EagerExpander {
3940
pub fn expand(
4041
&self,
42+
db: &dyn AstDatabase,
43+
arg_id: EagerMacroId,
4144
tt: &tt::Subtree,
4245
) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> {
4346
let expander = match *self {
4447
$( EagerExpander::$e_kind => $e_expand, )*
4548
};
46-
expander(tt)
49+
expander(db,arg_id,tt)
4750
}
4851
}
4952

@@ -80,7 +83,6 @@ pub fn find_builtin_macro(
8083

8184
register_builtin! {
8285
LAZY:
83-
8486
(column, Column) => column_expand,
8587
(compile_error, CompileError) => compile_error_expand,
8688
(file, File) => file_expand,
@@ -94,8 +96,8 @@ register_builtin! {
9496
(format_args_nl, FormatArgsNl) => format_args_expand,
9597

9698
EAGER:
97-
// eagers
98-
(concat, Concat) => concat_expand
99+
(concat, Concat) => concat_expand,
100+
(include, Include) => include_expand
99101
}
100102

101103
fn line_expand(
@@ -251,7 +253,11 @@ fn unquote_str(lit: &tt::Literal) -> Option<String> {
251253
token.value()
252254
}
253255

254-
fn concat_expand(tt: &tt::Subtree) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> {
256+
fn concat_expand(
257+
_db: &dyn AstDatabase,
258+
_arg_id: EagerMacroId,
259+
tt: &tt::Subtree,
260+
) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> {
255261
let mut text = String::new();
256262
for (i, t) in tt.token_trees.iter().enumerate() {
257263
match t {
@@ -266,6 +272,40 @@ fn concat_expand(tt: &tt::Subtree) -> Result<(tt::Subtree, FragmentKind), mbe::E
266272
Ok((quote!(#text), FragmentKind::Expr))
267273
}
268274

275+
fn relative_file(db: &dyn AstDatabase, call_id: MacroCallId, path: &str) -> Option<FileId> {
276+
let call_site = call_id.as_file().original_file(db);
277+
let path = RelativePath::new(&path);
278+
279+
db.resolve_relative_path(call_site, &path)
280+
}
281+
282+
fn include_expand(
283+
db: &dyn AstDatabase,
284+
arg_id: EagerMacroId,
285+
tt: &tt::Subtree,
286+
) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> {
287+
let path = tt
288+
.token_trees
289+
.get(0)
290+
.and_then(|tt| match tt {
291+
tt::TokenTree::Leaf(tt::Leaf::Literal(it)) => unquote_str(&it),
292+
_ => None,
293+
})
294+
.ok_or_else(|| mbe::ExpandError::ConversionError)?;
295+
296+
let file_id =
297+
relative_file(db, arg_id.into(), &path).ok_or_else(|| mbe::ExpandError::ConversionError)?;
298+
299+
// FIXME:
300+
// Handle include as expression
301+
let node =
302+
db.parse_or_expand(file_id.into()).ok_or_else(|| mbe::ExpandError::ConversionError)?;
303+
let res =
304+
mbe::syntax_node_to_token_tree(&node).ok_or_else(|| mbe::ExpandError::ConversionError)?.0;
305+
306+
Ok((res, FragmentKind::Items))
307+
}
308+
269309
#[cfg(test)]
270310
mod tests {
271311
use super::*;

crates/ra_hir_expand/src/eager.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,24 +42,26 @@ pub fn expand_eager_macro(
4242
// When `lazy_expand` is called, its *parent* file must be already exists.
4343
// Here we store an eager macro id for the argument expanded subtree here
4444
// for that purpose.
45-
let arg_id: MacroCallId = db
46-
.intern_eager_expansion({
47-
EagerCallLoc {
48-
def,
49-
fragment: FragmentKind::Expr,
50-
subtree: Arc::new(parsed_args.clone()),
51-
file_id: macro_call.file_id,
52-
}
53-
})
54-
.into();
45+
let arg_id = db.intern_eager_expansion({
46+
EagerCallLoc {
47+
def,
48+
fragment: FragmentKind::Expr,
49+
subtree: Arc::new(parsed_args.clone()),
50+
file_id: macro_call.file_id,
51+
}
52+
});
53+
let arg_file_id: MacroCallId = arg_id.into();
5554

5655
let parsed_args = mbe::token_tree_to_syntax_node(&parsed_args, FragmentKind::Expr).ok()?.0;
57-
let result =
58-
eager_macro_recur(db, InFile::new(arg_id.as_file(), parsed_args.syntax_node()), resolver)?;
56+
let result = eager_macro_recur(
57+
db,
58+
InFile::new(arg_file_id.as_file(), parsed_args.syntax_node()),
59+
resolver,
60+
)?;
5961
let subtree = to_subtree(&result)?;
6062

6163
if let MacroDefKind::BuiltInEager(eager) = def.kind {
62-
let (subtree, fragment) = eager.expand(&subtree).ok()?;
64+
let (subtree, fragment) = eager.expand(db, arg_id, &subtree).ok()?;
6365
let eager =
6466
EagerCallLoc { def, fragment, subtree: Arc::new(subtree), file_id: macro_call.file_id };
6567

crates/ra_hir_expand/src/name.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ pub mod known {
174174
line,
175175
stringify,
176176
concat,
177+
include,
177178
format_args,
178179
format_args_nl,
179180
env,

crates/ra_hir_ty/src/tests/macros.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,51 @@ fn main() {
438438
);
439439
}
440440

441+
#[test]
442+
fn infer_builtin_macros_include() {
443+
let (db, pos) = TestDB::with_position(
444+
r#"
445+
//- /main.rs
446+
#[rustc_builtin_macro]
447+
macro_rules! include {() => {}}
448+
449+
include!("foo.rs");
450+
451+
fn main() {
452+
bar()<|>;
453+
}
454+
455+
//- /foo.rs
456+
fn bar() -> u32 {0}
457+
"#,
458+
);
459+
assert_eq!("u32", type_at_pos(&db, pos));
460+
}
461+
462+
#[test]
463+
fn infer_builtin_macros_include_concat() {
464+
let (db, pos) = TestDB::with_position(
465+
r#"
466+
//- /main.rs
467+
#[rustc_builtin_macro]
468+
macro_rules! include {() => {}}
469+
470+
#[rustc_builtin_macro]
471+
macro_rules! concat {() => {}}
472+
473+
include!(concat!("f", "oo.rs"));
474+
475+
fn main() {
476+
bar()<|>;
477+
}
478+
479+
//- /foo.rs
480+
fn bar() -> u32 {0}
481+
"#,
482+
);
483+
assert_eq!("u32", type_at_pos(&db, pos));
484+
}
485+
441486
#[test]
442487
fn infer_builtin_macros_concat_with_lazy() {
443488
assert_snapshot!(

0 commit comments

Comments
 (0)