Report more errors for mixin declarations.
I added a fix for parsing static methods in mixins.
R=brianwilkerson@google.com, danrubel@google.com
Change-Id: Ib3c91f6cd5a2eb333f88102609f709fcac1ab9e7
Reviewed-on: https://dart-review.googlesource.com/72901
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 4c1e711..c9587ff 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -2318,7 +2318,10 @@
}
if (staticToken != null) {
assert(staticToken.isModifier);
- if (name?.lexeme == classDeclaration.name.name) {
+ String className = classDeclaration != null
+ ? classDeclaration.name.name
+ : mixinDeclaration.name.name;
+ if (name?.lexeme == className) {
// This error is also reported in OutlineBuilder.beginMethod
handleRecoverableError(
messageStaticConstructor, staticToken, staticToken);
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 70d9148..63dc9fb 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -485,12 +485,14 @@
try {
_isInNativeClass = node.nativeClause != null;
_enclosingClass = AbstractClassElementImpl.getImpl(node.declaredElement);
- _checkDuplicateClassMembers(node);
+
+ List<ClassMember> members = node.members;
+ _checkDuplicateClassMembers(members);
_checkForBuiltInIdentifierAsName(
node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME);
_checkForMemberWithClassName();
_checkForNoDefaultSuperConstructorImplicit(node);
- _checkForConflictingTypeVariableErrorCodes(node);
+ _checkForConflictingTypeVariableErrorCodes();
TypeName superclass = node.extendsClause?.superclass;
ImplementsClause implementsClause = node.implementsClause;
WithClause withClause = node.withClause;
@@ -503,7 +505,7 @@
}
_initializeInitialFieldElementsMap(_enclosingClass.fields);
- _checkForFinalNotInitializedInClass(node.members);
+ _checkForFinalNotInitializedInClass(members);
_checkForDuplicateDefinitionInheritance();
_checkForConflictingInstanceMethodSetter(node);
_checkForBadFunctionUse(node);
@@ -1034,12 +1036,14 @@
try {
// _isInNativeClass = node.nativeClause != null;
_enclosingClass = AbstractClassElementImpl.getImpl(node.declaredElement);
-// _checkDuplicateClassMembers(node);
+
+ List<ClassMember> members = node.members;
+ _checkDuplicateClassMembers(members);
// _checkForBuiltInIdentifierAsName(
// node.name, CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_NAME);
-// _checkForMemberWithClassName();
+ _checkForMemberWithClassName();
// _checkForNoDefaultSuperConstructorImplicit(node);
-// _checkForConflictingTypeVariableErrorCodes(node);
+ _checkForConflictingTypeVariableErrorCodes();
OnClause onClause = node.onClause;
ImplementsClause implementsClause = node.implementsClause;
@@ -1050,7 +1054,7 @@
}
_initializeInitialFieldElementsMap(_enclosingClass.fields);
- _checkForFinalNotInitializedInClass(node.members);
+ _checkForFinalNotInitializedInClass(members);
// _checkForDuplicateDefinitionInheritance();
// _checkForConflictingInstanceMethodSetter(node);
// _checkForBadFunctionUse(node);
@@ -1392,10 +1396,10 @@
/**
* Check that there are no members with the same name.
*/
- void _checkDuplicateClassMembers(ClassDeclaration node) {
+ void _checkDuplicateClassMembers(List<ClassMember> members) {
Map<String, Element> definedNames = new HashMap<String, Element>();
Set<String> visitedFields = new HashSet<String>();
- for (ClassMember member in node.members) {
+ for (ClassMember member in members) {
// We ignore constructors because they are checked in the method
// _checkForConflictingConstructorNameAndMember.
if (member is FieldDeclaration) {
@@ -2734,8 +2738,7 @@
* See [CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_CLASS], and
* [CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER].
*/
- void _checkForConflictingTypeVariableErrorCodes(
- ClassDeclaration declaration) {
+ void _checkForConflictingTypeVariableErrorCodes() {
for (TypeParameterElement typeParameter in _enclosingClass.typeParameters) {
String name = typeParameter.name;
// name is same as the name of the enclosing class
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index 4385697..11f98cc 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -1195,6 +1195,40 @@
expect(method.body, isNotNull);
}
+ void test_parseClassMember_method_static_class() {
+ var unit = parseCompilationUnit('class C { static void m() {} }');
+
+ ClassDeclaration c = unit.declarations[0];
+ MethodDeclaration method = c.members[0];
+ expect(method.documentationComment, isNull);
+ expect(method.externalKeyword, isNull);
+ expect(method.modifierKeyword, isNotNull);
+ expect(method.propertyKeyword, isNull);
+ expect(method.returnType, isNotNull);
+ expect(method.name, isNotNull);
+ expect(method.operatorKeyword, isNull);
+ expect(method.typeParameters, isNull);
+ expect(method.parameters, isNotNull);
+ expect(method.body, isNotNull);
+ }
+
+ void test_parseClassMember_method_static_mixin() {
+ var unit = parseCompilationUnit('mixin C { static void m() {} }');
+
+ MixinDeclaration c = unit.declarations[0];
+ MethodDeclaration method = c.members[0];
+ expect(method.documentationComment, isNull);
+ expect(method.externalKeyword, isNull);
+ expect(method.modifierKeyword, isNotNull);
+ expect(method.propertyKeyword, isNull);
+ expect(method.returnType, isNotNull);
+ expect(method.name, isNotNull);
+ expect(method.operatorKeyword, isNull);
+ expect(method.typeParameters, isNull);
+ expect(method.parameters, isNotNull);
+ expect(method.body, isNotNull);
+ }
+
void test_parseClassMember_method_trailing_commas() {
createParser('void f(int x, int y,) {}');
ClassMember member = parser.parseClassMember('C');
diff --git a/pkg/analyzer/test/src/dart/resolution/mixin_test.dart b/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
index d1bb294..b57f7fe 100644
--- a/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/mixin_test.dart
@@ -154,6 +154,131 @@
assertElementTypes(element.superclassConstraints, [objectType]);
}
+ test_error_conflictingTypeVariableAndClass() async {
+ addTestFile(r'''
+mixin M<M> {}
+''');
+ await resolveTestFile();
+ assertTestErrors([
+ CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_CLASS,
+ ]);
+ }
+
+ test_error_conflictingTypeVariableAndMember_field() async {
+ addTestFile(r'''
+mixin M<T> {
+ var T;
+}
+''');
+ await resolveTestFile();
+ assertTestErrors([
+ CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER,
+ ]);
+ }
+
+ test_error_conflictingTypeVariableAndMember_getter() async {
+ addTestFile(r'''
+mixin M<T> {
+ get T => null;
+}
+''');
+ await resolveTestFile();
+ assertTestErrors([
+ CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER,
+ ]);
+ }
+
+ test_error_conflictingTypeVariableAndMember_method() async {
+ addTestFile(r'''
+mixin M<T> {
+ T() {}
+}
+''');
+ await resolveTestFile();
+ assertTestErrors([
+ CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER,
+ ]);
+ }
+
+ test_error_conflictingTypeVariableAndMember_method_static() async {
+ addTestFile(r'''
+mixin M<T> {
+ static T() {}
+}
+''');
+ await resolveTestFile();
+ assertTestErrors([
+ CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER,
+ ]);
+ }
+
+ test_error_conflictingTypeVariableAndMember_setter() async {
+ addTestFile(r'''
+mixin M<T> {
+ void set T(_) {}
+}
+''');
+ await resolveTestFile();
+ assertTestErrors([
+ CompileTimeErrorCode.CONFLICTING_TYPE_VARIABLE_AND_MEMBER,
+ ]);
+ }
+
+ test_error_duplicateDefinition_field() async {
+ addTestFile(r'''
+mixin M {
+ int t;
+ int t;
+}
+''');
+ await resolveTestFile();
+ assertTestErrors([CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+ }
+
+ test_error_duplicateDefinition_field_method() async {
+ addTestFile(r'''
+mixin M {
+ int t;
+ void t() {}
+}
+''');
+ await resolveTestFile();
+ assertTestErrors([CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+ }
+
+ test_error_duplicateDefinition_getter() async {
+ addTestFile(r'''
+mixin M {
+ int get t => 0;
+ int get t => 0;
+}
+''');
+ await resolveTestFile();
+ assertTestErrors([CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+ }
+
+ test_error_duplicateDefinition_method() async {
+ addTestFile(r'''
+mixin M {
+ void t() {}
+ void t() {}
+}
+''');
+ await resolveTestFile();
+ assertTestErrors([CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+ }
+
+ test_error_duplicateDefinition_setter() async {
+ addTestFile(r'''
+mixin M {
+ void set t(_) {}
+ void set t(_) {}
+}
+''');
+ await resolveTestFile();
+ assertTestErrors([CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+ }
+
test_error_finalNotInitialized() async {
addTestFile(r'''
mixin M {
@@ -208,6 +333,17 @@
expect(fpElement.field, same(findElement.field('f')));
}
+ test_error_getterAndMethodWithSameName() async {
+ addTestFile(r'''
+mixin M {
+ void t() {}
+ int get t => 0;
+}
+''');
+ await resolveTestFile();
+ assertTestErrors([CompileTimeErrorCode.GETTER_AND_METHOD_WITH_SAME_NAME]);
+ }
+
test_error_implementsClause_deferredClass() async {
addTestFile(r'''
import 'dart:math' deferred as math;
@@ -263,6 +399,37 @@
assertTypeName(typeRef, null, 'void');
}
+ test_error_memberWithClassName_getter() async {
+ addTestFile(r'''
+mixin M {
+ int get M => 0;
+}
+''');
+ await resolveTestFile();
+ assertTestErrors([CompileTimeErrorCode.MEMBER_WITH_CLASS_NAME]);
+ }
+
+ test_error_memberWithClassName_OK_setter() async {
+ addTestFile(r'''
+mixin M {
+ void set M(_) {}
+}
+''');
+ await resolveTestFile();
+ assertNoTestErrors();
+ }
+
+ test_error_methodAndGetterWithSameName() async {
+ addTestFile(r'''
+mixin M {
+ int get t => 0;
+ void t() {}
+}
+''');
+ await resolveTestFile();
+ assertTestErrors([CompileTimeErrorCode.METHOD_AND_GETTER_WITH_SAME_NAME]);
+ }
+
test_error_mixinDeclaresConstructor() async {
addTestFile(r'''
mixin M {