[analyzer] Report errors for final class and mixin subtyping outside of its library.

Change-Id: I7fbd0d0e36d360ce1a02cf7c4ecd6ccd2a29c999
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/280206
Commit-Queue: Kallen Tu <kallentu@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml b/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml
index f2a042d..57ef619 100644
--- a/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml
+++ b/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml
@@ -500,8 +500,16 @@
   status: needsEvaluation
 CompileTimeErrorCode.FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE:
   status: needsEvaluation
+CompileTimeErrorCode.FINAL_CLASS_EXTENDED_OUTSIDE_OF_LIBRARY:
+  status: needsEvaluation
+CompileTimeErrorCode.FINAL_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY:
+  status: needsEvaluation
 CompileTimeErrorCode.FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR:
   status: needsEvaluation
+CompileTimeErrorCode.FINAL_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY:
+  status: needsEvaluation
+CompileTimeErrorCode.FINAL_MIXIN_MIXED_IN_OUTSIDE_OF_LIBRARY:
+  status: needsEvaluation
 CompileTimeErrorCode.FINAL_NOT_INITIALIZED:
   status: hasFix
 CompileTimeErrorCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1:
diff --git a/pkg/analyzer/lib/src/error/codes.g.dart b/pkg/analyzer/lib/src/error/codes.g.dart
index baae8df..f18a0df 100644
--- a/pkg/analyzer/lib/src/error/codes.g.dart
+++ b/pkg/analyzer/lib/src/error/codes.g.dart
@@ -1663,6 +1663,26 @@
   );
 
   ///  Parameters:
+  ///  0: the name of the final class being extended.
+  static const CompileTimeErrorCode FINAL_CLASS_EXTENDED_OUTSIDE_OF_LIBRARY =
+      CompileTimeErrorCode(
+    'INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY',
+    "The class '{0}' can't be extended outside of its library because it's a "
+        "final class.",
+    uniqueName: 'FINAL_CLASS_EXTENDED_OUTSIDE_OF_LIBRARY',
+  );
+
+  ///  Parameters:
+  ///  0: the name of the final class being implemented.
+  static const CompileTimeErrorCode FINAL_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY =
+      CompileTimeErrorCode(
+    'INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY',
+    "The class '{0}' can't be implemented outside of its library because it's "
+        "a final class.",
+    uniqueName: 'FINAL_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY',
+  );
+
+  ///  Parameters:
   ///  0: the name of the field in question
   static const CompileTimeErrorCode
       FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR = CompileTimeErrorCode(
@@ -1674,6 +1694,26 @@
   );
 
   ///  Parameters:
+  ///  0: the name of the final mixin being implemented.
+  static const CompileTimeErrorCode FINAL_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY =
+      CompileTimeErrorCode(
+    'INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY',
+    "The mixin '{0}' can't be implemented outside of its library because it's "
+        "a final mixin.",
+    uniqueName: 'FINAL_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY',
+  );
+
+  ///  Parameters:
+  ///  0: the name of the final mixin being mixed in.
+  static const CompileTimeErrorCode FINAL_MIXIN_MIXED_IN_OUTSIDE_OF_LIBRARY =
+      CompileTimeErrorCode(
+    'INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY',
+    "The mixin '{0}' can't be mixed-in outside of its library because it's a "
+        "final mixin.",
+    uniqueName: 'FINAL_MIXIN_MIXED_IN_OUTSIDE_OF_LIBRARY',
+  );
+
+  ///  Parameters:
   ///  0: the name of the uninitialized final variable
   static const CompileTimeErrorCode FINAL_NOT_INITIALIZED =
       CompileTimeErrorCode(
diff --git a/pkg/analyzer/lib/src/error/error_code_values.g.dart b/pkg/analyzer/lib/src/error/error_code_values.g.dart
index 9b25033..4be8d2b 100644
--- a/pkg/analyzer/lib/src/error/error_code_values.g.dart
+++ b/pkg/analyzer/lib/src/error/error_code_values.g.dart
@@ -193,7 +193,11 @@
   CompileTimeErrorCode.FIELD_INITIALIZER_OUTSIDE_CONSTRUCTOR,
   CompileTimeErrorCode.FIELD_INITIALIZER_REDIRECTING_CONSTRUCTOR,
   CompileTimeErrorCode.FIELD_INITIALIZING_FORMAL_NOT_ASSIGNABLE,
+  CompileTimeErrorCode.FINAL_CLASS_EXTENDED_OUTSIDE_OF_LIBRARY,
+  CompileTimeErrorCode.FINAL_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY,
   CompileTimeErrorCode.FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR,
+  CompileTimeErrorCode.FINAL_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY,
+  CompileTimeErrorCode.FINAL_MIXIN_MIXED_IN_OUTSIDE_OF_LIBRARY,
   CompileTimeErrorCode.FINAL_NOT_INITIALIZED,
   CompileTimeErrorCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_1,
   CompileTimeErrorCode.FINAL_NOT_INITIALIZED_CONSTRUCTOR_2,
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 608db1f..2951de1 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -1397,6 +1397,8 @@
       _checkForBaseClassOrMixinImplementedOutsideOfLibrary(implementsClause);
       _checkForInterfaceClassOrMixinSuperclassOutsideOfLibrary(
           superclass, withClause);
+      _checkForFinalSupertypeOutsideOfLibrary(
+          superclass, withClause, implementsClause);
       _checkForClassUsedAsMixin(withClause);
       _checkForSealedSupertypeOutsideOfLibrary(
           superclass, withClause, implementsClause);
@@ -2845,6 +2847,69 @@
     }
   }
 
