new conflicting-modifiers error code

This adds a new "conflicting modifiers" error code for new NNBD
modifier errors and replaces the existing "const and var" error
code with the new error code.

Change-Id: I1997bbb7f66e62d2de3c5042b6ea85861f2e00d8
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/99760
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Dan Rubel <danrubel@google.com>
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 3ba1fbb..b34e318 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -381,6 +381,7 @@
   ParserErrorCode.CATCH_SYNTAX_EXTRA_PARAMETERS,
   ParserErrorCode.CLASS_IN_CLASS,
   ParserErrorCode.COLON_IN_PLACE_OF_IN,
+  ParserErrorCode.CONFLICTING_MODIFIERS,
   ParserErrorCode.CONSTRUCTOR_WITH_RETURN_TYPE,
   ParserErrorCode.CONST_AFTER_FACTORY,
   ParserErrorCode.CONST_AND_COVARIANT,
diff --git a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
index de2684c..37689b9 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
@@ -65,6 +65,8 @@
 
   static const ParserErrorCode COLON_IN_PLACE_OF_IN = _COLON_IN_PLACE_OF_IN;
 
+  static const ParserErrorCode CONFLICTING_MODIFIERS = _CONFLICTING_MODIFIERS;
+
   // TODO(danrubel): Remove this unused error code
   static const ParserErrorCode CONST_AFTER_FACTORY = _MODIFIER_OUT_OF_ORDER;
 
@@ -72,7 +74,8 @@
 
   static const ParserErrorCode CONST_AND_FINAL = _CONST_AND_FINAL;
 
-  static const ParserErrorCode CONST_AND_VAR = _CONST_AND_VAR;
+  // TODO(danrubel): Remove this unused error code
+  static const ParserErrorCode CONST_AND_VAR = _CONFLICTING_MODIFIERS;
 
   static const ParserErrorCode CONST_CLASS = _CONST_CLASS;
 
diff --git a/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart b/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
index c02bde2..f3a1558 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
@@ -66,7 +66,7 @@
   _MODIFIER_OUT_OF_ORDER,
   _CONST_AND_COVARIANT,
   _CONST_AND_FINAL,
-  _CONST_AND_VAR,
+  _CONFLICTING_MODIFIERS,
   _CONST_CLASS,
   _VAR_AS_TYPE_NAME,
   _CONST_FACTORY,
@@ -137,6 +137,11 @@
     'COLON_IN_PLACE_OF_IN', r"For-in loops use 'in' rather than a colon.",
     correction: "Try replacing the colon with the keyword 'in'.");
 
+const ParserErrorCode _CONFLICTING_MODIFIERS = const ParserErrorCode(
+    'CONFLICTING_MODIFIERS',
+    r"Members can't be declared to be both '#string' and '#string2'.",
+    correction: "Try removing one of the keywords.");
+
 const ParserErrorCode _CONSTRUCTOR_WITH_RETURN_TYPE = const ParserErrorCode(
     'CONSTRUCTOR_WITH_RETURN_TYPE', r"Constructors can't have a return type.",
     correction: "Try removing the return type.");
@@ -151,10 +156,6 @@
     r"Members can't be declared to be both 'const' and 'final'.",
     correction: "Try removing either the 'const' or 'final' keyword.");
 
