Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 6ab2788

Browse files
committed
Migrate add_missing_match_arms to mutable ast
Requires a hack in order to work inside of macros
1 parent 35f2e82 commit 6ab2788

File tree

1 file changed

+33
-21
lines changed

1 file changed

+33
-21
lines changed

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

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,7 @@ use itertools::Itertools;
88
use syntax::ast::edit_in_place::Removable;
99
use syntax::ast::{self, make, AstNode, HasName, MatchArmList, MatchExpr, Pat};
1010

11-
use crate::{
12-
utils::{self, render_snippet, Cursor},
13-
AssistContext, AssistId, AssistKind, Assists,
14-
};
11+
use crate::{utils, AssistContext, AssistId, AssistKind, Assists};
1512

1613
// Assist: add_missing_match_arms
1714
//
@@ -202,7 +199,7 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
202199
AssistId("add_missing_match_arms", AssistKind::QuickFix),
203200
"Fill match arms",
204201
target_range,
205-
|builder| {
202+
|edit| {
206203
let new_match_arm_list = match_arm_list.clone_for_update();
207204

208205
// having any hidden variants means that we need a catch-all arm
@@ -252,24 +249,39 @@ pub(crate) fn add_missing_match_arms(acc: &mut Assists, ctx: &AssistContext<'_>)
252249
new_match_arm_list.add_arm(arm);
253250
}
254251

255-
let old_range = ctx.sema.original_range(match_arm_list.syntax()).range;
256-
match (first_new_arm, ctx.config.snippet_cap) {
257-
(Some(first_new_arm), Some(cap)) => {
258-
let extend_lifetime;
259-
let cursor =
260-
match first_new_arm.syntax().descendants().find_map(ast::WildcardPat::cast)
261-
{
262-
Some(it) => {
263-
extend_lifetime = it.syntax().clone();
264-
Cursor::Replace(&extend_lifetime)
265-
}
266-
None => Cursor::Before(first_new_arm.syntax()),
267-
};
268-
let snippet = render_snippet(cap, new_match_arm_list.syntax(), cursor);
269-
builder.replace_snippet(cap, old_range, snippet);
252+
if let (Some(first_new_arm), Some(cap)) = (first_new_arm, ctx.config.snippet_cap) {
253+
match first_new_arm.syntax().descendants().find_map(ast::WildcardPat::cast) {
254+
Some(it) => edit.add_placeholder_snippet(cap, it),
255+
None => edit.add_tabstop_before(cap, first_new_arm),
270256
}
271-
_ => builder.replace(old_range, new_match_arm_list.to_string()),
272257
}
258+
259+
// FIXME: Hack for mutable syntax trees not having great support for macros
260+
// Just replace the element that the original range came from
261+
let old_place = {
262+
// Find the original element
263+
let old_file_range = ctx.sema.original_range(match_arm_list.syntax());
264+
let file = ctx.sema.parse(old_file_range.file_id);
265+
let old_place = file.syntax().covering_element(old_file_range.range);
266+
267+
// Make `old_place` mut
268+
match old_place {
269+
syntax::SyntaxElement::Node(it) => {
270+
syntax::SyntaxElement::from(edit.make_syntax_mut(it))
271+
}
272+
syntax::SyntaxElement::Token(it) => {
273+
// Don't have a way to make tokens mut, so instead make the parent mut
274+
// and find the token again
275+
let parent = edit.make_syntax_mut(it.parent().unwrap());
276+
let mut_token =
277+
parent.covering_element(it.text_range()).into_token().unwrap();
278+
279+
syntax::SyntaxElement::from(mut_token)
280+
}
281+
}
282+
};
283+
284+
syntax::ted::replace(old_place, new_match_arm_list.syntax());
273285
},
274286
)
275287
}

0 commit comments

Comments
 (0)