Refactor and simpfily

This commit is contained in:
Edwin Cheng 2019-11-09 04:00:27 +08:00
parent 62ed93db13
commit d01e0abdb5
5 changed files with 43 additions and 90 deletions

View file

@ -8,22 +8,10 @@ use ra_prof::profile;
use ra_syntax::{AstNode, Parse, SyntaxNode}; use ra_syntax::{AstNode, Parse, SyntaxNode};
use crate::{ use crate::{
ast_id_map::AstIdMap, ExpansionInfo, HirFileId, HirFileIdRepr, MacroCallId, MacroCallLoc, ast_id_map::AstIdMap, HirFileId, HirFileIdRepr, MacroCallId, MacroCallLoc, MacroDefId,
MacroDefId, MacroFile, MacroFileKind, MacroFile, MacroFileKind,
}; };
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct ParseMacroWithInfo {
pub parsed: Parse<SyntaxNode>,
pub expansion_info: Arc<ExpansionInfo>,
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct MacroExpandInfo {
pub arg_map: Arc<mbe::TokenMap>,
pub def_map: Arc<mbe::TokenMap>,
}
// FIXME: rename to ExpandDatabase // FIXME: rename to ExpandDatabase
#[salsa::query_group(AstDatabaseStorage)] #[salsa::query_group(AstDatabaseStorage)]
pub trait AstDatabase: SourceDatabase { pub trait AstDatabase: SourceDatabase {
@ -36,14 +24,11 @@ pub trait AstDatabase: SourceDatabase {
fn intern_macro(&self, macro_call: MacroCallLoc) -> MacroCallId; fn intern_macro(&self, macro_call: MacroCallLoc) -> MacroCallId;
fn macro_arg(&self, id: MacroCallId) -> Option<(Arc<tt::Subtree>, Arc<mbe::TokenMap>)>; fn macro_arg(&self, id: MacroCallId) -> Option<(Arc<tt::Subtree>, Arc<mbe::TokenMap>)>;
fn macro_def(&self, id: MacroDefId) -> Option<(Arc<mbe::MacroRules>, Arc<mbe::TokenMap>)>; fn macro_def(&self, id: MacroDefId) -> Option<(Arc<mbe::MacroRules>, Arc<mbe::TokenMap>)>;
fn parse_macro(&self, macro_file: MacroFile) -> Option<Parse<SyntaxNode>>; fn parse_macro(
fn parse_macro_with_info(&self, macro_file: MacroFile) -> Option<ParseMacroWithInfo>;
fn macro_expand(
&self, &self,
macro_call: MacroCallId, macro_file: MacroFile,
) -> Result<(Arc<tt::Subtree>, MacroExpandInfo), String>; ) -> Option<(Parse<SyntaxNode>, Arc<mbe::RevTokenMap>)>;
fn macro_expand(&self, macro_call: MacroCallId) -> Result<Arc<tt::Subtree>, String>;
fn macro_expansion_info(&self, macro_file: MacroFile) -> Option<Arc<ExpansionInfo>>;
} }
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> {
@ -83,7 +68,7 @@ pub(crate) fn macro_arg(
pub(crate) fn macro_expand( pub(crate) fn macro_expand(
db: &dyn AstDatabase, db: &dyn AstDatabase,
id: MacroCallId, id: MacroCallId,
) -> Result<(Arc<tt::Subtree>, MacroExpandInfo), String> { ) -> Result<Arc<tt::Subtree>, String> {
let loc = db.lookup_intern_macro(id); let loc = db.lookup_intern_macro(id);
let macro_arg = db.macro_arg(id).ok_or("Fail to args in to tt::TokenTree")?; let macro_arg = db.macro_arg(id).ok_or("Fail to args in to tt::TokenTree")?;
@ -94,18 +79,14 @@ pub(crate) fn macro_expand(
if count > 65536 { if count > 65536 {
return Err(format!("Total tokens count exceed limit : count = {}", count)); return Err(format!("Total tokens count exceed limit : count = {}", count));
} }
Ok(Arc::new(tt))
Ok((
Arc::new(tt),
MacroExpandInfo { arg_map: macro_arg.1.clone(), def_map: macro_rules.1.clone() },
))
} }
pub(crate) fn parse_or_expand(db: &dyn AstDatabase, file_id: HirFileId) -> Option<SyntaxNode> { pub(crate) fn parse_or_expand(db: &dyn AstDatabase, file_id: HirFileId) -> Option<SyntaxNode> {
match file_id.0 { match file_id.0 {
HirFileIdRepr::FileId(file_id) => Some(db.parse(file_id).tree().syntax().clone()), HirFileIdRepr::FileId(file_id) => Some(db.parse(file_id).tree().syntax().clone()),
HirFileIdRepr::MacroFile(macro_file) => { HirFileIdRepr::MacroFile(macro_file) => {
db.parse_macro(macro_file).map(|it| it.syntax_node()) db.parse_macro(macro_file).map(|(it, _)| it.syntax_node())
} }
} }
} }
@ -113,15 +94,9 @@ pub(crate) fn parse_or_expand(db: &dyn AstDatabase, file_id: HirFileId) -> Optio
pub(crate) fn parse_macro( pub(crate) fn parse_macro(
db: &dyn AstDatabase, db: &dyn AstDatabase,
macro_file: MacroFile, macro_file: MacroFile,
) -> Option<Parse<SyntaxNode>> { ) -> Option<(Parse<SyntaxNode>, Arc<mbe::RevTokenMap>)> {
let _p = profile("parse_macro_query"); let _p = profile("parse_macro_query");
db.parse_macro_with_info(macro_file).map(|r| r.parsed)
}
pub(crate) fn parse_macro_with_info(
db: &dyn AstDatabase,
macro_file: MacroFile,
) -> Option<ParseMacroWithInfo> {
let macro_call_id = macro_file.macro_call_id; let macro_call_id = macro_file.macro_call_id;
let tt = db let tt = db
.macro_expand(macro_call_id) .macro_expand(macro_call_id)
@ -133,39 +108,12 @@ pub(crate) fn parse_macro_with_info(
}) })
.ok()?; .ok()?;
let (parsed, exp_map) = match macro_file.macro_file_kind { match macro_file.macro_file_kind {
MacroFileKind::Items => { MacroFileKind::Items => {
mbe::token_tree_to_items(&tt.0).map(|(p, map)| (p.to_syntax(), map)).ok()? mbe::token_tree_to_items(&tt).ok().map(|(p, map)| (p.to_syntax(), Arc::new(map)))
} }
MacroFileKind::Expr => { MacroFileKind::Expr => {
mbe::token_tree_to_expr(&tt.0).map(|(p, map)| (p.to_syntax(), map)).ok()? mbe::token_tree_to_expr(&tt).ok().map(|(p, map)| (p.to_syntax(), Arc::new(map)))
} }
}; }
let expand_info = tt.1;
let loc: MacroCallLoc = db.lookup_intern_macro(macro_call_id);
let arg_tt = loc.ast_id.to_node(db).token_tree();
let def_tt = loc.def.ast_id.to_node(db).token_tree();
let arg_range = arg_tt.map(|t| t.syntax().text_range());
let def_range = def_tt.map(|t| t.syntax().text_range());
let shift = db.macro_def(loc.def)?.0.shift();
let arg_map =
arg_range.map(|it| exp_map.map_ranges(&expand_info.arg_map, it, shift)).unwrap_or_default();
let def_map =
def_range.map(|it| exp_map.map_ranges(&expand_info.def_map, it, 0)).unwrap_or_default();
let info = ExpansionInfo { arg_map, def_map };
Some(ParseMacroWithInfo { parsed, expansion_info: Arc::new(info) })
}
pub(crate) fn macro_expansion_info(
db: &dyn AstDatabase,
macro_file: MacroFile,
) -> Option<Arc<ExpansionInfo>> {
db.parse_macro_with_info(macro_file).map(|res| res.expansion_info.clone())
} }

View file

@ -20,7 +20,6 @@ use ra_syntax::{
}; };
use crate::ast_id_map::FileAstId; use crate::ast_id_map::FileAstId;
use std::sync::Arc;
/// Input to the analyzer is a set of files, where each file is identified by /// Input to the analyzer is a set of files, where each file is identified by
/// `FileId` and contains source code. However, another source of source code in /// `FileId` and contains source code. However, another source of source code in
@ -69,19 +68,29 @@ impl HirFileId {
} }
/// Return expansion information if it is a macro-expansion file /// Return expansion information if it is a macro-expansion file
pub fn parent_expansion( pub fn parent_expansion(self, db: &dyn db::AstDatabase) -> Option<ExpansionInfo> {
self,
db: &dyn db::AstDatabase,
) -> Option<((HirFileId, HirFileId), Arc<ExpansionInfo>)> {
match self.0 { match self.0 {
HirFileIdRepr::FileId(_) => None, HirFileIdRepr::FileId(_) => None,
HirFileIdRepr::MacroFile(macro_file) => { HirFileIdRepr::MacroFile(macro_file) => {
let loc: MacroCallLoc = db.lookup_intern_macro(macro_file.macro_call_id); let loc: MacroCallLoc = db.lookup_intern_macro(macro_file.macro_call_id);
let def_file = loc.def.ast_id.file_id; let arg_range = loc.ast_id.to_node(db).token_tree()?.syntax().text_range();
let arg_file = loc.ast_id.file_id; let def_range = loc.def.ast_id.to_node(db).token_tree()?.syntax().text_range();
db.macro_expansion_info(macro_file).map(|ex| ((arg_file, def_file), ex)) let macro_def = db.macro_def(loc.def)?;
let shift = macro_def.0.shift();
let rev_map = db.parse_macro(macro_file)?.1;
let arg_token_map = db.macro_arg(macro_file.macro_call_id)?.1;
let def_token_map = macro_def.1;
let arg_map = rev_map.map_ranges(&arg_token_map, arg_range, shift);
let def_map = rev_map.map_ranges(&def_token_map, def_range, 0);
let arg_file = loc.ast_id.file_id;
let def_file = loc.def.ast_id.file_id;
Some(ExpansionInfo { arg_file, def_file, arg_map, def_map })
} }
} }
} }
@ -134,25 +143,24 @@ impl MacroCallId {
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
/// ExpansionInfo mainly describes how to map text range between src and expanded macro /// ExpansionInfo mainly describes how to map text range between src and expanded macro
pub struct ExpansionInfo { pub struct ExpansionInfo {
pub arg_map: Vec<(TextRange, TextRange)>, pub(crate) arg_file: HirFileId,
pub def_map: Vec<(TextRange, TextRange)>, pub(crate) def_file: HirFileId,
pub(crate) arg_map: Vec<(TextRange, TextRange)>,
pub(crate) def_map: Vec<(TextRange, TextRange)>,
} }
impl ExpansionInfo { impl ExpansionInfo {
pub fn find_range( pub fn find_range(&self, from: TextRange) -> Option<(HirFileId, TextRange)> {
&self,
from: TextRange,
(arg_file_id, def_file_id): (HirFileId, HirFileId),
) -> Option<(HirFileId, TextRange)> {
for (src, dest) in &self.arg_map { for (src, dest) in &self.arg_map {
if src.is_subrange(&from) { if src.is_subrange(&from) {
return Some((arg_file_id, *dest)); return Some((self.arg_file, *dest));
} }
} }
for (src, dest) in &self.def_map { for (src, dest) in &self.def_map {
if src.is_subrange(&from) { if src.is_subrange(&from) {
return Some((def_file_id, *dest)); return Some((self.def_file, *dest));
} }
} }

View file

@ -37,7 +37,7 @@ fn find_range_from_node(
let text_range = node.text_range(); let text_range = node.text_range();
let (file_id, text_range) = src let (file_id, text_range) = src
.parent_expansion(db) .parent_expansion(db)
.and_then(|(files, expansion_info)| expansion_info.find_range(text_range, files)) .and_then(|expansion_info| expansion_info.find_range(text_range))
.unwrap_or((src, text_range)); .unwrap_or((src, text_range));
// FIXME: handle recursive macro generated macro // FIXME: handle recursive macro generated macro
@ -139,7 +139,6 @@ impl NavigationTarget {
pub(crate) fn from_module(db: &RootDatabase, module: hir::Module) -> NavigationTarget { pub(crate) fn from_module(db: &RootDatabase, module: hir::Module) -> NavigationTarget {
let src = module.definition_source(db); let src = module.definition_source(db);
let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default(); let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default();
match src.ast { match src.ast {
ModuleSource::SourceFile(node) => { ModuleSource::SourceFile(node) => {
let (file_id, text_range) = find_range_from_node(db, src.file_id, node.syntax()); let (file_id, text_range) = find_range_from_node(db, src.file_id, node.syntax());
@ -324,9 +323,7 @@ impl NavigationTarget {
) -> NavigationTarget { ) -> NavigationTarget {
//FIXME: use `_` instead of empty string //FIXME: use `_` instead of empty string
let name = node.name().map(|it| it.text().clone()).unwrap_or_default(); let name = node.name().map(|it| it.text().clone()).unwrap_or_default();
let focus_range = node.name().map(|it| find_range_from_node(db, file_id, it.syntax()).1); let focus_range = node.name().map(|it| find_range_from_node(db, file_id, it.syntax()).1);
let (file_id, full_range) = find_range_from_node(db, file_id, node.syntax()); let (file_id, full_range) = find_range_from_node(db, file_id, node.syntax());
NavigationTarget::from_syntax( NavigationTarget::from_syntax(

View file

@ -94,10 +94,10 @@ impl FromIterator<TableEntry<FileId, Parse<ast::SourceFile>>> for SyntaxTreeStat
} }
} }
impl FromIterator<TableEntry<MacroFile, Option<Parse<SyntaxNode>>>> for SyntaxTreeStats { impl<M> FromIterator<TableEntry<MacroFile, Option<(Parse<SyntaxNode>, M)>>> for SyntaxTreeStats {
fn from_iter<T>(iter: T) -> SyntaxTreeStats fn from_iter<T>(iter: T) -> SyntaxTreeStats
where where
T: IntoIterator<Item = TableEntry<MacroFile, Option<Parse<SyntaxNode>>>>, T: IntoIterator<Item = TableEntry<MacroFile, Option<(Parse<SyntaxNode>, M)>>>,
{ {
let mut res = SyntaxTreeStats::default(); let mut res = SyntaxTreeStats::default();
for entry in iter { for entry in iter {

View file

@ -32,7 +32,7 @@ pub enum ExpandError {
pub use crate::syntax_bridge::{ pub use crate::syntax_bridge::{
ast_to_token_tree, syntax_node_to_token_tree, token_tree_to_expr, token_tree_to_items, ast_to_token_tree, syntax_node_to_token_tree, token_tree_to_expr, token_tree_to_items,
token_tree_to_macro_stmts, token_tree_to_pat, token_tree_to_ty, TokenMap, token_tree_to_macro_stmts, token_tree_to_pat, token_tree_to_ty, RevTokenMap, TokenMap,
}; };
/// This struct contains AST for a single `macro_rules` definition. What might /// This struct contains AST for a single `macro_rules` definition. What might