-const ParserErrorCode _CONST_AND_VAR = const ParserErrorCode(
-    'CONST_AND_VAR', r"Members can't be declared to be both 'const' and 'var'.",
-    correction: "Try removing either the 'const' or 'var' keyword.");
-
 const ParserErrorCode _CONST_CLASS = const ParserErrorCode(
     'CONST_CLASS', r"Classes can't be declared to be 'const'.",
     correction:
diff --git a/pkg/analyzer/test/src/task/options_test.dart b/pkg/analyzer/test/src/task/options_test.dart
index 69942af..b477f08 100644
--- a/pkg/analyzer/test/src/task/options_test.dart
+++ b/pkg/analyzer/test/src/task/options_test.dart
@@ -237,6 +237,7 @@
         declaredNames.remove('TODO_REGEX');
       } else if (errorType == ParserErrorCode) {
         declaredNames.remove('CONST_AFTER_FACTORY');
+        declaredNames.remove('CONST_AND_VAR');
       }
 
       // Assert that all remaining declared names are in errorCodeValues
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
index 668da04..5adbc2d 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -757,6 +757,36 @@
     tip: r"""Try replacing the colon with the keyword 'in'.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        String string,
+        String
+            string2)> templateConflictingModifiers = const Template<
+        Message Function(String string, String string2)>(
+    messageTemplate:
+        r"""Members can't be declared to be both '#string' and '#string2'.""",
+    tipTemplate: r"""Try removing one of the keywords.""",
+    withArguments: _withArgumentsConflictingModifiers);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String string, String string2)>
+    codeConflictingModifiers =
+    const Code<Message Function(String string, String string2)>(
+        "ConflictingModifiers", templateConflictingModifiers,
+        index: 59);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsConflictingModifiers(String string, String string2) {
+  if (string.isEmpty) throw 'No string provided';
+  if (string2.isEmpty) throw 'No string provided';
+  return new Message(codeConflictingModifiers,
+      message:
+          """Members can't be declared to be both '${string}' and '${string2}'.""",
+      tip: """Try removing one of the keywords.""",
+      arguments: {'string': string, 'string2': string2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<Message Function(String name)> templateConflictsWithConstructor =
     const Template<Message Function(String name)>(
         messageTemplate: r"""Conflicts with constructor '#name'.""",
@@ -940,15 +970,6 @@
     tip: r"""Try removing either the 'const' or 'final' keyword.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Null> codeConstAndVar = messageConstAndVar;
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const MessageCode messageConstAndVar = const MessageCode("ConstAndVar",
-    index: 59,
-    message: r"""Members can't be declared to be both 'const' and 'var'.""",
-    tip: r"""Try removing either the 'const' or 'var' keyword.""");
-
-// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeConstClass = messageConstClass;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
diff --git a/pkg/front_end/lib/src/fasta/parser/modifier_context.dart b/pkg/front_end/lib/src/fasta/parser/modifier_context.dart
index 8d8a225..4be5931 100644
--- a/pkg/front_end/lib/src/fasta/parser/modifier_context.dart
+++ b/pkg/front_end/lib/src/fasta/parser/modifier_context.dart
@@ -266,7 +266,7 @@
     } else if (finalToken != null) {
       parser.reportRecoverableError(next, fasta.messageConstAndFinal);
     } else if (varToken != null) {
-      parser.reportRecoverableError(next, fasta.messageConstAndVar);
+      reportConflictingModifiers(next, varToken);
     } else {
       throw 'Internal Error: Unexpected varFinalOrConst: $varFinalOrConst';
     }
@@ -435,7 +435,7 @@
     } else if (afterFactory) {
       reportExtraneousModifier(next);
     } else if (constToken != null) {
-      parser.reportRecoverableError(next, fasta.messageConstAndVar);
+      reportConflictingModifiers(next, constToken);
     } else if (finalToken != null) {
       parser.reportRecoverableError(next, fasta.messageFinalAndVar);
     } else {
@@ -444,10 +444,17 @@
     return next;
   }
 
-  void reportExtraneousModifier(Token token) {
-    if (token != null) {
+  void reportConflictingModifiers(Token modifier, Token earlierModifier) {
+    parser.reportRecoverableError(
+        modifier,
+        fasta.templateConflictingModifiers
+            .withArguments(modifier.lexeme, earlierModifier.lexeme));
+  }
+
+  void reportExtraneousModifier(Token modifier) {
+    if (modifier != null) {
       parser.reportRecoverableErrorWithToken(
-          token, fasta.templateExtraneousModifier);
+          modifier, fasta.templateExtraneousModifier);
     }
   }
 
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index 844ba61..783c4ac 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -42,6 +42,7 @@
 CantUseSuperBoundedTypeForInstanceCreation/analyzerCode: Fail
 CantUseSuperBoundedTypeForInstanceCreation/example: Fail
 ColonInPlaceOfIn/example: Fail
+ConflictingModifiers/script1: Fail
 ConflictsWithConstructor/example: Fail
 ConflictsWithFactory/analyzerCode: Fail
 ConflictsWithFactory/example: Fail
@@ -53,7 +54,6 @@
 ConstAndCovariant/script2: Fail
 ConstAndFinal/declaration3: Fail
 ConstAndFinal/declaration4: Fail
-ConstAndVar/script1: Fail
 ConstConstructorInSubclassOfMixinApplication/example: Fail
 ConstConstructorNonFinalField/example: Fail
 ConstConstructorRedirectionToNonConst/analyzerCode: Fail # The analyzer doesn't report this error.
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index bc98cf9..378716e 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -594,11 +594,11 @@
     - "const final int x = 5;"
     - "final const int x = 5;"
 
-ConstAndVar:
+ConflictingModifiers:
   index: 59
-  template: "Members can't be declared to be both 'const' and 'var'."
-  tip: "Try removing either the 'const' or 'var' keyword."
-  analyzerCode: ParserErrorCode.CONST_AND_VAR
+  template: "Members can't be declared to be both '#string' and '#string2'."
+  tip: "Try removing one of the keywords."
+  analyzerCode: ParserErrorCode.CONFLICTING_MODIFIERS
   script:
     - "class C { const var x; }"
     - "class C { var const x; }"