+  /// Check that if a direct supertype of a node is final, then it must be in
+  /// the same library.
+  ///
+  /// See [CompileTimeErrorCode.FINAL_CLASS_EXTENDED_OUTSIDE_OF_LIBRARY],
+  /// [CompileTimeErrorCode.FINAL_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY],
+  /// [CompileTimeErrorCode.FINAL_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY],
+  /// [CompileTimeErrorCode.FINAL_MIXIN_MIXED_IN_OUTSIDE_OF_LIBRARY].
+  void _checkForFinalSupertypeOutsideOfLibrary(NamedType? superclass,
+      WithClause? withClause, ImplementsClause? implementsClause) {
+    if (superclass != null) {
+      final type = superclass.type;
+      if (type is InterfaceType) {
+        final element = type.element;
+        if (element is ClassElementImpl &&
+            element.isFinal &&
+            element.library != _currentLibrary) {
+          errorReporter.reportErrorForNode(
+              CompileTimeErrorCode.FINAL_CLASS_EXTENDED_OUTSIDE_OF_LIBRARY,
+              superclass,
+              [element.name]);
+        }
+      }
+    }
+    if (withClause != null) {
+      for (NamedType namedType in withClause.mixinTypes) {
+        final type = namedType.type;
+        if (type is InterfaceType) {
+          final element = type.element;
+          if (element is MixinElementImpl &&
+              element.isFinal &&
+              element.library != _currentLibrary) {
+            errorReporter.reportErrorForNode(
+                CompileTimeErrorCode.FINAL_MIXIN_MIXED_IN_OUTSIDE_OF_LIBRARY,
+                namedType,
+                [element.name]);
+          }
+        }
+      }
+    }
+    if (implementsClause != null) {
+      for (NamedType namedType in implementsClause.interfaces) {
+        final type = namedType.type;
+        if (type is InterfaceType) {
+          final element = type.element;
+          if (element is ClassOrMixinElementImpl &&
+              element.isFinal &&
+              element.library != _currentLibrary) {
+            final ErrorCode errorCode;
+            if (element is ClassElement) {
+              errorCode = CompileTimeErrorCode
+                  .FINAL_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY;
+            } else {
+              errorCode = CompileTimeErrorCode
+                  .FINAL_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY;
+            }
+            errorReporter
+                .reportErrorForNode(errorCode, namedType, [element.name]);
+          }
+        }
+      }
+    }
+  }
+
   void _checkForGenericFunctionType(TypeAnnotation? node) {
     if (node == null) {
       return;
@@ -5164,6 +5229,7 @@
       );
       _checkForConflictingGenerics(node);
       _checkForBaseClassOrMixinImplementedOutsideOfLibrary(implementsClause);
+      _checkForFinalSupertypeOutsideOfLibrary(null, null, implementsClause);
       _checkForSealedSupertypeOutsideOfLibrary(null, null, implementsClause);
     }
   }
