mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-27 13:33:31 +00:00
Fix eager token mapping panics
This commit is contained in:
parent
cabe26c228
commit
2366c16bf9
7 changed files with 147 additions and 95 deletions
|
@ -338,7 +338,7 @@ fn macro_arg(
|
||||||
) -> Option<Arc<(tt::Subtree, mbe::TokenMap, fixup::SyntaxFixupUndoInfo)>> {
|
) -> Option<Arc<(tt::Subtree, mbe::TokenMap, fixup::SyntaxFixupUndoInfo)>> {
|
||||||
let loc = db.lookup_intern_macro_call(id);
|
let loc = db.lookup_intern_macro_call(id);
|
||||||
|
|
||||||
if let Some(EagerCallInfo { arg, arg_id: Some(_), error: _ }) = loc.eager.as_deref() {
|
if let Some(EagerCallInfo { arg, arg_id: _, error: _ }) = loc.eager.as_deref() {
|
||||||
return Some(Arc::new((arg.0.clone(), arg.1.clone(), Default::default())));
|
return Some(Arc::new((arg.0.clone(), arg.1.clone(), Default::default())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -404,7 +404,7 @@ fn censor_for_macro_input(loc: &MacroCallLoc, node: &SyntaxNode) -> FxHashSet<Sy
|
||||||
|
|
||||||
fn macro_arg_text(db: &dyn ExpandDatabase, id: MacroCallId) -> Option<GreenNode> {
|
fn macro_arg_text(db: &dyn ExpandDatabase, id: MacroCallId) -> Option<GreenNode> {
|
||||||
let loc = db.lookup_intern_macro_call(id);
|
let loc = db.lookup_intern_macro_call(id);
|
||||||
let arg = loc.kind.arg(db)?;
|
let arg = loc.kind.arg(db)?.value;
|
||||||
if matches!(loc.kind, MacroCallKind::FnLike { .. }) {
|
if matches!(loc.kind, MacroCallKind::FnLike { .. }) {
|
||||||
let first = arg.first_child_or_token().map_or(T![.], |it| it.kind());
|
let first = arg.first_child_or_token().map_or(T![.], |it| it.kind());
|
||||||
let last = arg.last_child_or_token().map_or(T![.], |it| it.kind());
|
let last = arg.last_child_or_token().map_or(T![.], |it| it.kind());
|
||||||
|
@ -490,8 +490,14 @@ fn macro_def(db: &dyn ExpandDatabase, id: MacroDefId) -> TokenExpander {
|
||||||
fn macro_expand(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<Arc<tt::Subtree>> {
|
fn macro_expand(db: &dyn ExpandDatabase, id: MacroCallId) -> ExpandResult<Arc<tt::Subtree>> {
|
||||||
let _p = profile::span("macro_expand");
|
let _p = profile::span("macro_expand");
|
||||||
let loc = db.lookup_intern_macro_call(id);
|
let loc = db.lookup_intern_macro_call(id);
|
||||||
|
|
||||||
|
// This might look a bit odd, but we do not expand the inputs to eager macros here.
|
||||||
|
// Eager macros inputs are expanded, well, eagerly when we collect the macro calls.
|
||||||
|
// That kind of expansion uses the ast id map of an eager macros input though which goes through
|
||||||
|
// the HirFileId machinery. As eager macro inputs are assigned a macro file id that query
|
||||||
|
// will end up going through here again, whereas we want to just want to inspect the raw input.
|
||||||
|
// As such we just return the input subtree here.
|
||||||
if let Some(EagerCallInfo { arg, arg_id: None, error }) = loc.eager.as_deref() {
|
if let Some(EagerCallInfo { arg, arg_id: None, error }) = loc.eager.as_deref() {
|
||||||
// This is an input expansion for an eager macro. These are already pre-expanded
|
|
||||||
return ExpandResult { value: Arc::new(arg.0.clone()), err: error.clone() };
|
return ExpandResult { value: Arc::new(arg.0.clone()), err: error.clone() };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,26 +67,37 @@ pub fn expand_eager_macro_input(
|
||||||
})),
|
})),
|
||||||
kind: MacroCallKind::FnLike { ast_id: call_id, expand_to: ExpandTo::Expr },
|
kind: MacroCallKind::FnLike { ast_id: call_id, expand_to: ExpandTo::Expr },
|
||||||
});
|
});
|
||||||
let arg_as_expr = match db.macro_arg_text(arg_id) {
|
|
||||||
Some(it) => it,
|
let ExpandResult { value: expanded_eager_input, err } = {
|
||||||
None => {
|
let arg_as_expr = match db.macro_arg_text(arg_id) {
|
||||||
return Ok(ExpandResult {
|
Some(it) => it,
|
||||||
value: None,
|
None => {
|
||||||
err: Some(ExpandError::other("invalid token tree")),
|
return Ok(ExpandResult {
|
||||||
})
|
value: None,
|
||||||
}
|
err: Some(ExpandError::other("invalid token tree")),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
eager_macro_recur(
|
||||||
|
db,
|
||||||
|
&Hygiene::new(db, macro_call.file_id),
|
||||||
|
InFile::new(arg_id.as_file(), SyntaxNode::new_root(arg_as_expr)),
|
||||||
|
krate,
|
||||||
|
resolver,
|
||||||
|
)?
|
||||||
};
|
};
|
||||||
let ExpandResult { value: expanded_eager_input, err } = eager_macro_recur(
|
|
||||||
db,
|
|
||||||
&Hygiene::new(db, macro_call.file_id),
|
|
||||||
InFile::new(arg_id.as_file(), SyntaxNode::new_root(arg_as_expr)),
|
|
||||||
krate,
|
|
||||||
resolver,
|
|
||||||
)?;
|
|
||||||
let Some(expanded_eager_input) = expanded_eager_input else {
|
let Some(expanded_eager_input) = expanded_eager_input else {
|
||||||
return Ok(ExpandResult { value: None, err });
|
return Ok(ExpandResult { value: None, err });
|
||||||
};
|
};
|
||||||
let (mut subtree, token_map) = mbe::syntax_node_to_token_tree(&expanded_eager_input);
|
// FIXME: This token map is pointless, it points into the expanded eager syntax node, but that
|
||||||
|
// node doesn't exist outside this function so we can't use this tokenmap.
|
||||||
|
// Ideally we'd need to patch the tokenmap of the pre-expanded input and then put that here
|
||||||
|
// or even better, forego expanding into a SyntaxNode altogether and instead construct a subtree
|
||||||
|
// in place! But that is kind of difficult.
|
||||||
|
let (mut subtree, _token_map) = mbe::syntax_node_to_token_tree(&expanded_eager_input);
|
||||||
|
let token_map = Default::default();
|
||||||
subtree.delimiter = crate::tt::Delimiter::unspecified();
|
subtree.delimiter = crate::tt::Delimiter::unspecified();
|
||||||
|
|
||||||
let loc = MacroCallLoc {
|
let loc = MacroCallLoc {
|
||||||
|
|
|
@ -149,16 +149,12 @@ impl HygieneInfo {
|
||||||
token_id = unshifted;
|
token_id = unshifted;
|
||||||
(&attr_args.1, self.attr_input_or_mac_def_start?)
|
(&attr_args.1, self.attr_input_or_mac_def_start?)
|
||||||
}
|
}
|
||||||
None => (
|
None => (&self.macro_arg.1, loc.kind.arg(db)?.map(|it| it.text_range().start())),
|
||||||
&self.macro_arg.1,
|
|
||||||
InFile::new(loc.kind.file_id(), loc.kind.arg(db)?.text_range().start()),
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
_ => match origin {
|
_ => match origin {
|
||||||
mbe::Origin::Call => (
|
mbe::Origin::Call => {
|
||||||
&self.macro_arg.1,
|
(&self.macro_arg.1, loc.kind.arg(db)?.map(|it| it.text_range().start()))
|
||||||
InFile::new(loc.kind.file_id(), loc.kind.arg(db)?.text_range().start()),
|
}
|
||||||
),
|
|
||||||
mbe::Origin::Def => match (&self.macro_def, &self.attr_input_or_mac_def_start) {
|
mbe::Origin::Def => match (&self.macro_def, &self.attr_input_or_mac_def_start) {
|
||||||
(TokenExpander::DeclarativeMacro(expander), Some(tt)) => {
|
(TokenExpander::DeclarativeMacro(expander), Some(tt)) => {
|
||||||
(&expander.def_site_token_map, *tt)
|
(&expander.def_site_token_map, *tt)
|
||||||
|
|
|
@ -154,8 +154,9 @@ pub enum MacroDefKind {
|
||||||
struct EagerCallInfo {
|
struct EagerCallInfo {
|
||||||
/// NOTE: This can be *either* the expansion result, *or* the argument to the eager macro!
|
/// NOTE: This can be *either* the expansion result, *or* the argument to the eager macro!
|
||||||
arg: Arc<(tt::Subtree, TokenMap)>,
|
arg: Arc<(tt::Subtree, TokenMap)>,
|
||||||
/// call id of the eager macro's input file. If this is none, macro call containing this call info
|
/// Call id of the eager macro's input file (this is the macro file for its fully expanded input).
|
||||||
/// is an eager macro's input, otherwise it is its output.
|
/// If this is none, `arg` contains the pre-expanded input, otherwise arg contains the
|
||||||
|
/// post-expanded input.
|
||||||
arg_id: Option<MacroCallId>,
|
arg_id: Option<MacroCallId>,
|
||||||
error: Option<ExpandError>,
|
error: Option<ExpandError>,
|
||||||
}
|
}
|
||||||
|
@ -270,53 +271,7 @@ impl HirFileId {
|
||||||
/// Return expansion information if it is a macro-expansion file
|
/// Return expansion information if it is a macro-expansion file
|
||||||
pub fn expansion_info(self, db: &dyn db::ExpandDatabase) -> Option<ExpansionInfo> {
|
pub fn expansion_info(self, db: &dyn db::ExpandDatabase) -> Option<ExpansionInfo> {
|
||||||
let macro_file = self.macro_file()?;
|
let macro_file = self.macro_file()?;
|
||||||
let loc: MacroCallLoc = db.lookup_intern_macro_call(macro_file.macro_call_id);
|
ExpansionInfo::new(db, macro_file)
|
||||||
|
|
||||||
let arg_tt = loc.kind.arg(db)?;
|
|
||||||
|
|
||||||
let macro_def = db.macro_def(loc.def);
|
|
||||||
let (parse, exp_map) = db.parse_macro_expansion(macro_file).value;
|
|
||||||
let macro_arg = db.macro_arg(macro_file.macro_call_id).unwrap_or_else(|| {
|
|
||||||
Arc::new((
|
|
||||||
tt::Subtree { delimiter: tt::Delimiter::UNSPECIFIED, token_trees: Vec::new() },
|
|
||||||
Default::default(),
|
|
||||||
Default::default(),
|
|
||||||
))
|
|
||||||
});
|
|
||||||
|
|
||||||
let def = loc.def.ast_id().left().and_then(|id| {
|
|
||||||
let def_tt = match id.to_node(db) {
|
|
||||||
ast::Macro::MacroRules(mac) => mac.token_tree()?,
|
|
||||||
ast::Macro::MacroDef(_) if matches!(macro_def, TokenExpander::BuiltInAttr(_)) => {
|
|
||||||
return None
|
|
||||||
}
|
|
||||||
ast::Macro::MacroDef(mac) => mac.body()?,
|
|
||||||
};
|
|
||||||
Some(InFile::new(id.file_id, def_tt))
|
|
||||||
});
|
|
||||||
let attr_input_or_mac_def = def.or_else(|| match loc.kind {
|
|
||||||
MacroCallKind::Attr { ast_id, invoc_attr_index, .. } => {
|
|
||||||
// FIXME: handle `cfg_attr`
|
|
||||||
let tt = ast_id
|
|
||||||
.to_node(db)
|
|
||||||
.doc_comments_and_attrs()
|
|
||||||
.nth(invoc_attr_index.ast_index())
|
|
||||||
.and_then(Either::left)?
|
|
||||||
.token_tree()?;
|
|
||||||
Some(InFile::new(ast_id.file_id, tt))
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
});
|
|
||||||
|
|
||||||
Some(ExpansionInfo {
|
|
||||||
expanded: InFile::new(self, parse.syntax_node()),
|
|
||||||
arg: InFile::new(loc.kind.file_id(), arg_tt),
|
|
||||||
attr_input_or_mac_def,
|
|
||||||
macro_arg_shift: mbe::Shift::new(¯o_arg.0),
|
|
||||||
macro_arg,
|
|
||||||
macro_def,
|
|
||||||
exp_map,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_builtin_derive_attr_node(
|
pub fn as_builtin_derive_attr_node(
|
||||||
|
@ -603,13 +558,18 @@ impl MacroCallKind {
|
||||||
FileRange { range, file_id }
|
FileRange { range, file_id }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn arg(&self, db: &dyn db::ExpandDatabase) -> Option<SyntaxNode> {
|
fn arg(&self, db: &dyn db::ExpandDatabase) -> Option<InFile<SyntaxNode>> {
|
||||||
match self {
|
match self {
|
||||||
MacroCallKind::FnLike { ast_id, .. } => {
|
MacroCallKind::FnLike { ast_id, .. } => ast_id
|
||||||
Some(ast_id.to_node(db).token_tree()?.syntax().clone())
|
.to_in_file_node(db)
|
||||||
|
.map(|it| Some(it.token_tree()?.syntax().clone()))
|
||||||
|
.transpose(),
|
||||||
|
MacroCallKind::Derive { ast_id, .. } => {
|
||||||
|
Some(ast_id.to_in_file_node(db).syntax().cloned())
|
||||||
|
}
|
||||||
|
MacroCallKind::Attr { ast_id, .. } => {
|
||||||
|
Some(ast_id.to_in_file_node(db).syntax().cloned())
|
||||||
}
|
}
|
||||||
MacroCallKind::Derive { ast_id, .. } => Some(ast_id.to_node(db).syntax().clone()),
|
|
||||||
MacroCallKind::Attr { ast_id, .. } => Some(ast_id.to_node(db).syntax().clone()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -627,7 +587,7 @@ impl MacroCallId {
|
||||||
/// 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
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct ExpansionInfo {
|
pub struct ExpansionInfo {
|
||||||
expanded: InFile<SyntaxNode>,
|
expanded: InMacroFile<SyntaxNode>,
|
||||||
/// The argument TokenTree or item for attributes
|
/// The argument TokenTree or item for attributes
|
||||||
arg: InFile<SyntaxNode>,
|
arg: InFile<SyntaxNode>,
|
||||||
/// The `macro_rules!` or attribute input.
|
/// The `macro_rules!` or attribute input.
|
||||||
|
@ -643,7 +603,7 @@ pub struct ExpansionInfo {
|
||||||
|
|
||||||
impl ExpansionInfo {
|
impl ExpansionInfo {
|
||||||
pub fn expanded(&self) -> InFile<SyntaxNode> {
|
pub fn expanded(&self) -> InFile<SyntaxNode> {
|
||||||
self.expanded.clone()
|
self.expanded.clone().into()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn call_node(&self) -> Option<InFile<SyntaxNode>> {
|
pub fn call_node(&self) -> Option<InFile<SyntaxNode>> {
|
||||||
|
@ -674,7 +634,7 @@ impl ExpansionInfo {
|
||||||
let token_id_in_attr_input = if let Some(item) = item {
|
let token_id_in_attr_input = if let Some(item) = item {
|
||||||
// check if we are mapping down in an attribute input
|
// check if we are mapping down in an attribute input
|
||||||
// this is a special case as attributes can have two inputs
|
// this is a special case as attributes can have two inputs
|
||||||
let call_id = self.expanded.file_id.macro_file()?.macro_call_id;
|
let call_id = self.expanded.file_id.macro_call_id;
|
||||||
let loc = db.lookup_intern_macro_call(call_id);
|
let loc = db.lookup_intern_macro_call(call_id);
|
||||||
|
|
||||||
let token_range = token.value.text_range();
|
let token_range = token.value.text_range();
|
||||||
|
@ -720,7 +680,7 @@ impl ExpansionInfo {
|
||||||
let relative_range =
|
let relative_range =
|
||||||
token.value.text_range().checked_sub(self.arg.value.text_range().start())?;
|
token.value.text_range().checked_sub(self.arg.value.text_range().start())?;
|
||||||
let token_id = self.macro_arg.1.token_by_range(relative_range)?;
|
let token_id = self.macro_arg.1.token_by_range(relative_range)?;
|
||||||
// conditionally shift the id by a declaratives macro definition
|
// conditionally shift the id by a declarative macro definition
|
||||||
self.macro_def.map_id_down(token_id)
|
self.macro_def.map_id_down(token_id)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -730,7 +690,7 @@ impl ExpansionInfo {
|
||||||
.ranges_by_token(token_id, token.value.kind())
|
.ranges_by_token(token_id, token.value.kind())
|
||||||
.flat_map(move |range| self.expanded.value.covering_element(range).into_token());
|
.flat_map(move |range| self.expanded.value.covering_element(range).into_token());
|
||||||
|
|
||||||
Some(tokens.map(move |token| self.expanded.with_value(token)))
|
Some(tokens.map(move |token| InFile::new(self.expanded.file_id.into(), token)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Map a token up out of the expansion it resides in into the arguments of the macro call of the expansion.
|
/// Map a token up out of the expansion it resides in into the arguments of the macro call of the expansion.
|
||||||
|
@ -739,12 +699,13 @@ impl ExpansionInfo {
|
||||||
db: &dyn db::ExpandDatabase,
|
db: &dyn db::ExpandDatabase,
|
||||||
token: InFile<&SyntaxToken>,
|
token: InFile<&SyntaxToken>,
|
||||||
) -> Option<(InFile<SyntaxToken>, Origin)> {
|
) -> Option<(InFile<SyntaxToken>, Origin)> {
|
||||||
|
assert_eq!(token.file_id, self.expanded.file_id.into());
|
||||||
// Fetch the id through its text range,
|
// Fetch the id through its text range,
|
||||||
let token_id = self.exp_map.token_by_range(token.value.text_range())?;
|
let token_id = self.exp_map.token_by_range(token.value.text_range())?;
|
||||||
// conditionally unshifting the id to accommodate for macro-rules def site
|
// conditionally unshifting the id to accommodate for macro-rules def site
|
||||||
let (mut token_id, origin) = self.macro_def.map_id_up(token_id);
|
let (mut token_id, origin) = self.macro_def.map_id_up(token_id);
|
||||||
|
|
||||||
let call_id = self.expanded.file_id.macro_file()?.macro_call_id;
|
let call_id = self.expanded.file_id.macro_call_id;
|
||||||
let loc = db.lookup_intern_macro_call(call_id);
|
let loc = db.lookup_intern_macro_call(call_id);
|
||||||
|
|
||||||
// Special case: map tokens from `include!` expansions to the included file
|
// Special case: map tokens from `include!` expansions to the included file
|
||||||
|
@ -794,6 +755,63 @@ impl ExpansionInfo {
|
||||||
tt.value.covering_element(range + tt.value.text_range().start()).into_token()?;
|
tt.value.covering_element(range + tt.value.text_range().start()).into_token()?;
|
||||||
Some((tt.with_value(token), origin))
|
Some((tt.with_value(token), origin))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn new(db: &dyn db::ExpandDatabase, macro_file: MacroFile) -> Option<ExpansionInfo> {
|
||||||
|
let loc: MacroCallLoc = db.lookup_intern_macro_call(macro_file.macro_call_id);
|
||||||
|
|
||||||
|
let arg_tt = loc.kind.arg(db)?;
|
||||||
|
|
||||||
|
let macro_def = db.macro_def(loc.def);
|
||||||
|
let (parse, exp_map) = db.parse_macro_expansion(macro_file).value;
|
||||||
|
let expanded = InMacroFile { file_id: macro_file, value: parse.syntax_node() };
|
||||||
|
|
||||||
|
let macro_arg = db
|
||||||
|
.macro_arg(match loc.eager.as_deref() {
|
||||||
|
Some(&EagerCallInfo { arg_id: Some(_), .. }) => return None,
|
||||||
|
_ => macro_file.macro_call_id,
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
Arc::new((
|
||||||
|
tt::Subtree { delimiter: tt::Delimiter::UNSPECIFIED, token_trees: Vec::new() },
|
||||||
|
Default::default(),
|
||||||
|
Default::default(),
|
||||||
|
))
|
||||||
|
});
|
||||||
|
|
||||||
|
let def = loc.def.ast_id().left().and_then(|id| {
|
||||||
|
let def_tt = match id.to_node(db) {
|
||||||
|
ast::Macro::MacroRules(mac) => mac.token_tree()?,
|
||||||
|
ast::Macro::MacroDef(_) if matches!(macro_def, TokenExpander::BuiltInAttr(_)) => {
|
||||||
|
return None
|
||||||
|
}
|
||||||
|
ast::Macro::MacroDef(mac) => mac.body()?,
|
||||||
|
};
|
||||||
|
Some(InFile::new(id.file_id, def_tt))
|
||||||
|
});
|
||||||
|
let attr_input_or_mac_def = def.or_else(|| match loc.kind {
|
||||||
|
MacroCallKind::Attr { ast_id, invoc_attr_index, .. } => {
|
||||||
|
// FIXME: handle `cfg_attr`
|
||||||
|
let tt = ast_id
|
||||||
|
.to_node(db)
|
||||||
|
.doc_comments_and_attrs()
|
||||||
|
.nth(invoc_attr_index.ast_index())
|
||||||
|
.and_then(Either::left)?
|
||||||
|
.token_tree()?;
|
||||||
|
Some(InFile::new(ast_id.file_id, tt))
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
});
|
||||||
|
|
||||||
|
Some(ExpansionInfo {
|
||||||
|
expanded,
|
||||||
|
arg: arg_tt,
|
||||||
|
attr_input_or_mac_def,
|
||||||
|
macro_arg_shift: mbe::Shift::new(¯o_arg.0),
|
||||||
|
macro_arg,
|
||||||
|
macro_def,
|
||||||
|
exp_map,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `AstId` points to an AST node in any file.
|
/// `AstId` points to an AST node in any file.
|
||||||
|
@ -805,6 +823,9 @@ impl<N: AstIdNode> AstId<N> {
|
||||||
pub fn to_node(&self, db: &dyn db::ExpandDatabase) -> N {
|
pub fn to_node(&self, db: &dyn db::ExpandDatabase) -> N {
|
||||||
self.to_ptr(db).to_node(&db.parse_or_expand(self.file_id))
|
self.to_ptr(db).to_node(&db.parse_or_expand(self.file_id))
|
||||||
}
|
}
|
||||||
|
pub fn to_in_file_node(&self, db: &dyn db::ExpandDatabase) -> InFile<N> {
|
||||||
|
InFile::new(self.file_id, self.to_ptr(db).to_node(&db.parse_or_expand(self.file_id)))
|
||||||
|
}
|
||||||
pub fn to_ptr(&self, db: &dyn db::ExpandDatabase) -> AstPtr<N> {
|
pub fn to_ptr(&self, db: &dyn db::ExpandDatabase) -> AstPtr<N> {
|
||||||
db.ast_id_map(self.file_id).get(self.value)
|
db.ast_id_map(self.file_id).get(self.value)
|
||||||
}
|
}
|
||||||
|
@ -820,6 +841,7 @@ impl ErasedAstId {
|
||||||
db.ast_id_map(self.file_id).get_raw(self.value)
|
db.ast_id_map(self.file_id).get_raw(self.value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `InFile<T>` stores a value of `T` inside a particular file/syntax tree.
|
/// `InFile<T>` stores a value of `T` inside a particular file/syntax tree.
|
||||||
///
|
///
|
||||||
/// Typical usages are:
|
/// Typical usages are:
|
||||||
|
@ -1038,6 +1060,18 @@ impl InFile<SyntaxToken> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
|
||||||
|
pub struct InMacroFile<T> {
|
||||||
|
pub file_id: MacroFile,
|
||||||
|
pub value: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> From<InMacroFile<T>> for InFile<T> {
|
||||||
|
fn from(macro_file: InMacroFile<T>) -> Self {
|
||||||
|
InFile { file_id: macro_file.file_id.into(), value: macro_file.value }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn ascend_node_border_tokens(
|
fn ascend_node_border_tokens(
|
||||||
db: &dyn db::ExpandDatabase,
|
db: &dyn db::ExpandDatabase,
|
||||||
InFile { file_id, value: node }: InFile<&SyntaxNode>,
|
InFile { file_id, value: node }: InFile<&SyntaxNode>,
|
||||||
|
|
|
@ -265,10 +265,14 @@ fn traverse(
|
||||||
|
|
||||||
// set macro and attribute highlighting states
|
// set macro and attribute highlighting states
|
||||||
match event.clone() {
|
match event.clone() {
|
||||||
Enter(NodeOrToken::Node(node)) if ast::TokenTree::can_cast(node.kind()) => {
|
Enter(NodeOrToken::Node(node))
|
||||||
|
if current_macro.is_none() && ast::TokenTree::can_cast(node.kind()) =>
|
||||||
|
{
|
||||||
tt_level += 1;
|
tt_level += 1;
|
||||||
}
|
}
|
||||||
Leave(NodeOrToken::Node(node)) if ast::TokenTree::can_cast(node.kind()) => {
|
Leave(NodeOrToken::Node(node))
|
||||||
|
if current_macro.is_none() && ast::TokenTree::can_cast(node.kind()) =>
|
||||||
|
{
|
||||||
tt_level -= 1;
|
tt_level -= 1;
|
||||||
}
|
}
|
||||||
Enter(NodeOrToken::Node(node)) if ast::Attr::can_cast(node.kind()) => {
|
Enter(NodeOrToken::Node(node)) if ast::Attr::can_cast(node.kind()) => {
|
||||||
|
@ -387,7 +391,7 @@ fn traverse(
|
||||||
};
|
};
|
||||||
let descended_element = if in_macro {
|
let descended_element = if in_macro {
|
||||||
// Attempt to descend tokens into macro-calls.
|
// Attempt to descend tokens into macro-calls.
|
||||||
match element {
|
let res = match element {
|
||||||
NodeOrToken::Token(token) if token.kind() != COMMENT => {
|
NodeOrToken::Token(token) if token.kind() != COMMENT => {
|
||||||
let token = match attr_or_derive_item {
|
let token = match attr_or_derive_item {
|
||||||
Some(AttrOrDerive::Attr(_)) => {
|
Some(AttrOrDerive::Attr(_)) => {
|
||||||
|
@ -412,7 +416,8 @@ fn traverse(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
e => e,
|
e => e,
|
||||||
}
|
};
|
||||||
|
res
|
||||||
} else {
|
} else {
|
||||||
element
|
element
|
||||||
};
|
};
|
||||||
|
|
|
@ -130,7 +130,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">+</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">+</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
||||||
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">#</span><span class="variable">x</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">27</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">#</span><span class="variable">x</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">27</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
||||||
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
||||||
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">-</span><span class="numeric_literal macro">5</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="punctuation macro">-</span><span class="numeric_literal macro">5</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
||||||
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">#</span><span class="numeric_literal">0</span><span class="numeric_literal">10</span><span class="variable">x</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">27</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">#</span><span class="numeric_literal">0</span><span class="numeric_literal">10</span><span class="variable">x</span><span class="format_specifier">}</span><span class="string_literal macro">!"</span><span class="comma macro">,</span> <span class="numeric_literal macro">27</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
||||||
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
||||||
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">0</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">}</span><span class="string_literal macro"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">0</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">5</span><span class="comma macro">,</span> <span class="string_literal macro">"x"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0.01</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
||||||
|
@ -166,7 +166,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="escape_sequence">\x41</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="none macro">A</span> <span class="operator macro">=</span> <span class="numeric_literal macro">92</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="escape_sequence">\x41</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="none macro">A</span> <span class="operator macro">=</span> <span class="numeric_literal macro">92</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
||||||
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">ничоси</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="none macro">ничоси</span> <span class="operator macro">=</span> <span class="numeric_literal macro">92</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="variable">ничоси</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="none macro">ничоси</span> <span class="operator macro">=</span> <span class="numeric_literal macro">92</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
||||||
|
|
||||||
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="variable">x</span><span class="format_specifier">?</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> "</span><span class="comma macro">,</span> <span class="unresolved_reference macro">thingy</span><span class="comma macro">,</span> <span class="unresolved_reference macro">n2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
<span class="macro">println</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="variable">x</span><span class="format_specifier">?</span><span class="format_specifier">}</span><span class="string_literal macro"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro"> "</span><span class="comma macro">,</span> <span class="none macro">thingy</span><span class="comma macro">,</span> <span class="none macro">n2</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
||||||
<span class="macro">panic</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
<span class="macro">panic</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
||||||
<span class="macro">panic</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"more </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
<span class="macro">panic</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"more </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
||||||
<span class="macro">assert</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="bool_literal macro">true</span><span class="comma macro">,</span> <span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
<span class="macro">assert</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="bool_literal macro">true</span><span class="comma macro">,</span> <span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">1</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
||||||
|
@ -174,5 +174,5 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
|
||||||
<span class="macro">toho</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">fmt"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
<span class="macro">toho</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">fmt"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
||||||
<span class="macro unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"mov eax, </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
<span class="macro unsafe">asm</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"mov eax, </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
||||||
<span class="macro">format_args</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">concat</span><span class="punctuation macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
<span class="macro">format_args</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="none macro">concat</span><span class="punctuation macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="comma macro">,</span> <span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
||||||
<span class="macro">format_args</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="none macro">format_args</span><span class="operator macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
<span class="macro">format_args</span><span class="macro_bang">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="none macro">format_args</span><span class="punctuation macro">!</span><span class="parenthesis macro">(</span><span class="string_literal macro">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal macro">"</span><span class="comma macro">,</span> <span class="numeric_literal macro">0</span><span class="parenthesis macro">)</span><span class="parenthesis macro">)</span><span class="semicolon">;</span>
|
||||||
<span class="brace">}</span></code></pre>
|
<span class="brace">}</span></code></pre>
|
|
@ -208,7 +208,7 @@ impl Shift {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
pub enum Origin {
|
pub enum Origin {
|
||||||
Def,
|
Def,
|
||||||
Call,
|
Call,
|
||||||
|
|
Loading…
Reference in a new issue