Version 2.16.0-133.0.dev

Merge commit '6e27367656c263fcce5fcb91586b3ea4a85e98d3' into 'dev'
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_descriptor.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_descriptor.dart
index 5f96489..e512626 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_descriptor.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_descriptor.dart
@@ -40,117 +40,133 @@
   /// Return `true` if the described element is a constructor.
   bool get isConstructor => kind == ElementKind.constructorKind;
 
-  /// Return `true` if the given [node] appears to be consistent with this kind
-  /// of element.
+  /// Return `true` if the given [node] appears to be consistent with the
+  /// element being described.
   bool matches(AstNode node) {
-    // TODO(brianwilkerson) Check the resolved element if one exists for more
+    // TODO(brianwilkerson) Check the resolved element, if one exists, for more
     //  accurate results.
     switch (kind) {
       case ElementKind.classKind:
-        // TODO: Handle this case.
+        // TODO(brianwilkerson) Handle this case.
         return false;
       case ElementKind.constantKind:
-        // TODO: Handle this case.
+        // TODO(brianwilkerson) Handle this case.
         return false;
       case ElementKind.constructorKind:
-        if (node is Annotation) {
-          var className = _nameFromIdentifier(node.name);
-          var constructorName = node.constructorName ?? '';
-          if (components[0] == constructorName && components[1] == className) {
-            return true;
-          }
-        } else if (node is InstanceCreationExpression) {
-          var name = node.constructorName;
-          var className = _nameFromIdentifier(name.type2.name);
-          var constructorName = name.name?.name ?? '';
-          if (components[0] == constructorName && components[1] == className) {
-            return true;
-          }
-        } else if (node is MethodInvocation) {
-          var target = node.target;
-          if (target == null) {
-            if (components[0] == '' && components[1] == node.methodName.name) {
-              return true;
-            }
-          } else if (target is Identifier) {
-            var className = _nameFromIdentifier(target);
-            var constructorName = node.methodName.name;
-            if (components[0] == constructorName &&
-                components[1] == className) {
-              return true;
-            }
-          }
-        }
-        return false;
+        return _matchesConstructor(node);
       case ElementKind.enumKind:
-        // TODO: Handle this case.
+        // TODO(brianwilkerson) Handle this case.
         return false;
       case ElementKind.extensionKind:
-        // TODO: Handle this case.
+        // TODO(brianwilkerson) Handle this case.
         return false;
       case ElementKind.fieldKind:
-        // TODO: Handle this case.
+        // TODO(brianwilkerson) Handle this case.
         return false;
       case ElementKind.functionKind:
-        if (node is MethodInvocation) {
-          if (node.realTarget == null &&
-              components[0] == node.methodName.name) {
-            return true;
-          }
-        }
-        return false;
+        return _matchesFunction(node);
       case ElementKind.getterKind:
-        // TODO: Handle this case.
+        // TODO(brianwilkerson) Handle this case.
         return false;
       case ElementKind.methodKind:
-        if (node is MethodInvocation) {
-          if (components[0] == node.methodName.name) {
-            var target = node.realTarget;
-            if (target == null) {
-              // TODO(brianwilkerson) If `node.target == null` then the invocation
-              //  should be in a subclass of the element's class.
-              return true;
-            } else {
-              var type = target.staticType;
-              if (type == null && target is SimpleIdentifier) {
-                var element = target.staticElement;
-                // TODO(brianwilkerson) Handle more than `ClassElement`.
-                if (element is ClassElement) {
-                  type = element.thisType;
-                }
-              }
-              if (type == null) {
-                // We can't get more specific type information, so we assume
-                // that the method might have been in the element's class.
+        return _matchesMethod(node);
+      case ElementKind.mixinKind:
+        // TODO(brianwilkerson) Handle this case.
+        return false;
+      case ElementKind.setterKind:
+        // TODO(brianwilkerson) Handle this case.
+        return false;
+      case ElementKind.typedefKind:
+        // TODO(brianwilkerson) Handle this case.
+        return false;
+      case ElementKind.variableKind:
+        // TODO(brianwilkerson) Handle this case.
+        return false;
+    }
+  }
+
+  /// Return `true` if the given [node] appears to be consistent with the
+  /// constructor being described.
+  bool _matchesConstructor(AstNode node) {
+    if (node is Annotation) {
+      var className = _nameFromIdentifier(node.name);
+      var constructorName = node.constructorName ?? '';
+      if (components[0] == constructorName && components[1] == className) {
+        return true;
+      }
+    } else if (node is InstanceCreationExpression) {
+      var name = node.constructorName;
+      var className = _nameFromIdentifier(name.type2.name);
+      var constructorName = name.name?.name ?? '';
+      if (components[0] == constructorName && components[1] == className) {
+        return true;
+      }
+    } else if (node is MethodInvocation) {
+      var target = node.target;
+      if (target == null) {
+        if (components[0] == '' && components[1] == node.methodName.name) {
+          return true;
+        }
+      } else if (target is Identifier) {
+        var className = _nameFromIdentifier(target);
+        var constructorName = node.methodName.name;
+        if (components[0] == constructorName && components[1] == className) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  /// Return `true` if the given [node] appears to be consistent with the
+  /// function being described.
+  bool _matchesFunction(AstNode node) {
+    if (node is MethodInvocation) {
+      if (node.realTarget == null && components[0] == node.methodName.name) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /// Return `true` if the given [node] appears to be consistent with the
+  /// method being described.
+  bool _matchesMethod(AstNode node) {
+    if (node is MethodInvocation) {
+      if (components[0] == node.methodName.name) {
+        var target = node.realTarget;
+        if (target == null) {
+          // TODO(brianwilkerson) If `node.target == null` then the invocation
+          //  should be in a subclass of the element's class.
+          return true;
+        } else {
+          var type = target.staticType;
+          if (type == null && target is SimpleIdentifier) {
+            var element = target.staticElement;
+            // TODO(brianwilkerson) Handle more than `ClassElement`.
+            if (element is ClassElement) {
+              type = element.thisType;
+            }
+          }
+          if (type == null) {
+            // We can't get more specific type information, so we assume
+            // that the method might have been in the element's class.
+            return true;
+          }
+          if (components[1] == type.element?.name) {
+            return true;
+          }
+          if (type is InterfaceType) {
+            for (var supertype in type.allSupertypes) {
+              if (components[1] == supertype.element.name) {
                 return true;
               }
-              if (components[1] == type.element?.name) {
-                return true;
-              }
-              if (type is InterfaceType) {
-                for (var supertype in type.allSupertypes) {
-                  if (components[1] == supertype.element.name) {
-                    return true;
-                  }
-                }
-              }
             }
           }
         }
-        return false;
-      case ElementKind.mixinKind:
-        // TODO: Handle this case.
-        return false;
-      case ElementKind.setterKind:
-        // TODO: Handle this case.
-        return false;
-      case ElementKind.typedefKind:
-        // TODO: Handle this case.
-        return false;
-      case ElementKind.variableKind:
-        // TODO: Handle this case.
-        return false;
+      }
     }
+    return false;
   }
 
   String _nameFromIdentifier(Identifier identifier) {
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 7abed7a..0186ba9 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -312,7 +312,7 @@
 
   List<ProducerGenerator> _getGenerators(ErrorCode errorCode) {
     if (errorCode is LintCode) {
-      return FixProcessor.lintProducerMap[errorCode.name] ?? [];
+      return FixProcessor.lintProducerMap[errorCode.uniqueLintName] ?? [];
     } else {
       // todo (pq): consider support for multiGenerators
       return FixProcessor.nonLintProducerMap[errorCode] ?? [];
@@ -326,6 +326,12 @@
   /// used to create correction producers. The generators are then used to build
   /// fixes for those diagnostics. The generators used for non-lint diagnostics
   /// are in the [nonLintProducerMap].
+  ///
+  /// The keys of the map are the unique names of the lint codes without the
+  /// `LintCode.` prefix. Generally the unique name is the same as the name of
+  /// the lint, so most of the keys are constants defined by [LintNames]. But
+  /// when a lint produces multiple codes, each with a different unique name,
+  /// the unique name must be used here.
   static final Map<String, List<ProducerGenerator>> lintProducerMap = {
     LintNames.always_declare_return_types: [
       AddReturnType.newInstance,
@@ -1355,7 +1361,7 @@
 
     var errorCode = error.errorCode;
     if (errorCode is LintCode) {
-      var generators = lintProducerMap[errorCode.name] ?? [];
+      var generators = lintProducerMap[errorCode.uniqueLintName] ?? [];
       for (var generator in generators) {
         await compute(generator());
       }
@@ -1428,3 +1434,12 @@
     required this.fixCount,
   });
 }
+
+extension on LintCode {
+  String get uniqueLintName {
+    if (uniqueName.startsWith('LintCode.')) {
+      return uniqueName.substring(9);
+    }
+    return uniqueName;
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
index 2e361ad..8138fda 100644
--- a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
@@ -976,6 +976,57 @@
   }
 
   @override
+  void visitSuperFormalParameter(covariant SuperFormalParameterImpl node) {
+    SuperFormalParameterElementImpl element;
+    if (node.parent is DefaultFormalParameter) {
+      element = node.declaredElement as SuperFormalParameterElementImpl;
+    } else {
+      var nameNode = node.identifier;
+      if (_elementWalker != null) {
+        element =
+            _elementWalker!.getParameter() as SuperFormalParameterElementImpl;
+      } else {
+        // Only for recovery, this should not happen in valid code.
+        element = SuperFormalParameterElementImpl(
+          name: nameNode.name,
+          nameOffset: nameNode.offset,
+          parameterKind: node.kind,
+        );
+        _elementHolder.enclose(element);
+        element.isConst = node.isConst;
+        element.isExplicitlyCovariant = node.covariantKeyword != null;
+        element.isFinal = node.isFinal;
+        _setCodeRange(element, node);
+      }
+      nameNode.staticElement = element;
+    }
+
+    _setOrCreateMetadataElements(element, node.metadata);
+
+    _withElementHolder(ElementHolder(element), () {
+      _withElementWalker(
+        _elementWalker != null ? ElementWalker.forParameter(element) : null,
+        () {
+          _withNameScope(() {
+            _buildTypeParameterElements(node.typeParameters);
+            node.typeParameters?.accept(this);
+            node.type?.accept(this);
+            if (_elementWalker != null) {
+              node.parameters?.accept(this);
+            } else {
+              // Only for recovery, this should not happen in valid code.
+              element.type = node.type?.type ?? _dynamicType;
+              _withElementWalker(null, () {
+                node.parameters?.accept(this);
+              });
+            }
+          });
+        },
+      );
+    });
+  }
+
+  @override
   void visitSwitchCase(SwitchCase node) {
     _buildLabelElements(node.labels, false, true);
 
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index cd47b1b..1d7d77c 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -4159,6 +4159,15 @@
       return;
     }
 
+    // TODO(scheglov) Restore when working on errors.
+    if (_currentLibrary.featureSet.isEnabled(Feature.super_parameters)) {
+      if (constructor.parameters.parameters.any((parameter) {
+        return parameter.notDefault is SuperFormalParameter;
+      })) {
+        return;
+      }
+    }
+
     // Ignore if the constructor has either an implicit super constructor
     // invocation or a redirecting constructor invocation.
     for (ConstructorInitializer constructorInitializer
diff --git a/pkg/analyzer/lib/src/test_utilities/find_element.dart b/pkg/analyzer/lib/src/test_utilities/find_element.dart
index 195647b..8a894ec 100644
--- a/pkg/analyzer/lib/src/test_utilities/find_element.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_element.dart
@@ -636,3 +636,14 @@
     return class_(name).unnamedConstructor!;
   }
 }
+
+extension ExecutableElementExtensions on ExecutableElement {
+  SuperFormalParameterElement superFormalParameter(String name) {
+    for (var parameter in parameters) {
+      if (parameter is SuperFormalParameterElement && parameter.name == name) {
+        return parameter;
+      }
+    }
+    throw StateError('Not found: $name');
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
index 1b491ac..7d2c061 100644
--- a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
@@ -259,6 +259,7 @@
   List<String> get experiments => [
         EnableString.constructor_tearoffs,
         EnableString.named_arguments_anywhere,
+        EnableString.super_parameters,
       ];
 
   /// The path that is not in [workspaceRootPath], contains external packages.
diff --git a/pkg/analyzer/test/src/dart/resolution/super_formal_parameter_test.dart b/pkg/analyzer/test/src/dart/resolution/super_formal_parameter_test.dart
new file mode 100644
index 0000000..6a24380
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolution/super_formal_parameter_test.dart
@@ -0,0 +1,130 @@
+// 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/test_utilities/find_element.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'context_collection_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(SuperFormalParameterTest);
+  });
+}
+
+@reflectiveTest
+class SuperFormalParameterTest extends PubPackageResolutionTest {
+  test_functionTyped() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A(Object a);
+}
+
+class B extends A {
+  B(super.a<T>(int b));
+}
+''');
+
+    var B = findElement.unnamedConstructor('B');
+    var element = B.superFormalParameter('a');
+
+    assertElement(
+      findNode.superFormalParameter('super.a'),
+      element,
+    );
+
+    assertElement(
+      findNode.typeParameter('T>'),
+      element.typeParameters[0],
+    );
+
+    assertElement(
+      findNode.simpleFormalParameter('b));'),
+      element.parameters[0],
+    );
+  }
+
+  test_invalid_notConstructor() async {
+    await assertNoErrorsInCode(r'''
+void f(super.a) {}
+''');
+
+    var f = findElement.topFunction('f');
+    var element = f.superFormalParameter('a');
+    assertTypeDynamic(element.type);
+
+    assertElement(
+      findNode.superFormalParameter('super.a'),
+      element,
+    );
+  }
+
+  test_optionalNamed() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A({int? a});
+}
+
+class B extends A {
+  B({super.a});
+}
+''');
+
+    assertElement(
+      findNode.superFormalParameter('super.a'),
+      findElement.unnamedConstructor('B').superFormalParameter('a'),
+    );
+  }
+
+  test_optionalPositional() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A([int? a]);
+}
+
+class B extends A {
+  B([super.a]);
+}
+''');
+
+    assertElement(
+      findNode.superFormalParameter('super.a'),
+      findElement.unnamedConstructor('B').superFormalParameter('a'),
+    );
+  }
+
+  test_requiredNamed() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A({required int a});
+}
+
+class B extends A {
+  B({required super.a});
+}
+''');
+
+    assertElement(
+      findNode.superFormalParameter('super.a'),
+      findElement.unnamedConstructor('B').superFormalParameter('a'),
+    );
+  }
+
+  test_requiredPositional() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  A(int a);
+}
+
+class B extends A {
+  B(super.a);
+}
+''');
+
+    assertElement(
+      findNode.superFormalParameter('super.a'),
+      findElement.unnamedConstructor('B').superFormalParameter('a'),
+    );
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/test_all.dart b/pkg/analyzer/test/src/dart/resolution/test_all.dart
index 0c72655..759b9e5 100644
--- a/pkg/analyzer/test/src/dart/resolution/test_all.dart
+++ b/pkg/analyzer/test/src/dart/resolution/test_all.dart
@@ -58,6 +58,7 @@
 import 'prefixed_identifier_test.dart' as prefixed_identifier;
 import 'property_access_test.dart' as property_access;
 import 'simple_identifier_test.dart' as simple_identifier;
+import 'super_formal_parameter_test.dart' as super_formal_parameter;
 import 'top_level_variable_test.dart' as top_level_variable;
 import 'top_type_inference_test.dart' as top_type_inference;
 import 'try_statement_test.dart' as try_statement;
@@ -119,6 +120,7 @@
     prefixed_identifier.main();
     property_access.main();
     simple_identifier.main();
+    super_formal_parameter.main();
     top_level_variable.main();
     top_type_inference.main();
     try_statement.main();
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 9b74e08..3d50b66 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -1525,6 +1525,23 @@
 ''');
   }
 
+  test_class_constructor_parameters_super_invalid_topFunction() async {
+    var library = await checkLibrary('''
+void f(super.a) {}
+''');
+    checkElementText(library, r'''
+library
+  definingUnit
+    functions
+      f @5
+        parameters
+          requiredPositional final super.a @13
+            type: dynamic
+            superConstructorParameter: <null>
+        returnType: void
+''');
+  }
+
   test_class_constructor_parameters_super_optionalNamed() async {
     var library = await checkLibrary('''
 class A {
diff --git a/pkg/analyzer_plugin/CHANGELOG.md b/pkg/analyzer_plugin/CHANGELOG.md
index 04ab329..ca17b41 100644
--- a/pkg/analyzer_plugin/CHANGELOG.md
+++ b/pkg/analyzer_plugin/CHANGELOG.md
@@ -1,3 +1,6 @@
+## 0.9.0
+- Support version `3.x` of the `analyzer` package
+
 ## 0.8.0
 - Require SDK `2.14` to use `Object.hash()`.
 - Require `yaml 3.1.0` to use `recover`.
diff --git a/pkg/analyzer_plugin/pubspec.yaml b/pkg/analyzer_plugin/pubspec.yaml
index 41b859d..c8b99c8 100644
--- a/pkg/analyzer_plugin/pubspec.yaml
+++ b/pkg/analyzer_plugin/pubspec.yaml
@@ -1,15 +1,15 @@
 name: analyzer_plugin
 description: A framework and support code for building plugins for the analysis server.
-version: 0.8.0
+version: 0.9.0
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer_plugin
 
 environment:
   sdk: '>=2.14.0 <3.0.0'
 
 dependencies:
-  analyzer: ^2.4.0
+  analyzer: ^3.0.0
   collection: ^1.15.0
-  dart_style: ^2.0.0
+  dart_style: ^2.2.1
   pub_semver: ^2.0.0
   yaml: ^3.1.0
 
diff --git a/tools/VERSION b/tools/VERSION
index e95ca1b..5cbc6ee 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 16
 PATCH 0
-PRERELEASE 132
+PRERELEASE 133
 PRERELEASE_PATCH 0
\ No newline at end of file