Auto merge of #16061 - Veykril:vec-completion, r=Veykril

fix: Fix fragment parser replacing matches with dummies on incomplete parses

Notably, this caused some completions in the `vec!` macro to no longer work. Fixes https://github.com/rust-lang/rust-analyzer/issues/15016
This commit is contained in:
bors 2023-12-13 09:59:13 +00:00
commit 94af6c63b7
2 changed files with 82 additions and 25 deletions

View file

@ -13,37 +13,97 @@ fn test_vec() {
check(
r#"
macro_rules! vec {
($($item:expr),*) => {{
let mut v = Vec::new();
$( v.push($item); )*
v
}};
() => (
$crate::__rust_force_expr!($crate::vec::Vec::new())
);
($elem:expr; $n:expr) => (
$crate::__rust_force_expr!($crate::vec::from_elem($elem, $n))
);
($($x:expr),+ $(,)?) => (
$crate::__rust_force_expr!(<[_]>::into_vec(
// This rustc_box is not required, but it produces a dramatic improvement in compile
// time when constructing arrays with many elements.
#[rustc_box]
$crate::boxed::Box::new([$($x),+])
))
);
}
macro_rules! __rust_force_expr {
($e:expr) => {
$e
};
}
fn main() {
vec!();
vec![1u32,2];
vec![a.];
}
"#,
expect![[r#"
macro_rules! vec {
($($item:expr),*) => {{
let mut v = Vec::new();
$( v.push($item); )*
v
}};
() => (
$crate::__rust_force_expr!($crate::vec::Vec::new())
);
($elem:expr; $n:expr) => (
$crate::__rust_force_expr!($crate::vec::from_elem($elem, $n))
);
($($x:expr),+ $(,)?) => (
$crate::__rust_force_expr!(<[_]>::into_vec(
// This rustc_box is not required, but it produces a dramatic improvement in compile
// time when constructing arrays with many elements.
#[rustc_box]
$crate::boxed::Box::new([$($x),+])
))
);
}
macro_rules! __rust_force_expr {
($e:expr) => {
$e
};
}
fn main() {
{
let mut v = Vec::new();
v
$crate::__rust_force_expr!($crate:: vec:: Vec:: new());
$crate::__rust_force_expr!(<[_]>:: into_vec(#[rustc_box]$crate:: boxed:: Box:: new([1u32, 2])));
/* error: expected Expr */$crate::__rust_force_expr!($crate:: vec:: from_elem((a.), $n));
}
"#]],
);
// FIXME we should ahev testing infra for multi level expansion tests
check(
r#"
macro_rules! __rust_force_expr {
($e:expr) => {
$e
};
{
let mut v = Vec::new();
v.push(1u32);
v.push(2);
v
}
fn main() {
__rust_force_expr!(crate:: vec:: Vec:: new());
__rust_force_expr!(<[_]>:: into_vec(#[rustc_box] crate:: boxed:: Box:: new([1u32, 2])));
__rust_force_expr/*+errors*/!(crate:: vec:: from_elem((a.), $n));
}
"#,
expect![[r#"
macro_rules! __rust_force_expr {
($e:expr) => {
$e
};
}
fn main() {
(crate ::vec::Vec::new());
(<[_]>::into_vec(#[rustc_box] crate ::boxed::Box::new([1u32, 2])));
/* error: expected Expr *//* parse error: expected field name or number */
/* parse error: expected expression */
/* parse error: expected R_PAREN */
/* parse error: expected COMMA */
/* parse error: expected expression, item or let statement */
(crate ::vec::from_elem((a.), $n));
}
"#]],
);
}

View file

@ -131,7 +131,6 @@ impl<'a, S: Span> TtIter<'a, S> {
let buffer = tt::buffer::TokenBuffer::from_tokens(self.inner.as_slice());
let parser_input = to_parser_input(&buffer);
let tree_traversal = entry_point.parse(&parser_input);
let mut cursor = buffer.begin();
let mut error = false;
for step in tree_traversal.iter() {
@ -163,12 +162,10 @@ impl<'a, S: Span> TtIter<'a, S> {
let mut curr = buffer.begin();
let mut res = vec![];
if cursor.is_root() {
while curr != cursor {
let Some(token) = curr.token_tree() else { break };
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();