[CQ] [linter] de-duplicate `reflectiveTestLoader` handling

De-duplicate `reflectiveTestLoader` detection and testing

Change-Id: Ia125bd10638b76452583b1a79c69884edcd9c72d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/412666
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Phil Quitslund <pquitslund@google.com>
diff --git a/pkg/linter/lib/src/extensions.dart b/pkg/linter/lib/src/extensions.dart
index 3193a12..6612d088 100644
--- a/pkg/linter/lib/src/extensions.dart
+++ b/pkg/linter/lib/src/extensions.dart
@@ -312,6 +312,16 @@
           _extendsClass(type.superclass, seenElements, className, library));
 }
 
+extension ElementAnnotationExtension on ElementAnnotation {
+  bool get isReflectiveTest => switch (element2) {
+    GetterElement(:var name3, :var library2) =>
+      name3 == 'reflectiveTest' &&
+          library2.uri.toString() ==
+              'package:test_reflective_loader/test_reflective_loader.dart',
+    _ => false,
+  };
+}
+
 extension ElementExtension on Element2? {
   Element2? get canonicalElement2 => switch (this) {
     PropertyAccessorElement2(:var variable3?) => variable3,
@@ -480,6 +490,12 @@
   }
 }
 
+extension InstanceElementExtension on InstanceElement2 {
+  bool get isReflectiveTest =>
+      this is ClassElement2 &&
+      metadata2.annotations.any((a) => a.isReflectiveTest);
+}
+
 extension InterfaceElementExtension on InterfaceElement2 {
   /// Whether this element has the exact [name] and defined in the file with
   /// the given [uri].
diff --git a/pkg/linter/lib/src/rules/strict_top_level_inference.dart b/pkg/linter/lib/src/rules/strict_top_level_inference.dart
index 8008fd9..45d2a13 100644
--- a/pkg/linter/lib/src/rules/strict_top_level_inference.dart
+++ b/pkg/linter/lib/src/rules/strict_top_level_inference.dart
@@ -268,23 +268,3 @@
     }
   }
 }
-
-extension on InstanceElement2 {
-  // TODO(pq): share w/ unreachable_from_main
-  bool get isReflectiveTest {
-    var self = this;
-    if (self is! ClassElement2) return false;
-
-    var metadata = self.metadata2;
-    for (var i = 0; i < metadata.annotations.length; i++) {
-      var annotation = metadata.annotations[i].element2;
-      if (annotation is GetterElement &&
-          annotation.name3 == 'reflectiveTest' &&
-          annotation.library2.uri.toString() ==
-              'package:test_reflective_loader/test_reflective_loader.dart') {
-        return true;
-      }
-    }
-    return false;
-  }
-}
diff --git a/pkg/linter/lib/src/rules/unreachable_from_main.dart b/pkg/linter/lib/src/rules/unreachable_from_main.dart
index 445eab6..1ce4475 100644
--- a/pkg/linter/lib/src/rules/unreachable_from_main.dart
+++ b/pkg/linter/lib/src/rules/unreachable_from_main.dart
@@ -13,6 +13,7 @@
 import 'package:pub_semver/pub_semver.dart';
 
 import '../analyzer.dart';
+import '../extensions.dart';
 
 const _desc = 'Unreachable top-level members in executable libraries.';
 
