diff options
-rw-r--r-- | crates/ide/src/diagnostics.rs | 99 |
1 files changed, 94 insertions, 5 deletions
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs index d3d8c86b5..c36c321f2 100644 --- a/crates/ide/src/diagnostics.rs +++ b/crates/ide/src/diagnostics.rs | |||
@@ -192,7 +192,8 @@ fn check_field_shorthand(acc: &mut Vec<Diagnostic>, file_id: FileId, node: &Synt | |||
192 | match_ast! { | 192 | match_ast! { |
193 | match node { | 193 | match node { |
194 | ast::RecordExpr(it) => check_expr_field_shorthand(acc, file_id, it), | 194 | ast::RecordExpr(it) => check_expr_field_shorthand(acc, file_id, it), |
195 | _ => None | 195 | ast::RecordPat(it) => check_pat_field_shorthand(acc, file_id, it), |
196 | _ => () | ||
196 | } | 197 | } |
197 | }; | 198 | }; |
198 | } | 199 | } |
@@ -200,11 +201,11 @@ fn check_field_shorthand(acc: &mut Vec<Diagnostic>, file_id: FileId, node: &Synt | |||
200 | fn check_expr_field_shorthand( | 201 | fn check_expr_field_shorthand( |
201 | acc: &mut Vec<Diagnostic>, | 202 | acc: &mut Vec<Diagnostic>, |
202 | file_id: FileId, | 203 | file_id: FileId, |
203 | record_lit: ast::RecordExpr, | 204 | record_expr: ast::RecordExpr, |
204 | ) { | 205 | ) { |
205 | let record_field_list = match record_lit.record_expr_field_list() { | 206 | let record_field_list = match record_expr.record_expr_field_list() { |
206 | Some(it) => it, | 207 | Some(it) => it, |
207 | None => (), | 208 | None => return, |
208 | }; | 209 | }; |
209 | for record_field in record_field_list.fields() { | 210 | for record_field in record_field_list.fields() { |
210 | let (name_ref, expr) = match record_field.name_ref().zip(record_field.expr()) { | 211 | let (name_ref, expr) = match record_field.name_ref().zip(record_field.expr()) { |
@@ -239,6 +240,48 @@ fn check_expr_field_shorthand( | |||
239 | } | 240 | } |
240 | } | 241 | } |
241 | 242 | ||
243 | fn check_pat_field_shorthand( | ||
244 | acc: &mut Vec<Diagnostic>, | ||
245 | file_id: FileId, | ||
246 | record_pat: ast::RecordPat, | ||
247 | ) { | ||
248 | let record_pat_field_list = match record_pat.record_pat_field_list() { | ||
249 | Some(it) => it, | ||
250 | None => return, | ||
251 | }; | ||
252 | for record_pat_field in record_pat_field_list.fields() { | ||
253 | let (name_ref, pat) = match record_pat_field.name_ref().zip(record_pat_field.pat()) { | ||
254 | Some(it) => it, | ||
255 | None => continue, | ||
256 | }; | ||
257 | |||
258 | let field_name = name_ref.syntax().text().to_string(); | ||
259 | let field_pat = pat.syntax().text().to_string(); | ||
260 | let field_name_is_tup_index = name_ref.as_tuple_field().is_some(); | ||
261 | if field_name != field_pat || field_name_is_tup_index { | ||
262 | continue; | ||
263 | } | ||
264 | |||
265 | let mut edit_builder = TextEdit::builder(); | ||
266 | edit_builder.delete(record_pat_field.syntax().text_range()); | ||
267 | edit_builder.insert(record_pat_field.syntax().text_range().start(), field_name); | ||
268 | let edit = edit_builder.finish(); | ||
269 | |||
270 | let field_range = record_pat_field.syntax().text_range(); | ||
271 | acc.push(Diagnostic { | ||
272 | // name: None, | ||
273 | range: field_range, | ||
274 | message: "Shorthand struct pattern".to_string(), | ||
275 | severity: Severity::WeakWarning, | ||
276 | fix: Some(Fix::new( | ||
277 | "Use struct field shorthand", | ||
278 | SourceFileEdit { file_id, edit }.into(), | ||
279 | field_range, | ||
280 | )), | ||
281 | }); | ||
282 | } | ||
283 | } | ||
284 | |||
242 | #[cfg(test)] | 285 | #[cfg(test)] |
243 | mod tests { | 286 | mod tests { |
244 | use expect_test::{expect, Expect}; | 287 | use expect_test::{expect, Expect}; |
@@ -735,7 +778,7 @@ mod a { | |||
735 | } | 778 | } |
736 | 779 | ||
737 | #[test] | 780 | #[test] |
738 | fn test_check_struct_shorthand_initialization() { | 781 | fn test_check_expr_field_shorthand() { |
739 | check_no_diagnostics( | 782 | check_no_diagnostics( |
740 | r#" | 783 | r#" |
741 | struct A { a: &'static str } | 784 | struct A { a: &'static str } |
@@ -787,6 +830,52 @@ fn main() { | |||
787 | } | 830 | } |
788 | 831 | ||
789 | #[test] | 832 | #[test] |
833 | fn test_check_pat_field_shorthand() { | ||
834 | check_no_diagnostics( | ||
835 | r#" | ||
836 | struct A { a: &'static str } | ||
837 | fn f(a: A) { let A { a: hello } = a; } | ||
838 | "#, | ||
839 | ); | ||
840 | check_no_diagnostics( | ||
841 | r#" | ||
842 | struct A(usize); | ||
843 | fn f(a: A) { let A { 0: 0 } = a; } | ||
844 | "#, | ||
845 | ); | ||
846 | |||
847 | check_fix( | ||
848 | r#" | ||
849 | struct A { a: &'static str } | ||
850 | fn f(a: A) { | ||
851 | let A { a<|>: a } = a; | ||
852 | } | ||
853 | "#, | ||
854 | r#" | ||
855 | struct A { a: &'static str } | ||
856 | fn f(a: A) { | ||
857 | let A { a } = a; | ||
858 | } | ||
859 | "#, | ||
860 | ); | ||
861 | |||
862 | check_fix( | ||
863 | r#" | ||
864 | struct A { a: &'static str, b: &'static str } | ||
865 | fn f(a: A) { | ||
866 | let A { a<|>: a, b } = a; | ||
867 | } | ||
868 | "#, | ||
869 | r#" | ||
870 | struct A { a: &'static str, b: &'static str } | ||
871 | fn f(a: A) { | ||
872 | let A { a, b } = a; | ||
873 | } | ||
874 | "#, | ||
875 | ); | ||
876 | } | ||
877 | |||
878 | #[test] | ||
790 | fn test_add_field_from_usage() { | 879 | fn test_add_field_from_usage() { |
791 | check_fix( | 880 | check_fix( |
792 | r" | 881 | r" |