From e59487de38b1be5b06b92eb4a9d30c0adb32d9db Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Tue, 7 Feb 2023 17:12:24 +0100 Subject: [PATCH] Add tests for float access macro call inputs --- .../hir-def/src/macro_expansion_tests/mbe.rs | 35 ++++++++++++++++ crates/mbe/src/syntax_bridge.rs | 2 +- crates/mbe/src/to_parser_input.rs | 4 ++ crates/mbe/src/tt_iter.rs | 41 ++++--------------- crates/tt/src/buffer.rs | 13 +++++- 5 files changed, 58 insertions(+), 37 deletions(-) diff --git a/crates/hir-def/src/macro_expansion_tests/mbe.rs b/crates/hir-def/src/macro_expansion_tests/mbe.rs index 2d5f2a692e..49bbc64bff 100644 --- a/crates/hir-def/src/macro_expansion_tests/mbe.rs +++ b/crates/hir-def/src/macro_expansion_tests/mbe.rs @@ -97,6 +97,41 @@ fn#19 main#20(#21)#21 {#22 "##]], ); } +#[test] +fn float_field_acces_macro_input() { + check( + r#" +macro_rules! foo { + ($expr:expr) => { + fn foo() { + $expr; + } + }; +} +foo!(x .0.1); +foo!(x .2. 3); +foo!(x .4 .5); +"#, + expect![[r#" +macro_rules! foo { + ($expr:expr) => { + fn foo() { + $expr; + } + }; +} +fn foo() { + (x.0.1); +} +fn foo() { + (x.2.3); +} +fn foo() { + (x.4.5); +} +"#]], + ); +} #[test] fn mbe_smoke_test() { diff --git a/crates/mbe/src/syntax_bridge.rs b/crates/mbe/src/syntax_bridge.rs index 8b9a3bca02..a4e3efaeb5 100644 --- a/crates/mbe/src/syntax_bridge.rs +++ b/crates/mbe/src/syntax_bridge.rs @@ -817,7 +817,7 @@ impl<'a> TtTreeSink<'a> { self.inner.token(SyntaxKind::DOT, "."); if has_pseudo_dot { - assert!(right.is_empty()); + assert!(right.is_empty(), "{left}.{right}"); } else { self.inner.start_node(SyntaxKind::NAME_REF); self.inner.token(SyntaxKind::INT_NUMBER, right); diff --git a/crates/mbe/src/to_parser_input.rs b/crates/mbe/src/to_parser_input.rs index d4c19b3ab8..6d20998bb4 100644 --- a/crates/mbe/src/to_parser_input.rs +++ b/crates/mbe/src/to_parser_input.rs @@ -45,6 +45,10 @@ pub(crate) fn to_parser_input(buffer: &TokenBuffer<'_>) -> parser::Input { .unwrap_or_else(|| panic!("Fail to convert given literal {:#?}", &lit)); res.push(kind); + + if kind == FLOAT_NUMBER && !inner_text.ends_with('.') { + res.was_joint(); + } } tt::Leaf::Ident(ident) => match ident.text.as_ref() { "_" => res.push(T![_]), diff --git a/crates/mbe/src/tt_iter.rs b/crates/mbe/src/tt_iter.rs index c05a2ca150..f744481f3a 100644 --- a/crates/mbe/src/tt_iter.rs +++ b/crates/mbe/src/tt_iter.rs @@ -140,7 +140,6 @@ impl<'a> TtIter<'a> { let mut cursor = buffer.begin(); let mut error = false; - let mut float_splits = vec![]; for step in tree_traversal.iter() { match step { parser::Step::Token { kind, mut n_input_tokens } => { @@ -152,7 +151,8 @@ impl<'a> TtIter<'a> { } } parser::Step::FloatSplit { .. } => { - float_splits.push(cursor); + // FIXME: We need to split the tree properly here, but mutating the token trees + // in the buffer is somewhat tricky to pull off. cursor = cursor.bump_subtree(); } parser::Step::Enter { .. } | parser::Step::Exit => (), @@ -170,40 +170,13 @@ impl<'a> TtIter<'a> { let mut res = vec![]; if cursor.is_root() { - if float_splits.is_empty() { - while curr != cursor { - if let Some(token) = curr.token_tree() { - res.push(token.cloned()); - } - curr = curr.bump(); - } - } else { - // let mut float_splits = float_splits.into_iter().peekable(); - // while let Some(tt) = curr.token_tree() { - // let mut tt = tt.cloned(); - // let mut tt_mut_ref = &mut tt; - // if let Some(fs) = float_splits.peek() { - // loop { - // curr = curr.bump_subtree(); - // if curr == *fs { - // float_splits.next(); - // } - // if curr.is_root() { - // break; - // } - // } - // } - // res.push(tt); - // } - - while curr != cursor { - if let Some(token) = curr.token_tree() { - res.push(token.cloned()); - } - curr = curr.bump(); - } + while curr != cursor { + let Some(token) = curr.token_tree() else { break }; + res.push(token.cloned()); + curr = curr.bump(); } } + self.inner = self.inner.as_slice()[res.len()..].iter(); let res = match res.len() { 0 | 1 => res.pop(), diff --git a/crates/tt/src/buffer.rs b/crates/tt/src/buffer.rs index c4b455e3f1..0615a3763d 100644 --- a/crates/tt/src/buffer.rs +++ b/crates/tt/src/buffer.rs @@ -7,7 +7,12 @@ use crate::{Leaf, Subtree, TokenTree}; struct EntryId(usize); #[derive(Copy, Clone, Debug, Eq, PartialEq)] -struct EntryPtr(EntryId, usize); +struct EntryPtr( + /// The index of the buffer containing the entry. + EntryId, + /// The index of the entry within the buffer. + usize, +); /// Internal type which is used instead of `TokenTree` to represent a token tree /// within a `TokenBuffer`. @@ -229,7 +234,11 @@ impl<'a, Span> Cursor<'a, Span> { Some(&Entry::Subtree(_, _, entry_id)) => { Cursor::create(self.buffer, EntryPtr(entry_id, 0)) } - _ => self.bump(), + Some(Entry::End(exit)) => match exit { + Some(exit) => Cursor::create(self.buffer, *exit), + None => self, + }, + _ => Cursor::create(self.buffer, EntryPtr(self.ptr.0, self.ptr.1 + 1)), } }