mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-14 06:03:58 +00:00
Add identity expansion checking
This commit is contained in:
parent
92b561b5c7
commit
e1a9461806
3 changed files with 55 additions and 3 deletions
|
@ -6,7 +6,7 @@ use mbe::{ExpandResult, MacroRules};
|
||||||
use ra_db::{salsa, SourceDatabase};
|
use ra_db::{salsa, SourceDatabase};
|
||||||
use ra_parser::FragmentKind;
|
use ra_parser::FragmentKind;
|
||||||
use ra_prof::profile;
|
use ra_prof::profile;
|
||||||
use ra_syntax::{AstNode, Parse, SyntaxKind::*, SyntaxNode};
|
use ra_syntax::{algo::diff, AstNode, Parse, SyntaxKind::*, SyntaxNode};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast_id_map::AstIdMap, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallLoc, EagerMacroId,
|
ast_id_map::AstIdMap, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallLoc, EagerMacroId,
|
||||||
|
@ -238,7 +238,7 @@ pub fn parse_macro_with_arg(
|
||||||
} else {
|
} else {
|
||||||
db.macro_expand(macro_call_id)
|
db.macro_expand(macro_call_id)
|
||||||
};
|
};
|
||||||
if let Some(err) = err {
|
if let Some(err) = &err {
|
||||||
// Note:
|
// Note:
|
||||||
// The final goal we would like to make all parse_macro success,
|
// The final goal we would like to make all parse_macro success,
|
||||||
// such that the following log will not call anyway.
|
// such that the following log will not call anyway.
|
||||||
|
@ -272,7 +272,25 @@ pub fn parse_macro_with_arg(
|
||||||
let fragment_kind = to_fragment_kind(db, macro_call_id);
|
let fragment_kind = to_fragment_kind(db, macro_call_id);
|
||||||
|
|
||||||
let (parse, rev_token_map) = mbe::token_tree_to_syntax_node(&tt, fragment_kind).ok()?;
|
let (parse, rev_token_map) = mbe::token_tree_to_syntax_node(&tt, fragment_kind).ok()?;
|
||||||
Some((parse, Arc::new(rev_token_map)))
|
|
||||||
|
if err.is_none() {
|
||||||
|
Some((parse, Arc::new(rev_token_map)))
|
||||||
|
} else {
|
||||||
|
// FIXME:
|
||||||
|
// In future, we should proprate the actual error with recovery information
|
||||||
|
// instead of ignore the error here.
|
||||||
|
|
||||||
|
// Safe check for recurisve identity macro
|
||||||
|
let node = parse.syntax_node();
|
||||||
|
let file: HirFileId = macro_file.into();
|
||||||
|
let call_node = file.call_node(db)?;
|
||||||
|
|
||||||
|
if !diff(&node, &call_node.value).is_empty() {
|
||||||
|
Some((parse, Arc::new(rev_token_map)))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a `MacroCallId`, return what `FragmentKind` it belongs to.
|
/// Given a `MacroCallId`, return what `FragmentKind` it belongs to.
|
||||||
|
|
|
@ -715,4 +715,34 @@ fn main() {
|
||||||
check_struct_shorthand_initialization,
|
check_struct_shorthand_initialization,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_bad_macro_stackover() {
|
||||||
|
check_no_diagnostic(
|
||||||
|
r#"
|
||||||
|
//- /main.rs
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! match_ast {
|
||||||
|
(match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) };
|
||||||
|
|
||||||
|
(match ($node:expr) {
|
||||||
|
$( ast::$ast:ident($it:ident) => $res:expr, )*
|
||||||
|
_ => $catch_all:expr $(,)?
|
||||||
|
}) => {{
|
||||||
|
$( if let Some($it) = ast::$ast::cast($node.clone()) { $res } else )*
|
||||||
|
{ $catch_all }
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let anchor = match_ast! {
|
||||||
|
match parent {
|
||||||
|
as => {},
|
||||||
|
_ => return None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,6 +95,10 @@ impl TreeDiff {
|
||||||
builder.replace(from.text_range(), to.to_string())
|
builder.replace(from.text_range(), to.to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.replacements.is_empty()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finds minimal the diff, which, applied to `from`, will result in `to`.
|
/// Finds minimal the diff, which, applied to `from`, will result in `to`.
|
||||||
|
|
Loading…
Reference in a new issue