Split DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE off; fixes #30084 and
fixes https://github.com/dart-lang/linter/issues/1349

Bug: https://github.com/dart-lang/sdk/issues/30084
Change-Id: I4954b883c1baf019a62776fec108eac60960b22e
Reviewed-on: https://dart-review.googlesource.com/c/88881
Commit-Queue: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Sigmund Cherem <sigmund@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 3e41b50..fdaed1b 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -277,9 +277,10 @@
   HintCode.DEAD_CODE,
   HintCode.DEAD_CODE_CATCH_FOLLOWING_CATCH,
   HintCode.DEAD_CODE_ON_CATCH_SUBTYPE,
-  HintCode.DEPRECATED_MEMBER_USE,
-  HintCode.DEPRECATED_FUNCTION_CLASS_DECLARATION,
   HintCode.DEPRECATED_EXTENDS_FUNCTION,
+  HintCode.DEPRECATED_FUNCTION_CLASS_DECLARATION,
+  HintCode.DEPRECATED_MEMBER_USE,
+  HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE,
   HintCode.DEPRECATED_MIXIN_FUNCTION,
   HintCode.DIVISION_OPTIMIZATION,
   HintCode.DUPLICATE_IMPORT,
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
index 9c10fe7..62c6a8a 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -68,6 +68,23 @@
           "Try replacing the use of the deprecated member with the replacement.");
 
   /**
+   * Deprecated members should not be invoked or used from within the package
+   * where they are declared.
+   *
+   * Intentionally separate from DEPRECATED_MEMBER_USE, so that package owners
+   * can ignore same-package deprecate member use Hints if they like, and
+   * continue to see cross-package deprecated member use Hints.
+   *
+   * Parameters:
+   * 0: the name of the member
+   */
+  static const HintCode DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE = const HintCode(
+      'DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE',
+      "'{0}' is deprecated and shouldn't be used.",
+      correction:
+          "Try replacing the use of the deprecated member with the replacement.");
+
+  /**
    * Users should not create a class named `Function` anymore.
    */
   static const HintCode DEPRECATED_FUNCTION_CLASS_DECLARATION = const HintCode(
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 050e255..9dc3ff1 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -716,11 +716,16 @@
       } else if (displayName == FunctionElement.CALL_METHOD_NAME &&
           node is MethodInvocation &&
           node.staticInvokeType is InterfaceType) {
-        displayName =
-            "${resolutionMap.staticInvokeTypeForInvocationExpression(node).displayName}.${element.displayName}";
+        DartType staticInvokeType =
+            resolutionMap.staticInvokeTypeForInvocationExpression(node);
+        displayName = "${staticInvokeType.displayName}.${element.displayName}";
       }
-      _errorReporter.reportErrorForNode(
-          HintCode.DEPRECATED_MEMBER_USE, node, [displayName]);
+      LibraryElement library =
+          element is LibraryElement ? element : element.library;
+      HintCode hintCode = _workspacePackage.contains(library.source.fullName)
+          ? HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE
+          : HintCode.DEPRECATED_MEMBER_USE;
+      _errorReporter.reportErrorForNode(hintCode, node, [displayName]);
     }
   }
 
diff --git a/pkg/analyzer/test/generated/resolver_test_case.dart b/pkg/analyzer/test/generated/resolver_test_case.dart
index 485d871..a682c9d 100644
--- a/pkg/analyzer/test/generated/resolver_test_case.dart
+++ b/pkg/analyzer/test/generated/resolver_test_case.dart
@@ -35,6 +35,8 @@
 import 'analysis_context_factory.dart';
 import 'test_support.dart';
 
+const String _defaultSourceName = "/test.dart";
+
 /**
  * An AST visitor used to verify that all of the nodes in an AST structure that
  * should have been resolved were resolved.
@@ -407,7 +409,8 @@
    * file will have the given [contents] set in the content provider. Return the
    * source representing the added file.
    */
