]> git.lizzy.rs Git - rust.git/commitdiff
minor: extract fix to file
authorAleksey Kladov <aleksey.kladov@gmail.com>
Mon, 17 May 2021 08:40:34 +0000 (11:40 +0300)
committerAleksey Kladov <aleksey.kladov@gmail.com>
Mon, 17 May 2021 08:40:34 +0000 (11:40 +0300)
crates/ide/src/diagnostics/fixes.rs
crates/ide/src/diagnostics/fixes/fill_missing_fields.rs [new file with mode: 0644]

index 695b59e27e6c7dce4deaf6222e1576335017844b..5330449f9b5519eb4183dc3149b5e31fe41a82ca 100644 (file)
@@ -1,10 +1,12 @@
 //! Provides a way to attach fixes to the diagnostics.
 //! The same module also has all curret custom fixes for the diagnostics implemented.
+mod fill_missing_fields;
+
 use hir::{
     db::AstDatabase,
     diagnostics::{
-        Diagnostic, IncorrectCase, MissingFields, MissingOkOrSomeInTailExpr, NoSuchField,
-        RemoveThisSemicolon, ReplaceFilterMapNextWithFindMap, UnresolvedModule,
+        Diagnostic, IncorrectCase, MissingOkOrSomeInTailExpr, NoSuchField, RemoveThisSemicolon,
+        ReplaceFilterMapNextWithFindMap, UnresolvedModule,
     },
     HasSource, HirDisplay, InFile, Semantics, VariantDef,
 };
@@ -15,7 +17,6 @@
     RootDatabase,
 };
 use syntax::{
-    algo,
     ast::{self, edit::IndentLevel, make, ArgListOwner},
     AstNode, TextRange,
 };
@@ -82,47 +83,6 @@ fn fix(
     }
 }
 
