Skip to content

Commit a52e86f

Browse files
Merge #1112
1112: Fix literal support in token tree to ast item list r=matklad a=edwin0cheng This PR implements following things : 1. Expose `next_token` from `ra_parse` 2. Fix the literal conversion in `token_tree_to_ast_item_list` 3. Add test for the conversion Co-authored-by: Edwin Cheng <[email protected]>
2 parents be9a44e + 7abc06b commit a52e86f

File tree

5 files changed

+101
-7
lines changed

5 files changed

+101
-7
lines changed

crates/ra_mbe/src/lib.rs

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ impl_froms!(TokenTree: Leaf, Subtree);
167167
)
168168
}
169169

170-
fn create_rules(macro_definition: &str) -> MacroRules {
170+
pub(crate) fn create_rules(macro_definition: &str) -> MacroRules {
171171
let source_file = ast::SourceFile::parse(macro_definition);
172172
let macro_definition =
173173
source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap();
@@ -176,7 +176,7 @@ impl_froms!(TokenTree: Leaf, Subtree);
176176
crate::MacroRules::parse(&definition_tt).unwrap()
177177
}
178178

179-
fn expand(rules: &MacroRules, invocation: &str) -> tt::Subtree {
179+
pub(crate) fn expand(rules: &MacroRules, invocation: &str) -> tt::Subtree {
180180
let source_file = ast::SourceFile::parse(invocation);
181181
let macro_invocation =
182182
source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap();
@@ -186,7 +186,7 @@ impl_froms!(TokenTree: Leaf, Subtree);
186186
rules.expand(&invocation_tt).unwrap()
187187
}
188188

189-
fn assert_expansion(rules: &MacroRules, invocation: &str, expansion: &str) {
189+
pub(crate) fn assert_expansion(rules: &MacroRules, invocation: &str, expansion: &str) {
190190
let expanded = expand(rules, invocation);
191191
assert_eq!(expanded.to_string(), expansion);
192192
}
@@ -337,4 +337,46 @@ SOURCE_FILE@[0; 40)
337337
);
338338
}
339339

340+
#[test]
341+
fn expand_literals_to_token_tree() {
342+
fn to_subtree(tt: &tt::TokenTree) -> &tt::Subtree {
343+
if let tt::TokenTree::Subtree(subtree) = tt {
344+
return &subtree;
345+
}
346+
unreachable!("It is not a subtree");
347+
}
348+
349+
fn to_literal(tt: &tt::TokenTree) -> &tt::Literal {
350+
if let tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) = tt {
351+
return lit;
352+
}
353+
unreachable!("It is not a literal");
354+
}
355+
356+
let rules = create_rules(
357+
r#"
358+
macro_rules! literals {
359+
($i:ident) => {
360+
{
361+
let a = 'c';
362+
let c = 1000;
363+
let f = 12E+99_f64;
364+
let s = "rust1";
365+
}
366+
}
367+
}
368+
"#,
369+
);
370+
let expansion = expand(&rules, "literals!(foo)");
371+
let stm_tokens = &to_subtree(&expansion.token_trees[0]).token_trees;
372+
373+
// [let] [a] [=] ['c'] [;]
374+
assert_eq!(to_literal(&stm_tokens[3]).text, "'c'");
375+
// [let] [c] [=] [1000] [;]
376+
assert_eq!(to_literal(&stm_tokens[5 + 3]).text, "1000");
377+
// [let] [f] [=] [12E+99_f64] [;]
378+
assert_eq!(to_literal(&stm_tokens[10 + 3]).text, "12E+99_f64");
379+
// [let] [s] [=] ["rust1"] [;]
380+
assert_eq!(to_literal(&stm_tokens[15 + 3]).text, "\"rust1\"");
381+
}
340382
}

crates/ra_mbe/src/syntax_bridge.rs

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use ra_parser::{TokenSource, TreeSink, ParseError};
22
use ra_syntax::{
33
AstNode, SyntaxNode, TextRange, SyntaxKind, SmolStr, SyntaxTreeBuilder, TreeArc, SyntaxElement,
4-
ast, SyntaxKind::*, TextUnit
4+
ast, SyntaxKind::*, TextUnit, classify_literal
55
};
66

