Issue 43397. Fix isDefaultConstructor when view from a legacy library.

Bug: https://github.com/dart-lang/sdk/issues/43397
Change-Id: I1cd4ae4bea441732d1c6ef68a917fcccb144ec62
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/162584
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index 9e26d98..a469a99 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -1919,6 +1919,7 @@
 
 /// A concrete implementation of a [ConstructorElement].
 class ConstructorElementImpl extends ExecutableElementImpl
+    with ConstructorElementMixin
     implements ConstructorElement {
   /// The constructor to which this constructor is redirecting.
   ConstructorElement _redirectedConstructor;
@@ -2008,23 +2009,6 @@
   }
 
   @override
-  bool get isDefaultConstructor {
-    // unnamed
-    String name = this.name;
-    if (name != null && name.isNotEmpty) {
-      return false;
-    }
-    // no required parameters
-    for (ParameterElement parameter in parameters) {
-      if (parameter.isNotOptional) {
-        return false;
-      }
-    }
-    // OK, can be used as default constructor
-    return true;
-  }
-
-  @override
   bool get isFactory {
     if (linkedNode != null) {
       ConstructorDeclaration linkedNode = this.linkedNode;
@@ -2164,6 +2148,26 @@
   }
 }
 
+/// Common implementation for methods defined in [ConstructorElement].
+mixin ConstructorElementMixin implements ConstructorElement {
+  @override
+  bool get isDefaultConstructor {
+    // unnamed
+    var name = this.name;
+    if (name != null && name.isNotEmpty) {
+      return false;
+    }
+    // no required parameters
+    for (ParameterElement parameter in parameters) {
+      if (parameter.isNotOptional) {
+        return false;
+      }
+    }
+    // OK, can be used as default constructor
+    return true;
+  }
+}
+
 /// A [TopLevelVariableElement] for a top-level 'const' variable that has an
 /// initializer.
 class ConstTopLevelVariableElementImpl extends TopLevelVariableElementImpl
diff --git a/pkg/analyzer/lib/src/dart/element/member.dart b/pkg/analyzer/lib/src/dart/element/member.dart
index 29c863b..a37c9d4 100644
--- a/pkg/analyzer/lib/src/dart/element/member.dart
+++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -19,7 +19,9 @@
 
 /// A constructor element defined in a parameterized type where the values of
 /// the type parameters are known.
-class ConstructorMember extends ExecutableMember implements ConstructorElement {
+class ConstructorMember extends ExecutableMember
+    with ConstructorElementMixin
+    implements ConstructorElement {
   /// Initialize a newly created element to represent a constructor, based on
   /// the [declaration], and applied [substitution].
   ConstructorMember(
@@ -46,9 +48,6 @@
   bool get isConstantEvaluated => declaration.isConstantEvaluated;
 
   @override
-  bool get isDefaultConstructor => declaration.isDefaultConstructor;
-
-  @override
   bool get isFactory => declaration.isFactory;
 
   @override
@@ -787,25 +786,15 @@
   @override
   bool get isInitializingFormal => declaration.isInitializingFormal;
 
-  @override
-  bool get isOptionalNamed {
-    if (isLegacy) {
-      return super.isNamed;
-    }
-    return super.isOptionalNamed;
-  }
-
-  @override
-  bool get isRequiredNamed {
-    if (isLegacy) {
-      return false;
-    }
-    return super.isRequiredNamed;
-  }
-
   @deprecated
   @override
-  ParameterKind get parameterKind => declaration.parameterKind;
+  ParameterKind get parameterKind {
+    var kind = declaration.parameterKind;
+    if (isLegacy && kind == ParameterKind.NAMED_REQUIRED) {
+      return ParameterKind.NAMED;
+    }
+    return kind;
+  }
 
   @override
   List<ParameterElement> get parameters {
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 75fcfb7..07891bc 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -3503,6 +3503,8 @@
     // try to find default generative super constructor
     ConstructorElement superUnnamedConstructor =
         superElement.unnamedConstructor;
+    superUnnamedConstructor =
+        _currentLibrary.toLegacyElementIfOptOut(superUnnamedConstructor);
     if (superUnnamedConstructor != null) {
       if (superUnnamedConstructor.isFactory) {
         _errorReporter.reportErrorForNode(
@@ -4309,6 +4311,8 @@
     }
     ConstructorElement superUnnamedConstructor =
         superElement.unnamedConstructor;
+    superUnnamedConstructor =
+        _currentLibrary.toLegacyElementIfOptOut(superUnnamedConstructor);
     if (superUnnamedConstructor != null) {
       if (superUnnamedConstructor.isFactory) {
         _errorReporter.reportErrorForNode(
diff --git a/pkg/analyzer/test/src/diagnostics/no_default_super_constructor_test.dart b/pkg/analyzer/test/src/diagnostics/no_default_super_constructor_test.dart
index 4995806..3643e02 100644
--- a/pkg/analyzer/test/src/diagnostics/no_default_super_constructor_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/no_default_super_constructor_test.dart
@@ -10,11 +10,15 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(NoDefaultSuperConstructorTest);
+    defineReflectiveTests(NoDefaultSuperConstructorWithNullSafetyTest);
   });
 }
 
 @reflectiveTest
-class NoDefaultSuperConstructorTest extends PubPackageResolutionTest {
+class NoDefaultSuperConstructorTest extends PubPackageResolutionTest
+    with NoDefaultSuperConstructorTestCases {}
+
+mixin NoDefaultSuperConstructorTestCases on PubPackageResolutionTest {
   test_explicitDefaultSuperConstructor() async {
     await assertNoErrorsInCode(r'''
 class A {
@@ -81,3 +85,38 @@
     ]);
   }
 }
+
+@reflectiveTest
+class NoDefaultSuperConstructorWithNullSafetyTest
+    extends PubPackageResolutionTest
+    with NoDefaultSuperConstructorTestCases, WithNullSafetyMixin {
+  test_super_requiredParameter_legacySubclass_explicitConstructor() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+class A {
+  A({required String s});
+}
+''');
+    await assertNoErrorsInCode(r'''
+// @dart=2.8
+import 'a.dart';
+
+class B extends A {
+  B();
+}
+''');
+  }
+
+  test_super_requiredParameter_legacySubclass_implicitConstructor() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+class A {
+  A({required String s});
+}
+''');
+    await assertNoErrorsInCode(r'''
+// @dart=2.8
+import 'a.dart';
+
+class B extends A {}
+''');
+  }
+}