analyzer: enforce TargetKind.overridableMember and optionalParameter

Change-Id: Ic34e9df7ea10acd81e7280c4f77ec7b6b3ab86e3
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/365680
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Samuel Rawlins <srawlins@google.com>
diff --git a/pkg/analyzer/lib/src/error/annotation_verifier.dart b/pkg/analyzer/lib/src/error/annotation_verifier.dart
index e1fb491..e601785 100644
--- a/pkg/analyzer/lib/src/error/annotation_verifier.dart
+++ b/pkg/analyzer/lib/src/error/annotation_verifier.dart
@@ -586,6 +586,21 @@
   /// when the annotation is marked as being valid for the given [kinds] of
   /// targets.
   bool _isValidTarget(AstNode target, Set<TargetKind> kinds) {
+    // `TargetKind.overridableMember` is complex, so we handle it separately.
+    if (kinds.contains(TargetKind.overridableMember)) {
+      if ((target is FieldDeclaration && !target.isStatic) ||
+          target is MethodDeclaration && !target.isStatic) {
+        var parent = target.parent;
+        if (parent is ClassDeclaration ||
+            parent is ExtensionTypeDeclaration ||
+            parent is MixinDeclaration) {
+          // Members of `EnumDeclaration`s and `ExtensionDeclaration`s are not
+          // overridable.
+          return true;
+        }
+      }
+    }
+
     return switch (target) {
       ClassDeclaration() =>
         kinds.contains(TargetKind.classType) || kinds.contains(TargetKind.type),
@@ -609,7 +624,8 @@
       MethodDeclaration() => kinds.contains(TargetKind.method),
       MixinDeclaration() =>
         kinds.contains(TargetKind.mixinType) || kinds.contains(TargetKind.type),
-      FormalParameter() => kinds.contains(TargetKind.parameter),
+      FormalParameter() => kinds.contains(TargetKind.parameter) ||
+          (target.isOptional && kinds.contains(TargetKind.optionalParameter)),
       FunctionTypeAlias() ||
       GenericTypeAlias() =>
         kinds.contains(TargetKind.typedefType) ||
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_packages.dart b/pkg/analyzer/lib/src/test_utilities/mock_packages.dart
index de5b3fb1..8db3012 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_packages.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_packages.dart
@@ -350,10 +350,14 @@
   static const extensionType = TargetKind._('extension types', 'extensionType');
   static const field = TargetKind._('fields', 'field');
   static const function = TargetKind._('top-level functions', 'function');
+  static const optionalParameter =
+      TargetKind._('optional parameters', 'optionalParameter');
   static const library = TargetKind._('libraries', 'library');
   static const getter = TargetKind._('getters', 'getter');
   static const method = TargetKind._('methods', 'method');
   static const mixinType = TargetKind._('mixins', 'mixinType');
+  static const overridableMember =
+      TargetKind._('overridable members', 'overridableMember');
   static const parameter = TargetKind._('parameters', 'parameter');
   static const setter = TargetKind._('setters', 'setter');
   static const topLevelVariable =
@@ -373,10 +377,12 @@
     extensionType,
     field,
     function,
+    overridableMember,
     library,
     getter,
     method,
     mixinType,
+    optionalParameter,
     parameter,
     setter,
     topLevelVariable,
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index b8b068c..fdb98f3 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -14,7 +14,7 @@
   crypto: ^3.0.0
   glob: ^2.0.0
   macros: '>=0.1.0-0 <0.1.1'
-  meta: ^1.14.0
+  meta: ^1.15.0
   package_config: ^2.0.0
   path: ^1.9.0
   pub_semver: ^2.1.4
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_annotation_target_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_annotation_target_test.dart
index 566aa3c..5146ba5 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_annotation_target_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_annotation_target_test.dart
@@ -1068,6 +1068,215 @@
 ''');
   }
 
+  void test_optionalParameter_optionalNamed() async {
+    await assertNoErrorsInCode('''
+import 'package:meta/meta_meta.dart';
+
+@Target({TargetKind.optionalParameter})
+class A {
+  const A();
+}
+
+void f({@A() int? x}) {}
+''');
+  }
+
+  void test_optionalParameter_optionalPositional() async {
+    await assertNoErrorsInCode('''
+import 'package:meta/meta_meta.dart';
+
+@Target({TargetKind.optionalParameter})
+class A {
+  const A();
+}
+
+void f([@A() int? x]) {}
+''');
+  }
+
+  void test_optionalParameter_requiredNamed() async {
+    await assertErrorsInCode('''
+import 'package:meta/meta_meta.dart';
+
+@Target({TargetKind.optionalParameter})
+class A {
+  const A();
+}
+
+void f({@A() required int x}) {}
+''', [
+      error(WarningCode.INVALID_ANNOTATION_TARGET, 114, 1),
+    ]);
+  }
+
+  void test_optionalParameter_requiredPositional() async {
+    await assertErrorsInCode('''
+import 'package:meta/meta_meta.dart';
+
+@Target({TargetKind.optionalParameter})
+class A {
+  const A();
+}
+
+void f(@A() int x) {}
+''', [
+      error(WarningCode.INVALID_ANNOTATION_TARGET, 113, 1),
+    ]);
+  }
+
+  void test_overridableMember_constructor() async {
+    await assertErrorsInCode('''
+import 'package:meta/meta_meta.dart';
+
+@Target({TargetKind.overridableMember})
+class A {
+  const A();
+}
+
+class C {
+  @A()
+  C();
+}
+''', [
+      error(WarningCode.INVALID_ANNOTATION_TARGET, 118, 1),
+    ]);
+  }
+
+  void test_overridableMember_instanceGetter() async {
+    await assertNoErrorsInCode('''
+import 'package:meta/meta_meta.dart';
+
+@Target({TargetKind.overridableMember})
+class A {
+  const A();
+}
+
+class C {
+  @A()
+  int get x => 0;
+}
+''');
+  }
+
+  void test_overridableMember_instanceMethod() async {
+    await assertNoErrorsInCode('''
+import 'package:meta/meta_meta.dart';
+
+@Target({TargetKind.overridableMember})
+class A {
+  const A();
+}
+
+class C {
+  @A()
+  int x() => 0;
+}
+''');
+  }
+
+  void test_overridableMember_instanceMethod_onEnum() async {
+    await assertErrorsInCode('''
+import 'package:meta/meta_meta.dart';
+
+@Target({TargetKind.overridableMember})
+class A {
+  const A();
+}
+
+enum E {
+  one, two;
+  @A()
+  int x() => 0;
+}
+''', [
+      error(WarningCode.INVALID_ANNOTATION_TARGET, 129, 1),
+    ]);
+  }
+
+  void test_overridableMember_instanceMethod_onExtension() async {
+    await assertErrorsInCode('''
+import 'package:meta/meta_meta.dart';
+
+@Target({TargetKind.overridableMember})
+class A {
+  const A();
+}
+
+extension E on int {
+  @A()
+  int x() => 0;
+}
+''', [
+      error(WarningCode.INVALID_ANNOTATION_TARGET, 129, 1),
+    ]);
+  }
+
+  void test_overridableMember_instanceMethod_onMixin() async {
+    await assertNoErrorsInCode('''
+import 'package:meta/meta_meta.dart';
+
+@Target({TargetKind.overridableMember})
+class A {
+  const A();
+}
+
+mixin M {
+  @A()
+  int x() => 0;
+}
+''');
+  }
+
+  void test_overridableMember_instanceOperator() async {
+    await assertNoErrorsInCode('''
+import 'package:meta/meta_meta.dart';
+
+@Target({TargetKind.overridableMember})
+class A {
+  const A();
+}
+
+class C {
+  @A()
+  int operator +(int value) => 0;
+}
+''');
+  }
+
+  void test_overridableMember_instanceSetter() async {
+    await assertNoErrorsInCode('''
+import 'package:meta/meta_meta.dart';
+
+@Target({TargetKind.overridableMember})
+class A {
+  const A();
+}
+
+class C {
+  @A()
+  set x(int value) {}
+}
+''');
+  }
+
+  void test_overridableMember_staticMethod() async {
+    await assertErrorsInCode('''
+import 'package:meta/meta_meta.dart';
+
+@Target({TargetKind.overridableMember})
+class A {
+  const A();
+}
+
+class C {
+  @A()
+  static int x() => 0;
+}
+''', [
+      error(WarningCode.INVALID_ANNOTATION_TARGET, 118, 1),
+    ]);
+  }
+
   void test_parameter_function() async {
     await assertErrorsInCode('''
 import 'package:meta/meta_meta.dart';