use ra_syntax::{
TextRange, TextUnit, SourceFile, AstNode, SyntaxNode, TreeArc, SyntaxNodePtr,
+ SyntaxKind::*,
ast::{self, NameOwner},
};
def.expand(input).map(Arc::new)
}
-fn macro_call_to_tt(call: &ast::MacroCall) -> Option<tt::TokenTree> {
- None
+fn macro_call_to_tt(call: &ast::MacroCall) -> Option<tt::Subtree> {
+ let tt = call.token_tree()?;
+ convert_tt(tt.syntax())
+}
+
+fn convert_tt(tt: &SyntaxNode) -> Option<tt::Subtree> {
+ let first_child = tt.first_child()?;
+ let last_child = tt.last_child()?;
+ let delimiter = match (first_child.kind(), last_child.kind()) {
+ (L_PAREN, R_PAREN) => tt::Delimiter::Parenthesis,
+ (L_CURLY, R_CURLY) => tt::Delimiter::Brace,
+ (L_BRACK, R_BRACK) => tt::Delimiter::Bracket,
+ _ => return None,
+ };
+ let mut token_trees = Vec::new();
+ for child in tt.children().skip(1) {
+ if child == first_child || child == last_child || child.kind().is_trivia() {
+ continue;
+ }
+ let child = if child.kind() == TOKEN_TREE {
+ convert_tt(child)?.into()
+ } else if child.kind().is_keyword() {
+ let text = child.leaf_text().unwrap().clone();
+ tt::Leaf::from(tt::Ident { text }).into()
+ } else {
+ return None;
+ };
+ token_trees.push(child)
+ }
+
+ let res = tt::Subtree {
+ delimiter,
+ token_trees,
+ };
+ Some(res)
}
Leaf(Leaf),
Subtree(Subtree),
}
+impl_froms!(TokenTree: Leaf, Subtree);
pub(crate) enum Leaf {
Literal(Literal),
Punct(Punct),
Ident(Ident),
}
+impl_froms!(Leaf: Literal, Punct, Ident);
pub(crate) struct Subtree {
- delimiter: Delimiter,
- token_trees: Vec<TokenTree>,
+ pub(crate) delimiter: Delimiter,
+ pub(crate) token_trees: Vec<TokenTree>,
}
pub(crate) enum Delimiter {
}
pub(crate) struct Literal {
- text: SmolStr,
+ pub(crate) text: SmolStr,
}
pub(crate) struct Punct {
- char: char,
+ pub(crate) char: char,
}
pub(crate) struct Ident {
- text: SmolStr,
+ pub(crate) text: SmolStr,
}