Analyzer: add two checks for the @internal annotation.

The meta package does not yet have an `internal` constant;
this CL just adds one to the mock packages for testing.

Two checks are implemented:

* Hint if an @internal annotation is found on an element which is
  already part of a package's public API (based on file path).
* Hint if an element annotated with @internal is exported from a
  package's public API.

The notion of "public API" is also implemented for each type of Package:
BasicPackage, BazelPackage, GnPackage, PackageBuildPackage,
and PubPackage.

Bug: https://github.com/dart-lang/sdk/issues/28066
Change-Id: Ifc2709028afcd241f59e802f5952539f717704c3
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/163126
Commit-Queue: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index 71b8251..9e50585 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -534,6 +534,9 @@
   /// Return `true` if this element has an annotation of the form `@factory`.
   bool get hasFactory;
 
+  /// Return `true` if this element has an annotation of the form `@internal`.
+  bool get hasInternal;
+
   /// Return `true` if this element has an annotation of the form `@isTest`.
   bool get hasIsTest;
 
@@ -717,6 +720,10 @@
   /// subclasses as being immutable.
   bool get isImmutable;
 
+  /// Return `true` if this annotation marks the associated element as being
+  /// internal to its package.
+  bool get isInternal;
+
   /// Return `true` if this annotation marks the associated member as running
   /// a single test.
   bool get isIsTest;
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 4f13b90..9312ea8 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -492,10 +492,12 @@
   HintCode.INFERENCE_FAILURE_ON_UNINITIALIZED_VARIABLE,
   HintCode.INFERENCE_FAILURE_ON_UNTYPED_PARAMETER,
   HintCode.INVALID_ANNOTATION_TARGET,
+  HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT,
   HintCode.INVALID_FACTORY_ANNOTATION,
   HintCode.INVALID_FACTORY_METHOD_DECL,
   HintCode.INVALID_FACTORY_METHOD_IMPL,
   HintCode.INVALID_IMMUTABLE_ANNOTATION,
+  HintCode.INVALID_INTERNAL_ANNOTATION,
   HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_AT_SIGN,
   HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_EQUALS,
   HintCode.INVALID_LANGUAGE_VERSION_OVERRIDE_GREATER,
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index ecf68fe..63df85d 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -2313,6 +2313,10 @@
   /// as being immutable.
   static const String _IMMUTABLE_VARIABLE_NAME = "immutable";
 
+  /// The name of the top-level variable used to mark an element as being
+  /// internal to its package.
+  static const String _INTERNAL_VARIABLE_NAME = "internal";
+
   /// The name of the top-level variable used to mark a constructor as being
   /// literal.
   static const String _LITERAL_VARIABLE_NAME = "literal";
@@ -2460,6 +2464,12 @@
       element.library?.name == _META_LIB_NAME;
 
   @override
+  bool get isInternal =>
+      element is PropertyAccessorElement &&
+      element.name == _INTERNAL_VARIABLE_NAME &&
+      element.library?.name == _META_LIB_NAME;
+
+  @override
   bool get isIsTest =>
       element is PropertyAccessorElement &&
       element.name == _IS_TEST_VARIABLE_NAME &&
@@ -2748,6 +2758,18 @@
   }
 
   @override
