Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-expand/src/db.rs')
| -rw-r--r-- | crates/hir-expand/src/db.rs | 189 |
1 files changed, 3 insertions, 186 deletions
diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs index b5f5785a54..5c9520d397 100644 --- a/crates/hir-expand/src/db.rs +++ b/crates/hir-expand/src/db.rs @@ -2,20 +2,12 @@ use base_db::{Crate, SourceDatabase}; use span::Span; -use syntax::{AstNode, SyntaxNode, SyntaxToken, ast}; -use syntax_bridge::{DocCommentDesugarMode, syntax_node_to_token_tree}; +use syntax::ast; use crate::{ AstId, BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerExpander, - EditionedFileId, FileRange, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, - builtin::pseudo_derive_attr_expansion, - cfg_process::attr_macro_input_to_token_tree, - declarative::DeclarativeMacroExpander, - fixup::{self, SyntaxFixupUndoInfo}, - hygiene::{span_with_call_site_ctxt, span_with_def_site_ctxt, span_with_mixed_site_ctxt}, - proc_macro::CustomProcMacroExpander, - span_map::{RealSpanMap, SpanMap}, - tt, + EditionedFileId, FileRange, HirFileId, MacroDefId, MacroDefKind, + declarative::DeclarativeMacroExpander, proc_macro::CustomProcMacroExpander, }; #[derive(Debug, Clone, Copy, Eq, PartialEq)] @@ -62,181 +54,6 @@ fn resolve_span(db: &dyn ExpandDatabase, Span { range, anchor, ctx: _ }: Span) - FileRange { file_id, range: range + anchor_offset } } -/// This expands the given macro call, but with different arguments. This is -/// used for completion, where we want to see what 'would happen' if we insert a -/// token. The `token_to_map` mapped down into the expansion, with the mapped -/// token(s) returned with their priority. -pub fn expand_speculative( - db: &dyn ExpandDatabase, - actual_macro_call: MacroCallId, - speculative_args: &SyntaxNode, - token_to_map: SyntaxToken, -) -> Option<(SyntaxNode, Vec<(SyntaxToken, u8)>)> { - let loc = actual_macro_call.loc(db); - let (_, _, span) = *actual_macro_call.macro_arg_considering_derives(db, &loc.kind); - - let span_map = RealSpanMap::absolute(span.anchor.file_id); - let span_map = SpanMap::RealSpanMap(&span_map); - - // Build the subtree and token mapping for the speculative args - let (mut tt, undo_info) = match &loc.kind { - MacroCallKind::FnLike { .. } => ( - syntax_bridge::syntax_node_to_token_tree( - speculative_args, - span_map, - span, - if loc.def.is_proc_macro() { - DocCommentDesugarMode::ProcMacro - } else { - DocCommentDesugarMode::Mbe - }, - ), - SyntaxFixupUndoInfo::NONE, - ), - MacroCallKind::Attr { .. } if loc.def.is_attribute_derive() => ( - syntax_bridge::syntax_node_to_token_tree( - speculative_args, - span_map, - span, - DocCommentDesugarMode::ProcMacro, - ), - SyntaxFixupUndoInfo::NONE, - ), - MacroCallKind::Derive { derive_macro_id, .. } => { - let MacroCallKind::Attr { censored_attr_ids: attr_ids, .. } = - &derive_macro_id.loc(db).kind - else { - unreachable!("`derive_macro_id` should be `MacroCallKind::Attr`"); - }; - attr_macro_input_to_token_tree( - db, - speculative_args, - span_map, - span, - true, - attr_ids, - loc.krate, - ) - } - MacroCallKind::Attr { censored_attr_ids: attr_ids, .. } => attr_macro_input_to_token_tree( - db, - speculative_args, - span_map, - span, - false, - attr_ids, - loc.krate, - ), - }; - - let attr_arg = match &loc.kind { - MacroCallKind::Attr { censored_attr_ids: attr_ids, .. } => { - if loc.def.is_attribute_derive() { - // for pseudo-derive expansion we actually pass the attribute itself only - ast::Attr::cast(speculative_args.clone()) - .and_then(|attr| { - if let ast::Meta::TokenTreeMeta(meta) = attr.meta()? { - meta.token_tree() - } else { - None - } - }) - .map(|token_tree| { - let mut tree = syntax_node_to_token_tree( - token_tree.syntax(), - span_map, - span, - DocCommentDesugarMode::ProcMacro, - ); - tree.set_top_subtree_delimiter_kind(tt::DelimiterKind::Invisible); - tree.set_top_subtree_delimiter_span(tt::DelimSpan::from_single(span)); - tree - }) - } else { - // Attributes may have an input token tree, build the subtree and map for this as well - // then try finding a token id for our token if it is inside this input subtree. - let item = ast::Item::cast(speculative_args.clone())?; - let (_, meta) = - attr_ids.invoc_attr().find_attr_range_with_source_opt(db, loc.krate, &item)?; - if let ast::Meta::TokenTreeMeta(meta) = meta - && let Some(tt) = meta.token_tree() - { - let mut attr_arg = syntax_bridge::syntax_node_to_token_tree( - tt.syntax(), - span_map, - span, - DocCommentDesugarMode::ProcMacro, - ); - attr_arg.set_top_subtree_delimiter_kind(tt::DelimiterKind::Invisible); - Some(attr_arg) - } else { - None - } - } - } - _ => None, - }; - - // Do the actual expansion, we need to directly expand the proc macro due to the attribute args - // Otherwise the expand query will fetch the non speculative attribute args and pass those instead. - let mut speculative_expansion = match loc.def.kind { - MacroDefKind::ProcMacro(ast, expander, _) => { - let span = crate::proc_macro_span(db, ast); - tt.set_top_subtree_delimiter_kind(tt::DelimiterKind::Invisible); - tt.set_top_subtree_delimiter_span(tt::DelimSpan::from_single(span)); - expander.expand( - db, - loc.def.krate, - loc.krate, - &tt, - attr_arg.as_ref(), - span_with_def_site_ctxt(db, span, actual_macro_call.into(), loc.def.edition), - span_with_call_site_ctxt(db, span, actual_macro_call.into(), loc.def.edition), - span_with_mixed_site_ctxt(db, span, actual_macro_call.into(), loc.def.edition), - ) - } - MacroDefKind::BuiltInAttr(_, it) if it.is_derive() => { - pseudo_derive_attr_expansion(&tt, attr_arg.as_ref()?, span) - } - MacroDefKind::Declarative(it, _) => db - .decl_macro_expander(loc.krate, it) - .expand_unhygienic(db, &tt, loc.kind.call_style(), span), - MacroDefKind::BuiltIn(_, it) => { - it.expand(db, actual_macro_call, &tt, span).map_err(Into::into) - } - MacroDefKind::BuiltInDerive(_, it) => { - it.expand(db, actual_macro_call, &tt, span).map_err(Into::into) - } - MacroDefKind::BuiltInEager(_, it) => { - it.expand(db, actual_macro_call, &tt, span).map_err(Into::into) - } - MacroDefKind::BuiltInAttr(_, it) => it.expand(db, actual_macro_call, &tt, span), - MacroDefKind::UnimplementedBuiltIn(_) => crate::expand_unimplemented_builtin_macro(span), - }; - - let expand_to = loc.expand_to(); - - fixup::reverse_fixups(&mut speculative_expansion.value, &undo_info); - let (node, rev_tmap) = - crate::token_tree_to_syntax_node(db, &speculative_expansion.value, expand_to); - - let syntax_node = node.syntax_node(); - let token = rev_tmap - .ranges_with_span(span_map.span_for_range(token_to_map.text_range())) - .filter_map(|(range, ctx)| syntax_node.covering_element(range).into_token().zip(Some(ctx))) - .map(|(t, ctx)| { - // prefer tokens of the same kind and text, as well as non opaque marked ones - // Note the inversion of the score here, as we want to prefer the first token in case - // of all tokens having the same score - let ranking = ctx.is_opaque(db) as u8 - + 2 * (t.kind() != token_to_map.kind()) as u8 - + 4 * ((t.text() != token_to_map.text()) as u8); - (t, ranking) - }) - .collect(); - Some((node.syntax_node(), token)) -} - impl<'db> TokenExpander<'db> { fn macro_expander(db: &'db dyn ExpandDatabase, id: MacroDefId) -> TokenExpander<'db> { match id.kind { |