]> git.lizzy.rs Git - rust.git/commitdiff
wip enum record/tuple generation
authorYoshua Wuyts <yoshuawuyts@gmail.com>
Tue, 10 Aug 2021 20:08:14 +0000 (22:08 +0200)
committerYoshua Wuyts <yoshuawuyts@gmail.com>
Tue, 10 Aug 2021 20:08:14 +0000 (22:08 +0200)
crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs
crates/ide_assists/src/utils/gen_trait_fn_body.rs
crates/syntax/src/ast/expr_ext.rs

index d8d62b73b880d63dc093aff688d072aa4f20441e..7aa99bb937e9e7108b3233fd0e51a55c29feb0d7 100644 (file)
@@ -765,7 +765,7 @@ enum Foo {
     Baz {
         quz: String,
         fez: String,
-    }
+    },
 }
 
 impl PartialEq for Foo {
index af870f38969002f6977c1aec4cca7cbe577c33d9..782bc56ab32777be50dfffefe3894fa195caab1b 100644 (file)
@@ -346,15 +346,73 @@ fn gen_discriminant() -> ast::Expr {
         // `Hash` cannot be derived for unions, so no default impl can be provided.
         ast::Adt::Union(_) => return None,
 
-        // FIXME: generate trait variants
         ast::Adt::Enum(enum_) => {
             // => std::mem::discriminant(self) == std::mem::discriminant(other)
-            let lhs = make::expr_path(make::ext::ident_path("self"));
-            let lhs = make::expr_call(gen_discriminant(), make::arg_list(Some(lhs)));
-            let rhs = make::expr_path(make::ext::ident_path("other"));
-            let rhs = make::expr_call(gen_discriminant(), make::arg_list(Some(rhs)));
-            let cmp = make::expr_op(ast::BinOp::EqualityTest, lhs, rhs);
-            make::block_expr(None, Some(cmp)).indent(ast::edit::IndentLevel(1))
+            let self_name = make::expr_path(make::ext::ident_path("self"));
+            let lhs = make::expr_call(gen_discriminant(), make::arg_list(Some(self_name.clone())));
+            let other_name = make::expr_path(make::ext::ident_path("other"));
+            let rhs = make::expr_call(gen_discriminant(), make::arg_list(Some(other_name.clone())));
+            let eq_check = make::expr_op(ast::BinOp::EqualityTest, lhs, rhs);
+
+            let mut case_count = 0;
+            let mut arms = vec![];
+            for variant in enum_.variant_list()?.variants() {
+                case_count += 1;
+                match variant.field_list() {
+                    // => (Self::Bar { bin: l_bin }, Self::Bar { bin: r_bin }) => l_bin == r_bin,
+                    Some(ast::FieldList::RecordFieldList(list)) => {
+                        // let mut pats = vec![];
+                        // let mut fields = vec![];
+                        for field in list.fields() {
+                            // let field_name = field.name()?;
+                            // let pat = make::record_pat(path, pats);
+                            // let pat = make::ident_pat(false, false, field_name.clone());
+                            // pats.push(pat.into());
+
+                            // let path = make::ext::ident_path(&field_name.to_string());
+                            // let method_call = gen_clone_call(make::expr_path(path));
+                            // let name_ref = make::name_ref(&field_name.to_string());
+                            // let field = make::record_expr_field(name_ref, Some(method_call));
+                            // fields.push(field);
+                        }
+                        // let pat = make::record_pat(variant_name.clone(), pats.into_iter());
+                        // let fields = make::record_expr_field_list(fields);
+                        // let record_expr = make::record_expr(variant_name, fields).into();
+                        // arms.push(make::match_arm(Some(pat.into()), None, record_expr));
+                        todo!("implement tuple record iteration")
+                    }
+                    Some(ast::FieldList::TupleFieldList(list)) => {
+                        todo!("implement tuple enum iteration")
+                    }
+                    None => continue,
+                }
+            }
+
+            if !arms.is_empty() && case_count > arms.len() {
+                let lhs = make::wildcard_pat().into();
+                arms.push(make::match_arm(Some(lhs), None, make::expr_literal("true").into()));
+            }
+
+            let expr = match arms.len() {
+                0 => eq_check,
+                _ => {
+                    let condition = make::condition(eq_check, None);
+
+                    let match_target = make::expr_tuple(vec![self_name, other_name]);
+                    let list = make::match_arm_list(arms).indent(ast::edit::IndentLevel(1));
+                    let match_expr = Some(make::expr_match(match_target, list));
+                    let then_branch = make::block_expr(None, match_expr);
+                    let then_branch = then_branch.indent(ast::edit::IndentLevel(1));
+
+                    let else_branche = make::expr_literal("false");
+                    let else_branche = make::block_expr(None, Some(else_branche.into()))
+                        .indent(ast::edit::IndentLevel(1));
+
+                    make::expr_if(condition, then_branch, Some(else_branche.into()))
+                }
+            };
+
+            make::block_expr(None, Some(expr)).indent(ast::edit::IndentLevel(1))
         }
         ast::Adt::Struct(strukt) => match strukt.field_list() {
             Some(ast::FieldList::RecordFieldList(field_list)) => {
index b615037b7e391b85ec530e94b6c43b627866f279..2dfb0d1ad31cfeb516e521e7041c88e6d2a00661 100644 (file)
@@ -160,6 +160,18 @@ pub enum ElseBranch {
     IfExpr(ast::IfExpr),
 }
 
+impl From<ast::BlockExpr> for ElseBranch {
+    fn from(block_expr: ast::BlockExpr) -> Self {
+        Self::Block(block_expr)
+    }
+}
+
+impl From<ast::IfExpr> for ElseBranch {
+    fn from(if_expr: ast::IfExpr) -> Self {
+        Self::IfExpr(if_expr)
+    }
+}
+
 impl ast::IfExpr {
     pub fn then_branch(&self) -> Option<ast::BlockExpr> {
         self.blocks().next()