+  bool get hasInternal {
+    var metadata = this.metadata;
+    for (var i = 0; i < metadata.length; i++) {
+      var annotation = metadata[i];
+      if (annotation.isInternal) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  @override
   bool get hasIsTest {
     var metadata = this.metadata;
     for (var i = 0; i < metadata.length; i++) {
@@ -5996,6 +6018,9 @@
   bool get hasFactory => false;
 
   @override
+  bool get hasInternal => false;
+
+  @override
   bool get hasIsTest => false;
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart
index a37c9d4..5c08ec5 100644
--- a/pkg/analyzer/lib/src/dart/element/member.dart
+++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -460,6 +460,9 @@
   bool get hasFactory => _declaration.hasFactory;
 
   @override
+  bool get hasInternal => _declaration.hasInternal;
+
+  @override
   bool get hasIsTest => _declaration.hasIsTest;
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
index 9d9c4eb..9be0aa2 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -577,6 +577,19 @@
       "The annotation '{0}' can only be used on {1}");
 
   /**
+   * This hint is generated anywhere where an element annotated with `@internal`
+   * is exported as a part of a package's public API.
+   *
+   * Parameters:
+   * 0: the name of the element
+   */
+  static const HintCode INVALID_EXPORT_OF_INTERNAL_ELEMENT = HintCode(
+      'INVALID_EXPORT_OF_INTERNAL_ELEMENT',
+      "The member '{0}' can't be exported as a part of a package's public "
+          "API.",
+      correction: "Try using a hide clause to hide '{0}'.");
+
+  /**
    * This hint is generated anywhere a @factory annotation is associated with
    * anything other than a method.
    */
@@ -612,6 +625,15 @@
       'INVALID_IMMUTABLE_ANNOTATION',
       "Only classes can be annotated as being immutable.");
 
+  /**
+   * This hint is generated anywhere a @internal annotation is associated with
+   * an element found in a package's public API.
+   */
+  static const HintCode INVALID_INTERNAL_ANNOTATION = HintCode(
+      'INVALID_INTERNAL_ANNOTATION',
+      "Only public elements in a package's private API can be annotated as "
+          "being internal.");
+
   /// Invalid Dart language version comments don't follow the specification [1].
   /// If a comment begins with "@dart" or "dart" (letters in any case),
   /// followed by optional whitespace, followed by optional non-alphanumeric,
@@ -922,7 +944,7 @@
 
   /**
    * This hint is generated anywhere where a member annotated with `@protected`
-   * is used outside an instance member of a subclass.
+   * is used outside of an instance member of a subclass.
    *
    * Parameters:
    * 0: the name of the member
diff --git a/pkg/analyzer/lib/src/error/best_practices_verifier.dart b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
index 24c9c85..5d65e55 100644
--- a/pkg/analyzer/lib/src/error/best_practices_verifier.dart
+++ b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
@@ -21,6 +21,7 @@
 import 'package:analyzer/src/dart/element/type_system.dart';
 import 'package:analyzer/src/dart/resolver/body_inference_context.dart';
 import 'package:analyzer/src/dart/resolver/exit_detector.dart';
+import 'package:analyzer/src/dart/resolver/scope.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/engine.dart';
@@ -113,6 +114,11 @@
     );
   }
 
+  bool get _inPublicPackageApi {
+    return _workspacePackage != null &&
+        _workspacePackage.sourceIsInPublicApi(_currentLibrary.source);
+  }
+
   @override
   void visitAnnotation(Annotation node) {
     ElementAnnotation element = node.elementAnnotation;
@@ -132,6 +138,35 @@
         _errorReporter.reportErrorForNode(
             HintCode.INVALID_IMMUTABLE_ANNOTATION, node, []);
       }
+    } else if (element.isInternal) {
+      var parentElement = parent is Declaration ? parent.declaredElement : null;
+      if (parent is TopLevelVariableDeclaration) {
+        for (VariableDeclaration variable in parent.variables.variables) {
+          if (Identifier.isPrivateName(variable.declaredElement.name)) {
+            _errorReporter.reportErrorForNode(
+                HintCode.INVALID_INTERNAL_ANNOTATION, variable, []);
+          }
+        }
+      } else if (parent is FieldDeclaration) {
+        for (VariableDeclaration variable in parent.fields.variables) {
+          if (Identifier.isPrivateName(variable.declaredElement.name)) {
+            _errorReporter.reportErrorForNode(
+                HintCode.INVALID_INTERNAL_ANNOTATION, variable, []);
+          }
+        }
+      } else if (parent is ConstructorDeclaration) {
+        var class_ = parent.declaredElement.enclosingElement;
+        if (class_.isPrivate || (parentElement?.isPrivate ?? false)) {
+          _errorReporter.reportErrorForNode(
+              HintCode.INVALID_INTERNAL_ANNOTATION, node, []);
+        }
+      } else if (parentElement?.isPrivate ?? false) {
+        _errorReporter
+            .reportErrorForNode(HintCode.INVALID_INTERNAL_ANNOTATION, node, []);
+      } else if (_inPublicPackageApi) {
+        _errorReporter
+            .reportErrorForNode(HintCode.INVALID_INTERNAL_ANNOTATION, node, []);
+      }
     } else if (element.isLiteral == true) {
       if (parent is! ConstructorDeclaration ||
           (parent as ConstructorDeclaration).constKeyword == null) {
@@ -319,6 +354,7 @@
   @override
   void visitExportDirective(ExportDirective node) {
     _checkForDeprecatedMemberUse(node.uriElement, node);
+    _checkForInternalExport(node);
     super.visitExportDirective(node);
   }
 
@@ -994,6 +1030,31 @@
     }
   }
 
+  /// Check that the namespace exported by [node] does not include any elements
+  /// annotated with `@internal`.
+  void _checkForInternalExport(ExportDirective node) {
+    if (!_inPublicPackageApi) return;
+
+    var libraryElement = node.uriElement;
+    if (libraryElement == null) return;
+    if (libraryElement.hasInternal) {
+      _errorReporter.reportErrorForNode(
+          HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT,
+          node,
+          [libraryElement.displayName]);
+    }
+    var exportNamespace =
+        NamespaceBuilder().createExportNamespaceForDirective(node.element);
+    exportNamespace.definedNames.forEach((String name, Element element) {
+      if (element.hasInternal) {
+        _errorReporter.reportErrorForNode(
+            HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT,
+            node,
+            [element.displayName]);
+      }
+    });
+  }
+
   void _checkForInvalidFactory(MethodDeclaration decl) {
     // Check declaration.
     // Note that null return types are expected to be flagged by other analyses.
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_packages.dart b/pkg/analyzer/lib/src/test_utilities/mock_packages.dart
index 2f054b5..9482e66 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_packages.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_packages.dart
@@ -28,6 +28,7 @@
 const _DoNotStore doNotStore = _DoNotStore();
 const _Factory factory = const _Factory();
 const Immutable immutable = const Immutable();
+const _Internal internal = const Internal();
 const _Literal literal = const _Literal();
 const _MustCallSuper mustCallSuper = const _MustCallSuper();
 const _NonVirtual nonVirtual = const _NonVirtual();
@@ -50,6 +51,9 @@
   final String reason;
   const Immutable([this.reason]);
 }
+class _Internal {
+  const Internal();
+}
 class _Literal {
   const _Literal();
 }
diff --git a/pkg/analyzer/lib/src/workspace/basic.dart b/pkg/analyzer/lib/src/workspace/basic.dart
index fb02a62..5f3be2a 100644
--- a/pkg/analyzer/lib/src/workspace/basic.dart
+++ b/pkg/analyzer/lib/src/workspace/basic.dart
@@ -80,4 +80,12 @@
   @override
   Map<String, List<Folder>> packagesAvailableTo(String libraryPath) =>
       workspace.packageMap;
+
+  @override
+  bool sourceIsInPublicApi(Source source) {
+    // Since every source file in a BasicPackage is in the same directory, they
+    // are all in the public API of the package. A file in a subdirectory
+    // is in a separate package.
+    return true;
+  }
 }
diff --git a/pkg/analyzer/lib/src/workspace/bazel.dart b/pkg/analyzer/lib/src/workspace/bazel.dart
index 0320187..2c474e6 100644
--- a/pkg/analyzer/lib/src/workspace/bazel.dart
+++ b/pkg/analyzer/lib/src/workspace/bazel.dart
@@ -260,6 +260,19 @@
   WorkspacePackage findPackageFor(String filePath) {
     path.Context context = provider.pathContext;
     Folder folder = provider.getFolder(context.dirname(filePath));
+    if (!context.isWithin(root, folder.path)) {
+      return null;
+    }
+
+    // Handle files which are given with their location in "bazel-bin", etc.
+    // This does not typically happen during usual analysis, but it still could,
+    // and it can come up in tests.
+    if ([genfiles, ...binPaths]
+        .any((binPath) => context.isWithin(binPath, folder.path))) {
+      var relative = context.relative(filePath, from: root);
+      return findPackageFor(
+          context.joinAll([root, ...context.split(relative).skip(1)]));
+    }
 
     while (true) {
       Folder parent = folder.parent;
@@ -300,7 +313,8 @@
       // [folder]'s path, relative to [root]. For example, "foo/bar".
       String relative = context.relative(folder.path, from: root);
       for (String bin in binPaths) {
-        Folder binChild = provider.getFolder(context.join(bin, relative));
+        Folder binChild =
+            provider.getFolder(context.normalize(context.join(bin, relative)));
         if (binChild.exists &&
             binChild.getChildren().any((c) => c.path.endsWith('.packages'))) {
           // [folder]'s sister folder within [bin] contains a ".packages" file.
@@ -548,4 +562,41 @@
   //  lists.
   Map<String, List<Folder>> packagesAvailableTo(String libraryPath) =>
       <String, List<Folder>>{};
+
+  @override
+  bool sourceIsInPublicApi(Source source) {
+    var filePath = filePathFromSource(source);
+    if (filePath == null) return false;
+
+    var libFolder = workspace.provider.pathContext.join(root, 'lib');
+    if (workspace.provider.pathContext.isWithin(libFolder, filePath)) {
+      // A file in "$root/lib" is public iff it is not in "$root/lib/src".
+      var libSrcFolder = workspace.provider.pathContext.join(libFolder, 'src');
+      return !workspace.provider.pathContext.isWithin(libSrcFolder, filePath);
+    }
+
+    var relativeRoot =
+        workspace.provider.pathContext.relative(root, from: workspace.root);
+    for (var binPath in workspace.binPaths) {
+      libFolder =
+          workspace.provider.pathContext.join(binPath, relativeRoot, 'lib');
+      if (workspace.provider.pathContext.isWithin(libFolder, filePath)) {
+        // A file in "$bin/lib" is public iff it is not in "$bin/lib/src".
+        var libSrcFolder =
+            workspace.provider.pathContext.join(libFolder, 'src');
+        return !workspace.provider.pathContext.isWithin(libSrcFolder, filePath);
+      }
+    }
+
+    libFolder = workspace.provider.pathContext
+        .join(workspace.genfiles, relativeRoot, 'lib');
+    if (workspace.provider.pathContext.isWithin(libFolder, filePath)) {
+      // A file in "$genfiles/lib" is public iff it is not in
+      // "$genfiles/lib/src".
+      var libSrcFolder = workspace.provider.pathContext.join(libFolder, 'src');
+      return !workspace.provider.pathContext.isWithin(libSrcFolder, filePath);
+    }
+
+    return false;
+  }
 }
diff --git a/pkg/analyzer/lib/src/workspace/gn.dart b/pkg/analyzer/lib/src/workspace/gn.dart
index cca441f..fe78cc0 100644
--- a/pkg/analyzer/lib/src/workspace/gn.dart
+++ b/pkg/analyzer/lib/src/workspace/gn.dart
@@ -237,4 +237,17 @@
   @override
   Map<String, List<Folder>> packagesAvailableTo(String libraryPath) =>
       workspace.packageMap;
+
+  @override
+  bool sourceIsInPublicApi(Source source) {
+    var filePath = filePathFromSource(source);
+    if (filePath == null) return false;
+    var libFolder = workspace.provider.pathContext.join(root, 'lib');
+    if (workspace.provider.pathContext.isWithin(libFolder, filePath)) {
+      var libSrcFolder =
+          workspace.provider.pathContext.join(root, 'lib', 'src');
+      return !workspace.provider.pathContext.isWithin(libSrcFolder, filePath);
+    }
+    return false;
+  }
 }
diff --git a/pkg/analyzer/lib/src/workspace/package_build.dart b/pkg/analyzer/lib/src/workspace/package_build.dart
index 60eb742..7240390 100644
--- a/pkg/analyzer/lib/src/workspace/package_build.dart
+++ b/pkg/analyzer/lib/src/workspace/package_build.dart
@@ -137,6 +137,12 @@
   /// package:build does it.
   static const String _pubspecName = 'pubspec.yaml';
 
+  static const List<String> _generatedPathParts = [
+    '.dart_tool',
+    'build',
+    'generated'
+  ];
+
   /// The resource provider used to access the file system.
   final ResourceProvider provider;
 
@@ -286,7 +292,7 @@
           final yaml = loadYaml(pubspec.readAsStringSync());
           final packageName = yaml['name'] as String;
           final generatedRootPath = provider.pathContext
-              .join(folder.path, '.dart_tool', 'build', 'generated');
+              .joinAll([folder.path, ..._generatedPathParts]);
           final generatedThisPath =
               provider.pathContext.join(generatedRootPath, packageName);
           return PackageBuildWorkspace._(provider, packageMap, folder.path,
@@ -334,4 +340,26 @@
   @override
   Map<String, List<Folder>> packagesAvailableTo(String libraryPath) =>
       workspace._packageMap;
+
+  @override
+  bool sourceIsInPublicApi(Source source) {
+    var filePath = filePathFromSource(source);
+    if (filePath == null) return false;
+    var libFolder = workspace.provider.pathContext.join(root, 'lib');
+    if (workspace.provider.pathContext.isWithin(libFolder, filePath)) {
+      // A file in "$root/lib" is public iff it is not in "$root/lib/src".
+      var libSrcFolder = workspace.provider.pathContext.join(libFolder, 'src');
+      return !workspace.provider.pathContext.isWithin(libSrcFolder, filePath);
+    }
+
+    libFolder = workspace.provider.pathContext.joinAll(
+        [root, ...PackageBuildWorkspace._generatedPathParts, 'test', 'lib']);
+    if (workspace.provider.pathContext.isWithin(libFolder, filePath)) {
+      // A file in "$generated/lib" is public iff it is not in
+      // "$generated/lib/src".
+      var libSrcFolder = workspace.provider.pathContext.join(libFolder, 'src');
+      return !workspace.provider.pathContext.isWithin(libSrcFolder, filePath);
+    }
+    return false;
+  }
 }
diff --git a/pkg/analyzer/lib/src/workspace/pub.dart b/pkg/analyzer/lib/src/workspace/pub.dart
index f47327d..1fed22e 100644
--- a/pkg/analyzer/lib/src/workspace/pub.dart
+++ b/pkg/analyzer/lib/src/workspace/pub.dart
@@ -120,4 +120,20 @@
     //  [libraryPath] is inside the `lib` directory.
     return workspace.packageMap;
   }
+
+  @override
+
+  /// A Pub package's public API consists of libraries found in the top-level
+  /// "lib" directory, and any subdirectories, excluding the "src" directory
+  /// just inside the top-level "lib" directory.
+  bool sourceIsInPublicApi(Source source) {
+    var filePath = filePathFromSource(source);
+    if (filePath == null) return false;
+    var libFolder = workspace.provider.pathContext.join(root, 'lib');
+    if (!workspace.provider.pathContext.isWithin(libFolder, filePath)) {
+      return false;
+    }
+    var libSrcFolder = workspace.provider.pathContext.join(root, 'lib', 'src');
+    return !workspace.provider.pathContext.isWithin(libSrcFolder, filePath);
+  }
 }
diff --git a/pkg/analyzer/lib/src/workspace/workspace.dart b/pkg/analyzer/lib/src/workspace/workspace.dart
index d9dc17a..0b83b88 100644
--- a/pkg/analyzer/lib/src/workspace/workspace.dart
+++ b/pkg/analyzer/lib/src/workspace/workspace.dart
@@ -67,6 +67,9 @@
   /// path of the root of those packages for all of the packages that could
   /// validly be imported by the library with the given [libraryPath].
   Map<String, List<Folder>> packagesAvailableTo(String libraryPath);
+
+  /// Return whether [source] is located in this package's public API.
+  bool sourceIsInPublicApi(Source source);
 }
 
 /// An interface for a workspace that contains a default analysis options file.
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_export_of_internal_element_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_export_of_internal_element_test.dart
new file mode 100644
index 0000000..40ce958
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/invalid_export_of_internal_element_test.dart
@@ -0,0 +1,512 @@
+// Copyright (c) 2020, 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/dart/analysis/analysis_context.dart';
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/test_utilities/mock_packages.dart';
+import 'package:analyzer/src/workspace/bazel.dart';
+import 'package:analyzer/src/workspace/package_build.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(InvalidExportOfInternalElement_BazelPackageTest);
+    defineReflectiveTests(
+        InvalidExportOfInternalElement_PackageBuildPackageTest);
+    defineReflectiveTests(InvalidExportOfInternalElement_PubPackageTest);
+  });
+}
+
+@reflectiveTest
+class InvalidExportOfInternalElement_BazelPackageTest
+    extends BazelWorkspaceResolutionTest
+    with InvalidExportOfInternalElementTest {
+  /// A cached analysis context for resolving sources via the same [Workspace].
+  AnalysisContext analysisContext;
+
+  String get testPackageBazelBinPath => '$workspaceRootPath/bazel-bin/dart/my';
+
+  String get testPackageGenfilesPath =>
+      '$workspaceRootPath/bazel-genfiles/dart/my';
+
+  @override
+  String get testPackageLibPath => myPackageLibPath;
+
+  @override
+  Future<ResolvedUnitResult> resolveFile(String path) {
+    analysisContext ??= contextFor(path);
+    assert(analysisContext.workspace is BazelWorkspace);
+    return analysisContext.currentSession.getResolvedUnit(path);
+  }
+
+  @override
+  void setUp() async {
+    super.setUp();
+    var metaPath = '$workspaceThirdPartyDartPath/meta';
+    MockPackages.addMetaPackageFiles(
+      getFolder(metaPath),
+    );
+    newFile('$testPackageBazelBinPath/my.packages');
+    newFolder('$workspaceRootPath/bazel-out');
+  }
+
+  void test_exporterIsInBazelBinLib() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+    await resolveFile2(testPackageImplementationFilePath);
+
+    newFile('$testPackageBazelBinPath/lib/bar.dart', content: r'''
+export 'src/foo.dart';
+''');
+    await resolveFile2('$testPackageBazelBinPath/lib/bar.dart');
+
+    assertErrorsInResolvedUnit(result, [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 22),
+    ]);
+  }
+
+  void test_exporterIsInBazelBinLibSrc() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+    await resolveFile2(testPackageImplementationFilePath);
+
+    newFile('$testPackageBazelBinPath/lib/src/bar.dart', content: r'''
+export 'foo.dart';
+''');
+    await resolveFile2('$testPackageBazelBinPath/lib/src/bar.dart');
+
+    assertErrorsInResolvedUnit(result, []);
+  }
+
+  void test_exporterIsInGenfilesLib() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+    await resolveFile2(testPackageImplementationFilePath);
+
+    newFile('$testPackageGenfilesPath/lib/bar.dart', content: r'''
+export 'src/foo.dart';
+''');
+    await resolveFile2('$testPackageGenfilesPath/lib/bar.dart');
+
+    assertErrorsInResolvedUnit(result, [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 22),
+    ]);
+  }
+
+  void test_exporterIsInGenfilesLibSrc() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+    await resolveFile2(testPackageImplementationFilePath);
+
+    newFile('$testPackageGenfilesPath/lib/src/bar.dart', content: r'''
+export 'foo.dart';
+''');
+    await resolveFile2('$testPackageGenfilesPath/lib/src/bar.dart');
+
+    assertErrorsInResolvedUnit(result, []);
+  }
+
+  void test_exporterIsInLib() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    newFile('$testPackageLibPath/bar.dart', content: r'''
+export 'src/foo.dart';
+''');
+    await resolveFile2('$testPackageLibPath/bar.dart');
+
+    assertErrorsInResolvedUnit(result, [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 22),
+    ]);
+  }
+
+  void test_exporterIsInLibSrc() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    newFile('$testPackageLibPath/src/bar.dart', content: r'''
+export 'foo.dart';
+''');
+    await resolveFile2('$testPackageLibPath/src/bar.dart');
+
+    assertErrorsInResolvedUnit(result, []);
+  }
+
+  void test_exporterIsInTest() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    newFile('$myPackageRootPath/test/foo_test.dart', content: r'''
+export 'package:dart.my/src/foo.dart';
+''');
+    await resolveFile2('$myPackageRootPath/test/foo_test.dart');
+
+    assertErrorsInResolvedUnit(result, []);
+  }
+
+  void test_internalIsInBazelBin() async {
+    newFile('$testPackageBazelBinPath/lib/src/foo.dart', content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    await assertErrorsInCode(r'''
+export 'package:dart.my/src/foo.dart';
+''', [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 38),
+    ]);
+  }
+
+  void test_internalIsInGenfiles() async {
+    newFile('$testPackageGenfilesPath/lib/src/foo.dart', content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    await assertErrorsInCode(r'''
+export 'package:dart.my/src/foo.dart';
+''', [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 38),
+    ]);
+  }
+
+  void test_internalIsInLibSrc() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    await assertErrorsInCode(r'''
+export 'package:dart.my/src/foo.dart';
+''', [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 38),
+    ]);
+  }
+}
+
+@reflectiveTest
+class InvalidExportOfInternalElement_PackageBuildPackageTest
+    extends InvalidExportOfInternalElement_PubPackageTest {
+  /// A cached analysis context for resolving sources via the same [Workspace].
+  AnalysisContext analysisContext;
+
+  String get testPackageDartToolPath =>
+      '$testPackageRootPath/.dart_tool/build/generated/test';
+
+  @override
+  Future<ResolvedUnitResult> resolveFile(String path) {
+    analysisContext ??= contextFor(path);
+    assert(analysisContext.workspace is PackageBuildWorkspace);
+    return analysisContext.currentSession.getResolvedUnit(path);
+  }
+
+  @override
+  void setUp() async {
+    analysisContext = null;
+    super.setUp();
+    newFolder(testPackageDartToolPath);
+  }
+
+  void test_exporterInGeneratedLib() async {
+    newFile('$testPackageRootPath/lib/src/foo.dart', content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+    await resolveFile2('$testPackageRootPath/lib/src/foo.dart');
+
+    newFile('$testPackageDartToolPath/lib/bar.dart', content: r'''
+export 'package:test/src/foo.dart';
+''');
+    await resolveFile2('$testPackageDartToolPath/lib/bar.dart');
+
+    assertErrorsInResolvedUnit(result, [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 35),
+    ]);
+  }
+
+  void test_exporterInGeneratedLibSrc() async {
+    newFile('$testPackageRootPath/lib/src/foo.dart', content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+    await resolveFile2('$testPackageRootPath/lib/src/foo.dart');
+
+    newFile('$testPackageDartToolPath/lib/src/bar.dart', content: r'''
+export 'package:test/src/foo.dart';
+''');
+    await resolveFile2('$testPackageDartToolPath/lib/src/bar.dart');
+
+    assertErrorsInResolvedUnit(result, []);
+  }
+
+  void test_exporterInLib() async {
+    newFile('$testPackageRootPath/lib/src/foo.dart', content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+    await resolveFile2('$testPackageRootPath/lib/src/foo.dart');
+
+    newFile('$testPackageRootPath/lib/bar.dart', content: r'''
+export 'package:test/src/foo.dart';
+''');
+    await resolveFile2('$testPackageRootPath/lib/bar.dart');
+
+    assertErrorsInResolvedUnit(result, [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 35),
+    ]);
+  }
+
+  void test_exporterInLibSrc() async {
+    newFile('$testPackageRootPath/lib/src/foo.dart', content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+    await resolveFile2('$testPackageRootPath/lib/src/foo.dart');
+
+    newFile('$testPackageRootPath/lib/src/bar.dart', content: r'''
+export 'package:test/src/foo.dart';
+''');
+    await resolveFile2('$testPackageRootPath/lib/src/bar.dart');
+
+    assertErrorsInResolvedUnit(result, []);
+  }
+
+  void test_internalIsInGeneratedLibSrc() async {
+    newFile('$testPackageDartToolPath/lib/src/foo.dart', content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    await assertErrorsInCode(r'''
+export 'package:test/src/foo.dart';
+''', [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 35),
+    ]);
+  }
+
+  void test_internalIsLibSrc() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    await assertErrorsInCode(r'''
+export 'package:test/src/foo.dart';
+''', [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 35),
+    ]);
+  }
+}
+
+@reflectiveTest
+class InvalidExportOfInternalElement_PubPackageTest
+    extends PubPackageResolutionTest with InvalidExportOfInternalElementTest {
+  @override
+  void setUp() async {
+    super.setUp();
+    writeTestPackageConfigWithMeta();
+    newFile('$testPackageRootPath/pubspec.yaml', content: r'''
+name: test
+version: 0.0.1
+''');
+  }
+
+  void test_exporterIsInLib() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    newFile('$testPackageLibPath/bar.dart', content: r'''
+export 'src/foo.dart';
+''');
+    await resolveFile2('$testPackageLibPath/bar.dart');
+
+    assertErrorsInResolvedUnit(result, [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 22),
+    ]);
+  }
+
+  void test_exporterIsInLibSrc() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    newFile('$testPackageLibPath/src/bar.dart', content: r'''
+export 'foo.dart';
+''');
+    await resolveFile2('$testPackageLibPath/src/bar.dart');
+
+    assertErrorsInResolvedUnit(result, []);
+  }
+
+  void test_exporterIsInTest() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    newFile('$testPackageRootPath/test/foo_test.dart', content: r'''
+export 'package:test/src/foo.dart';
+''');
+    await resolveFile2('$testPackageRootPath/test/foo_test.dart');
+
+    assertErrorsInResolvedUnit(result, []);
+  }
+
+  void test_internalIsLibSrc() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    await assertErrorsInCode(r'''
+export 'package:test/src/foo.dart';
+''', [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 35),
+    ]);
+  }
+}
+
+mixin InvalidExportOfInternalElementTest on ContextResolutionTest {
+  String get testPackageImplementationFilePath =>
+      '$testPackageLibPath/src/foo.dart';
+
+  String get testPackageLibPath;
+
+  void test_hideCombinator_internalHidden() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+class Two {}
+''');
+
+    await assertNoErrorsInCode(r'''
+export 'src/foo.dart' hide One;
+''');
+  }
+
+  void test_hideCombinator_internalNotHidden() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+class Two {}
+''');
+
+    await assertErrorsInCode(r'''
+export 'src/foo.dart' hide Two;
+''', [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 31),
+    ]);
+  }
+
+  void test_noCombinators() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    await assertErrorsInCode(r'''
+export 'src/foo.dart';
+''', [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 22),
+    ]);
+  }
+
+  void test_noCombinators_indirectExport() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+export 'bar.dart';
+''');
+
+    newFile('$testPackageLibPath/src/bar.dart', content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+
+    await assertErrorsInCode(r'''
+export 'src/foo.dart';
+''', [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 22),
+    ]);
+  }
+
+  void test_noCombinators_library() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+@internal
+library foo;
+
+import 'package:meta/meta.dart';
+''');
+
+    await assertErrorsInCode(r'''
+export 'src/foo.dart';
+''', [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 22),
+    ]);
+  }
+
+  void test_noCombinators_library_notInternal() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+library foo;
+''');
+
+    await assertNoErrorsInCode(r'''
+export 'src/foo.dart';
+''');
+  }
+
+  void test_noCombinators_noInternal() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+class One {}
+''');
+
+    await assertNoErrorsInCode(r'''
+export 'src/foo.dart';
+''');
+  }
+
+  void test_showCombinator_internalNotShown() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+class Two {}
+''');
+
+    await assertNoErrorsInCode(r'''
+export 'src/foo.dart' show Two;
+''');
+  }
+
+  void test_showCombinator_internalShown() async {
+    newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+class Two {}
+''');
+
+    await assertErrorsInCode(r'''
+export 'src/foo.dart' show One;
+''', [
+      error(HintCode.INVALID_EXPORT_OF_INTERNAL_ELEMENT, 0, 31),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_internal_annotation_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_internal_annotation_test.dart
new file mode 100644
index 0000000..2dee934
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/invalid_internal_annotation_test.dart
@@ -0,0 +1,361 @@
+// Copyright (c) 2020, 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(InvalidInternalAnnotationTest);
+  });
+}
+
+@reflectiveTest
+class InvalidInternalAnnotationTest extends PubPackageResolutionTest {
+  String get testPackageImplementationFilePath =>
+      '$testPackageLibPath/src/foo.dart';
+
+  @override
+  void setUp() async {
+    super.setUp();
+    writeTestPackageConfigWithMeta();
+    await newFile('$testPackageRootPath/pubspec.yaml', content: r'''
+name: test
+version: 0.0.1
+''');
+  }
+
+  void test_annotationInLib() async {
+    await newFile('$testPackageLibPath/foo.dart', content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+    await resolveFile2('$testPackageLibPath/foo.dart');
+
+    assertErrorsInResolvedUnit(result, [
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 33, 9),
+    ]);
+  }
+
+  void test_annotationInLib_onLibrary() async {
+    await newFile('$testPackageLibPath/foo.dart', content: r'''
+@internal
+library foo;
+import 'package:meta/meta.dart';
+''');
+    await resolveFile2('$testPackageLibPath/foo.dart');
+
+    assertErrorsInResolvedUnit(result, [
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 0, 9),
+    ]);
+  }
+
+  void test_annotationInLibSrc() async {
+    await newFile('$testPackageLibPath/src/foo.dart', content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+    await resolveFile2('$testPackageLibPath/src/foo.dart');
+
+    assertErrorsInResolvedUnit(result, []);
+  }
+
+  void test_annotationInLibSrcSubdirectory() async {
+    await newFile('$testPackageLibPath/src/foo/foo.dart', content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+    await resolveFile2('$testPackageLibPath/src/foo/foo.dart');
+
+    assertErrorsInResolvedUnit(result, []);
+  }
+
+  void test_annotationInLibSubdirectory() async {
+    await newFile('$testPackageLibPath/foo/foo.dart', content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+    await resolveFile2('$testPackageLibPath/foo/foo.dart');
+
+    assertErrorsInResolvedUnit(result, [
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 33, 9),
+    ]);
+  }
+
+  void test_annotationInTest() async {
+    await newFile('$testPackageRootPath/test/foo_test.dart', content: r'''
+import 'package:meta/meta.dart';
+@internal class One {}
+''');
+    await resolveFile2('$testPackageRootPath/test/foo_test.dart');
+
+    assertErrorsInResolvedUnit(result, []);
+  }
+
+  void test_privateClass() async {
+    await newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal class _One {}
+''');
+    await resolveFile2(testPackageImplementationFilePath);
+
+    assertErrorsInResolvedUnit(result, [
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 33, 9),
+      error(HintCode.UNUSED_ELEMENT, 49, 4),
+    ]);
+  }
+
+  void test_privateClassConstructor_named() async {
+    await newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+class _C {
+  @internal _C.named();
+}
+''');
+    await resolveFile2(testPackageImplementationFilePath);
+
+    assertErrorsInResolvedUnit(result, [
+      error(HintCode.UNUSED_ELEMENT, 39, 2),
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 46, 9),
+    ]);
+  }
+
+  void test_privateClassConstructor_unnamed() async {
+    await newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+class _C {
+  @internal _C();
+}
+''');
+    await resolveFile2(testPackageImplementationFilePath);
+
+    assertErrorsInResolvedUnit(result, [
+      error(HintCode.UNUSED_ELEMENT, 39, 2),
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 46, 9),
+    ]);
+  }
+
+  void test_privateConstructor() async {
+    await newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+class C {
+  @internal C._f();
+}
+''');
+    await resolveFile2(testPackageImplementationFilePath);
+
+    assertErrorsInResolvedUnit(result, [
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 45, 9),
+    ]);
+  }
+
+  void test_privateEnum() async {
+    await newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal enum _E {one}
+''');
+    await resolveFile2(testPackageImplementationFilePath);
+
+    assertErrorsInResolvedUnit(result, [
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 33, 9),
+      error(HintCode.UNUSED_ELEMENT, 48, 2),
+      error(HintCode.UNUSED_FIELD, 52, 3),
+    ]);
+  }
+
+  void test_privateEnumValue() async {
+    await newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+enum E {@internal _one}
+''');
+    await resolveFile2(testPackageImplementationFilePath);
+
+    assertErrorsInResolvedUnit(result, [
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 41, 9),
+      error(HintCode.UNUSED_FIELD, 51, 4),
+    ]);
+  }
+
+  void test_privateExtension() async {
+    await newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal extension _One on String {}
+''');
+    await resolveFile2(testPackageImplementationFilePath);
+
+    assertErrorsInResolvedUnit(result, [
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 33, 9),
+    ]);
+  }
+
+  void test_privateExtension_unnamed() async {
+    await newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+@internal extension on String {}
+''');
+    await resolveFile2(testPackageImplementationFilePath);
+
+    assertErrorsInResolvedUnit(result, [
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 33, 9),
+    ]);
+  }
+
+  void test_privateField_instance() async {
+    await newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+class C {
+  @internal int _i = 0;
+}
+''');
+    await resolveFile2(testPackageImplementationFilePath);
+
+    assertErrorsInResolvedUnit(result, [
+      error(HintCode.UNUSED_FIELD, 59, 2),
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 59, 6),
+    ]);
+  }
+
+  void test_privateField_static() async {
+    await newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+class C {
+  @internal static int _i = 0;
+}
+''');
+    await resolveFile2(testPackageImplementationFilePath);
+
+    assertErrorsInResolvedUnit(result, [
+      error(HintCode.UNUSED_FIELD, 66, 2),
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 66, 6),
+    ]);
+  }
+
+  void test_privateGetter() async {
+    await newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+class C {
+  @internal int get _i => 0;
+}
+''');
+    await resolveFile2(testPackageImplementationFilePath);
+
+    assertErrorsInResolvedUnit(result, [
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 45, 9),
+      error(HintCode.UNUSED_ELEMENT, 63, 2),
+    ]);
+  }
+
+  void test_privateMethod_instance() async {
+    await newFile(testPackageImplementationFilePath, content: r'''
+import 'package:meta/meta.dart';
+class C {
+  @internal void _f() {}
+}
+''');
+    await resolveFile2(testPackageImplementationFilePath);
+
+    assertErrorsInResolvedUnit(result, [
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 45, 9),
+      error(HintCode.UNUSED_ELEMENT, 60, 2),
+    ]);
+  }
+
+  void test_privateMethod_static() async {
+    await newFile('$testPackageLibPath/src/foo.dart', content: r'''
+import 'package:meta/meta.dart';
+class C {
+  @internal static void _f() {}
+}
+''');
+    await resolveFile2('$testPackageLibPath/src/foo.dart');
+
+    assertErrorsInResolvedUnit(result, [
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 45, 9),
+      error(HintCode.UNUSED_ELEMENT, 67, 2),
+    ]);
+  }
+
+  void test_privateMixin() async {
+    await newFile('$testPackageLibPath/src/foo.dart', content: r'''
+import 'package:meta/meta.dart';
+@internal mixin _One {}
+''');
+    await resolveFile2('$testPackageLibPath/src/foo.dart');
+
+    assertErrorsInResolvedUnit(result, [
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 33, 9),
+      error(HintCode.UNUSED_ELEMENT, 49, 4),
+    ]);
+  }
+
+  void test_privateTopLevelFunction() async {
+    await newFile('$testPackageLibPath/src/foo.dart', content: r'''
+import 'package:meta/meta.dart';
+@internal void _f() {}
+''');
+    await resolveFile2('$testPackageLibPath/src/foo.dart');
+
+    assertErrorsInResolvedUnit(result, [
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 33, 9),
+      error(HintCode.UNUSED_ELEMENT, 48, 2),
+    ]);
+  }
+
+  void test_privateTopLevelVariable() async {
+    await newFile('$testPackageLibPath/src/foo.dart', content: r'''
+import 'package:meta/meta.dart';
+@internal int _i = 1;
+''');
+    await resolveFile2('$testPackageLibPath/src/foo.dart');
+
+    assertErrorsInResolvedUnit(result, [
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 47, 6),
+      error(HintCode.UNUSED_ELEMENT, 47, 2),
+    ]);
+  }
+
+  void test_privateTypedef() async {
+    await newFile('$testPackageLibPath/src/foo.dart', content: r'''
+import 'package:meta/meta.dart';
+@internal typedef _T = void Function();
+''');
+    await resolveFile2('$testPackageLibPath/src/foo.dart');
+
+    assertErrorsInResolvedUnit(result, [
+      error(HintCode.INVALID_INTERNAL_ANNOTATION, 33, 9),
+      error(HintCode.UNUSED_ELEMENT, 51, 2),
+    ]);
+  }
+
+  void test_publicMethod_privateClass() async {
+    await newFile('$testPackageLibPath/src/foo.dart', content: r'''
+import 'package:meta/meta.dart';
+class _C {
+  @internal void f() {}
+}
+''');
+    await resolveFile2('$testPackageLibPath/src/foo.dart');
+
+    assertErrorsInResolvedUnit(result, [
+      error(HintCode.UNUSED_ELEMENT, 39, 2),
+    ]);
+  }
+
+  void test_publicMethod_privateClass_static() async {
+    await newFile('$testPackageLibPath/src/foo.dart', content: r'''
+import 'package:meta/meta.dart';
+class _C {
+  @internal static void f() {}
+}
+''');
+    await resolveFile2('$testPackageLibPath/src/foo.dart');
+
+    assertErrorsInResolvedUnit(result, [
+      error(HintCode.UNUSED_ELEMENT, 39, 2),
+      error(HintCode.UNUSED_ELEMENT, 68, 1),
+    ]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index 55f08d2..08a65a1 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -279,6 +279,8 @@
 import 'invalid_constant_test.dart' as invalid_constant;
 import 'invalid_constructor_name_test.dart' as invalid_constructor_name;
 import 'invalid_exception_value_test.dart' as invalid_exception_value;
+import 'invalid_export_of_internal_element_test.dart'
+    as invalid_export_of_internal_element;
 import 'invalid_extension_argument_count_test.dart'
     as invalid_extension_argument_count;
 import 'invalid_factory_annotation_test.dart' as invalid_factory_annotation;
@@ -287,6 +289,7 @@
     as invalid_factory_name_not_a_class;
 import 'invalid_field_type_in_struct_test.dart' as invalid_field_type_in_struct;
 import 'invalid_immutable_annotation_test.dart' as invalid_immutable_annotation;
+import 'invalid_internal_annotation_test.dart' as invalid_internal_annotation;
 import 'invalid_language_override_greater_test.dart'
     as invalid_language_override_greater;
 import 'invalid_language_override_test.dart' as invalid_language_override;
@@ -828,12 +831,14 @@
     invalid_constant.main();
     invalid_constructor_name.main();
     invalid_exception_value.main();
+    invalid_export_of_internal_element.main();
     invalid_extension_argument_count.main();
     invalid_factory_annotation.main();
     invalid_factory_method_impl.main();
     invalid_factory_name_not_a_class.main();
     invalid_field_type_in_struct.main();
     invalid_immutable_annotation.main();
+    invalid_internal_annotation.main();
     invalid_language_override_greater.main();
     invalid_language_override.main();
     invalid_literal_annotation.main();