Completion. Issue 54746. Don't suggest extension members in the body of class-like declarations.

Bug: https://github.com/dart-lang/sdk/issues/54746
Change-Id: Ia8e6a3a864caf75bebd13fe28e3419962b6f7a63
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/355510
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Keerti Parthasarathy <keertip@google.com>
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
index 86b2a8a..505c032 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/extension_member_contributor.dart
@@ -34,6 +34,10 @@
         return;
       }
 
+      if (request.target.isInClassLikeBody) {
+        return;
+      }
+
       var thisClassType = request.target.enclosingInterfaceElement?.thisType;
       if (thisClassType != null) {
         _addExtensionMembers(extensions, defaultKind, thisClassType);
diff --git a/pkg/analysis_server/test/client/completion_driver_test.dart b/pkg/analysis_server/test/client/completion_driver_test.dart
index 9010f1c..d42c566 100644
--- a/pkg/analysis_server/test/client/completion_driver_test.dart
+++ b/pkg/analysis_server/test/client/completion_driver_test.dart
@@ -61,6 +61,9 @@
   /// Return `true` if keywords should be included in the text to be compared.
   bool get includeKeywords => true;
 
+  /// Return `true` if overrides should be included in the text to be compared.
+  bool get includeOverrides => true;
+
   @override
   Future<List<CompletionSuggestion>> addTestFile(String content,
       {int? offset}) async {
@@ -197,6 +200,8 @@
               allowedIdentifiers.contains(completion);
         } else if (kind == CompletionSuggestionKind.KEYWORD) {
           return includeKeywords;
+        } else if (kind == CompletionSuggestionKind.OVERRIDE) {
+          return includeOverrides;
         } else if (allowedKinds.contains(kind)) {
           return true;
         }
diff --git a/pkg/analysis_server/test/services/completion/dart/declaration/extension_member_test.dart b/pkg/analysis_server/test/services/completion/dart/declaration/extension_member_test.dart
index f11b778..c1d13cd 100644
--- a/pkg/analysis_server/test/services/completion/dart/declaration/extension_member_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/declaration/extension_member_test.dart
@@ -21,6 +21,9 @@
   @override
   bool get includeKeywords => false;
 
+  @override
+  bool get includeOverrides => false;
+
   Future<void> test_extensionOverride_doesNotMatch_partial() async {
     await computeSuggestions('''
 extension E on int {
@@ -61,6 +64,52 @@
 ''');
   }
 
+  Future<void> test_inClassBody() async {
+    await computeSuggestions('''
+class A {
+  ^
+}
+
+extension on Object {
+  void a0() {}
+}
+''');
+
+    assertResponse(r'''
+suggestions
+''');
+  }
+
+  Future<void> test_inClassBody_partial() async {
+    await computeSuggestions('''
+class A {
+  a^
+}
+
+extension on Object {
+  void a0() {}
+}
+''');
+    assertResponse(r'''
+replacement
+  left: 1
+suggestions
+''');
+  }
+
+  Future<void> test_inEnumBody() async {
+    await computeSuggestions('''
+enum A {
+  v;
+  ^
+}
+
+extension on Object {
+  void a0() {}
+}
+''');
+  }
+
   Future<void> test_inExtendedClass() async {
     await computeSuggestions('''
 class Person {
@@ -224,6 +273,53 @@
 ''');
   }
 
+  Future<void> test_inExtensionBody() async {
+    await computeSuggestions('''
+extension A on int {
+  ^
+}
+
+extension on Object {
+  void a0() {}
+}
+''');
+
+    assertResponse(r'''
+suggestions
+''');
+  }
+
+  Future<void> test_inExtensionTypeBody() async {
+    await computeSuggestions('''
+extension type A(int it) {
+  ^
+}
+
+extension on Object {
+  void a0() {}
+}
+''');
+
+    assertResponse(r'''
+suggestions
+''');
+  }
+
+  Future<void> test_inMixinBody() async {
+    await computeSuggestions('''
+mixin A {
+  ^
+}
+
+extension on Object {
+  void a0() {}
+}
+''');
+    assertResponse(r'''
+suggestions
+''');
+  }
+
   Future<void> test_inMixinOnExtendedType() async {
     await computeSuggestions('''
 class Person { }
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
index d346631..8b3059f 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
@@ -429,6 +429,18 @@
     return isExistingRightParenthesis(token.next);
   }
 
+  bool get isInClassLikeBody {
+    switch (containingNode) {
+      case ClassDeclaration():
+      case EnumDeclaration():
+      case ExtensionDeclaration():
+      case ExtensionTypeDeclaration():
+      case MixinDeclaration():
+        return true;
+    }
+    return false;
+  }
+
   Token? get lastTokenOfEntity {
     final entity = this.entity;
     if (entity is AstNode) {