Make unnecessary_breaks apply to default clauses

Fixes https://github.com/dart-lang/linter/issues/5061.

Change-Id: Ia5b9db3921d1d3aa95e19bc88cd3b4cde666d919
Bug: https://github.com/dart-lang/linter/issues/5061
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/380285
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_break_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_break_test.dart
index 50ff1a0..d9d4fc6 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/remove_break_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_break_test.dart
@@ -32,6 +32,8 @@
       1; break;
     case 2:
       2; break;
+    default:
+      3; break;
   }
 }
 ''');
@@ -42,6 +44,8 @@
       1;
     case 2:
       2;
+    default:
+      3;
   }
 }
 ''');
@@ -57,6 +61,9 @@
     case 2:
       2;
       break;
+    default:
+      3;
+      break;
   }
 }
 ''');
@@ -67,6 +74,8 @@
       1;
     case 2:
       2;
+    default:
+      3;
   }
 }
 ''');
@@ -107,6 +116,29 @@
 ''');
   }
 
+  Future<void> test_single_sameLine_default() async {
+    await resolveTestCode('''
+void f() {
+  switch (0) {
+    case 1:
+      1;
+    default:
+      2; break;
+  }
+}
+''');
+    await assertHasFix('''
+void f() {
+  switch (0) {
+    case 1:
+      1;
+    default:
+      2;
+  }
+}
+''');
+  }
+
   Future<void> test_single_separateLine() async {
     await resolveTestCode('''
 void f() {
@@ -130,4 +162,28 @@
 }
 ''');
   }
+
+  Future<void> test_single_separateLine_default() async {
+    await resolveTestCode('''
+void f() {
+  switch (0) {
+    case 1:
+      1;
+    default:
+      2;
+      break;
+  }
+}
+''');
+    await assertHasFix('''
+void f() {
+  switch (0) {
+    case 1:
+      1;
+    default:
+      2;
+  }
+}
+''');
+  }
 }
diff --git a/pkg/linter/lib/src/rules/unnecessary_breaks.dart b/pkg/linter/lib/src/rules/unnecessary_breaks.dart
index faccf37..bf716ac 100644
--- a/pkg/linter/lib/src/rules/unnecessary_breaks.dart
+++ b/pkg/linter/lib/src/rules/unnecessary_breaks.dart
@@ -90,7 +90,7 @@
   visitBreakStatement(BreakStatement node) {
     if (node.label != null) return;
     var parent = node.parent;
-    if (parent is SwitchPatternCase) {
+    if (parent is SwitchMember) {
       var statements = parent.statements;
       if (statements.length == 1) return;
       if (node == statements.last) {
diff --git a/pkg/linter/test/rules/unnecessary_breaks_test.dart b/pkg/linter/test/rules/unnecessary_breaks_test.dart
index 0e3ab29..c363f4b 100644
--- a/pkg/linter/test/rules/unnecessary_breaks_test.dart
+++ b/pkg/linter/test/rules/unnecessary_breaks_test.dart
@@ -17,6 +17,73 @@
   @override
   String get lintRule => 'unnecessary_breaks';
 
+  test_default() async {
+    await assertDiagnostics(r'''
+f() {
+  switch (1) {
+    case 1:
+      f();
+    default:
+      f();
+      break;
+  }
+}
+''', [
+      lint(74, 6),
+    ]);
+  }
+
+  test_default_empty() async {
+    // We allow the body of a `case` clause to be just a single `break;`,
+    // because that's necessary to prevent the clause from being grouped with
+    // the clause that follows it.
+    //
+    // For a `default` clause, that's not necessary, because the `default`
+    // clause is required to come last. But we allow just a single `break;`
+    // anyway, for consistency.
+    await assertNoDiagnostics(r'''
+f() {
+  switch (1) {
+    case 2:
+      f();
+    default:
+      break;
+  }
+}
+''');
+  }
+
+  test_default_notLast_ok() async {
+    // No lint is needed because there is already a DEAD_CODE warning.
+    await assertDiagnostics(r'''
+f(bool c) {
+  switch (1) {
+    case 1:
+      f(true);
+    default:
+      break;
+      f(true);
+  }
+}
+''', [
+      // No lint.
+      error(WarningCode.DEAD_CODE, 86, 8),
+    ]);
+  }
+
+  test_switch_pre30_default_ok() async {
+    await assertNoDiagnostics(r'''
+// @dart=2.19
+f() {
+  switch (1) {
+    default:
+      f();
+      break;
+  }
+}
+''');
+  }
+
   test_switch_pre30_ok() async {
     await assertNoDiagnostics(r'''
 // @dart=2.19
@@ -46,6 +113,20 @@
     ]);
   }
 
+  test_switchPatternCase_default_ok() async {
+    await assertNoDiagnostics(r'''
+f(bool c) {
+  switch (1) {
+    case 1:
+      f(true);
+    default:
+      if (c) break;
+      f(true);
+  }
+}
+''');
+  }
+
   test_switchPatternCase_empty_ok() async {
     await assertNoDiagnostics(r'''
 f() {