-impl DiagnosticWithFix for MissingFields {
-    fn fix(
-        &self,
-        sema: &Semantics<RootDatabase>,
-        _resolve: &AssistResolveStrategy,
-    ) -> Option<Assist> {
-        // Note that although we could add a diagnostics to
-        // fill the missing tuple field, e.g :
-        // `struct A(usize);`
-        // `let a = A { 0: () }`
-        // but it is uncommon usage and it should not be encouraged.
-        if self.missed_fields.iter().any(|it| it.as_tuple_index().is_some()) {
-            return None;
-        }
-
-        let root = sema.db.parse_or_expand(self.file)?;
-        let field_list_parent = self.field_list_parent.to_node(&root);
-        let old_field_list = field_list_parent.record_expr_field_list()?;
-        let new_field_list = old_field_list.clone_for_update();
-        for f in self.missed_fields.iter() {
-            let field =
-                make::record_expr_field(make::name_ref(&f.to_string()), Some(make::expr_unit()))
-                    .clone_for_update();
-            new_field_list.add_field(field);
-        }
-
-        let edit = {
-            let mut builder = TextEdit::builder();
-            algo::diff(&old_field_list.syntax(), &new_field_list.syntax())
-                .into_text_edit(&mut builder);
-            builder.finish()
-        };
-        Some(fix(
-            "fill_missing_fields",
-            "Fill struct fields",
-            SourceChange::from_text_edit(self.file.original_file(sema.db), edit),
-            sema.original_range(&field_list_parent.syntax()).range,
-        ))
-    }
-}
-
 impl DiagnosticWithFix for MissingOkOrSomeInTailExpr {
     fn fix(
         &self,
diff --git a/crates/ide/src/diagnostics/fixes/fill_missing_fields.rs b/crates/ide/src/diagnostics/fixes/fill_missing_fields.rs
new file mode 100644 (file)
index 0000000..123c2f0
--- /dev/null
@@ -0,0 +1,192 @@
+use hir::{db::AstDatabase, diagnostics::MissingFields, Semantics};
+use ide_assists::AssistResolveStrategy;
+use ide_db::{source_change::SourceChange, RootDatabase};
+use syntax::{algo, ast::make, AstNode};
+use text_edit::TextEdit;
+
+use crate::{
+    diagnostics::{fix, fixes::DiagnosticWithFix},
+    Assist,
+};
+
+impl DiagnosticWithFix for MissingFields {
+    fn fix(
+        &self,
+        sema: &Semantics<RootDatabase>,
+        _resolve: &AssistResolveStrategy,
+    ) -> Option<Assist> {
+        // Note that although we could add a diagnostics to
+        // fill the missing tuple field, e.g :
+        // `struct A(usize);`
+        // `let a = A { 0: () }`
+        // but it is uncommon usage and it should not be encouraged.
+        if self.missed_fields.iter().any(|it| it.as_tuple_index().is_some()) {
+            return None;
+        }
+
+        let root = sema.db.parse_or_expand(self.file)?;
+        let field_list_parent = self.field_list_parent.to_node(&root);
+        let old_field_list = field_list_parent.record_expr_field_list()?;
+        let new_field_list = old_field_list.clone_for_update();
+        for f in self.missed_fields.iter() {
+            let field =
+                make::record_expr_field(make::name_ref(&f.to_string()), Some(make::expr_unit()))
+                    .clone_for_update();
+            new_field_list.add_field(field);
+        }
+
+        let edit = {
+            let mut builder = TextEdit::builder();
+            algo::diff(&old_field_list.syntax(), &new_field_list.syntax())
+                .into_text_edit(&mut builder);
+            builder.finish()
+        };
+        Some(fix(
+            "fill_missing_fields",
+            "Fill struct fields",
+            SourceChange::from_text_edit(self.file.original_file(sema.db), edit),
+            sema.original_range(&field_list_parent.syntax()).range,
+        ))
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::diagnostics::tests::{check_fix, check_no_diagnostics};
+
+    #[test]
+    fn test_fill_struct_fields_empty() {
+        check_fix(
+            r#"
+struct TestStruct { one: i32, two: i64 }
+
+fn test_fn() {
+    let s = TestStruct {$0};
+}
+"#,
+            r#"
+struct TestStruct { one: i32, two: i64 }
+
+fn test_fn() {
+    let s = TestStruct { one: (), two: () };
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn test_fill_struct_fields_self() {
+        check_fix(
+            r#"
+struct TestStruct { one: i32 }
+
+impl TestStruct {
+    fn test_fn() { let s = Self {$0}; }
+}
+"#,
+            r#"
+struct TestStruct { one: i32 }
+
+impl TestStruct {
+    fn test_fn() { let s = Self { one: () }; }
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn test_fill_struct_fields_enum() {
+        check_fix(
+            r#"
+enum Expr {
+    Bin { lhs: Box<Expr>, rhs: Box<Expr> }
+}
+
+impl Expr {
+    fn new_bin(lhs: Box<Expr>, rhs: Box<Expr>) -> Expr {
+        Expr::Bin {$0 }
+    }
+}
+"#,
+            r#"
+enum Expr {
+    Bin { lhs: Box<Expr>, rhs: Box<Expr> }
+}
+
+impl Expr {
+    fn new_bin(lhs: Box<Expr>, rhs: Box<Expr>) -> Expr {
+        Expr::Bin { lhs: (), rhs: () }
+    }
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn test_fill_struct_fields_partial() {
+        check_fix(
+            r#"
+struct TestStruct { one: i32, two: i64 }
+
+fn test_fn() {
+    let s = TestStruct{ two: 2$0 };
+}
+"#,
+            r"
+struct TestStruct { one: i32, two: i64 }
+
+fn test_fn() {
+    let s = TestStruct{ two: 2, one: () };
+}
+",
+        );
+    }
+
+    #[test]
+    fn test_fill_struct_fields_raw_ident() {
+        check_fix(
+            r#"
+struct TestStruct { r#type: u8 }
+
+fn test_fn() {
+    TestStruct { $0 };
+}
+"#,
+            r"
+struct TestStruct { r#type: u8 }
+
+fn test_fn() {
+    TestStruct { r#type: ()  };
+}
+",
+        );
+    }
+
+    #[test]
+    fn test_fill_struct_fields_no_diagnostic() {
+        check_no_diagnostics(
+            r#"
+struct TestStruct { one: i32, two: i64 }
+
+fn test_fn() {
+    let one = 1;
+    let s = TestStruct{ one, two: 2 };
+}
+        "#,
+        );
+    }
+
+    #[test]
+    fn test_fill_struct_fields_no_diagnostic_on_spread() {
+        check_no_diagnostics(
+            r#"
+struct TestStruct { one: i32, two: i64 }
+
+fn test_fn() {
+    let one = 1;
+    let s = TestStruct{ ..a };
+}
+"#,
+        );
+    }
+}