Move hypothetical expansion to hir_expand

This commit is contained in:
Florian Diebold 2020-03-08 11:02:14 +01:00
parent f617455d10
commit afdf08e964
4 changed files with 43 additions and 39 deletions

View file

@ -12,8 +12,7 @@ use hir_expand::ExpansionInfo;
use ra_db::{FileId, FileRange};
use ra_prof::profile;
use ra_syntax::{
algo::{self, skip_trivia_token},
ast, AstNode, Direction, SyntaxNode, SyntaxToken, TextRange, TextUnit,
algo::skip_trivia_token, ast, AstNode, Direction, SyntaxNode, SyntaxToken, TextRange, TextUnit,
};
use rustc_hash::{FxHashMap, FxHashSet};
@ -74,7 +73,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
pub fn expand_hypothetical(
&self,
actual_macro_call: &ast::MacroCall,
hypothetical_call: &ast::MacroCall,
hypothetical_args: &ast::TokenTree,
token_to_map: SyntaxToken,
) -> Option<(SyntaxNode, SyntaxToken)> {
let macro_call =
@ -82,24 +81,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
let sa = self.analyze2(macro_call.map(|it| it.syntax()), None);
let macro_call_id = macro_call
.as_call_id(self.db, |path| sa.resolver.resolve_path_as_macro(self.db, &path))?;
let macro_file = macro_call_id.as_file().macro_file().unwrap();
let (tt, tmap_1) =
hir_expand::syntax_node_to_token_tree(hypothetical_call.token_tree().unwrap().syntax())
.unwrap();
let range = token_to_map
.text_range()
.checked_sub(hypothetical_call.token_tree().unwrap().syntax().text_range().start())?;
let token_id = tmap_1.token_by_range(range)?;
let macro_def = hir_expand::db::expander(self.db, macro_call_id)?;
let (node, tmap_2) = hir_expand::db::parse_macro_with_arg(
self.db,
macro_file,
Some(std::sync::Arc::new((tt, tmap_1))),
)?;
let token_id = macro_def.0.map_id_down(token_id);
let range = tmap_2.range_by_token(token_id)?.by_kind(token_to_map.kind())?;
let token = algo::find_covering_element(&node.syntax_node(), range).into_token()?;
Some((node.syntax_node(), token))
hir_expand::db::expand_hypothetical(self.db, macro_call_id, hypothetical_args, token_to_map)
}
pub fn descend_into_macros(&self, token: SyntaxToken) -> SyntaxToken {

View file

@ -72,6 +72,30 @@ pub trait AstDatabase: SourceDatabase {
fn intern_eager_expansion(&self, eager: EagerCallLoc) -> EagerMacroId;
}
/// 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 returned.
pub fn expand_hypothetical(
db: &impl AstDatabase,
actual_macro_call: MacroCallId,
hypothetical_args: &ra_syntax::ast::TokenTree,
token_to_map: ra_syntax::SyntaxToken,
) -> Option<(SyntaxNode, ra_syntax::SyntaxToken)> {
let macro_file = MacroFile { macro_call_id: actual_macro_call };
let (tt, tmap_1) = mbe::syntax_node_to_token_tree(hypothetical_args.syntax()).unwrap();
let range =
token_to_map.text_range().checked_sub(hypothetical_args.syntax().text_range().start())?;
let token_id = tmap_1.token_by_range(range)?;
let macro_def = expander(db, actual_macro_call)?;
let (node, tmap_2) =
parse_macro_with_arg(db, macro_file, Some(std::sync::Arc::new((tt, tmap_1))))?;
let token_id = macro_def.0.map_id_down(token_id);
let range = tmap_2.range_by_token(token_id)?.by_kind(token_to_map.kind())?;
let token = ra_syntax::algo::find_covering_element(&node.syntax_node(), range).into_token()?;
Some((node.syntax_node(), token))
}
pub(crate) fn ast_id_map(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<AstIdMap> {
let map =
db.parse_or_expand(file_id).map_or_else(AstIdMap::default, |it| AstIdMap::from_source(&it));
@ -133,10 +157,7 @@ pub(crate) fn macro_expand(
macro_expand_with_arg(db, id, None)
}
pub fn expander(
db: &dyn AstDatabase,
id: MacroCallId,
) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> {
fn expander(db: &dyn AstDatabase, id: MacroCallId) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> {
let lazy_id = match id {
MacroCallId::LazyMacro(id) => id,
MacroCallId::EagerMacro(_id) => {
@ -149,7 +170,7 @@ pub fn expander(
Some(macro_rules)
}
pub(crate) fn macro_expand_with_arg(
fn macro_expand_with_arg(
db: &dyn AstDatabase,
id: MacroCallId,
arg: Option<Arc<(tt::Subtree, mbe::TokenMap)>>,
@ -158,7 +179,9 @@ pub(crate) fn macro_expand_with_arg(
MacroCallId::LazyMacro(id) => id,
MacroCallId::EagerMacro(id) => {
if arg.is_some() {
return Err("hypothetical macro expansion not implemented for eager macro".to_owned());
return Err(
"hypothetical macro expansion not implemented for eager macro".to_owned()
);
} else {
return Ok(db.lookup_intern_eager_expansion(id).subtree);
}
@ -225,13 +248,15 @@ pub fn parse_macro_with_arg(
.collect::<Vec<_>>()
.join("\n");
eprintln!(
log::warn!(
"fail on macro_parse: (reason: {} macro_call: {:#}) parents: {}",
err, node.value, parents
err,
node.value,
parents
);
}
_ => {
eprintln!("fail on macro_parse: (reason: {})", err);
log::warn!("fail on macro_parse: (reason: {})", err);
}
}
})

View file

@ -157,13 +157,6 @@ impl HirFileId {
}
}
}
pub fn macro_file(self) -> Option<MacroFile> {
match self.0 {
HirFileIdRepr::FileId(_) => None,
HirFileIdRepr::MacroFile(m) => Some(m),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@ -303,7 +296,7 @@ pub struct ExpansionInfo {
exp_map: Arc<mbe::TokenMap>,
}
pub use mbe::{syntax_node_to_token_tree, Origin};
pub use mbe::Origin;
use ra_parser::FragmentKind;
impl ExpansionInfo {

View file

@ -119,11 +119,15 @@ impl<'a> CompletionContext<'a> {
{
break;
}
let hypothetical_args = match macro_call_with_fake_ident.token_tree() {
Some(tt) => tt,
None => break,
};
if let (Some(actual_expansion), Some(hypothetical_expansion)) = (
ctx.sema.expand(&actual_macro_call),
ctx.sema.expand_hypothetical(
&actual_macro_call,
&macro_call_with_fake_ident,
&hypothetical_args,
fake_ident_token,
),
) {