This commit is contained in:
Lukas Wirth 2023-11-25 17:10:18 +01:00
parent ab8f12e169
commit 92d447f976
26 changed files with 102 additions and 123 deletions

View file

@ -17,10 +17,10 @@ use profile::Count;
use rustc_hash::FxHasher;
use syntax::{ast, AstNode, AstPtr, SyntaxNode, SyntaxNodePtr};
pub use base_db::span::ErasedFileAstId;
use crate::db;
pub use base_db::span::ErasedFileAstId;
/// `AstId` points to an AST node in any file.
///
/// It is stable across reparses, and can be used as salsa key/value.

View file

@ -293,13 +293,8 @@ impl Attr {
if tts.is_empty() {
return None;
}
// FIXME: Absolutely wrong
let call_site = match tts.first().unwrap() {
tt::TokenTree::Leaf(l) => l.span().ctx,
tt::TokenTree::Subtree(s) => s.delimiter.open.ctx,
};
// FIXME: This is necessarily a hack. It'd be nice if we could avoid allocation
// here.
// here or maybe just parse a mod path from a token tree directly
let subtree = tt::Subtree {
delimiter: tt::Delimiter::unspecified(),
token_trees: tts.to_vec(),
@ -313,6 +308,7 @@ impl Attr {
return None;
}
let path = meta.path()?;
let call_site = span_map.span_for_range(path.syntax().text_range()).ctx;
Some((
ModPath::from_src(db, path, SpanMapRef::ExpansionSpanMap(&span_map))?,
call_site,

View file

@ -553,7 +553,7 @@ pub(crate) fn include_arg_to_tt(
let Some(EagerCallInfo { arg, arg_id, .. }) = loc.eager.as_deref() else {
panic!("include_arg_to_tt called on non include macro call: {:?}", &loc.eager);
};
let path = parse_string(&arg.0)?;
let path = parse_string(&arg)?;
let file_id = relative_file(db, *arg_id, &path, false)?;
// why are we not going through a SyntaxNode here?

View file

@ -190,15 +190,16 @@ pub fn expand_speculative(
speculative_args: &SyntaxNode,
token_to_map: SyntaxToken,
) -> Option<(SyntaxNode, SyntaxToken)> {
// FIXME spanmaps
let loc = db.lookup_intern_macro_call(actual_macro_call);
// Build the subtree and token mapping for the speculative args
let _censor = censor_for_macro_input(&loc, speculative_args);
let span_map = RealSpanMap::absolute(SpanAnchor::DUMMY.file_id);
let span_map = SpanMapRef::RealSpanMap(&span_map);
let mut tt = mbe::syntax_node_to_token_tree(
speculative_args,
// we don't leak these spans into any query so its fine to make them absolute
SpanMapRef::RealSpanMap(&RealSpanMap::empty(SpanAnchor::DUMMY.file_id)),
span_map,
);
let attr_arg = match loc.kind {
@ -216,10 +217,7 @@ pub fn expand_speculative(
}?;
match attr.token_tree() {
Some(token_tree) => {
let mut tree = syntax_node_to_token_tree(
token_tree.syntax(),
SpanMapRef::RealSpanMap(&RealSpanMap::empty(SpanAnchor::DUMMY.file_id)),
);
let mut tree = syntax_node_to_token_tree(token_tree.syntax(), span_map);
tree.delimiter = tt::Delimiter::UNSPECIFIED;
Some(tree)
@ -243,12 +241,7 @@ pub fn expand_speculative(
MacroDefKind::BuiltInDerive(expander, ..) => {
// this cast is a bit sus, can we avoid losing the typedness here?
let adt = ast::Adt::cast(speculative_args.clone()).unwrap();
expander.expand(
db,
actual_macro_call,
&adt,
SpanMapRef::RealSpanMap(&RealSpanMap::empty(SpanAnchor::DUMMY.file_id)),
)
expander.expand(db, actual_macro_call, &adt, span_map)
}
MacroDefKind::Declarative(it) => {
db.decl_macro_expander(loc.krate, it).expand_unhygienic(tt)
@ -305,6 +298,8 @@ fn parse_or_expand_with_err(
}
}
// FIXME: We should verify that the parsed node is one of the many macro node variants we expect
// instead of having it be untyped
fn parse_macro_expansion(
db: &dyn ExpandDatabase,
macro_file: MacroFileId,
@ -330,6 +325,18 @@ fn parse_macro_expansion_error(
.map(|it| it.0.errors().to_vec().into_boxed_slice())
}
fn parse_with_map(db: &dyn ExpandDatabase, file_id: HirFileId) -> (Parse<SyntaxNode>, SpanMap) {
match file_id.repr() {
HirFileIdRepr::FileId(file_id) => {
(db.parse(file_id).to_syntax(), SpanMap::RealSpanMap(db.real_span_map(file_id)))
}
HirFileIdRepr::MacroFile(macro_file) => {
let (parse, map) = db.parse_macro_expansion(macro_file).value;
(parse, SpanMap::ExpansionSpanMap(map))
}
}
}
fn macro_arg(
db: &dyn ExpandDatabase,
id: MacroCallId,
@ -361,32 +368,22 @@ fn macro_arg(
.then(|| loc.eager.as_deref())
.flatten()
{
ValueResult::ok(Some(Arc::new(arg.0.clone())))
ValueResult::ok(Some(arg.clone()))
} else {
//FIXME: clean this up, the ast id map lookup is done twice here
let (parse, map) = match loc.kind.file_id().repr() {
HirFileIdRepr::FileId(file_id) => {
let syntax = db.parse(file_id).to_syntax();
(syntax, SpanMap::RealSpanMap(db.real_span_map(file_id)))
}
HirFileIdRepr::MacroFile(macro_file) => {
let (parse, map) = db.parse_macro_expansion(macro_file).value;
(parse, SpanMap::ExpansionSpanMap(map))
}
};
let (parse, map) = parse_with_map(db, loc.kind.file_id());
let root = parse.syntax_node();
let syntax = match loc.kind {
MacroCallKind::FnLike { ast_id, .. } => {
let node = &ast_id.to_ptr(db).to_node(&root);
let offset = node.syntax().text_range().start();
match node.token_tree().map(|it| it.syntax().clone()) {
match node.token_tree() {
Some(tt) => {
if let Some(e) = mismatched_delimiters(&tt) {
let tt = tt.syntax();
if let Some(e) = mismatched_delimiters(tt) {
return ValueResult::only_err(e);
}
tt
tt.clone()
}
None => {
return ValueResult::only_err(Arc::new(Box::new([
@ -479,17 +476,8 @@ fn decl_macro_expander(
id: AstId<ast::Macro>,
) -> Arc<DeclarativeMacroExpander> {
let is_2021 = db.crate_graph()[def_crate].edition >= Edition::Edition2021;
let (root, map) = match id.file_id.repr() {
HirFileIdRepr::FileId(file_id) => {
// FIXME: Arc
// FIXME: id.to_ptr duplicated, expensive
(db.parse(file_id).syntax_node(), SpanMap::RealSpanMap(db.real_span_map(file_id)))
}
HirFileIdRepr::MacroFile(macro_file) => {
let (parse, map) = db.parse_macro_expansion(macro_file).value;
(parse.syntax_node(), SpanMap::ExpansionSpanMap(map))
}
};
let (root, map) = parse_with_map(db, id.file_id);
let root = root.syntax_node();
let transparency = |node| {
// ... would be nice to have the item tree here
@ -568,21 +556,8 @@ fn macro_expand(
let ExpandResult { value: tt, mut err } = match loc.def.kind {
MacroDefKind::ProcMacro(..) => return db.expand_proc_macro(macro_call_id),
MacroDefKind::BuiltInDerive(expander, ..) => {
// FIXME: add firewall query for this?
let hir_file_id = loc.kind.file_id();
let (root, map) = match hir_file_id.repr() {
HirFileIdRepr::FileId(file_id) => {
// FIXME: query for span map
(
db.parse(file_id).syntax_node(),
SpanMap::RealSpanMap(db.real_span_map(file_id)),
)
}
HirFileIdRepr::MacroFile(macro_file) => {
let (parse, map) = db.parse_macro_expansion(macro_file).value;
(parse.syntax_node(), SpanMap::ExpansionSpanMap(map))
}
};
let (root, map) = parse_with_map(db, loc.kind.file_id());
let root = root.syntax_node();
let MacroCallKind::Derive { ast_id, .. } = loc.kind else { unreachable!() };
let node = ast_id.to_ptr(db).to_node(&root);
@ -710,9 +685,9 @@ fn token_tree_to_syntax_node(
ExpandTo::Type => mbe::TopEntryPoint::Type,
ExpandTo::Expr => mbe::TopEntryPoint::Expr,
};
let mut tm = mbe::token_tree_to_syntax_node(tt, entry_point);
let (parse, mut span_map) = mbe::token_tree_to_syntax_node(tt, entry_point);
// FIXME: now what the hell is going on here
tm.1.span_map.sort_by(|(_, a), (_, b)| {
span_map.span_map.sort_by(|(_, a), (_, b)| {
a.anchor.file_id.cmp(&b.anchor.file_id).then_with(|| {
let map = db.ast_id_map(a.anchor.file_id.into());
map.get_erased(a.anchor.ast_id)
@ -721,7 +696,7 @@ fn token_tree_to_syntax_node(
.cmp(&map.get_erased(b.anchor.ast_id).text_range().start())
})
});
tm
(parse, span_map)
}
fn check_tt_count(tt: &tt::Subtree) -> Result<(), ExpandResult<Arc<tt::Subtree>>> {

View file

@ -81,7 +81,7 @@ pub fn expand_eager_macro_input(
// FIXME: Spans!
let mut subtree = mbe::syntax_node_to_token_tree(
&expanded_eager_input,
RealSpanMap::empty(<SpanAnchor as tt::SpanAnchor>::DUMMY.file_id),
RealSpanMap::absolute(<SpanAnchor as tt::SpanAnchor>::DUMMY.file_id),
);
subtree.delimiter = crate::tt::Delimiter::UNSPECIFIED;
@ -89,11 +89,7 @@ pub fn expand_eager_macro_input(
let loc = MacroCallLoc {
def,
krate,
eager: Some(Box::new(EagerCallInfo {
arg: Arc::new((subtree,)),
arg_id,
error: err.clone(),
})),
eager: Some(Box::new(EagerCallInfo { arg: Arc::new(subtree), arg_id, error: err.clone() })),
kind: MacroCallKind::FnLike { ast_id: call_id, expand_to },
call_site,
};

View file

@ -8,7 +8,7 @@ use base_db::span::{MacroCallId, SpanData, SyntaxContextId};
use crate::db::ExpandDatabase;
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct SyntaxContextData {
pub outer_expn: Option<MacroCallId>,
pub outer_transparency: Transparency,

View file

@ -135,7 +135,7 @@ pub enum MacroDefKind {
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct EagerCallInfo {
/// The expanded argument of the eager macro.
arg: Arc<(tt::Subtree,)>,
arg: Arc<tt::Subtree>,
/// Call id of the eager macro's input file (this is the macro file for its fully expanded input).
arg_id: MacroCallId,
error: Option<ExpandError>,
@ -537,8 +537,6 @@ impl MacroCallKind {
FileRange { range, file_id }
}
// FIXME: -> InFile<SyntaxNode> it should be impossible for the token tree to be missing at
// this point!
fn arg(&self, db: &dyn db::ExpandDatabase) -> InFile<Option<SyntaxNode>> {
match self {
MacroCallKind::FnLike { ast_id, .. } => {
@ -561,7 +559,6 @@ impl MacroCallKind {
pub struct ExpansionInfo {
pub expanded: InMacroFile<SyntaxNode>,
/// The argument TokenTree or item for attributes
// FIXME: Can this ever be `None`?
arg: InFile<Option<SyntaxNode>>,
/// The `macro_rules!` or attribute input.
attr_input_or_mac_def: Option<InFile<ast::TokenTree>>,

View file

@ -77,7 +77,8 @@ pub struct RealSpanMap {
}
impl RealSpanMap {
pub fn empty(file_id: FileId) -> Self {
/// Creates a real file span map that returns absolute ranges (relative ranges to the root ast id).
pub fn absolute(file_id: FileId) -> Self {
RealSpanMap { file_id, pairs: Box::from([(TextSize::new(0), ROOT_ERASED_FILE_AST_ID)]) }
}