Consistent blank after => members in class-likes (#2146)

Closes #1143

The `class` emitter already used `writeln` following a `=>` method to
include blank lines between members. Make this consistent for enums,
extensions, and mixins. Extract a method and use it for each type.

Sort changelog with user-facing changes at the top.
diff --git a/pkgs/code_builder/CHANGELOG.md b/pkgs/code_builder/CHANGELOG.md
index f8459a3..893d23f 100644
--- a/pkgs/code_builder/CHANGELOG.md
+++ b/pkgs/code_builder/CHANGELOG.md
@@ -1,9 +1,11 @@
 ## 4.10.2-wip
 
+* Support `Expression.newInstanceNamed` with empty name
+* Consistently add blank lines between `=>` in class-like definitions.
+* Fixed bug: Fields declared with `static` and `external` now produce code with
+  correct order
 * Upgrade `dart_style` and `source_gen` to remove `package:macros` dependency.
 * Require Dart `^3.6.0` due to the upgrades.
-* Support `Expression.newInstanceNamed` with empty name
-* Fixed bug: Fields declared with `static` and `external` now produce code with correct order
 
 ## 4.10.1
 
diff --git a/pkgs/code_builder/lib/src/emitter.dart b/pkgs/code_builder/lib/src/emitter.dart
index 64e2aa4..5d94eb9 100644
--- a/pkgs/code_builder/lib/src/emitter.dart
+++ b/pkgs/code_builder/lib/src/emitter.dart
@@ -162,13 +162,7 @@
       visitField(f, out);
       out.writeln();
     }
-    for (var m in spec.methods) {
-      visitMethod(m, out);
-      if (_isLambdaMethod(m)) {
-        out.writeln(';');
-      }
-      out.writeln();
-    }
+    _visitMethods(spec.methods, out);
     out.writeln(' }');
     return out;
   }
@@ -201,13 +195,7 @@
       visitField(f, out);
       out.writeln();
     }
-    for (var m in spec.methods) {
-      visitMethod(m, out);
-      if (_isLambdaMethod(m)) {
-        out.write(';');
-      }
-      out.writeln();
-    }
+    _visitMethods(spec.methods, out);
     out.write('  }');
     return out;
   }
@@ -326,13 +314,7 @@
       visitField(f, out);
       out.writeln();
     }
-    for (var m in spec.methods) {
-      visitMethod(m, out);
-      if (_isLambdaMethod(m)) {
-        out.write(';');
-      }
-      out.writeln();
-    }
+    _visitMethods(spec.methods, out);
     out.writeln(' }');
     return out;
   }
@@ -372,13 +354,7 @@
       visitField(f, out);
       out.writeln();
     }
-    for (var m in spec.methods) {
-      visitMethod(m, out);
-      if (_isLambdaMethod(m)) {
-        out.writeln(';');
-      }
-      out.writeln();
-    }
+    _visitMethods(spec.methods, out);
     out.writeln('}');
     return out;
   }
@@ -800,6 +776,16 @@
     }
   }
 
+  void _visitMethods(Iterable<Method> methods, StringSink out) {
+    for (final m in methods) {
+      visitMethod(m, out);
+      if (_isLambdaMethod(m)) {
+        out.writeln(';');
+      }
+      out.writeln();
+    }
+  }
+
   @override
   StringSink visitReference(Reference spec, [StringSink? output]) =>
       (output ??= StringBuffer())..write(allocator.allocate(spec));
@@ -907,13 +893,7 @@
       visitField(f, out);
       out.writeln();
     }
-    for (var m in spec.methods) {
-      visitMethod(m, out);
-      if (_isLambdaMethod(m)) {
-        out.write(';');
-      }
-      out.writeln();
-    }
+    _visitMethods(spec.methods, out);
     out.writeln(' }');
     return out;
   }
diff --git a/pkgs/code_builder/test/specs/enum_test.dart b/pkgs/code_builder/test/specs/enum_test.dart
index 5a0b19a..3a8238a 100644
--- a/pkgs/code_builder/test/specs/enum_test.dart
+++ b/pkgs/code_builder/test/specs/enum_test.dart
@@ -373,6 +373,7 @@
       c;
 
       int get myInt => 123;
+
       Iterable<String> myStrings() sync* {
         yield 'a';
         yield 'b';