Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-expand/src/eager.rs')
| -rw-r--r-- | crates/hir-expand/src/eager.rs | 84 |
1 files changed, 47 insertions, 37 deletions
diff --git a/crates/hir-expand/src/eager.rs b/crates/hir-expand/src/eager.rs index 59a92ff0ab..7ee3fd375f 100644 --- a/crates/hir-expand/src/eager.rs +++ b/crates/hir-expand/src/eager.rs @@ -31,22 +31,24 @@ use crate::{ MacroCallLoc, MacroDefId, MacroDefKind, UnresolvedMacro, }; -pub fn expand_eager_macro( +pub fn expand_eager_macro_input( db: &dyn ExpandDatabase, krate: CrateId, macro_call: InFile<ast::MacroCall>, def: MacroDefId, resolver: &dyn Fn(ModPath) -> Option<MacroDefId>, ) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro> { - let MacroDefKind::BuiltInEager(eager, _) = def.kind else { - panic!("called `expand_eager_macro` on non-eager macro def {def:?}") + assert!(matches!(def.kind, MacroDefKind::BuiltInEager(..))); + let token_tree = macro_call.value.token_tree(); + + let Some(token_tree) = token_tree else { + return Ok(ExpandResult { value: None, err: + Some(ExpandError::other( + "invalid token tree" + )), + }); }; - let hygiene = Hygiene::new(db, macro_call.file_id); - let parsed_args = macro_call - .value - .token_tree() - .map(|tt| mbe::syntax_node_to_token_tree(tt.syntax()).0) - .unwrap_or_else(tt::Subtree::empty); + let (parsed_args, arg_token_map) = mbe::syntax_node_to_token_tree(token_tree.syntax()); let ast_map = db.ast_id_map(macro_call.file_id); let call_id = InFile::new(macro_call.file_id, ast_map.ast_id(¯o_call.value)); @@ -60,41 +62,40 @@ pub fn expand_eager_macro( def, krate, eager: Some(Box::new(EagerCallInfo { - arg_or_expansion: Arc::new(parsed_args.clone()), - included_file: None, + arg: Arc::new((parsed_args, arg_token_map)), + arg_id: None, error: None, })), kind: MacroCallKind::FnLike { ast_id: call_id, expand_to: ExpandTo::Expr }, }); - - let parsed_args = mbe::token_tree_to_syntax_node(&parsed_args, mbe::TopEntryPoint::Expr).0; - let ExpandResult { value, mut err } = eager_macro_recur( + let arg_as_expr = match db.macro_arg_text(arg_id) { + Some(it) => it, + None => { + return Ok(ExpandResult { + value: None, + err: Some(ExpandError::other("invalid token tree")), + }) + } + }; + let ExpandResult { value: expanded_eager_input, err } = eager_macro_recur( db, - &hygiene, - InFile::new(arg_id.as_file(), parsed_args.syntax_node()), + &Hygiene::new(db, macro_call.file_id), + InFile::new(arg_id.as_file(), SyntaxNode::new_root(arg_as_expr)), krate, resolver, )?; - let Some(value ) = value else { + let Some(expanded_eager_input) = expanded_eager_input else { return Ok(ExpandResult { value: None, err }) }; - let subtree = { - let mut subtree = mbe::syntax_node_to_token_tree(&value).0; - subtree.delimiter = crate::tt::Delimiter::unspecified(); - subtree - }; - - let res = eager.expand(db, arg_id, &subtree); - if err.is_none() { - err = res.err; - } + let (mut subtree, token_map) = mbe::syntax_node_to_token_tree(&expanded_eager_input); + subtree.delimiter = crate::tt::Delimiter::unspecified(); let loc = MacroCallLoc { def, krate, eager: Some(Box::new(EagerCallInfo { - arg_or_expansion: Arc::new(res.value.subtree), - included_file: res.value.included_file, + arg: Arc::new((subtree, token_map)), + arg_id: Some(arg_id), error: err.clone(), })), kind: MacroCallKind::FnLike { ast_id: call_id, expand_to }, @@ -118,8 +119,9 @@ fn lazy_expand( MacroCallKind::FnLike { ast_id: macro_call.with_value(ast_id), expand_to }, ); - let file_id = id.as_file(); - db.parse_or_expand_with_err(file_id).map(|parse| InFile::new(file_id, parse)) + let macro_file = id.as_macro_file(); + + db.parse_macro_expansion(macro_file).map(|parse| InFile::new(macro_file.into(), parse.0)) } fn eager_macro_recur( @@ -142,13 +144,13 @@ fn eager_macro_recur( let def = match child.path().and_then(|path| ModPath::from_src(db, path, hygiene)) { Some(path) => macro_resolver(path.clone()).ok_or(UnresolvedMacro { path })?, None => { - error = Some(ExpandError::Other("malformed macro invocation".into())); + error = Some(ExpandError::other("malformed macro invocation")); continue; } }; let ExpandResult { value, err } = match def.kind { MacroDefKind::BuiltInEager(..) => { - let id = match expand_eager_macro( + let ExpandResult { value, err } = match expand_eager_macro_input( db, krate, curr.with_value(child.clone()), @@ -158,9 +160,17 @@ fn eager_macro_recur( Ok(it) => it, Err(err) => return Err(err), }; - id.map(|call| { - call.map(|call| db.parse_or_expand(call.as_file()).clone_for_update()) - }) + match value { + Some(call) => { + let ExpandResult { value, err: err2 } = + db.parse_macro_expansion(call.as_macro_file()); + ExpandResult { + value: Some(value.0.syntax_node().clone_for_update()), + err: err.or(err2), + } + } + None => ExpandResult { value: None, err }, + } } MacroDefKind::Declarative(_) | MacroDefKind::BuiltIn(..) @@ -180,7 +190,7 @@ fn eager_macro_recur( krate, macro_resolver, )?; - let err = if err.is_none() { error } else { err }; + let err = err.or(error); ExpandResult { value, err } } }; |