mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-12 21:28:51 +00:00
Improve remove dervie attrs
This commit is contained in:
parent
ec645f2d75
commit
4a303366c8
3 changed files with 98 additions and 10 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1012,6 +1012,7 @@ dependencies = [
|
||||||
"ra_prof",
|
"ra_prof",
|
||||||
"ra_syntax",
|
"ra_syntax",
|
||||||
"ra_tt",
|
"ra_tt",
|
||||||
|
"test_utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -18,3 +18,4 @@ ra_parser = { path = "../ra_parser" }
|
||||||
ra_prof = { path = "../ra_prof" }
|
ra_prof = { path = "../ra_prof" }
|
||||||
tt = { path = "../ra_tt", package = "ra_tt" }
|
tt = { path = "../ra_tt", package = "ra_tt" }
|
||||||
mbe = { path = "../ra_mbe", package = "ra_mbe" }
|
mbe = { path = "../ra_mbe", package = "ra_mbe" }
|
||||||
|
test_utils = { path = "../test_utils"}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
use crate::{db::AstDatabase, LazyMacroId};
|
use crate::{db::AstDatabase, LazyMacroId};
|
||||||
use ra_db::{CrateId, ProcMacroId};
|
use ra_db::{CrateId, ProcMacroId};
|
||||||
|
use tt::buffer::{Cursor, TokenBuffer};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||||
pub struct ProcMacroExpander {
|
pub struct ProcMacroExpander {
|
||||||
|
@ -36,22 +37,107 @@ impl ProcMacroExpander {
|
||||||
.clone()
|
.clone()
|
||||||
.ok_or_else(|| err!("No derive macro found."))?;
|
.ok_or_else(|| err!("No derive macro found."))?;
|
||||||
|
|
||||||
let tt = remove_derive_atr(tt, &proc_macro.name)
|
let tt = remove_derive_attrs(tt)
|
||||||
.ok_or_else(|| err!("Fail to remove derive for custom derive"))?;
|
.ok_or_else(|| err!("Fail to remove derive for custom derive"))?;
|
||||||
|
|
||||||
proc_macro.expander.expand(&tt, None).map_err(mbe::ExpandError::from)
|
proc_macro.expander.expand(&tt, None).map_err(mbe::ExpandError::from)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_derive_atr(tt: &tt::Subtree, _name: &str) -> Option<tt::Subtree> {
|
fn eat_punct(cursor: &mut Cursor, c: char) -> bool {
|
||||||
// FIXME: proper handle the remove derive
|
if let Some(tt::TokenTree::Leaf(tt::Leaf::Punct(punct))) = cursor.token_tree() {
|
||||||
// We assume the first 2 tokens are #[derive(name)]
|
if punct.char == c {
|
||||||
if tt.token_trees.len() > 2 {
|
*cursor = cursor.bump();
|
||||||
let mut tt = tt.clone();
|
return true;
|
||||||
tt.token_trees.remove(0);
|
}
|
||||||
tt.token_trees.remove(0);
|
}
|
||||||
return Some(tt);
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eat_subtree(cursor: &mut Cursor, kind: tt::DelimiterKind) -> bool {
|
||||||
|
if let Some(tt::TokenTree::Subtree(subtree)) = cursor.token_tree() {
|
||||||
|
if Some(kind) == subtree.delimiter_kind() {
|
||||||
|
*cursor = cursor.bump_subtree();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eat_ident(cursor: &mut Cursor, t: &str) -> bool {
|
||||||
|
if let Some(tt::TokenTree::Leaf(tt::Leaf::Ident(ident))) = cursor.token_tree() {
|
||||||
|
if t == ident.text.as_str() {
|
||||||
|
*cursor = cursor.bump();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remove_derive_attrs(tt: &tt::Subtree) -> Option<tt::Subtree> {
|
||||||
|
let buffer = TokenBuffer::new(&tt.token_trees);
|
||||||
|
let mut p = buffer.begin();
|
||||||
|
let mut result = tt::Subtree::default();
|
||||||
|
|
||||||
|
while !p.eof() {
|
||||||
|
let curr = p;
|
||||||
|
|
||||||
|
if eat_punct(&mut p, '#') {
|
||||||
|
eat_punct(&mut p, '!');
|
||||||
|
let parent = p;
|
||||||
|
if eat_subtree(&mut p, tt::DelimiterKind::Bracket) {
|
||||||
|
if eat_ident(&mut p, "derive") {
|
||||||
|
p = parent.bump();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.token_trees.push(curr.token_tree()?.clone());
|
||||||
|
p = curr.bump();
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
Some(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
use test_utils::assert_eq_text;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_remove_derive_attrs() {
|
||||||
|
let tt = mbe::parse_to_token_tree(
|
||||||
|
r#"
|
||||||
|
#[allow(unused)]
|
||||||
|
#[derive(Copy)]
|
||||||
|
#[derive(Hello)]
|
||||||
|
struct A {
|
||||||
|
bar: u32
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
.0;
|
||||||
|
let result = format!("{:#?}", remove_derive_attrs(&tt).unwrap());
|
||||||
|
|
||||||
|
assert_eq_text!(
|
||||||
|
&result,
|
||||||
|
r#"
|
||||||
|
SUBTREE $
|
||||||
|
PUNCH # [alone] 0
|
||||||
|
SUBTREE [] 1
|
||||||
|
IDENT allow 2
|
||||||
|
SUBTREE () 3
|
||||||
|
IDENT unused 4
|
||||||
|
IDENT struct 15
|
||||||
|
IDENT A 16
|
||||||
|
SUBTREE {} 17
|
||||||
|
IDENT bar 18
|
||||||
|
PUNCH : [alone] 19
|
||||||
|
IDENT u32 20
|
||||||
|
"#
|
||||||
|
.trim()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue