Version 2.16.0-145.0.dev

Merge commit '7ab78c48052c9a3c15e572303f20412be07df6ed' into 'dev'
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 455a0f6..576a41f 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -31,6 +31,7 @@
         templateExpectedButGot,
         templateExpectedIdentifier,
         templateExperimentNotEnabled,
+        templateExtraneousModifier,
         templateInternalProblemUnhandled,
         templateUnexpectedToken;
 import 'package:_fe_analyzer_shared/src/parser/parser.dart'
@@ -51,7 +52,7 @@
     show translateErrorToken;
 import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' hide StringToken;
 import 'package:_fe_analyzer_shared/src/scanner/token.dart'
-    show StringToken, SyntheticStringToken, SyntheticToken;
+    show KeywordToken, StringToken, SyntheticStringToken, SyntheticToken;
 import 'package:_fe_analyzer_shared/src/scanner/token_constants.dart';
 import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/ast/ast.dart';
@@ -1552,6 +1553,13 @@
       if (superKeyword != null) {
         assert(thisKeyword == null,
             "Can't have both 'this' and 'super' in a parameter.");
+        if (keyword is KeywordToken && keyword.keyword == Keyword.VAR) {
+          handleRecoverableError(
+            templateExtraneousModifier.withArguments(keyword),
+            keyword,
+            keyword,
+          );
+        }
         node = ast.superFormalParameter(
             comment: comment,
             metadata: metadata,
diff --git a/pkg/analyzer/test/src/diagnostics/extraneous_modifier_test.dart b/pkg/analyzer/test/src/diagnostics/extraneous_modifier_test.dart
new file mode 100644
index 0000000..915db60
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/extraneous_modifier_test.dart
@@ -0,0 +1,66 @@
+// Copyright (c) 2021, 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:analyzer/src/dart/error/syntactic_errors.dart';
+import 'package:analyzer_utilities/check/check.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../util/ast_check.dart';
+import '../../util/token_check.dart';
+import 'parser_diagnostics.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ExtraneousModifierTest);
+  });
+}
+
+@reflectiveTest
+class ExtraneousModifierTest extends ParserDiagnosticsTest {
+  test_simpleFormalParameter_const() async {
+    var parseResult = parseStringWithErrors(r'''
+class A {
+  A(const a);
+}
+''');
+    parseResult.assertErrors([
+      error(ParserErrorCode.EXTRANEOUS_MODIFIER, 14, 5),
+    ]);
+    check(parseResult.findNode.simpleFormalParameter('a);'))
+      ..keyword.isKeywordConst
+      ..type.isNull
+      ..identifier.isNotNull;
+  }
+
+  test_simpleFormalParameter_var() async {
+    var parseResult = parseStringWithErrors(r'''
+class A {
+  A(var a);
+}
+''');
+    parseResult.assertNoErrors();
+    check(parseResult.findNode.simpleFormalParameter('a);'))
+      ..keyword.isKeywordVar
+      ..type.isNull
+      ..identifier.isNotNull;
+  }
+
+  test_superFormalParameter_var() async {
+    var parseResult = parseStringWithErrors(r'''
+class A {
+  A(var super.a);
+}
+''');
+    parseResult.assertErrors([
+      error(ParserErrorCode.EXTRANEOUS_MODIFIER, 14, 3),
+    ]);
+    check(parseResult.findNode.superFormalParameter('super.a'))
+      ..keyword.isKeywordVar
+      ..superKeyword.isKeywordSuper
+      ..type.isNull
+      ..identifier.isNotNull
+      ..typeParameters.isNull
+      ..parameters.isNull;
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/function_typed_parameter_var_test.dart b/pkg/analyzer/test/src/diagnostics/function_typed_parameter_var_test.dart
new file mode 100644
index 0000000..b9c031c
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/function_typed_parameter_var_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2021, 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:analyzer/src/dart/error/syntactic_errors.dart';
+import 'package:analyzer_utilities/check/check.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../util/ast_check.dart';
+import '../../util/token_check.dart';
+import 'parser_diagnostics.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(FunctionTypedParameterVarTest);
+  });
+}
+
+@reflectiveTest
+class FunctionTypedParameterVarTest extends ParserDiagnosticsTest {
+  test_superFormalParameter_var_functionTyped() async {
+    var parseResult = parseStringWithErrors(r'''
+class A {
+  A(var super.a<T>());
+}
+''');
+    parseResult.assertErrors([
+      error(ParserErrorCode.FUNCTION_TYPED_PARAMETER_VAR, 14, 3),
+    ]);
+    check(parseResult.findNode.superFormalParameter('super.a'))
+      ..keyword.isNull
+      ..superKeyword.isKeywordSuper
+      ..type.isNull
+      ..identifier.isNotNull
+      ..typeParameters.isNotNull.typeParameters.hasLength(1)
+      ..parameters.isNotNull;
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/parser_diagnostics.dart b/pkg/analyzer/test/src/diagnostics/parser_diagnostics.dart
new file mode 100644
index 0000000..975d781
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/parser_diagnostics.dart
@@ -0,0 +1,64 @@
+// Copyright (c) 2021, 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:analyzer/dart/analysis/features.dart';
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/dart/analysis/utilities.dart';
+import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:analyzer/src/test_utilities/find_node.dart';
+
+import '../../generated/test_support.dart';
+
+class ParserDiagnosticsTest {
+  ExpectedError error(
+    ErrorCode code,
+    int offset,
+    int length, {
+    Pattern? correctionContains,
+    String? text,
+    List<Pattern> messageContains = const [],
+    List<ExpectedContextMessage> contextMessages = const [],
+  }) {
+    return ExpectedError(
+      code,
+      offset,
+      length,
+      correctionContains: correctionContains,
+      message: text,
+      messageContains: messageContains,
+      expectedContextMessages: contextMessages,
+    );
+  }
+
+  ParseStringResult parseStringWithErrors(String content) {
+    return parseString(
+      content: content,
+      featureSet: FeatureSet.fromEnableFlags2(
+        sdkLanguageVersion: ExperimentStatus.currentVersion,
+        flags: [
+          Feature.enhanced_enums.enableString,
+          Feature.super_parameters.enableString,
+        ],
+      ),
+      throwIfDiagnostics: false,
+    );
+  }
+}
+
+extension ParseStringResultExtension on ParseStringResult {
+  FindNode get findNode {
+    return FindNode(content, unit);
+  }
+
+  void assertErrors(List<ExpectedError> expectedErrors) {
+    var errorListener = GatheringErrorListener();
+    errorListener.addAll(errors);
+    errorListener.assertErrors(expectedErrors);
+  }
+
+  void assertNoErrors() {
+    assertErrors(const []);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index 639450e..8bed89d 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -194,6 +194,7 @@
     as extra_annotation_on_struct_field;
 import 'extra_positional_arguments_test.dart' as extra_positional_arguments;
 import 'extra_size_annotation_carray_test.dart' as extra_size_annotation_carray;
+import 'extraneous_modifier_test.dart' as extraneous_modifier;
 import 'ffi_leaf_call_must_not_use_handle_test.dart'
     as ffi_leaf_call_must_not_use_handle;
 import 'ffi_native_test.dart' as ffi_native_test;
@@ -227,6 +228,7 @@
     as for_in_of_invalid_element_type;
 import 'for_in_of_invalid_type_test.dart' as for_in_of_invalid_type;
 import 'for_in_with_const_variable_test.dart' as for_in_with_const_variable;
+import 'function_typed_parameter_var_test.dart' as function_typed_parameter_var;
 import 'generic_function_type_cannot_be_bound_test.dart'
     as generic_function_type_cannot_be_bound;
 import 'generic_struct_subclass_test.dart' as generic_struct_subclass;
@@ -857,6 +859,7 @@
     extra_annotation_on_struct_field.main();
     extra_positional_arguments.main();
     extra_size_annotation_carray.main();
+    extraneous_modifier.main();
     ffi_leaf_call_must_not_use_handle.main();
     ffi_native_test.main();
     field_in_struct_with_initializer.main();
@@ -876,6 +879,7 @@
     for_in_of_invalid_element_type.main();
     for_in_of_invalid_type.main();
     for_in_with_const_variable.main();
+    function_typed_parameter_var.main();
     generic_function_type_cannot_be_bound.main();
     generic_struct_subclass.main();
     getter_not_assignable_setter_types.main();
diff --git a/pkg/analyzer/test/util/ast_check.dart b/pkg/analyzer/test/util/ast_check.dart
new file mode 100644
index 0000000..d990153
--- /dev/null
+++ b/pkg/analyzer/test/util/ast_check.dart
@@ -0,0 +1,85 @@
+// Copyright (c) 2021, 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:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer_utilities/check/check.dart';
+
+extension FormalParameterExtension on CheckTarget<FormalParameter> {
+  CheckTarget<SimpleIdentifier?> get identifier {
+    return nest(
+      value.identifier,
+      (selected) => 'has identifier ${valueStr(selected)}',
+    );
+  }
+}
+
+extension SimpleFormalParameterExtension on CheckTarget<SimpleFormalParameter> {
+  CheckTarget<Token?> get keyword {
+    return nest(
+      value.keyword,
+      (selected) => 'has keyword ${valueStr(selected)}',
+    );
+  }
+
+  CheckTarget<TypeAnnotation?> get type {
+    return nest(
+      value.type,
+      (selected) => 'has type ${valueStr(selected)}',
+    );
+  }
+}
+
+extension SuperFormalParameterExtension on CheckTarget<SuperFormalParameter> {
+  CheckTarget<SimpleIdentifier> get identifier {
+    return nest(
+      value.identifier,
+      (selected) => 'has identifier ${valueStr(selected)}',
+    );
+  }
+
+  CheckTarget<Token?> get keyword {
+    return nest(
+      value.keyword,
+      (selected) => 'has keyword ${valueStr(selected)}',
+    );
+  }
+
+  CheckTarget<FormalParameterList?> get parameters {
+    return nest(
+      value.parameters,
+      (selected) => 'has parameters ${valueStr(selected)}',
+    );
+  }
+
+  CheckTarget<Token?> get superKeyword {
+    return nest(
+      value.superKeyword,
+      (selected) => 'has superKeyword ${valueStr(selected)}',
+    );
+  }
+
+  CheckTarget<TypeAnnotation?> get type {
+    return nest(
+      value.type,
+      (selected) => 'has type ${valueStr(selected)}',
+    );
+  }
+
+  CheckTarget<TypeParameterList?> get typeParameters {
+    return nest(
+      value.typeParameters,
+      (selected) => 'has typeParameters ${valueStr(selected)}',
+    );
+  }
+}
+
+extension TypeParameterListExtension on CheckTarget<TypeParameterList> {
+  CheckTarget<List<TypeParameter>> get typeParameters {
+    return nest(
+      value.typeParameters,
+      (selected) => 'has typeParameters ${valueStr(selected)}',
+    );
+  }
+}
diff --git a/pkg/analyzer/test/util/token_check.dart b/pkg/analyzer/test/util/token_check.dart
new file mode 100644
index 0000000..7d8fc24
--- /dev/null
+++ b/pkg/analyzer/test/util/token_check.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2021, 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:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/token.dart';
+import 'package:analyzer_utilities/check/check.dart';
+
+extension KeywordTokenExtension on CheckTarget<KeywordToken> {
+  CheckTarget<Keyword> get keyword {
+    return nest(
+      value.keyword,
+      (selected) => 'has keyword ${valueStr(selected)}',
+    );
+  }
+}
+
+extension TokenExtension on CheckTarget<Token?> {
+  CheckTarget<KeywordToken> get isKeyword {
+    return isA<KeywordToken>();
+  }
+
+  void get isKeywordConst {
+    isKeyword.keyword.isEqualTo(Keyword.CONST);
+  }
+
+  void get isKeywordSuper {
+    isKeyword.keyword.isEqualTo(Keyword.SUPER);
+  }
+
+  void get isKeywordVar {
+    isKeyword.keyword.isEqualTo(Keyword.VAR);
+  }
+}
diff --git a/tools/VERSION b/tools/VERSION
index 0516db1..e94eb46 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 16
 PATCH 0
-PRERELEASE 144
+PRERELEASE 145
 PRERELEASE_PATCH 0
\ No newline at end of file