aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/release.yaml34
-rw-r--r--crates/assists/src/handlers/generate_from_impl_for_enum.rs150
-rw-r--r--crates/assists/src/tests/generated.rs2
-rw-r--r--xtask/src/dist.rs2
4 files changed, 158 insertions, 30 deletions
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index 82448f719..32c7cf7ef 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -121,6 +121,34 @@ jobs:
121 name: dist-x86_64-unknown-linux-gnu 121 name: dist-x86_64-unknown-linux-gnu
122 path: ./dist 122 path: ./dist
123 123
124 dist-x86_64-unknown-linux-musl:
125 name: dist (x86_64-unknown-linux-musl)
126 runs-on: ubuntu-20.04
127 env:
128 RA_TARGET: x86_64-unknown-linux-musl
129 # For some reason `-crt-static` is not working for clang without lld
130 RUSTFLAGS: "-C link-arg=-fuse-ld=lld -C target-feature=-crt-static"
131 container:
132 image: rust:alpine
133 volumes:
134 - /usr/local/cargo/registry
135
136 steps:
137 - name: Install dependencies
138 run: apk add --no-cache git clang lld musl-dev
139
140 - name: Checkout repository
141 uses: actions/checkout@v2
142
143 - name: Dist
144 run: cargo xtask dist
145
146 - name: Upload artifacts
147 uses: actions/upload-artifact@v1
148 with:
149 name: dist-x86_64-unknown-linux-musl
150 path: ./dist
151
124 dist-aarch64-unknown-linux-gnu: 152 dist-aarch64-unknown-linux-gnu:
125 name: dist (aarch64-unknown-linux-gnu) 153 name: dist (aarch64-unknown-linux-gnu)
126 runs-on: ubuntu-16.04 154 runs-on: ubuntu-16.04
@@ -216,7 +244,7 @@ jobs:
216 publish: 244 publish:
217 name: publish 245 name: publish
218 runs-on: ubuntu-16.04 246 runs-on: ubuntu-16.04
219 needs: ['dist-x86_64-pc-windows-msvc', 'dist-aarch64-pc-windows-msvc', 'dist-x86_64-unknown-linux-gnu', 'dist-aarch64-unknown-linux-gnu', 'dist-x86_64-apple-darwin', 'dist-aarch64-apple-darwin'] 247 needs: ['dist-x86_64-pc-windows-msvc', 'dist-aarch64-pc-windows-msvc', 'dist-x86_64-unknown-linux-gnu', 'dist-x86_64-unknown-linux-musl', 'dist-aarch64-unknown-linux-gnu', 'dist-x86_64-apple-darwin', 'dist-aarch64-apple-darwin']
220 steps: 248 steps:
221 - name: Install Nodejs 249 - name: Install Nodejs
222 uses: actions/setup-node@v1 250 uses: actions/setup-node@v1
@@ -249,6 +277,10 @@ jobs:
249 path: dist 277 path: dist
250 - uses: actions/download-artifact@v1 278 - uses: actions/download-artifact@v1
251 with: 279 with:
280 name: dist-x86_64-unknown-linux-musl
281 path: dist
282 - uses: actions/download-artifact@v1
283 with:
252 name: dist-aarch64-unknown-linux-gnu 284 name: dist-aarch64-unknown-linux-gnu
253 path: dist 285 path: dist
254 - uses: actions/download-artifact@v1 286 - uses: actions/download-artifact@v1
diff --git a/crates/assists/src/handlers/generate_from_impl_for_enum.rs b/crates/assists/src/handlers/generate_from_impl_for_enum.rs
index d9af6ab11..f6febd3aa 100644
--- a/crates/assists/src/handlers/generate_from_impl_for_enum.rs
+++ b/crates/assists/src/handlers/generate_from_impl_for_enum.rs
@@ -1,6 +1,12 @@
1use ast::GenericParamsOwner;
1use ide_db::helpers::FamousDefs; 2use ide_db::helpers::FamousDefs;
2use ide_db::RootDatabase; 3use ide_db::RootDatabase;
3use syntax::ast::{self, AstNode, NameOwner}; 4use itertools::Itertools;
5use stdx::format_to;
6use syntax::{
7 ast::{self, AstNode, NameOwner},
8 SmolStr,
9};
4use test_utils::mark; 10use test_utils::mark;
5 11
6use crate::{AssistContext, AssistId, AssistKind, Assists}; 12use crate::{AssistContext, AssistId, AssistKind, Assists};
@@ -18,7 +24,7 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
18// 24//
19// impl From<u32> for A { 25// impl From<u32> for A {
20// fn from(v: u32) -> Self { 26// fn from(v: u32) -> Self {
21// A::One(v) 27// Self::One(v)
22// } 28// }
23// } 29// }
24// ``` 30// ```
@@ -26,17 +32,22 @@ pub(crate) fn generate_from_impl_for_enum(acc: &mut Assists, ctx: &AssistContext
26 let variant = ctx.find_node_at_offset::<ast::Variant>()?; 32 let variant = ctx.find_node_at_offset::<ast::Variant>()?;
27 let variant_name = variant.name()?; 33 let variant_name = variant.name()?;
28 let enum_name = variant.parent_enum().name()?; 34 let enum_name = variant.parent_enum().name()?;
29 let field_list = match variant.kind() { 35 let enum_type_params = variant.parent_enum().generic_param_list();
30 ast::StructKind::Tuple(field_list) => field_list, 36 let (field_name, field_type) = match variant.kind() {
31 _ => return None, 37 ast::StructKind::Tuple(field_list) => {
32 }; 38 if field_list.fields().count() != 1 {
33 if field_list.fields().count() != 1 { 39 return None;
34 return None; 40 }
35 } 41 (None, field_list.fields().next()?.ty()?)
36 let field_type = field_list.fields().next()?.ty()?; 42 }
37 let path = match field_type { 43 ast::StructKind::Record(field_list) => {
38 ast::Type::PathType(it) => it, 44 if field_list.fields().count() != 1 {
39 _ => return None, 45 return None;
46 }
47 let field = field_list.fields().next()?;
48 (Some(field.name()?), field.ty()?)
49 }
50 ast::StructKind::Unit => return None,
40 }; 51 };
41 52
42 if existing_from_impl(&ctx.sema, &variant).is_some() { 53 if existing_from_impl(&ctx.sema, &variant).is_some() {
@@ -51,18 +62,48 @@ pub(crate) fn generate_from_impl_for_enum(acc: &mut Assists, ctx: &AssistContext
51 target, 62 target,
52 |edit| { 63 |edit| {
53 let start_offset = variant.parent_enum().syntax().text_range().end(); 64 let start_offset = variant.parent_enum().syntax().text_range().end();
54 let buf = format!( 65 let mut buf = String::from("\n\nimpl");
55 r#" 66 if let Some(type_params) = &enum_type_params {
67 format_to!(buf, "{}", type_params.syntax());
68 }
69 format_to!(buf, " From<{}> for {}", field_type.syntax(), enum_name);
70 if let Some(type_params) = enum_type_params {
71 let lifetime_params = type_params
72 .lifetime_params()
73 .filter_map(|it| it.lifetime())
74 .map(|it| SmolStr::from(it.text()));
75 let type_params = type_params
76 .type_params()
77 .filter_map(|it| it.name())
78 .map(|it| SmolStr::from(it.text()));
56 79
57impl From<{0}> for {1} {{ 80 let generic_params = lifetime_params.chain(type_params).format(", ");
58 fn from(v: {0}) -> Self {{ 81 format_to!(buf, "<{}>", generic_params)
59 {1}::{2}(v) 82 }
83 if let Some(name) = field_name {
84 format_to!(
85 buf,
86 r#" {{
87 fn from({0}: {1}) -> Self {{
88 Self::{2} {{ {0} }}
89 }}
90}}"#,
91 name.text(),
92 field_type.syntax(),
93 variant_name,
94 );
95 } else {
96 format_to!(
97 buf,
98 r#" {{
99 fn from(v: {}) -> Self {{
100 Self::{}(v)
60 }} 101 }}
61}}"#, 102}}"#,
62 path.syntax(), 103 field_type.syntax(),
63 enum_name, 104 variant_name,
64 variant_name 105 );
65 ); 106 }
66 edit.insert(start_offset, buf); 107 edit.insert(start_offset, buf);
67 }, 108 },
68 ) 109 )
@@ -106,7 +147,7 @@ mod tests {
106 147
107impl From<u32> for A { 148impl From<u32> for A {
108 fn from(v: u32) -> Self { 149 fn from(v: u32) -> Self {
109 A::One(v) 150 Self::One(v)
110 } 151 }
111}"#, 152}"#,
112 ); 153 );
@@ -121,7 +162,7 @@ impl From<u32> for A {
121 162
122impl From<foo::bar::baz::Boo> for A { 163impl From<foo::bar::baz::Boo> for A {
123 fn from(v: foo::bar::baz::Boo) -> Self { 164 fn from(v: foo::bar::baz::Boo) -> Self {
124 A::One(v) 165 Self::One(v)
125 } 166 }
126}"#, 167}"#,
127 ); 168 );
@@ -145,7 +186,17 @@ impl From<foo::bar::baz::Boo> for A {
145 186
146 #[test] 187 #[test]
147 fn test_add_from_impl_struct_variant() { 188 fn test_add_from_impl_struct_variant() {
148 check_not_applicable("enum A { $0One { x: u32 } }"); 189 check_assist(
190 generate_from_impl_for_enum,
191 "enum A { $0One { x: u32 } }",
192 r#"enum A { One { x: u32 } }
193
194impl From<u32> for A {
195 fn from(x: u32) -> Self {
196 Self::One { x }
197 }
198}"#,
199 );
149 } 200 }
150 201
151 #[test] 202 #[test]
@@ -157,7 +208,7 @@ enum A { $0One(u32), }
157 208
158impl From<u32> for A { 209impl From<u32> for A {
159 fn from(v: u32) -> Self { 210 fn from(v: u32) -> Self {
160 A::One(v) 211 Self::One(v)
161 } 212 }
162} 213}
163"#, 214"#,
@@ -183,7 +234,7 @@ pub trait From<T> {
183 234
184impl From<u32> for A { 235impl From<u32> for A {
185 fn from(v: u32) -> Self { 236 fn from(v: u32) -> Self {
186 A::One(v) 237 Self::One(v)
187 } 238 }
188} 239}
189 240
@@ -198,4 +249,49 @@ pub trait From<T> {
198}"#, 249}"#,
199 ); 250 );
200 } 251 }
252
253 #[test]
254 fn test_add_from_impl_static_str() {
255 check_assist(
256 generate_from_impl_for_enum,
257 "enum A { $0One(&'static str) }",
258 r#"enum A { One(&'static str) }
259
260impl From<&'static str> for A {
261 fn from(v: &'static str) -> Self {
262 Self::One(v)
263 }
264}"#,
265 );
266 }
267
268 #[test]
269 fn test_add_from_impl_generic_enum() {
270 check_assist(
271 generate_from_impl_for_enum,
272 "enum Generic<T, U: Clone> { $0One(T), Two(U) }",
273 r#"enum Generic<T, U: Clone> { One(T), Two(U) }
274
275impl<T, U: Clone> From<T> for Generic<T, U> {
276 fn from(v: T) -> Self {
277 Self::One(v)
278 }
279}"#,
280 );
281 }
282
283 #[test]
284 fn test_add_from_impl_with_lifetime() {
285 check_assist(
286 generate_from_impl_for_enum,
287 "enum Generic<'a> { $0One(&'a i32) }",
288 r#"enum Generic<'a> { One(&'a i32) }
289
290impl<'a> From<&'a i32> for Generic<'a> {
291 fn from(v: &'a i32) -> Self {
292 Self::One(v)
293 }
294}"#,
295 );
296 }
201} 297}
diff --git a/crates/assists/src/tests/generated.rs b/crates/assists/src/tests/generated.rs
index 6f2b22bc2..0516deaff 100644
--- a/crates/assists/src/tests/generated.rs
+++ b/crates/assists/src/tests/generated.rs
@@ -499,7 +499,7 @@ enum A { One(u32) }
499 499
500impl From<u32> for A { 500impl From<u32> for A {
501 fn from(v: u32) -> Self { 501 fn from(v: u32) -> Self {
502 A::One(v) 502 Self::One(v)
503 } 503 }
504} 504}
505"#####, 505"#####,
diff --git a/xtask/src/dist.rs b/xtask/src/dist.rs
index 6bc34106b..56bf9f99d 100644
--- a/xtask/src/dist.rs
+++ b/xtask/src/dist.rs
@@ -59,7 +59,7 @@ fn dist_client(version: &str, release_tag: &str) -> Result<()> {
59 59
60fn dist_server() -> Result<()> { 60fn dist_server() -> Result<()> {
61 let target = get_target(); 61 let target = get_target();
62 if target.contains("-linux-gnu") { 62 if target.contains("-linux-gnu") || target.contains("-linux-musl") {
63 env::set_var("CC", "clang"); 63 env::set_var("CC", "clang");
64 } 64 }
65 65