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 {