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 {}