quick-fix for `NO_ANNOTATION_CONSTRUCTOR_ARGUMENTS`

Change-Id: I0213b8a82d253cb2fbacd5c4331aaffe94f0a160
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/366889
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Phil Quitslund <pquitslund@google.com>
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/add_empty_argument_list.dart b/pkg/analysis_server/lib/src/services/correction/dart/add_empty_argument_list.dart
new file mode 100644
index 0000000..90fd658
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/add_empty_argument_list.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2024, 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:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/src/dart/ast/ast.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+
+class AddEmptyArgumentList extends ResolvedCorrectionProducer {
+  @override
+  bool get canBeAppliedInBulk => true;
+
+  @override
+  bool get canBeAppliedToFile => true;
+
+  @override
+  FixKind get fixKind => DartFixKind.ADD_EMPTY_ARGUMENT_LIST;
+
+  @override
+  FixKind get multiFixKind => DartFixKind.ADD_EMPTY_ARGUMENT_LIST_MULTI;
+
+  @override
+  Future<void> compute(ChangeBuilder builder) async {
+    var node = this.node;
+    if (node is! AnnotationImpl) return;
+
+    await builder.addDartFileEdit(file, (builder) {
+      builder.addSimpleInsertion(node.end, '()');
+    });
+  }
+}
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 93a0e36..edbabcb 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
@@ -1179,9 +1179,7 @@
 CompileTimeErrorCode.NEW_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT:
   status: hasFix
 CompileTimeErrorCode.NO_ANNOTATION_CONSTRUCTOR_ARGUMENTS:
-  status: needsFix
-  notes: |-
-    Add an empty argument list.
+  status: hasFix
 CompileTimeErrorCode.NO_COMBINED_SUPER_SIGNATURE:
   status: noFix
 CompileTimeErrorCode.NO_DEFAULT_SUPER_CONSTRUCTOR_EXPLICIT:
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index 222bb74..03c2b73 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -51,6 +51,16 @@
     DartFixKindPriority.DEFAULT,
     "Add 'super.{0}'",
   );
+  static const ADD_EMPTY_ARGUMENT_LIST = FixKind(
+    'dart.fix.add.empty.argument.list',
+    DartFixKindPriority.DEFAULT,
+    'Add empty argument list',
+  );
+  static const ADD_EMPTY_ARGUMENT_LIST_MULTI = FixKind(
+    'dart.fix.add.empty.argument.list.multi',
+    DartFixKindPriority.IN_FILE,
+    'Add empty argument lists everywhere in file',
+  );
   static const ADD_CONST = FixKind(
     'dart.fix.add.const',
     DartFixKindPriority.DEFAULT,
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index d7a4b61..351c01b 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -8,6 +8,7 @@
 import 'package:analysis_server/src/services/correction/dart/add_call_super.dart';
 import 'package:analysis_server/src/services/correction/dart/add_const.dart';
 import 'package:analysis_server/src/services/correction/dart/add_diagnostic_property_reference.dart';
+import 'package:analysis_server/src/services/correction/dart/add_empty_argument_list.dart';
 import 'package:analysis_server/src/services/correction/dart/add_enum_constant.dart';
 import 'package:analysis_server/src/services/correction/dart/add_eol_at_end_of_file.dart';
 import 'package:analysis_server/src/services/correction/dart/add_explicit_call.dart';
@@ -1044,6 +1045,9 @@
   CompileTimeErrorCode.NEW_WITH_UNDEFINED_CONSTRUCTOR: [
     CreateConstructor.new,
   ],
+  CompileTimeErrorCode.NO_ANNOTATION_CONSTRUCTOR_ARGUMENTS: [
+    AddEmptyArgumentList.new,
+  ],
   CompileTimeErrorCode.NON_ABSTRACT_CLASS_INHERITS_ABSTRACT_MEMBER_FIVE_PLUS: [
     CreateMissingOverrides.new,
     CreateNoSuchMethod.new,
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_empty_argument_list_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_empty_argument_list_test.dart
new file mode 100644
index 0000000..a065666
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_empty_argument_list_test.dart
@@ -0,0 +1,66 @@
+// Copyright (c) 2024, 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:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(AddEmptyArgumentListTest);
+    defineReflectiveTests(AddEmptyArgumentListMultiTest);
+  });
+}
+
+@reflectiveTest
+class AddEmptyArgumentListMultiTest extends FixProcessorTest {
+  @override
+  FixKind get kind => DartFixKind.ADD_EMPTY_ARGUMENT_LIST_MULTI;
+
+  Future<void> test_singleFile() async {
+    await resolveTestCode('''
+class A {
+  const A();
+}
+@A
+@A
+main() {}
+''');
+    await assertHasFixAllFix(
+        CompileTimeErrorCode.NO_ANNOTATION_CONSTRUCTOR_ARGUMENTS, '''
+class A {
+  const A();
+}
+@A()
+@A()
+main() {}
+''');
+  }
+}
+
+@reflectiveTest
+class AddEmptyArgumentListTest extends FixProcessorTest {
+  @override
+  FixKind get kind => DartFixKind.ADD_EMPTY_ARGUMENT_LIST;
+
+  Future<void> test_annotationConstructorMissingArgs() async {
+    await resolveTestCode('''
+class A {
+  const A();
+}
+@A
+main() {}
+''');
+    await assertHasFix('''
+class A {
+  const A();
+}
+@A()
+main() {}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
index 16f32dc..e64b87b 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
@@ -11,6 +11,7 @@
 import 'add_curly_braces_test.dart' as add_curly_braces;
 import 'add_diagnostic_property_reference_test.dart'
     as add_diagnostic_property_reference;
+import 'add_empty_argument_list_test.dart' as add_empty_argument_list;
 import 'add_enum_constant_test.dart' as add_enum_constant_test;
 import 'add_eol_at_end_of_file_test.dart' as add_eol_at_end_of_file;
 import 'add_explicit_call_test.dart' as add_explicit_call;
@@ -295,6 +296,7 @@
     add_const.main();
     add_curly_braces.main();
     add_diagnostic_property_reference.main();
+    add_empty_argument_list.main();
     add_enum_constant_test.main();
     add_eol_at_end_of_file.main();
     add_explicit_call.main();