]> git.lizzy.rs Git - rust.git/blob - src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_impl.rs
Rollup merge of #99460 - JanBeh:PR_asref_asmut_docs, r=joshtriplett
[rust.git] / src / tools / rust-analyzer / crates / ide-assists / src / handlers / generate_impl.rs
1 use syntax::ast::{self, AstNode, HasName};
2
3 use crate::{utils::generate_impl_text, AssistContext, AssistId, AssistKind, Assists};
4
5 // Assist: generate_impl
6 //
7 // Adds a new inherent impl for a type.
8 //
9 // ```
10 // struct Ctx<T: Clone> {
11 //     data: T,$0
12 // }
13 // ```
14 // ->
15 // ```
16 // struct Ctx<T: Clone> {
17 //     data: T,
18 // }
19 //
20 // impl<T: Clone> Ctx<T> {
21 //     $0
22 // }
23 // ```
24 pub(crate) fn generate_impl(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
25     let nominal = ctx.find_node_at_offset::<ast::Adt>()?;
26     let name = nominal.name()?;
27     let target = nominal.syntax().text_range();
28
29     acc.add(
30         AssistId("generate_impl", AssistKind::Generate),
31         format!("Generate impl for `{}`", name),
32         target,
33         |edit| {
34             let start_offset = nominal.syntax().text_range().end();
35             match ctx.config.snippet_cap {
36                 Some(cap) => {
37                     let snippet = generate_impl_text(&nominal, "    $0");
38                     edit.insert_snippet(cap, start_offset, snippet);
39                 }
40                 None => {
41                     let snippet = generate_impl_text(&nominal, "");
42                     edit.insert(start_offset, snippet);
43                 }
44             }
45         },
46     )
47 }
48
49 #[cfg(test)]
50 mod tests {
51     use crate::tests::{check_assist, check_assist_target};
52
53     use super::*;
54
55     #[test]
56     fn test_add_impl() {
57         check_assist(
58             generate_impl,
59             "struct Foo {$0}\n",
60             "struct Foo {}\n\nimpl Foo {\n    $0\n}\n",
61         );
62         check_assist(
63             generate_impl,
64             "struct Foo<T: Clone> {$0}",
65             "struct Foo<T: Clone> {}\n\nimpl<T: Clone> Foo<T> {\n    $0\n}",
66         );
67         check_assist(
68             generate_impl,
69             "struct Foo<'a, T: Foo<'a>> {$0}",
70             "struct Foo<'a, T: Foo<'a>> {}\n\nimpl<'a, T: Foo<'a>> Foo<'a, T> {\n    $0\n}",
71         );
72         check_assist(
73             generate_impl,
74             r#"
75             struct MyOwnArray<T, const S: usize> {}$0"#,
76             r#"
77             struct MyOwnArray<T, const S: usize> {}
78
79             impl<T, const S: usize> MyOwnArray<T, S> {
80                 $0
81             }"#,
82         );
83         check_assist(
84             generate_impl,
85             r#"
86             #[cfg(feature = "foo")]
87             struct Foo<'a, T: Foo<'a>> {$0}"#,
88             r#"
89             #[cfg(feature = "foo")]
90             struct Foo<'a, T: Foo<'a>> {}
91
92             #[cfg(feature = "foo")]
93             impl<'a, T: Foo<'a>> Foo<'a, T> {
94                 $0
95             }"#,
96         );
97
98         check_assist(
99             generate_impl,
100             r#"
101             #[cfg(not(feature = "foo"))]
102             struct Foo<'a, T: Foo<'a>> {$0}"#,
103             r#"
104             #[cfg(not(feature = "foo"))]
105             struct Foo<'a, T: Foo<'a>> {}
106
107             #[cfg(not(feature = "foo"))]
108             impl<'a, T: Foo<'a>> Foo<'a, T> {
109                 $0
110             }"#,
111         );
112
113         check_assist(
114             generate_impl,
115             r#"
116             struct Defaulted<T = i32> {}$0"#,
117             r#"
118             struct Defaulted<T = i32> {}
119
120             impl<T> Defaulted<T> {
121                 $0
122             }"#,
123         );
124
125         check_assist(
126             generate_impl,
127             r#"
128             struct Defaulted<'a, 'b: 'a, T: Debug + Clone + 'a + 'b = String, const S: usize> {}$0"#,
129             r#"
130             struct Defaulted<'a, 'b: 'a, T: Debug + Clone + 'a + 'b = String, const S: usize> {}
131
132             impl<'a, 'b: 'a, T: Debug + Clone + 'a + 'b, const S: usize> Defaulted<'a, 'b, T, S> {
133                 $0
134             }"#,
135         );
136
137         check_assist(
138             generate_impl,
139             r#"pub trait Trait {}
140 struct Struct<T>$0
141 where
142     T: Trait,
143 {
144     inner: T,
145 }"#,
146             r#"pub trait Trait {}
147 struct Struct<T>
148 where
149     T: Trait,
150 {
151     inner: T,
152 }
153
154 impl<T> Struct<T>
155 where
156     T: Trait,
157 {
158     $0
159 }"#,
160         );
161     }
162
163     #[test]
164     fn add_impl_target() {
165         check_assist_target(
166             generate_impl,
167             "
168 struct SomeThingIrrelevant;
169 /// Has a lifetime parameter
170 struct Foo<'a, T: Foo<'a>> {$0}
171 struct EvenMoreIrrelevant;
172 ",
173             "/// Has a lifetime parameter
174 struct Foo<'a, T: Foo<'a>> {}",
175         );
176     }
177 }