Skip to content

Commit a6e71ba

Browse files
authored
Merge pull request #19740 from vishruth-thimmaiah/unwrap_path_type
feat: add an assist to unwrap a type with a generic arg
2 parents d24c37e + 77f7a9a commit a6e71ba

File tree

3 files changed

+175
-0
lines changed

3 files changed

+175
-0
lines changed
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
use ide_db::assists::AssistId;
2+
use syntax::{
3+
AstNode,
4+
ast::{self, GenericArg, HasGenericArgs},
5+
};
6+
7+
use crate::{AssistContext, Assists};
8+
9+
// Assist: unwrap_type_to_generic_arg
10+
//
11+
// This assist unwraps a type into its generic type argument.
12+
//
13+
// ```
14+
// fn foo() -> $0Option<i32> {
15+
// todo!()
16+
// }
17+
// ```
18+
// ->
19+
// ```
20+
// fn foo() -> i32 {
21+
// todo!()
22+
// }
23+
// ```
24+
pub(crate) fn unwrap_type_to_generic_arg(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
25+
let path_type = ctx.find_node_at_offset::<ast::PathType>()?;
26+
let path = path_type.path()?;
27+
let segment = path.segment()?;
28+
let args_list = segment.generic_arg_list()?;
29+
30+
let mut generic_arg = None;
31+
32+
for arg in args_list.generic_args() {
33+
match arg {
34+
GenericArg::ConstArg(_) | GenericArg::LifetimeArg(_) => (),
35+
GenericArg::TypeArg(arg) if generic_arg.is_none() => {
36+
generic_arg = Some(arg);
37+
}
38+
_ => return None,
39+
}
40+
}
41+
42+
let generic_arg = generic_arg?;
43+
44+
acc.add(
45+
AssistId::refactor_extract("unwrap_type_to_generic_arg"),
46+
format!("Unwrap type to type argument {generic_arg}"),
47+
path_type.syntax().text_range(),
48+
|builder| {
49+
let mut editor = builder.make_editor(path_type.syntax());
50+
editor.replace(path_type.syntax(), generic_arg.syntax());
51+
52+
builder.add_file_edits(ctx.vfs_file_id(), editor);
53+
},
54+
)
55+
}
56+
57+
#[cfg(test)]
58+
mod tests {
59+
use super::*;
60+
use crate::tests::{check_assist, check_assist_not_applicable};
61+
62+
#[test]
63+
fn test_unwrap_type_to_generic_arg() {
64+
check_assist(
65+
unwrap_type_to_generic_arg,
66+
r#"
67+
//- minicore: option
68+
fn foo() -> $0Option<i32> {
69+
todo!()
70+
}
71+
"#,
72+
r#"
73+
fn foo() -> i32 {
74+
todo!()
75+
}
76+
"#,
77+
);
78+
}
79+
80+
#[test]
81+
fn unwrap_type_to_generic_arg_not_applicable_for_non_generic_arg_list() {
82+
check_assist_not_applicable(
83+
unwrap_type_to_generic_arg,
84+
r#"
85+
fn foo() -> $0i32 {}
86+
"#,
87+
);
88+
}
89+
90+
#[test]
91+
fn unwrap_type_to_generic_arg_not_applicable_for_multiple_generic_args() {
92+
check_assist_not_applicable(
93+
unwrap_type_to_generic_arg,
94+
r#"
95+
//- minicore: result
96+
fn foo() -> $0Result<i32, ()> {
97+
todo!()
98+
}
99+
"#,
100+
);
101+
}
102+
103+
#[test]
104+
fn unwrap_type_to_generic_arg_with_lifetime_and_const() {
105+
check_assist(
106+
unwrap_type_to_generic_arg,
107+
r#"
108+
enum Foo<'a, T, const N: usize> {
109+
Bar(T),
110+
Baz(&'a [T; N]),
111+
}
112+
113+
fn test<'a>() -> $0Foo<'a, i32, 3> {
114+
todo!()
115+
}
116+
"#,
117+
r#"
118+
enum Foo<'a, T, const N: usize> {
119+
Bar(T),
120+
Baz(&'a [T; N]),
121+
}
122+
123+
fn test<'a>() -> i32 {
124+
todo!()
125+
}
126+
"#,
127+
);
128+
}
129+
130+
#[test]
131+
fn unwrap_type_to_generic_arg_in_let_stmt() {
132+
check_assist(
133+
unwrap_type_to_generic_arg,
134+
r#"
135+
enum Foo<T> {
136+
Bar(T),
137+
Baz,
138+
}
139+
140+
fn test() {
141+
let foo: $0Foo<i32> = todo!();
142+
}
143+
"#,
144+
r#"
145+
enum Foo<T> {
146+
Bar(T),
147+
Baz,
148+
}
149+
150+
fn test() {
151+
let foo: i32 = todo!();
152+
}
153+
"#,
154+
);
155+
}
156+
}

src/tools/rust-analyzer/crates/ide-assists/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ mod handlers {
229229
mod unwrap_block;
230230
mod unwrap_return_type;
231231
mod unwrap_tuple;
232+
mod unwrap_type_to_generic_arg;
232233
mod wrap_return_type;
233234
mod wrap_unwrap_cfg_attr;
234235

@@ -369,6 +370,7 @@ mod handlers {
369370
unwrap_block::unwrap_block,
370371
unwrap_return_type::unwrap_return_type,
371372
unwrap_tuple::unwrap_tuple,
373+
unwrap_type_to_generic_arg::unwrap_type_to_generic_arg,
372374
wrap_return_type::wrap_return_type,
373375
wrap_unwrap_cfg_attr::wrap_unwrap_cfg_attr,
374376

src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3481,6 +3481,23 @@ fn main() {
34813481
)
34823482
}
34833483

3484+
#[test]
3485+
fn doctest_unwrap_type_to_generic_arg() {
3486+
check_doc_test(
3487+
"unwrap_type_to_generic_arg",
3488+
r#####"
3489+
fn foo() -> $0Option<i32> {
3490+
todo!()
3491+
}
3492+
"#####,
3493+
r#####"
3494+
fn foo() -> i32 {
3495+
todo!()
3496+
}
3497+
"#####,
3498+
)
3499+
}
3500+
34843501
#[test]
34853502
fn doctest_wrap_return_type_in_option() {
34863503
check_doc_test(

0 commit comments

Comments
 (0)