-  Source addSource(String contents) => addNamedSource("/test.dart", contents);
+  Source addSource(String contents) =>
+      addNamedSource(_defaultSourceName, contents);
 
   /**
    * The [code] that assigns the value to the variable "v", no matter how. We
@@ -457,8 +460,8 @@
    */
   // TODO(rnystrom): Use this in more tests that have the same structure.
   Future<void> assertErrorsInCode(String code, List<ErrorCode> errors,
-      {bool verify: true}) async {
-    Source source = addSource(code);
+      {bool verify: true, String sourceName: _defaultSourceName}) async {
+    Source source = addNamedSource(sourceName, code);
     await computeAnalysisResult(source);
     assertErrors(source, errors);
     if (verify) {
diff --git a/pkg/analyzer/test/src/diagnostics/deprecated_member_use_test.dart b/pkg/analyzer/test/src/diagnostics/deprecated_member_use_test.dart
index b65409d..1dcc23e 100644
--- a/pkg/analyzer/test/src/diagnostics/deprecated_member_use_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/deprecated_member_use_test.dart
@@ -3,12 +3,15 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/source.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../../generated/resolver_test_case.dart';
 
 main() {
   defineReflectiveSuite(() {
+    defineReflectiveTests(DeprecatedMemberUseFromSamePackageTest);
+    defineReflectiveTests(DeprecatedMemberUseFromSamePackageTest_Driver);
     defineReflectiveTests(DeprecatedMemberUseTest);
     defineReflectiveTests(DeprecatedMemberUseTest_Driver);
   });
@@ -16,14 +19,92 @@
 
 @reflectiveTest
 class DeprecatedMemberUseTest extends ResolverTestCase {
-  test__methodInvocation_contructor() async {
-    await assertErrorsInCode(r'''
+  /// Write a pubspec file at [root], so that BestPracticesVerifier can see that
+  /// [root] is the root of a BasicWorkspace, and a BasicWorkspacePackage.
+  void newBasicPackage(String root) {
+    newFile('$root/pubspec.yaml');
+  }
+
+  test_methodInvocation_contructor() async {
+    resetWithFooLibrary(r'''
+class A {
+  @Deprecated('0.9')
+  m() {}
+}
+''');
+
+    newBasicPackage('/pkg1');
+    assertErrorsInCode(r'''
+import 'package:foo/foo.dart';
+void main() => A().m();
+''', [HintCode.DEPRECATED_MEMBER_USE], sourceName: '/pkg1/lib/lib1.dart');
+  }
+
+  test_methodInvocation_constant() async {
+    resetWithFooLibrary(r'''
+class A {
+  @deprecated
+  m() {}
+}
+''');
+
+    newBasicPackage('/pkg1');
+    assertErrorsInCode(r'''
+import 'package:foo/foo.dart';
+void main() => A().m();
+''', [HintCode.DEPRECATED_MEMBER_USE], sourceName: '/pkg1/lib/lib1.dart');
+  }
+
+  void resetWithFooLibrary(String source) {
+    super.resetWith(packages: [
+      ['foo', source]
+    ]);
+  }
+
+  test_export() async {
+    resetWithFooLibrary(r'''
+@deprecated
+library deprecated_library;
+class A {}
+''');
+
+    newBasicPackage('/pkg1');
+    assertErrorsInCode('''
+export 'package:foo/foo.dart';
+''', [HintCode.DEPRECATED_MEMBER_USE], sourceName: '/pkg1/lib/lib1.dart');
+  }
+
+  test_import() async {
+    resetWithFooLibrary(r'''
+@deprecated
+library deprecated_library;
+class A {}
+''');
+
+    newBasicPackage('/pkg1');
+    assertErrorsInCode(r'''
+import 'package:foo/foo.dart';
+f(A a) {}
+''', [HintCode.DEPRECATED_MEMBER_USE], sourceName: '/pkg1/lib/lib1.dart');
+  }
+}
+
+@reflectiveTest
+class DeprecatedMemberUseTest_Driver extends DeprecatedMemberUseTest {
+  @override
+  bool get enableNewAnalysisDriver => true;
+}
+
+@reflectiveTest
+class DeprecatedMemberUseFromSamePackageTest extends ResolverTestCase {
+  test_methodInvocation_contructor() async {
+    assertErrorsInCode(r'''
 class A {
   @Deprecated('0.9')
   m() {}
   n() {m();}
 }
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
   }
 
   test_call() async {
@@ -36,7 +117,7 @@
     a();
   }
 }
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
   }
 
   test_compoundAssignment() async {
@@ -49,7 +130,7 @@
   A b;
   a += b;
 }
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
   }
 
   test_export() async {
@@ -60,7 +141,7 @@
 ''');
     await assertErrorsInCode('''
 export 'deprecated_library.dart';
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
   }
 
   test_field() async {
@@ -72,7 +153,7 @@
 f(A a) {
   return a.x;
 }
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
   }
 
   test_getter() async {
@@ -84,7 +165,7 @@
 f(A a) {
   return a.m;
 }
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
   }
 
   test_import() async {
@@ -96,7 +177,7 @@
     await assertErrorsInCode(r'''
 import 'deprecated_library.dart';
 f(A a) {}
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
   }
 
   test_inDeprecatedClass() async {
@@ -215,7 +296,7 @@
 f(A a) {
   return a[1];
 }
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
   }
 
   test_instanceCreation_defaultConstructor() async {
@@ -227,7 +308,7 @@
 f() {
   A a = new A(1);
 }
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
   }
 
   test_instanceCreation_namedConstructor() async {
@@ -239,7 +320,7 @@
 f() {
   A a = new A.named(1);
 }
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
   }
 
   test_methodInvocation_constant() async {
@@ -249,7 +330,7 @@
   m() {}
   n() {m();}
 }
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
   }
 
   test_operator() async {
@@ -262,7 +343,7 @@
   A b;
   return a + b;
 }
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
   }
 
   test_parameter_named() async {
@@ -271,7 +352,7 @@
   m({@deprecated int x}) {}
   n() {m(x: 1);}
 }
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
   }
 
   test_parameter_named_inDefiningFunction() async {
@@ -322,7 +403,7 @@
   m([@deprecated int x]) {}
   n() {m(1);}
 }
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
   }
 
   test_setter() async {
@@ -334,7 +415,7 @@
 f(A a) {
   return a.s = 1;
 }
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
   }
 
   test_superConstructor_defaultConstructor() async {
@@ -346,7 +427,7 @@
 class B extends A {
   B() : super() {}
 }
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
   }
 
   test_superConstructor_namedConstructor() async {
@@ -358,12 +439,13 @@
 class B extends A {
   B() : super.named() {}
 }
-''', [HintCode.DEPRECATED_MEMBER_USE]);
+''', [HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE]);
   }
 }
 
 @reflectiveTest
-class DeprecatedMemberUseTest_Driver extends DeprecatedMemberUseTest {
+class DeprecatedMemberUseFromSamePackageTest_Driver
+    extends DeprecatedMemberUseFromSamePackageTest {
   @override
   bool get enableNewAnalysisDriver => true;
 }
diff --git a/pkg/compiler/analysis_options.yaml b/pkg/compiler/analysis_options.yaml
index 3400954..af22f6b 100644
--- a/pkg/compiler/analysis_options.yaml
+++ b/pkg/compiler/analysis_options.yaml
@@ -5,4 +5,8 @@
 analyzer:
   errors:
     todo: ignore
+    # Allow cross-package deprecated calls
+    # TODO(srawlins): clean these up and remove this "ignore."
     deprecated_member_use: ignore
+    # Allow deprecated calls from within the same package
+    deprecated_member_use_from_same_package: ignore
diff --git a/pkg/front_end/analysis_options.yaml b/pkg/front_end/analysis_options.yaml
index d5ea4fe..ae13d06 100644
--- a/pkg/front_end/analysis_options.yaml
+++ b/pkg/front_end/analysis_options.yaml
@@ -9,6 +9,8 @@
     # Allow having TODOs in the code
     todo: ignore
 
-    # Allow deprecated calls (although it would be nice to have a distinction
-    # between internal and external deprecated calls).
+    # Allow cross-package deprecated calls
+    # TODO(srawlins): clean these up and remove this "ignore."
     deprecated_member_use: ignore
+    # Allow deprecated calls from within the same package
+    deprecated_member_use_from_same_package: ignore