aboutsummaryrefslogtreecommitdiff
path: root/crates/assists/src/handlers/generate_impl.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/assists/src/handlers/generate_impl.rs')
-rw-r--r--crates/assists/src/handlers/generate_impl.rs148
1 files changed, 0 insertions, 148 deletions
diff --git a/crates/assists/src/handlers/generate_impl.rs b/crates/assists/src/handlers/generate_impl.rs
deleted file mode 100644
index 9af45192b..000000000
--- a/crates/assists/src/handlers/generate_impl.rs
+++ /dev/null
@@ -1,148 +0,0 @@
1use itertools::Itertools;
2use stdx::format_to;
3use syntax::ast::{self, AstNode, AttrsOwner, GenericParamsOwner, NameOwner};
4
5use crate::{AssistContext, AssistId, AssistKind, Assists};
6
7// Assist: generate_impl
8//
9// Adds a new inherent impl for a type.
10//
11// ```
12// struct Ctx<T: Clone> {
13// data: T,$0
14// }
15// ```
16// ->
17// ```
18// struct Ctx<T: Clone> {
19// data: T,
20// }
21//
22// impl<T: Clone> Ctx<T> {
23// $0
24// }
25// ```
26pub(crate) fn generate_impl(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
27 let nominal = ctx.find_node_at_offset::<ast::AdtDef>()?;
28 let name = nominal.name()?;
29 let target = nominal.syntax().text_range();
30
31 acc.add(
32 AssistId("generate_impl", AssistKind::Generate),
33 format!("Generate impl for `{}`", name),
34 target,
35 |edit| {
36 let type_params = nominal.generic_param_list();
37 let start_offset = nominal.syntax().text_range().end();
38 let mut buf = String::new();
39 buf.push_str("\n\n");
40 nominal
41 .attrs()
42 .filter(|attr| {
43 attr.as_simple_call().map(|(name, _arg)| name == "cfg").unwrap_or(false)
44 })
45 .for_each(|attr| buf.push_str(format!("{}\n", attr.to_string()).as_str()));
46
47 buf.push_str("impl");
48 if let Some(type_params) = &type_params {
49 format_to!(buf, "{}", type_params.syntax());
50 }
51 buf.push_str(" ");
52 buf.push_str(name.text().as_str());
53 if let Some(type_params) = type_params {
54 let lifetime_params = type_params
55 .lifetime_params()
56 .filter_map(|it| it.lifetime())
57 .map(|it| it.text().clone());
58 let type_params = type_params
59 .type_params()
60 .filter_map(|it| it.name())
61 .map(|it| it.text().clone());
62
63 let generic_params = lifetime_params.chain(type_params).format(", ");
64 format_to!(buf, "<{}>", generic_params)
65 }
66 match ctx.config.snippet_cap {
67 Some(cap) => {
68 buf.push_str(" {\n $0\n}");
69 edit.insert_snippet(cap, start_offset, buf);
70 }
71 None => {
72 buf.push_str(" {\n}");
73 edit.insert(start_offset, buf);
74 }
75 }
76 },
77 )
78}
79
80#[cfg(test)]
81mod tests {
82 use crate::tests::{check_assist, check_assist_target};
83
84 use super::*;
85
86 #[test]
87 fn test_add_impl() {
88 check_assist(
89 generate_impl,
90 "struct Foo {$0}\n",
91 "struct Foo {}\n\nimpl Foo {\n $0\n}\n",
92 );
93 check_assist(
94 generate_impl,
95 "struct Foo<T: Clone> {$0}",
96 "struct Foo<T: Clone> {}\n\nimpl<T: Clone> Foo<T> {\n $0\n}",
97 );
98 check_assist(
99 generate_impl,
100 "struct Foo<'a, T: Foo<'a>> {$0}",
101 "struct Foo<'a, T: Foo<'a>> {}\n\nimpl<'a, T: Foo<'a>> Foo<'a, T> {\n $0\n}",
102 );
103 check_assist(
104 generate_impl,
105 r#"
106 #[cfg(feature = "foo")]
107 struct Foo<'a, T: Foo<'a>> {$0}"#,
108 r#"
109 #[cfg(feature = "foo")]
110 struct Foo<'a, T: Foo<'a>> {}
111
112 #[cfg(feature = "foo")]
113 impl<'a, T: Foo<'a>> Foo<'a, T> {
114 $0
115 }"#,
116 );
117
118 check_assist(
119 generate_impl,
120 r#"
121 #[cfg(not(feature = "foo"))]
122 struct Foo<'a, T: Foo<'a>> {$0}"#,
123 r#"
124 #[cfg(not(feature = "foo"))]
125 struct Foo<'a, T: Foo<'a>> {}
126
127 #[cfg(not(feature = "foo"))]
128 impl<'a, T: Foo<'a>> Foo<'a, T> {
129 $0
130 }"#,
131 );
132 }
133
134 #[test]
135 fn add_impl_target() {
136 check_assist_target(
137 generate_impl,
138 "
139struct SomeThingIrrelevant;
140/// Has a lifetime parameter
141struct Foo<'a, T: Foo<'a>> {$0}
142struct EvenMoreIrrelevant;
143",
144 "/// Has a lifetime parameter
145struct Foo<'a, T: Foo<'a>> {}",
146 );
147 }
148}