Skip to content

Commit

Permalink
use the included file as the source of expanded include macro
Browse files Browse the repository at this point in the history
Signed-off-by: Yilin Chen <[email protected]>
  • Loading branch information
sticnarf committed Mar 21, 2021
1 parent a0ed87f commit 3bb9efb
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 28 deletions.
10 changes: 8 additions & 2 deletions crates/hir_def/src/nameres/mod_resolution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ impl ModDir {
name: &Name,
attr_path: Option<&SmolStr>,
) -> Result<(FileId, bool, ModDir), String> {
let is_include_macro = file_id.is_include_macro(db.upcast());
let file_id = file_id.original_file(db.upcast());

let mut candidate_files = Vec::new();
Expand All @@ -70,8 +71,13 @@ impl ModDir {
candidate_files.push(self.dir_path.join_attr(attr_path, self.root_non_dir_owner))
}
None => {
candidate_files.push(format!("{}{}.rs", self.dir_path.0, name));
candidate_files.push(format!("{}{}/mod.rs", self.dir_path.0, name));
if is_include_macro {
candidate_files.push(format!("{}.rs", name));
candidate_files.push(format!("{}/mod.rs", name));
} else {
candidate_files.push(format!("{}{}.rs", self.dir_path.0, name));
candidate_files.push(format!("{}{}/mod.rs", self.dir_path.0, name));
}
}
};

Expand Down
66 changes: 44 additions & 22 deletions crates/hir_expand/src/builtin_macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ macro_rules! register_builtin {
db: &dyn AstDatabase,
arg_id: EagerMacroId,
tt: &tt::Subtree,
) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
) -> ExpandResult<Option<ExpandedEager>> {
let expander = match *self {
$( EagerExpander::$e_kind => $e_expand, )*
};
Expand All @@ -61,6 +61,20 @@ macro_rules! register_builtin {
};
}

#[derive(Debug)]
pub struct ExpandedEager {
pub(crate) subtree: tt::Subtree,
pub(crate) fragment: FragmentKind,
/// The included file ID of the include macro.
pub(crate) included_file: Option<FileId>,
}

impl ExpandedEager {
fn new(subtree: tt::Subtree, fragment: FragmentKind) -> Self {
ExpandedEager { subtree, fragment, included_file: None }
}
}