@@ -187,10 +188,7 @@
       // This for-loop style is copied from analyzer's `hasX` getters on
       // [Element].
       for (var i = 0; i < metadata.annotations.length; i++) {
-        var annotation = metadata.annotations[i].element2;
-        if (annotation is GetterElement &&
-            annotation.name3 == 'reflectiveTest' &&
-            annotation.library2.name3 == 'test_reflective_loader') {
+        if (metadata.annotations[i].isReflectiveTest) {
           // The class is instantiated through the use of mirrors in
           // 'test_reflective_loader'.
           var unnamedConstructor = element.constructors2.firstWhereOrNull(
diff --git a/pkg/linter/test/rule_test_support.dart b/pkg/linter/test/rule_test_support.dart
index 7719ef7..3a9c561 100644
--- a/pkg/linter/test/rule_test_support.dart
+++ b/pkg/linter/test/rule_test_support.dart
@@ -199,6 +199,25 @@
   @override
   List<String> get _collectionIncludedPaths => [workspaceRootPath];
 
+  void addReflectiveTestLoaderDep() {
+    // TODO(pq): consider mopcing this into `writeTestPackageConfig`
+    var testReflectiveLoaderPath = '$workspaceRootPath/test_reflective_loader';
+    var packageConfigBuilder = PackageConfigFileBuilder();
+    packageConfigBuilder.add(
+      name: 'test_reflective_loader',
+      rootPath: testReflectiveLoaderPath,
+    );
+    writeTestPackageConfig(packageConfigBuilder);
+    newFile('$testReflectiveLoaderPath/lib/test_reflective_loader.dart', r'''
+library test_reflective_loader;
+
+const Object reflectiveTest = _ReflectiveTest();
+class _ReflectiveTest {
+  const _ReflectiveTest();
+}
+''');
+  }
+
   /// Asserts that the number of diagnostics reported in [content] matches the
   /// number of [expectedDiagnostics] and that they have the expected error
   /// descriptions and locations.
diff --git a/pkg/linter/test/rules/strict_top_level_inference_test.dart b/pkg/linter/test/rules/strict_top_level_inference_test.dart
index d7843c2..c957156 100644
--- a/pkg/linter/test/rules/strict_top_level_inference_test.dart
+++ b/pkg/linter/test/rules/strict_top_level_inference_test.dart
@@ -24,25 +24,6 @@
   @override
   String get lintRule => LintNames.strict_top_level_inference;
 
-  void addReflectiveTestLoaderDep() {
-    // TODO(pq): share setup logic with unreachable_from_main_test
-    var testReflectiveLoaderPath = '$workspaceRootPath/test_reflective_loader';
-    var packageConfigBuilder = PackageConfigFileBuilder();
-    packageConfigBuilder.add(
-      name: 'test_reflective_loader',
-      rootPath: testReflectiveLoaderPath,
-    );
-    writeTestPackageConfig(packageConfigBuilder);
-    newFile('$testReflectiveLoaderPath/lib/test_reflective_loader.dart', r'''
-library test_reflective_loader;
-
-const Object reflectiveTest = _ReflectiveTest();
-class _ReflectiveTest {
-  const _ReflectiveTest();
-}
-''');
-  }
-
   test_constructorParameter_named() async {
     await assertDiagnostics(
       r'''
diff --git a/pkg/linter/test/rules/unreachable_from_main_test.dart b/pkg/linter/test/rules/unreachable_from_main_test.dart
index fed49ae..986d81e 100644
--- a/pkg/linter/test/rules/unreachable_from_main_test.dart
+++ b/pkg/linter/test/rules/unreachable_from_main_test.dart
@@ -798,21 +798,7 @@
   }
 
   test_constructor_reachableViaTestReflectiveLoader() async {
-    var testReflectiveLoaderPath = '$workspaceRootPath/test_reflective_loader';
-    var packageConfigBuilder = PackageConfigFileBuilder();
-    packageConfigBuilder.add(
-      name: 'test_reflective_loader',
-      rootPath: testReflectiveLoaderPath,
-    );
-    writeTestPackageConfig(packageConfigBuilder);
-    newFile('$testReflectiveLoaderPath/lib/test_reflective_loader.dart', r'''
-library test_reflective_loader;
-
-const Object reflectiveTest = _ReflectiveTest();
-class _ReflectiveTest {
-  const _ReflectiveTest();
-}
-''');
+    addReflectiveTestLoaderDep();
     await assertNoDiagnostics(r'''
 import 'package:test_reflective_loader/test_reflective_loader.dart';