Check for conflict with static members

Change-Id: I7966f2211104b54bfa4f2b026ad8a706d3f2bd6c
Reviewed-on: https://dart-review.googlesource.com/c/88956
Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
Commit-Queue: Peter von der Ahé <ahe@google.com>
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
index 3712941..3c87fc7 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -7934,6 +7934,26 @@
     tip: r"""Try re-ordering the modifiers.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeStaticAndInstanceConflict =
+    messageStaticAndInstanceConflict;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageStaticAndInstanceConflict = const MessageCode(
+    "StaticAndInstanceConflict",
+    analyzerCodes: <String>["CONFLICTING_STATIC_AND_INSTANCE"],
+    message: r"""This static member conflicts with an instance member.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codeStaticAndInstanceConflictCause =
+    messageStaticAndInstanceConflictCause;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messageStaticAndInstanceConflictCause = const MessageCode(
+    "StaticAndInstanceConflictCause",
+    severity: Severity.context,
+    message: r"""This is the instance member.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Code<Null> codeStaticConstructor = messageStaticConstructor;
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
diff --git a/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart b/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
index 4d5c736..a98fb47 100644
--- a/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
@@ -17,6 +17,8 @@
         messageInheritedMembersConflict,
         messageInheritedMembersConflictCause1,
         messageInheritedMembersConflictCause2,
+        messageStaticAndInstanceConflict,
+        messageStaticAndInstanceConflictCause,
         templateDuplicatedDeclaration,
         templateDuplicatedDeclarationCause,
         templateMissingImplementationCause,
@@ -54,6 +56,7 @@
 /// Language Specification](
 /// ../../../../../../docs/language/dartLangSpec.tex#classMemberConflicts).
 bool isInheritanceConflict(Declaration a, Declaration b) {
+  if (a.isStatic) return true;
   if (memberKind(a.target) == memberKind(b.target)) return false;
   if (a.isField) return !(b.isField || b.isGetter || b.isSetter);
   if (b.isField) return !(a.isField || a.isGetter || a.isSetter);
@@ -145,6 +148,22 @@
                   b.fileUri, b.charOffset, name.length),
             ]);
       }
+    } else if (a.isStatic != b.isStatic) {
+      Declaration staticMember;
+      Declaration instanceMember;
+      if (a.isStatic) {
+        staticMember = a;
+        instanceMember = b;
+      } else {
+        staticMember = b;
+        instanceMember = a;
+      }
+      cls.library.addProblem(messageStaticAndInstanceConflict,
+          staticMember.charOffset, name.length, staticMember.fileUri,
+          context: <LocatedMessage>[
+            messageStaticAndInstanceConflictCause.withLocation(
+                instanceMember.fileUri, instanceMember.charOffset, name.length)
+          ]);
     } else {
       // This message can be reported twice (when merging localMembers with
       // classSetters, or localSetters with classMembers). By ensuring that
@@ -238,10 +257,6 @@
         scope = mixin.scope;
       }
     }
-    // TODO(ahe): Consider if removing static members from [localMembers] and
-    // [localSetters] makes sense. It depends on what semantic checks we need
-    // to perform with respect to static members and inherited members with the
-    // same name.
 
     /// Members (excluding setters) declared in [cls].
     List<Declaration> localMembers =
@@ -506,7 +521,7 @@
     while (i < aList.length && j < bList.length) {
       final Declaration a = aList[i];
       final Declaration b = bList[j];
-      if (a.isStatic) {
+      if (mergeKind == MergeKind.interfaces && a.isStatic) {
         i++;
         continue;
       }
@@ -531,7 +546,7 @@
     }
     while (i < aList.length) {
       final Declaration a = aList[i];
-      if (!a.isStatic) {
+      if (mergeKind != MergeKind.interfaces || !a.isStatic) {
         handleOnlyA(a, mergeKind);
         result[storeIndex++] = a;
       }
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index 20e3338..d92d6b8 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -326,6 +326,8 @@
 SourceOutlineSummary/example: Fail
 StackOverflow/example: Fail
 StaticAfterConst/script1: Fail
+StaticAndInstanceConflict/script1: Fail # TODO(ahe): This is fixed when enabling ClassHierarchyBuilder in all modes.
+StaticAndInstanceConflict/script2: Fail # TODO(ahe): This is fixed when enabling ClassHierarchyBuilder in all modes.
 SuperAsExpression/example: Fail
 SuperAsIdentifier/example: Fail
 SuperNullAware/example: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index a885932..50c5be3 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -3386,3 +3386,22 @@
   template: "The class 'Object' can't use mixins."
   frontendInternal: true
   external: test/fasta/object_supertype_test.dart
+
+StaticAndInstanceConflict:
+  template: "This static member conflicts with an instance member."
+  script:
+    - |
+      class C {
+        set foo(value) {}
+        static get foo => 42;
+      }
+    - |
+      class C {
+        static set foo(value) {}
+        get foo => 42;
+      }
+  analyzerCode: CONFLICTING_STATIC_AND_INSTANCE
+
+StaticAndInstanceConflictCause:
+  template: "This is the instance member."
+  severity: CONTEXT