pub fn find_builtin_macro(
ident: &name::Name,
krate: CrateId,
Expand Down Expand Up @@ -280,7 +294,7 @@ fn compile_error_expand(
_db: &dyn AstDatabase,
_id: EagerMacroId,
tt: &tt::Subtree,
) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
) -> ExpandResult<Option<ExpandedEager>> {
let err = match &*tt.token_trees {
[tt::TokenTree::Leaf(tt::Leaf::Literal(it))] => {
let text = it.text.as_str();
Expand All @@ -294,14 +308,14 @@ fn compile_error_expand(
_ => mbe::ExpandError::BindingError("`compile_error!` argument must be a string".into()),
};

ExpandResult { value: Some((quote! {}, FragmentKind::Items)), err: Some(err) }
ExpandResult { value: Some(ExpandedEager::new(quote! {}, FragmentKind::Items)), err: Some(err) }
}

fn concat_expand(
_db: &dyn AstDatabase,
_arg_id: EagerMacroId,
tt: &tt::Subtree,
) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
) -> ExpandResult<Option<ExpandedEager>> {
let mut err = None;
let mut text = String::new();
for (i, t) in tt.token_trees.iter().enumerate() {
Expand All @@ -325,7 +339,7 @@ fn concat_expand(
}
}
}
ExpandResult { value: Some((quote!(#text), FragmentKind::Expr)), err }
ExpandResult { value: Some(ExpandedEager::new(quote!(#text), FragmentKind::Expr)), err }
}

fn relative_file(
Expand Down Expand Up @@ -361,21 +375,27 @@ fn include_expand(
db: &dyn AstDatabase,
arg_id: EagerMacroId,
tt: &tt::Subtree,
) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
) -> ExpandResult<Option<ExpandedEager>> {
let res = (|| {
let path = parse_string(tt)?;
let file_id = relative_file(db, arg_id.into(), &path, false)?;

Ok(parse_to_token_tree(&db.file_text(file_id))
let subtree = parse_to_token_tree(&db.file_text(file_id))
.ok_or_else(|| mbe::ExpandError::ConversionError)?
.0)
.0;
Ok((subtree, file_id))
})();

match res {
Ok(res) => {
Ok((subtree, file_id)) => {
// FIXME:
// Handle include as expression
ExpandResult::ok(Some((res, FragmentKind::Items)))

ExpandResult::ok(Some(ExpandedEager {
subtree,
fragment: FragmentKind::Items,
included_file: Some(file_id),
}))
}
Err(e) => ExpandResult::only_err(e),
}
Expand All @@ -385,7 +405,7 @@ fn include_bytes_expand(
_db: &dyn AstDatabase,
_arg_id: EagerMacroId,
tt: &tt::Subtree,
) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
) -> ExpandResult<Option<ExpandedEager>> {
if let Err(e) = parse_string(tt) {
return ExpandResult::only_err(e);
}
Expand All @@ -398,14 +418,14 @@ fn include_bytes_expand(
id: tt::TokenId::unspecified(),
}))],
};
ExpandResult::ok(Some((res, FragmentKind::Expr)))
ExpandResult::ok(Some(ExpandedEager::new(res, FragmentKind::Expr)))
}

fn include_str_expand(
db: &dyn AstDatabase,
arg_id: EagerMacroId,
tt: &tt::Subtree,
) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
) -> ExpandResult<Option<ExpandedEager>> {
let path = match parse_string(tt) {
Ok(it) => it,
Err(e) => return ExpandResult::only_err(e),
Expand All @@ -418,14 +438,14 @@ fn include_str_expand(
let file_id = match relative_file(db, arg_id.into(), &path, true) {
Ok(file_id) => file_id,
Err(_) => {
return ExpandResult::ok(Some((quote!(""), FragmentKind::Expr)));
return ExpandResult::ok(Some(ExpandedEager::new(quote!(""), FragmentKind::Expr)));
}
};

let text = db.file_text(file_id);
let text = &*text;

ExpandResult::ok(Some((quote!(#text), FragmentKind::Expr)))
ExpandResult::ok(Some(ExpandedEager::new(quote!(#text), FragmentKind::Expr)))
}

fn get_env_inner(db: &dyn AstDatabase, arg_id: EagerMacroId, key: &str) -> Option<String> {
Expand All @@ -437,7 +457,7 @@ fn env_expand(
db: &dyn AstDatabase,
arg_id: EagerMacroId,
tt: &tt::Subtree,
) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
) -> ExpandResult<Option<ExpandedEager>> {
let key = match parse_string(tt) {
Ok(it) => it,
Err(e) => return ExpandResult::only_err(e),
Expand All @@ -461,14 +481,14 @@ fn env_expand(
});
let expanded = quote! { #s };

ExpandResult { value: Some((expanded, FragmentKind::Expr)), err }
ExpandResult { value: Some(ExpandedEager::new(expanded, FragmentKind::Expr)), err }
}

fn option_env_expand(
db: &dyn AstDatabase,
arg_id: EagerMacroId,
tt: &tt::Subtree,
) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
) -> ExpandResult<Option<ExpandedEager>> {
let key = match parse_string(tt) {
Ok(it) => it,
Err(e) => return ExpandResult::only_err(e),
Expand All @@ -479,7 +499,7 @@ fn option_env_expand(
Some(s) => quote! { std::option::Some(#s) },
};

ExpandResult::ok(Some((expanded, FragmentKind::Expr)))
ExpandResult::ok(Some(ExpandedEager::new(expanded, FragmentKind::Expr)))
}

#[cfg(test)]
Expand Down Expand Up @@ -553,16 +573,18 @@ mod tests {
subtree: Arc::new(parsed_args.clone()),
krate,
call: call_id,
included_file: None,
}
});

let (subtree, fragment) = expander.expand(&db, arg_id, &parsed_args).value.unwrap();
let expanded = expander.expand(&db, arg_id, &parsed_args).value.unwrap();
let eager = EagerCallLoc {
def,
fragment,
subtree: Arc::new(subtree),
fragment: expanded.fragment,
subtree: Arc::new(expanded.subtree),
krate,
call: call_id,
included_file: expanded.included_file,
};

let id: MacroCallId = db.intern_eager_expansion(eager).into();
Expand Down
13 changes: 10 additions & 3 deletions crates/hir_expand/src/eager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ pub fn expand_eager_macro(
subtree: Arc::new(parsed_args.clone()),
krate,
call: call_id,
included_file: None,
}
});
let arg_file_id: MacroCallId = arg_id.into();
Expand All @@ -143,9 +144,15 @@ pub fn expand_eager_macro(
if let MacroDefKind::BuiltInEager(eager, _) = def.kind {
let res = eager.expand(db, arg_id, &subtree);

let (subtree, fragment) = diagnostic_sink.expand_result_option(res)?;
let eager =
EagerCallLoc { def, fragment, subtree: Arc::new(subtree), krate, call: call_id };
let expanded = diagnostic_sink.expand_result_option(res)?;
let eager = EagerCallLoc {
def,
fragment: expanded.fragment,
subtree: Arc::new(expanded.subtree),
krate,
call: call_id,
included_file: expanded.included_file,
};

Ok(db.intern_eager_expansion(eager))
} else {
Expand Down
23 changes: 22 additions & 1 deletion crates/hir_expand/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,11 @@ impl HirFileId {
}
MacroCallId::EagerMacro(id) => {
let loc = db.lookup_intern_eager_expansion(id);
loc.call.file_id
if let Some(included_file) = loc.included_file {
return included_file;
} else {
loc.call.file_id
}
}
};
file_id.original_file(db)
Expand Down Expand Up @@ -188,6 +192,21 @@ impl HirFileId {
}
}
}

/// Return whether this file is an include macro
pub fn is_include_macro(&self, db: &dyn db::AstDatabase) -> bool {
match self.0 {
HirFileIdRepr::MacroFile(macro_file) => match macro_file.macro_call_id {
MacroCallId::EagerMacro(id) => {
let loc = db.lookup_intern_eager_expansion(id);
return loc.included_file.is_some();
}
_ => {}
},
_ => {}
}
false
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
Expand Down Expand Up @@ -315,6 +334,8 @@ pub struct EagerCallLoc {
pub(crate) subtree: Arc<tt::Subtree>,
pub(crate) krate: CrateId,
pub(crate) call: AstId<ast::MacroCall>,
// The included file ID of the include macro.
pub(crate) included_file: Option<FileId>,
}

/// ExpansionInfo mainly describes how to map text range between src and expanded macro
Expand Down
23 changes: 23 additions & 0 deletions crates/hir_ty/src/tests/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,29 @@ fn bar() -> u32 {0}
);
}

#[test]
fn infer_builtin_macros_include_child_mod() {
check_types(
r#"
//- /main.rs
#[rustc_builtin_macro]
macro_rules! include {() => {}}
include!("f/foo.rs");
fn main() {
bar::bar();
} //^ u32
//- /f/foo.rs
pub mod bar;
//- /f/bar.rs
pub fn bar() -> u32 {0}
"#,
);
}

#[test]
fn infer_builtin_macros_include_str() {
check_types(
Expand Down

0 comments on commit 3bb9efb

Please sign in to comment.