diff --git a/pkg/analyzer/messages.yaml b/pkg/analyzer/messages.yaml
index 13bae56..2e9a042 100644
--- a/pkg/analyzer/messages.yaml
+++ b/pkg/analyzer/messages.yaml
@@ -5018,6 +5018,18 @@
         C(String s) : f = int.parse(s);
       }
       ```
+  FINAL_CLASS_EXTENDED_OUTSIDE_OF_LIBRARY:
+    sharedName: INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY
+    problemMessage: "The class '{0}' can't be extended outside of its library because it's a final class."
+    comment: |-
+      Parameters:
+      0: the name of the final class being extended.
+  FINAL_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY:
+    sharedName: INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY
+    problemMessage: "The class '{0}' can't be implemented outside of its library because it's a final class."
+    comment: |-
+      Parameters:
+      0: the name of the final class being implemented.
   FINAL_INITIALIZED_IN_DECLARATION_AND_CONSTRUCTOR:
     problemMessage: "'{0}' is final and was given a value when it was declared, so it can't be set to a new value."
     correctionMessage: Try removing one of the initializations.
@@ -5067,6 +5079,18 @@
         C(this.f);
       }
       ```
+  FINAL_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY:
+    sharedName: INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY
+    problemMessage: "The mixin '{0}' can't be implemented outside of its library because it's a final mixin."
+    comment: |-
+      Parameters:
+      0: the name of the final mixin being implemented.
+  FINAL_MIXIN_MIXED_IN_OUTSIDE_OF_LIBRARY:
+    sharedName: INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY
+    problemMessage: "The mixin '{0}' can't be mixed-in outside of its library because it's a final mixin."
+    comment: |-
+      Parameters:
+      0: the name of the final mixin being mixed in.
   FINAL_NOT_INITIALIZED:
     problemMessage: "The final variable '{0}' must be initialized."
     correctionMessage: Try initializing the variable.
