mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-13 21:54:42 +00:00
Move hypothetical expansion to hir_expand
This commit is contained in:
parent
f617455d10
commit
afdf08e964
4 changed files with 43 additions and 39 deletions
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
¯o_call_with_fake_ident,
|
||||
&hypothetical_args,
|
||||
fake_ident_token,
|
||||
),
|
||||
) {
|
||||
|
|
Loading…
Reference in a new issue