mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-14 06:03:58 +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_db::{FileId, FileRange};
|
||||||
use ra_prof::profile;
|
use ra_prof::profile;
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
algo::{self, skip_trivia_token},
|
algo::skip_trivia_token, ast, AstNode, Direction, SyntaxNode, SyntaxToken, TextRange, TextUnit,
|
||||||
ast, AstNode, Direction, SyntaxNode, SyntaxToken, TextRange, TextUnit,
|
|
||||||
};
|
};
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
|
|
||||||
|
@ -74,7 +73,7 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
|
||||||
pub fn expand_hypothetical(
|
pub fn expand_hypothetical(
|
||||||
&self,
|
&self,
|
||||||
actual_macro_call: &ast::MacroCall,
|
actual_macro_call: &ast::MacroCall,
|
||||||
hypothetical_call: &ast::MacroCall,
|
hypothetical_args: &ast::TokenTree,
|
||||||
token_to_map: SyntaxToken,
|
token_to_map: SyntaxToken,
|
||||||
) -> Option<(SyntaxNode, SyntaxToken)> {
|
) -> Option<(SyntaxNode, SyntaxToken)> {
|
||||||
let macro_call =
|
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 sa = self.analyze2(macro_call.map(|it| it.syntax()), None);
|
||||||
let macro_call_id = macro_call
|
let macro_call_id = macro_call
|
||||||
.as_call_id(self.db, |path| sa.resolver.resolve_path_as_macro(self.db, &path))?;
|
.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();
|
hir_expand::db::expand_hypothetical(self.db, macro_call_id, hypothetical_args, token_to_map)
|
||||||
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))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn descend_into_macros(&self, token: SyntaxToken) -> SyntaxToken {
|
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;
|
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> {
|
pub(crate) fn ast_id_map(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<AstIdMap> {
|
||||||
let map =
|
let map =
|
||||||
db.parse_or_expand(file_id).map_or_else(AstIdMap::default, |it| AstIdMap::from_source(&it));
|
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)
|
macro_expand_with_arg(db, id, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn expander(
|
fn expander(db: &dyn AstDatabase, id: MacroCallId) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> {
|
||||||
db: &dyn AstDatabase,
|
|
||||||
id: MacroCallId,
|
|
||||||
) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> {
|
|
||||||
let lazy_id = match id {
|
let lazy_id = match id {
|
||||||
MacroCallId::LazyMacro(id) => id,
|
MacroCallId::LazyMacro(id) => id,
|
||||||
MacroCallId::EagerMacro(_id) => {
|
MacroCallId::EagerMacro(_id) => {
|
||||||
|
@ -149,7 +170,7 @@ pub fn expander(
|
||||||
Some(macro_rules)
|
Some(macro_rules)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn macro_expand_with_arg(
|
fn macro_expand_with_arg(
|
||||||
db: &dyn AstDatabase,
|
db: &dyn AstDatabase,
|
||||||
id: MacroCallId,
|
id: MacroCallId,
|
||||||
arg: Option<Arc<(tt::Subtree, mbe::TokenMap)>>,
|
arg: Option<Arc<(tt::Subtree, mbe::TokenMap)>>,
|
||||||
|
@ -158,7 +179,9 @@ pub(crate) fn macro_expand_with_arg(
|
||||||
MacroCallId::LazyMacro(id) => id,
|
MacroCallId::LazyMacro(id) => id,
|
||||||
MacroCallId::EagerMacro(id) => {
|
MacroCallId::EagerMacro(id) => {
|
||||||
if arg.is_some() {
|
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 {
|
} else {
|
||||||
return Ok(db.lookup_intern_eager_expansion(id).subtree);
|
return Ok(db.lookup_intern_eager_expansion(id).subtree);
|
||||||
}
|
}
|
||||||
|
@ -225,13 +248,15 @@ pub fn parse_macro_with_arg(
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join("\n");
|
.join("\n");
|
||||||
|
|
||||||
eprintln!(
|
log::warn!(
|
||||||
"fail on macro_parse: (reason: {} macro_call: {:#}) parents: {}",
|
"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)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
@ -303,7 +296,7 @@ pub struct ExpansionInfo {
|
||||||
exp_map: Arc<mbe::TokenMap>,
|
exp_map: Arc<mbe::TokenMap>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use mbe::{syntax_node_to_token_tree, Origin};
|
pub use mbe::Origin;
|
||||||
use ra_parser::FragmentKind;
|
use ra_parser::FragmentKind;
|
||||||
|
|
||||||
impl ExpansionInfo {
|
impl ExpansionInfo {
|
||||||
|
|
|
@ -119,11 +119,15 @@ impl<'a> CompletionContext<'a> {
|
||||||
{
|
{
|
||||||
break;
|
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)) = (
|
if let (Some(actual_expansion), Some(hypothetical_expansion)) = (
|
||||||
ctx.sema.expand(&actual_macro_call),
|
ctx.sema.expand(&actual_macro_call),
|
||||||
ctx.sema.expand_hypothetical(
|
ctx.sema.expand_hypothetical(
|
||||||
&actual_macro_call,
|
&actual_macro_call,
|
||||||
¯o_call_with_fake_ident,
|
&hypothetical_args,
|
||||||
fake_ident_token,
|
fake_ident_token,
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
|
|
Loading…
Reference in a new issue