diff --git a/pkg/analyzer/test/src/diagnostics/final_class_extended_outside_of_library_test.dart b/pkg/analyzer/test/src/diagnostics/final_class_extended_outside_of_library_test.dart
new file mode 100644
index 0000000..7aa3298
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/final_class_extended_outside_of_library_test.dart
@@ -0,0 +1,80 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(FinalClassExtendedOutsideOfLibraryTest);
+  });
+}
+
+@reflectiveTest
+class FinalClassExtendedOutsideOfLibraryTest extends PubPackageResolutionTest {
+  test_inside() async {
+    await assertNoErrorsInCode(r'''
+final class Foo {}
+class Bar extends Foo {}
+''');
+  }
+
+  test_outside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final class Foo {}
+''');
+
+    await assertErrorsInCode(r'''
+import 'foo.dart';
+class Bar extends Foo {}
+''', [
+      error(
+          CompileTimeErrorCode.FINAL_CLASS_EXTENDED_OUTSIDE_OF_LIBRARY, 37, 3),
+    ]);
+  }
+
+  test_outside_viaTypedef_inside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final class Foo {}
+typedef FooTypedef = Foo;
+''');
+
+    await assertErrorsInCode(r'''
+import 'foo.dart';
+class Bar extends FooTypedef {}
+''', [
+      error(
+          CompileTimeErrorCode.FINAL_CLASS_EXTENDED_OUTSIDE_OF_LIBRARY, 37, 10),
+    ]);
+  }
+
+  test_outside_viaTypedef_outside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final class Foo {}
+''');
+
+    await assertErrorsInCode(r'''
+import 'foo.dart';
+typedef FooTypedef = Foo;
+class Bar extends FooTypedef {}
+''', [
+      error(
+          CompileTimeErrorCode.FINAL_CLASS_EXTENDED_OUTSIDE_OF_LIBRARY, 63, 10),
+    ]);
+  }
+
+  test_subtypeOfBase_outside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final class Foo {}
+class Bar extends Foo {}
+''');
+
+    await assertNoErrorsInCode(r'''
+import 'foo.dart';
+class Bar2 extends Bar {}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/final_class_implemented_outside_of_library_test.dart b/pkg/analyzer/test/src/diagnostics/final_class_implemented_outside_of_library_test.dart
new file mode 100644
index 0000000..0fda9fa
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/final_class_implemented_outside_of_library_test.dart
@@ -0,0 +1,207 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(FinalClassImplementedOutsideOfLibraryTest);
+  });
+}
+
+@reflectiveTest
+class FinalClassImplementedOutsideOfLibraryTest
+    extends PubPackageResolutionTest {
+  test_class_inside() async {
+    await assertNoErrorsInCode(r'''
+final class Foo {}
+class Bar implements Foo {}
+''');
+  }
+
+  test_class_outside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final class Foo {}
+''');
+
+    await assertErrorsInCode(r'''
+import 'foo.dart';
+class Bar implements Foo {}
+''', [
+      error(CompileTimeErrorCode.FINAL_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 40,
+          3),
+    ]);
+  }
+
+  test_class_outside_viaTypedef_inside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final class Foo {}
+typedef FooTypedef = Foo;
+''');
+
+    await assertErrorsInCode(r'''
+import 'foo.dart';
+class Bar implements FooTypedef {}
+''', [
+      error(CompileTimeErrorCode.FINAL_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 40,
+          10),
+    ]);
+  }
+
+  test_class_outside_viaTypedef_outside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final class Foo {}
+''');
+
+    await assertErrorsInCode(r'''
+import 'foo.dart';
+typedef FooTypedef = Foo;
+class Bar implements FooTypedef {}
+''', [
+      error(CompileTimeErrorCode.FINAL_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 66,
+          10),
+    ]);
+  }
+
+  test_class_subtypeOfFinal_outside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final class Foo {}
+class Bar implements Foo {}
+''');
+
+    await assertNoErrorsInCode(r'''
+import 'foo.dart';
+class Bar2 implements Bar {}
+''');
+  }
+
+  test_enum_inside() async {
+    await assertNoErrorsInCode(r'''
+final class Foo {}
+enum Bar implements Foo { bar }
+''');
+  }
+
+  test_enum_outside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final class Foo {}
+''');
+
+    await assertErrorsInCode(r'''
+import 'foo.dart';
+enum Bar implements Foo { bar }
+''', [
+      error(CompileTimeErrorCode.FINAL_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 39,
+          3),
+    ]);
+  }
+
+  test_enum_outside_viaTypedef_inside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final class Foo {}
+typedef FooTypedef = Foo;
+''');
+
+    await assertErrorsInCode(r'''
+import 'foo.dart';
+enum Bar implements FooTypedef { bar }
+''', [
+      error(CompileTimeErrorCode.FINAL_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 39,
+          10),
+    ]);
+  }
+
+  test_enum_outside_viaTypedef_outside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final class Foo {}
+''');
+
+    await assertErrorsInCode(r'''
+import 'foo.dart';
+typedef FooTypedef = Foo;
+enum Bar implements FooTypedef { bar }
+''', [
+      error(CompileTimeErrorCode.FINAL_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 65,
+          10),
+    ]);
+  }
+
+  test_enum_subtypeOfFinal_outside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final class Foo {}
+class Bar implements Foo {}
+''');
+
+    await assertNoErrorsInCode(r'''
+import 'foo.dart';
+enum Bar2 implements Bar { bar }
+''');
+  }
+
+  test_mixin_inside() async {
+    await assertNoErrorsInCode(r'''
+final class Foo {}
+mixin Bar implements Foo {}
+''');
+  }
+
+  test_mixin_outside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final class Foo {}
+''');
+
+    await assertErrorsInCode(r'''
+import 'foo.dart';
+mixin Bar implements Foo {}
+''', [
+      error(CompileTimeErrorCode.FINAL_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 40,
+          3),
+    ]);
+  }
+
+  test_mixin_outside_viaTypedef_inside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final class Foo {}
+typedef FooTypedef = Foo;
+''');
+
+    await assertErrorsInCode(r'''
+import 'foo.dart';
+mixin Bar implements FooTypedef {}
+''', [
+      error(CompileTimeErrorCode.FINAL_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 40,
+          10),
+    ]);
+  }
+
+  test_mixin_outside_viaTypedef_outside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final class Foo {}
+''');
+
+    await assertErrorsInCode(r'''
+import 'foo.dart';
+typedef FooTypedef = Foo;
+mixin Bar implements FooTypedef {}
+''', [
+      error(CompileTimeErrorCode.FINAL_CLASS_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 66,
+          10),
+    ]);
+  }
+
+  test_mixin_subtypeOfFinal_outside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final class Foo {}
+class Bar implements Foo {}
+''');
+
+    await assertNoErrorsInCode(r'''
+import 'foo.dart';
+mixin Bar2 implements Bar {}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/final_mixin_implemented_outside_of_library_test.dart b/pkg/analyzer/test/src/diagnostics/final_mixin_implemented_outside_of_library_test.dart
new file mode 100644
index 0000000..23a7bb7
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/final_mixin_implemented_outside_of_library_test.dart
@@ -0,0 +1,207 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(FinalMixinImplementedOutsideOfLibraryTest);
+  });
+}
+
+@reflectiveTest
+class FinalMixinImplementedOutsideOfLibraryTest
+    extends PubPackageResolutionTest {
+  test_class_inside() async {
+    await assertNoErrorsInCode(r'''
+final mixin Foo {}
+class Bar implements Foo {}
+''');
+  }
+
+  test_class_outside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final mixin Foo {}
+''');
+
+    await assertErrorsInCode(r'''
+import 'foo.dart';
+class Bar implements Foo {}
+''', [
+      error(CompileTimeErrorCode.FINAL_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 40,
+          3),
+    ]);
+  }
+
+  test_class_outside_viaTypedef_inside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final mixin Foo {}
+typedef FooTypedef = Foo;
+''');
+
+    await assertErrorsInCode(r'''
+import 'foo.dart';
+class Bar implements FooTypedef {}
+''', [
+      error(CompileTimeErrorCode.FINAL_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 40,
+          10),
+    ]);
+  }
+
+  test_class_outside_viaTypedef_outside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final mixin Foo {}
+''');
+
+    await assertErrorsInCode(r'''
+import 'foo.dart';
+typedef FooTypedef = Foo;
+class Bar implements FooTypedef {}
+''', [
+      error(CompileTimeErrorCode.FINAL_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 66,
+          10),
+    ]);
+  }
+
+  test_class_subtypeOfFinal_outside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final mixin Foo {}
+class Bar implements Foo {}
+''');
+
+    await assertNoErrorsInCode(r'''
+import 'foo.dart';
+class Bar2 implements Bar {}
+''');
+  }
+
+  test_enum_inside() async {
+    await assertNoErrorsInCode(r'''
+final mixin Foo {}
+enum Bar implements Foo { bar }
+''');
+  }
+
+  test_enum_outside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final mixin Foo {}
+''');
+
+    await assertErrorsInCode(r'''
+import 'foo.dart';
+enum Bar implements Foo { bar }
+''', [
+      error(CompileTimeErrorCode.FINAL_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 39,
+          3),
+    ]);
+  }
+
+  test_enum_outside_viaTypedef_inside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final mixin Foo {}
+typedef FooTypedef = Foo;
+''');
+
+    await assertErrorsInCode(r'''
+import 'foo.dart';
+enum Bar implements FooTypedef { bar }
+''', [
+      error(CompileTimeErrorCode.FINAL_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 39,
+          10),
+    ]);
+  }
+
+  test_enum_outside_viaTypedef_outside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final mixin Foo {}
+''');
+
+    await assertErrorsInCode(r'''
+import 'foo.dart';
+typedef FooTypedef = Foo;
+enum Bar implements FooTypedef { bar }
+''', [
+      error(CompileTimeErrorCode.FINAL_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 65,
+          10),
+    ]);
+  }
+
+  test_enum_subtypeOfFinal_outside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final mixin Foo {}
+class Bar implements Foo {}
+''');
+
+    await assertNoErrorsInCode(r'''
+import 'foo.dart';
+enum Bar2 implements Bar { bar }
+''');
+  }
+
+  test_mixin_inside() async {
+    await assertNoErrorsInCode(r'''
+final mixin Foo {}
+mixin Bar implements Foo {}
+''');
+  }
+
+  test_mixin_outside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final mixin Foo {}
+''');
+
+    await assertErrorsInCode(r'''
+import 'foo.dart';
+mixin Bar implements Foo {}
+''', [
+      error(CompileTimeErrorCode.FINAL_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 40,
+          3),
+    ]);
+  }
+
+  test_mixin_outside_viaTypedef_inside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final mixin Foo {}
+typedef FooTypedef = Foo;
+''');
+
+    await assertErrorsInCode(r'''
+import 'foo.dart';
+mixin Bar implements FooTypedef {}
+''', [
+      error(CompileTimeErrorCode.FINAL_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 40,
+          10),
+    ]);
+  }
+
+  test_mixin_outside_viaTypedef_outside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final mixin Foo {}
+''');
+
+    await assertErrorsInCode(r'''
+import 'foo.dart';
+typedef FooTypedef = Foo;
+mixin Bar implements FooTypedef {}
+''', [
+      error(CompileTimeErrorCode.FINAL_MIXIN_IMPLEMENTED_OUTSIDE_OF_LIBRARY, 66,
+          10),
+    ]);
+  }
+
+  test_mixin_subtypeOfFinal_outside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final mixin Foo {}
+class Bar implements Foo {}
+''');
+
+    await assertNoErrorsInCode(r'''
+import 'foo.dart';
+mixin Bar2 implements Bar {}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/final_mixin_mixed_in_outside_of_library_test.dart b/pkg/analyzer/test/src/diagnostics/final_mixin_mixed_in_outside_of_library_test.dart
new file mode 100644
index 0000000..3c3b0d8
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/final_mixin_mixed_in_outside_of_library_test.dart
@@ -0,0 +1,131 @@
+// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(FinalMixinMixedInOutsideOfLibraryTest);
+  });
+}
+
+@reflectiveTest
+class FinalMixinMixedInOutsideOfLibraryTest extends PubPackageResolutionTest {
+  test_class_inside() async {
+    await assertNoErrorsInCode(r'''
+final mixin Foo {}
+class Bar with Foo {}
+''');
+  }
+
+  test_class_outside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final mixin Foo {}
+''');
+
+    await assertErrorsInCode(r'''
+import 'foo.dart';
+class Bar with Foo {}
+''', [
+      error(
+          CompileTimeErrorCode.FINAL_MIXIN_MIXED_IN_OUTSIDE_OF_LIBRARY, 34, 3),
+    ]);
+  }
+
+  test_class_outside_viaTypedef_inside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final mixin Foo {}
+typedef FooTypedef = Foo;
+''');
+
+    await assertErrorsInCode(r'''
+import 'foo.dart';
+class Bar with FooTypedef {}
+''', [
+      error(
+          CompileTimeErrorCode.FINAL_MIXIN_MIXED_IN_OUTSIDE_OF_LIBRARY, 34, 10),
+    ]);
+  }
+
+  test_class_outside_viaTypedef_outside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final mixin Foo {}
+''');
+
+    await assertErrorsInCode(r'''
+import 'foo.dart';
+typedef FooTypedef = Foo;
+class Bar with FooTypedef {}
+''', [
+      error(
+          CompileTimeErrorCode.FINAL_MIXIN_MIXED_IN_OUTSIDE_OF_LIBRARY, 60, 10),
+    ]);
+  }
+
+  test_class_subtypeOfBase_outside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final mixin Foo {}
+class Bar with Foo {}
+''');
+
+    await assertNoErrorsInCode(r'''
+import 'foo.dart';
+class Bar2 extends Bar {}
+''');
+  }
+
+  test_enum_inside() async {
+    await assertNoErrorsInCode(r'''
+final mixin Foo {}
+enum Bar with Foo { bar }
+''');
+  }
+
+  test_enum_outside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final mixin Foo {}
+''');
+
+    await assertErrorsInCode(r'''
+import 'foo.dart';
+enum Bar with Foo { bar }
+''', [
+      error(
+          CompileTimeErrorCode.FINAL_MIXIN_MIXED_IN_OUTSIDE_OF_LIBRARY, 33, 3),
+    ]);
+  }
+
+  test_enum_outside_viaTypedef_inside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final mixin Foo {}
+typedef FooTypedef = Foo;
+''');
+
+    await assertErrorsInCode(r'''
+import 'foo.dart';
+enum Bar with FooTypedef { bar }
+''', [
+      error(
+          CompileTimeErrorCode.FINAL_MIXIN_MIXED_IN_OUTSIDE_OF_LIBRARY, 33, 10),
+    ]);
+  }
+
+  test_enum_outside_viaTypedef_outside() async {
+    newFile('$testPackageLibPath/foo.dart', r'''
+final mixin Foo {}
+''');
+
+    await assertErrorsInCode(r'''
+import 'foo.dart';
+typedef FooTypedef = Foo;
+enum Bar with FooTypedef { bar }
+''', [
+      error(
+          CompileTimeErrorCode.FINAL_MIXIN_MIXED_IN_OUTSIDE_OF_LIBRARY, 59, 10),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index 3436aee..d3808fe 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -265,8 +265,16 @@
     as field_initializing_formal_not_assignable;
 import 'field_must_be_external_in_struct_test.dart'
     as field_must_be_external_in_struct;
+import 'final_class_extended_outside_of_library_test.dart'
+    as final_class_extended_outside_of_library;
+import 'final_class_implemented_outside_of_library_test.dart'
+    as final_class_implemented_outside_of_library;
 import 'final_initialized_in_declaration_and_constructor_test.dart'
     as final_initialized_in_declaration_and_constructor;
+import 'final_mixin_implemented_outside_of_library_test.dart'
+    as final_mixin_implemented_outside_of_library;
+import 'final_mixin_mixed_in_outside_of_library_test.dart'
+    as final_mixin_mixed_in_outside_of_library;
 import 'final_not_initialized_constructor_test.dart'
     as final_not_initialized_constructor;
 import 'final_not_initialized_test.dart' as final_not_initialized;
@@ -1032,6 +1040,10 @@
     field_initializer_redirecting_constructor.main();
     field_initializing_formal_not_assignable.main();
     field_must_be_external_in_struct.main();
+    final_class_extended_outside_of_library.main();
+    final_class_implemented_outside_of_library.main();
+    final_mixin_implemented_outside_of_library.main();
+    final_mixin_mixed_in_outside_of_library.main();
     final_not_initialized_constructor.main();
     final_not_initialized.main();
     for_in_of_invalid_element_type.main();
diff --git a/tests/language/class_modifiers/final/final_class_extend_outside_error_test.dart b/tests/language/class_modifiers/final/final_class_extend_outside_error_test.dart
index 035e333..61b0cce 100644
--- a/tests/language/class_modifiers/final/final_class_extend_outside_error_test.dart
+++ b/tests/language/class_modifiers/final/final_class_extend_outside_error_test.dart
@@ -9,12 +9,12 @@
 import 'final_class_extend_lib.dart';
 
 abstract class AOutside extends FinalClass {}
-// ^
-// [analyzer] unspecified
+//                              ^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY
 // [cfe] unspecified
 
 class BOutside extends FinalClass {
-// ^
-// [analyzer] unspecified
+//                     ^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY
 // [cfe] unspecified
 }
diff --git a/tests/language/class_modifiers/final/final_class_implement_outside_error_test.dart b/tests/language/class_modifiers/final/final_class_implement_outside_error_test.dart
index a846b74..efa88a9 100644
--- a/tests/language/class_modifiers/final/final_class_implement_outside_error_test.dart
+++ b/tests/language/class_modifiers/final/final_class_implement_outside_error_test.dart
@@ -9,13 +9,13 @@
 import 'final_class_implement_lib.dart';
 
 abstract class AOutside implements FinalClass {}
-// ^
-// [analyzer] unspecified
+//                                 ^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY
 // [cfe] unspecified
 
 class BOutside implements FinalClass {
-// ^
-// [analyzer] unspecified
+//                        ^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY
 // [cfe] unspecified
   @override
   int foo = 1;
diff --git a/tests/language/class_modifiers/final/final_class_typedef_subtype_error_test.dart b/tests/language/class_modifiers/final/final_class_typedef_subtype_error_test.dart
index 6865fdb..0fe24de 100644
--- a/tests/language/class_modifiers/final/final_class_typedef_subtype_error_test.dart
+++ b/tests/language/class_modifiers/final/final_class_typedef_subtype_error_test.dart
@@ -10,13 +10,13 @@
 import 'final_class_typedef_lib.dart';
 
 class ATypeDef extends FinalClassTypeDef {}
-// ^
-// [analyzer] unspecified
+//                     ^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY
 // [cfe] unspecified
 
 class BTypeDef implements FinalClassTypeDef {
-// ^
-// [analyzer] unspecified
+//                        ^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY
 // [cfe] unspecified
   @override
   int foo = 1;
diff --git a/tests/language/class_modifiers/final/final_class_typedef_used_outside_error_test.dart b/tests/language/class_modifiers/final/final_class_typedef_used_outside_error_test.dart
index bc74010..617e292 100644
--- a/tests/language/class_modifiers/final/final_class_typedef_used_outside_error_test.dart
+++ b/tests/language/class_modifiers/final/final_class_typedef_used_outside_error_test.dart
@@ -13,13 +13,13 @@
 typedef ATypeDef = FinalClass;
 
 class A extends ATypeDef {}
-// ^
-// [analyzer] unspecified
+//              ^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY
 // [cfe] unspecified
 
 class B implements ATypeDef {
-// ^
-// [analyzer] unspecified
+//                 ^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY
 // [cfe] unspecified
   int foo = 1;
 }
diff --git a/tests/language/class_modifiers/final/final_mixin_implement_outside_error_test.dart b/tests/language/class_modifiers/final/final_mixin_implement_outside_error_test.dart
index b75e021..5a74768 100644
--- a/tests/language/class_modifiers/final/final_mixin_implement_outside_error_test.dart
+++ b/tests/language/class_modifiers/final/final_mixin_implement_outside_error_test.dart
@@ -9,13 +9,13 @@
 import 'final_mixin_implement_lib.dart';
 
 abstract class AOutside implements FinalMixin {}
-// ^
-// [analyzer] unspecified
+//                                 ^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY
 // [cfe] unspecified
 
 class BOutside implements FinalMixin {
-// ^
-// [analyzer] unspecified
+//                        ^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY
 // [cfe] unspecified
   @override
   int foo = 1;
diff --git a/tests/language/class_modifiers/final/final_mixin_typedef_with_outside_error_test.dart b/tests/language/class_modifiers/final/final_mixin_typedef_with_outside_error_test.dart
index 92276ad..d4acf8b 100644
--- a/tests/language/class_modifiers/final/final_mixin_typedef_with_outside_error_test.dart
+++ b/tests/language/class_modifiers/final/final_mixin_typedef_with_outside_error_test.dart
@@ -9,11 +9,11 @@
 import 'final_mixin_typedef_with_lib.dart';
 
 abstract class AOutside with FinalMixinTypeDef {}
-// ^
-// [analyzer] unspecified
+//                           ^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY
 // [cfe] unspecified
 
 class BOutside with FinalMixinTypeDef {}
-// ^
-// [analyzer] unspecified
+//                  ^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY
 // [cfe] unspecified
diff --git a/tests/language/class_modifiers/final/final_mixin_with_outside_error_test.dart b/tests/language/class_modifiers/final/final_mixin_with_outside_error_test.dart
index c526040..0eb6367 100644
--- a/tests/language/class_modifiers/final/final_mixin_with_outside_error_test.dart
+++ b/tests/language/class_modifiers/final/final_mixin_with_outside_error_test.dart
@@ -9,11 +9,11 @@
 import 'final_mixin_with_lib.dart';
 
 abstract class AOutside with FinalMixin {}
-// ^
-// [analyzer] unspecified
+//                           ^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY
 // [cfe] unspecified
 
 class BOutside with FinalMixin {}
-// ^
-// [analyzer] unspecified
+//                  ^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.INVALID_USE_OF_TYPE_OUTSIDE_LIBRARY
 // [cfe] unspecified