77
/// Maps `tt::TokenId` to the relative range of the original token.
@@ -103,10 +103,12 @@ fn convert_tt(
103103
Some(res)
104104
}
105105

106+
#[derive(Debug)]
106107
struct TtTokenSource {
107108
tokens: Vec<TtToken>,
108109
}
109110

111+
#[derive(Debug)]
110112
struct TtToken {
111113
kind: SyntaxKind,
112114
is_joint_to_next: bool,
@@ -189,7 +191,7 @@ impl TtTokenSource {
189191
{
190192
let tok = match token {
191193
tt::Leaf::Literal(l) => TtToken {
192-
kind: SyntaxKind::INT_NUMBER, // FIXME
194+
kind: classify_literal(&l.text).unwrap().kind,
193195
is_joint_to_next: false,
194196
text: l.text.clone(),
195197
},
@@ -355,3 +357,44 @@ impl<'a> TreeSink for TtTreeSink<'a> {
355357
self.inner.error(error, self.text_pos)
356358
}
357359
}
360+
361+
#[cfg(test)]
362+
mod tests {
363+
use super::*;
364+
use crate::tests::{expand, create_rules};
365+
366+
#[test]
367+
fn convert_tt_token_source() {
368+
let rules = create_rules(
369+
r#"
370+
macro_rules! literals {
371+
($i:ident) => {
372+
{
373+
let a = 'c';
374+
let c = 1000;
375+
let f = 12E+99_f64;
376+
let s = "rust1";
377+
}
378+
}
379+
}
380+
"#,
381+
);
382+
let expansion = expand(&rules, "literals!(foo)");
383+
let tt_src = TtTokenSource::new(&expansion);
384+
385+
// [{]
386+
// [let] [a] [=] ['c'] [;]
387+
assert_eq!(tt_src.tokens[1 + 3].text, "'c'");
388+
assert_eq!(tt_src.tokens[1 + 3].kind, CHAR);
389+
// [let] [c] [=] [1000] [;]
390+
assert_eq!(tt_src.tokens[1 + 5 + 3].text, "1000");
391+
assert_eq!(tt_src.tokens[1 + 5 + 3].kind, INT_NUMBER);
392+
// [let] [f] [=] [12E+99_f64] [;]
393+
assert_eq!(tt_src.tokens[1 + 10 + 3].text, "12E+99_f64");
394+
assert_eq!(tt_src.tokens[1 + 10 + 3].kind, FLOAT_NUMBER);
395+
396+
// [let] [s] [=] ["rust1"] [;]
397+
assert_eq!(tt_src.tokens[1 + 15 + 3].text, "\"rust1\"");
398+
assert_eq!(tt_src.tokens[1 + 15 + 3].kind, STRING);
399+
}
400+
}

crates/ra_syntax/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ pub use crate::{
4040
syntax_text::SyntaxText,
4141
syntax_node::{Direction, SyntaxNode, WalkEvent, TreeArc, SyntaxTreeBuilder, SyntaxElement, SyntaxToken},
4242
ptr::{SyntaxNodePtr, AstPtr},
43-
parsing::{tokenize, Token},
43+
parsing::{tokenize, classify_literal, Token},
4444
};
4545

4646
use ra_text_edit::AtomTextEdit;

crates/ra_syntax/src/parsing.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::{
1111
syntax_node::GreenNode,
1212
};
1313

14-
pub use self::lexer::{tokenize, Token};
14+
pub use self::lexer::{tokenize, classify_literal, Token};
1515

1616
pub(crate) use self::reparsing::incremental_reparse;
1717

crates/ra_syntax/src/parsing/lexer.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,3 +214,12 @@ fn scan_literal_suffix(ptr: &mut Ptr) {
214214
}
215215
ptr.bump_while(is_ident_continue);
216216
}
217+
218+
pub fn classify_literal(text: &str) -> Option<Token> {
219+
let tkn = next_token(text);
220+
if !tkn.kind.is_literal() || tkn.len.to_usize() != text.len() {
221+
return None;
222+
}
223+
224+
Some(tkn)
225+
}

0 commit comments

Comments
 (0)