Issue 35548. Don't report CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD when mixin has a static field.

R=brianwilkerson@google.com

Bug: https://github.com/dart-lang/sdk/issues/35548
Change-Id: I46a2006574e31505a860a9e54640b643bb514ae7
Reviewed-on: https://dart-review.googlesource.com/c/88600
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index b6f9cc0..0016e02 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -544,7 +544,7 @@
       const CompileTimeErrorCode(
           'CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD',
           "Const constructor can't be declared for a class with a mixin "
-          "that declares a field.",
+          "that declares an instance field.",
           correction: "Try removing the 'const' keyword or "
               "removing the 'with' clause from the class declaration, "
               "or removing fields from the mixin class.");
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index baee3b51..7992ecf 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -2570,15 +2570,26 @@
     if (constructor.factoryKeyword != null) {
       return;
     }
+
     // check for mixins
+    var hasInstanceField = false;
     for (var mixin in _enclosingClass.mixins) {
-      if (mixin.element.fields.isNotEmpty) {
-        _errorReporter.reportErrorForNode(
-            CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD,
-            constructor.returnType);
-        return;
+      var fields = mixin.element.fields;
+      for (var i = 0; i < fields.length; ++i) {
+        if (!fields[i].isStatic) {
+          hasInstanceField = true;
+          break;
+        }
       }
     }
+    if (hasInstanceField) {
+      // TODO(scheglov) Provide the list of fields.
+      _errorReporter.reportErrorForNode(
+          CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD,
+          constructor.returnType);
+      return;
+    }
+
     // try to find and check super constructor invocation
     for (ConstructorInitializer initializer in constructor.initializers) {
       if (initializer is SuperConstructorInvocation) {
diff --git a/pkg/analyzer/test/generated/compile_time_error_code_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
index 82008a0..c266770 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_test.dart
@@ -889,37 +889,6 @@
     verify([source]);
   }
 
-  test_constConstructorWithMixinWithField() async {
-    Source source = addSource(r'''
-class A {
-  var a;
-}
-class B extends Object with A {
-  const B();
-}''');
-    await computeAnalysisResult(source);
-
-    assertErrors(source, [
-      CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD,
-      CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD
-    ]);
-    verify([source]);
-  }
-
-  test_constConstructorWithMixinWithField_final() async {
-    Source source = addSource(r'''
-class A {
-  final int a = 0;
-}
-class B extends Object with A {
-  const B();
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(
-        source, [CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD]);
-    verify([source]);
-  }
-
   test_constConstructorWithNonConstSuper_explicit() async {
     Source source = addSource(r'''
 class A {
diff --git a/pkg/analyzer/test/generated/non_error_resolver_driver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_driver_test.dart
index 87b7388..300cae8 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_driver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_driver_test.dart
@@ -68,12 +68,6 @@
 
   @override
   @failingTest
-  test_constConstructorWithMixinWithField_withoutSuperMixins() {
-    return super.test_constConstructorWithMixinWithField_withoutSuperMixins();
-  }
-
-  @override
-  @failingTest
   test_null_callOperator() {
     return super.test_null_callOperator();
   }
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index 8ab7c1a..7eb938a 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -26,12 +26,6 @@
 @reflectiveTest
 class NonErrorResolverTest extends NonErrorResolverTestBase {
   @override
-  @failingTest
-  test_constConstructorWithMixinWithField_withoutSuperMixins() {
-    return super.test_constConstructorWithMixinWithField_withoutSuperMixins();
-  }
-
-  @override
   @failingTest // Does not work with old task model
   test_infer_mixin_new_syntax() {
     return super.test_infer_mixin_new_syntax();
@@ -1050,32 +1044,6 @@
     verify([source]);
   }
 
-  test_constConstructorWithMixinWithField_withoutSuperMixins() async {
-    Source source = addSource(r'''
-class M {
-}
-class A extends Object with M {
-  const A();
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      CompileTimeErrorCode.CONST_CONSTRUCTOR_IN_SUBCLASS_OF_MIXIN_APPLICATION
-    ]);
-    verify([source]);
-  }
-
-  test_constConstructorWithMixinWithField_withSuperMixins_new_syntax() async {
-    Source source = addSource(r'''
-mixin M {
-}
-class A extends Object with M {
-  const A();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
   test_constConstructorWithNonConstSuper_explicit() async {
     Source source = addSource(r'''
 class A {
diff --git a/pkg/analyzer/test/src/diagnostics/const_constructor_with_mixin_with_field_test.dart b/pkg/analyzer/test/src/diagnostics/const_constructor_with_mixin_with_field_test.dart
new file mode 100644
index 0000000..2102064
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/const_constructor_with_mixin_with_field_test.dart
@@ -0,0 +1,146 @@
+// Copyright (c) 2019, 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/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+import '../dart/resolution/resolution.dart';
+import '../dart/resolution/task_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConstConstructorWithMixinWithFieldTest_DriverTest);
+    defineReflectiveTests(ConstConstructorWithMixinWithFieldTest_TaskTest);
+  });
+}
+
+@reflectiveTest
+mixin ConstConstructorWithMixinWithFieldMixin implements ResolutionTest {
+  test_class_instance() async {
+    addTestFile(r'''
+class A {
+  var a;
+}
+
+class B extends Object with A {
+  const B();
+}
+''');
+    await resolveTestFile();
+    assertTestErrors([
+      CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD,
+      CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD,
+    ]);
+  }
+
+  test_class_instance_final() async {
+    addTestFile(r'''
+class A {
+  final a = 0;
+}
+
+class B extends Object with A {
+  const B();
+}
+''');
+    await resolveTestFile();
+    assertTestErrors([
+      CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD,
+    ]);
+  }
+
+  test_class_noFields() async {
+    addTestFile(r'''
+class M {}
+
+class X extends Object with M {
+  const X();
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+  }
+
+  test_class_static() async {
+    addTestFile(r'''
+class M {
+  static final a = 0;
+}
+
+class X extends Object with M {
+  const X();
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+  }
+
+  test_mixin_instance() async {
+    addTestFile(r'''
+mixin M {
+  var a;
+}
+
+class X extends Object with M {
+  const X();
+}
+''');
+    await resolveTestFile();
+    assertTestErrors([
+      CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD,
+      CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_NON_FINAL_FIELD,
+    ]);
+  }
+
+  test_mixin_instance_final() async {
+    addTestFile(r'''
+mixin M {
+  final a = 0;
+}
+
+class X extends Object with M {
+  const X();
+}
+''');
+    await resolveTestFile();
+    assertTestErrors([
+      CompileTimeErrorCode.CONST_CONSTRUCTOR_WITH_MIXIN_WITH_FIELD,
+    ]);
+  }
+
+  test_mixin_noFields() async {
+    addTestFile(r'''
+mixin M {}
+
+class X extends Object with M {
+  const X();
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+  }
+
+  test_mixin_static() async {
+    addTestFile(r'''
+mixin M {
+  static final a = 0;
+}
+
+class X extends Object with M {
+  const X();
+}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+  }
+}
+
+@reflectiveTest
+class ConstConstructorWithMixinWithFieldTest_DriverTest
+    extends DriverResolutionTest with ConstConstructorWithMixinWithFieldMixin {}
+
+@reflectiveTest
+class ConstConstructorWithMixinWithFieldTest_TaskTest extends TaskResolutionTest
+    with ConstConstructorWithMixinWithFieldMixin {}