Skip to content

Commit f6bffa4

Browse files
committed
Auto merge of #15345 - lowr:fix/add_missing_match_arms-upmap-failure, r=Veykril
Don't provide `add_missing_match_arms` assist when upmapping match arm list failed Fixes #15310 We shouldn't provide the assist when we fail to find the original match arm list. Note that this PR will temporarily make the assist not applicable when attribute macro operates on the match expression in question, just like the case in #15310, for most of the current stable toolchain users. This is because the sysroot-abi proc-macro-srv on the current stable [discards] spans for `Group` delimiters in some code paths, which the popular `proc-macro2` crate almost always calls, and it makes the identity of match arm list's brackets lost, leading to the upmapping failure. This has been fixed by #14960, which will land in the next stable, 1.71. [discards]: https://github.com/rust-lang/rust/blob/8ede3aae28fe6e4d52b38157d7bfe0d3bceef225/src/tools/rust-analyzer/crates/proc-macro-srv/src/abis/abi_sysroot/ra_server.rs#L231
2 parents efc5a81 + fbec711 commit f6bffa4

File tree

3 files changed

+37
-17
lines changed

3 files changed

+37
-17
lines changed

crates/ide-assists/src/handlers/add_missing_match_arms.rs

+25-6
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ use crate::{utils, AssistContext, AssistId, AssistKind, Assists};
3737
pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
3838
let match_expr = ctx.find_node_at_offset_with_descend::<ast::MatchExpr>()?;
3939
let match_arm_list = match_expr.match_arm_list()?;
40-
let target_range = ctx.sema.original_range(match_expr.syntax()).range;
40+
let arm_list_range = ctx.sema.original_range_opt(match_arm_list.syntax())?;
4141

42-
if let None = cursor_at_trivial_match_arm_list(ctx, &match_expr, &match_arm_list) {
42+
if cursor_at_trivial_match_arm_list(ctx, &match_expr, &match_arm_list).is_none() {
4343
let arm_list_range = ctx.sema.original_range(match_arm_list.syntax()).range;
4444
let cursor_in_range = arm_list_range.contains_range(ctx.selection_trimmed());
4545
if cursor_in_range {
@@ -198,7 +198,7 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
198198
acc.add(
199199
AssistId("add_missing_match_arms", AssistKind::QuickFix),
200200
"Fill match arms",
201-
target_range,
201+
ctx.sema.original_range(match_expr.syntax()).range,
202202
|edit| {
203203
let new_match_arm_list = match_arm_list.clone_for_update();
204204

@@ -262,9 +262,8 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
262262
// Just replace the element that the original range came from
263263
let old_place = {
264264
// Find the original element
265-
let old_file_range = ctx.sema.original_range(match_arm_list.syntax());
266-
let file = ctx.sema.parse(old_file_range.file_id);
267-
let old_place = file.syntax().covering_element(old_file_range.range);
265+
let file = ctx.sema.parse(arm_list_range.file_id);
266+
let old_place = file.syntax().covering_element(arm_list_range.range);
268267

269268
// Make `old_place` mut
270269
match old_place {
@@ -1922,4 +1921,24 @@ fn foo(t: E) {
19221921
}"#,
19231922
);
19241923
}
1924+
1925+
#[test]
1926+
fn not_applicable_when_match_arm_list_cannot_be_upmapped() {
1927+
check_assist_not_applicable(
1928+
add_missing_match_arms,
1929+
r#"
1930+
macro_rules! foo {
1931+
($($t:tt)*) => {
1932+
$($t)* {}
1933+
}
1934+
}
1935+
1936+
enum E { A }
1937+
1938+
fn main() {
1939+
foo!(match E::A$0);
1940+
}
1941+
"#,
1942+
);
1943+
}
19251944
}

crates/proc-macro-srv/src/server.rs

+11-10
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ use token_stream::TokenStreamBuilder;
1717
mod symbol;
1818
pub use symbol::*;
1919

20-
use std::ops::{Bound, Range};
20+
use std::{
21+
iter,
22+
ops::{Bound, Range},
23+
};
2124

2225
use crate::tt;
2326

@@ -80,9 +83,7 @@ impl server::TokenStream for RustAnalyzer {
8083
stream.is_empty()
8184
}
8285
fn from_str(&mut self, src: &str) -> Self::TokenStream {
83-
use std::str::FromStr;
84-
85-
Self::TokenStream::from_str(src).expect("cannot parse string")
86+
src.parse().expect("cannot parse string")
8687
}
8788
fn to_string(&mut self, stream: &Self::TokenStream) -> String {
8889
stream.to_string()
@@ -101,7 +102,7 @@ impl server::TokenStream for RustAnalyzer {
101102
},
102103
};
103104
let tree = TokenTree::from(group);
104-
Self::TokenStream::from_iter(vec![tree])
105+
Self::TokenStream::from_iter(iter::once(tree))
105106
}
106107

107108
bridge::TokenTree::Ident(ident) => {
@@ -111,7 +112,7 @@ impl server::TokenStream for RustAnalyzer {
111112
let ident: tt::Ident = tt::Ident { text, span: ident.span };
112113
let leaf = tt::Leaf::from(ident);
113114
let tree = TokenTree::from(leaf);
114-
Self::TokenStream::from_iter(vec![tree])
115+
Self::TokenStream::from_iter(iter::once(tree))
115116
}
116117

117118
bridge::TokenTree::Literal(literal) => {
@@ -123,7 +124,7 @@ impl server::TokenStream for RustAnalyzer {
123124
let literal = tt::Literal { text, span: literal.0.span };
124125
let leaf = tt::Leaf::from(literal);
125126
let tree = TokenTree::from(leaf);
126-
Self::TokenStream::from_iter(vec![tree])
127+
Self::TokenStream::from_iter(iter::once(tree))
127128
}
128129

129130
bridge::TokenTree::Punct(p) => {
@@ -134,7 +135,7 @@ impl server::TokenStream for RustAnalyzer {
134135
};
135136
let leaf = tt::Leaf::from(punct);
136137
let tree = TokenTree::from(leaf);
137-
Self::TokenStream::from_iter(vec![tree])
138+
Self::TokenStream::from_iter(iter::once(tree))
138139
}
139140
}
140141
}
@@ -355,12 +356,12 @@ impl server::Server for RustAnalyzer {
355356
}
356357

357358
fn intern_symbol(ident: &str) -> Self::Symbol {
358-
// FIXME: should be self.interner once the proc-macro api allows is
359+
// FIXME: should be `self.interner` once the proc-macro api allows it.
359360
Symbol::intern(&SYMBOL_INTERNER, &::tt::SmolStr::from(ident))
360361
}
361362

362363
fn with_symbol_string(symbol: &Self::Symbol, f: impl FnOnce(&str)) {
363-
// FIXME: should be self.interner once the proc-macro api allows is
364+
// FIXME: should be `self.interner` once the proc-macro api allows it.
364365
f(symbol.text(&SYMBOL_INTERNER).as_str())
365366
}
366367
}

crates/tt/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ pub mod token_id {
6565
}
6666
impl TokenTree {
6767
pub const fn empty() -> Self {
68-
Self::Subtree(Subtree { delimiter: Delimiter::unspecified(), token_trees: vec![] })
68+
Self::Subtree(Subtree::empty())
6969
}
7070
}
7171

0 commit comments

Comments
 (0)