Issue 52059. Don't suggest final/var in ObjectPattern in ForEachPartsWithPattern, suggest getters instead.

Bug: https://github.com/dart-lang/sdk/issues/52059
Change-Id: If5e1c40fa75735077b2b77a5941d16fe2c767f3e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/296501
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analysis_server/test/services/completion/dart/location/object_pattern_test.dart b/pkg/analysis_server/test/services/completion/dart/location/object_pattern_test.dart
index 9c1abcf..3c03948 100644
--- a/pkg/analysis_server/test/services/completion/dart/location/object_pattern_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/location/object_pattern_test.dart
@@ -123,6 +123,192 @@
   }
 
   Future<void>
+      test_forEachPartsWithPattern_first_afterColon_withoutGetter() async {
+    await computeSuggestions('''
+void f1(List<A1> x0) {
+  for (final A1(: ^) in x0) {}
+}
+class A0 {
+  int f01 = 0;
+  int get g01 => 0;
+  set s01(x) {}
+  int m01() => 0;
+  static int f02 = 0;
+  static int get g02 => 0;
+  static int m02() => 0;
+  static set s02(x) {}
+}
+class A1 extends A0 {
+  int f11 = 0;
+  int get g11 => 0;
+  set s11(x) {}
+  int m11() => 0;
+  static int f12 = 0;
+  static int get g12 => 0;
+  static int m12() => 0;
+  static set s12(x) {}
+}
+''');
+    assertResponse(r'''
+suggestions
+  f01
+    kind: field
+  f11
+    kind: field
+  g01
+    kind: getter
+  g11
+    kind: getter
+''');
+  }
+
+  Future<void>
+      test_forEachPartsWithPattern_first_afterColon_withoutGetter_partial() async {
+    await computeSuggestions('''
+void f1(List<A1> x0) {
+  for (final A1(: g^) in x0) {}
+}
+class A0 {
+  int f01 = 0;
+  int get g01 => 0;
+  set s01(x) {}
+  int m01() => 0;
+  static int f02 = 0;
+  static int get g02 => 0;
+  static int m02() => 0;
+  static set s02(x) {}
+}
+class A1 extends A0 {
+  int f11 = 0;
+  int get g11 => 0;
+  set s11(x) {}
+  int m11() => 0;
+  static int f12 = 0;
+  static int get g12 => 0;
+  static int m12() => 0;
+  static set s12(x) {}
+}
+''');
+    if (isProtocolVersion2) {
+      assertResponse(r'''
+replacement
+  left: 1
+suggestions
+  g01
+    kind: getter
+  g11
+    kind: getter
+''');
+    } else {
+      assertResponse(r'''
+replacement
+  left: 1
+suggestions
+  f01
+    kind: field
+  f11
+    kind: field
+  g01
+    kind: getter
+  g11
+    kind: getter
+''');
+    }
+  }
+
+  Future<void> test_forEachPartsWithPattern_first_beforeColon() async {
+    await computeSuggestions('''
+void f1(List<A1> x0) {
+  for (final A1(^:) in x0) {}
+}
+class A0 {
+  int f01 = 0;
+  int get g01 => 0;
+  set s01(x) {}
+  int m01() => 0;
+  static int f02 = 0;
+  static int get g02 => 0;
+  static int m02() => 0;
+  static set s02(x) {}
+}
+class A1 extends A0 {
+  int f11 = 0;
+  int get g11 => 0;
+  set s11(x) {}
+  int m11() => 0;
+  static int f12 = 0;
+  static int get g12 => 0;
+  static int m12() => 0;
+  static set s12(x) {}
+}
+''');
+    assertResponse(r'''
+suggestions
+  f01
+    kind: field
+  f11
+    kind: field
+  g01
+    kind: getter
+  g11
+    kind: getter
+''');
+  }
+
+  Future<void> test_forEachPartsWithPattern_first_beforeColon_partial() async {
+    await computeSuggestions('''
+void f1(List<A1> x0) {
+  for (final A1(g^:) in x0) {}
+}
+class A0 {
+  int f01 = 0;
+  int get g01 => 0;
+  set s01(x) {}
+  int m01() => 0;
+  static int f02 = 0;
+  static int get g02 => 0;
+  static int m02() => 0;
+  static set s02(x) {}
+}
+class A1 extends A0 {
+  int f11 = 0;
+  int get g11 => 0;
+  set s11(x) {}
+  int m11() => 0;
+  static int f12 = 0;
+  static int get g12 => 0;
+  static int m12() => 0;
+  static set s12(x) {}
+}
+''');
+    if (isProtocolVersion2) {
+      assertResponse(r'''
+replacement
+  left: 1
+suggestions
+  g01
+    kind: getter
+  g11
+    kind: getter
+''');
+    } else {
+      assertResponse(r'''
+replacement
+  left: 1
+suggestions
+  f01
+    kind: field
+  f11
+    kind: field
+  g01
+    kind: getter
+  g11
+    kind: getter
+''');
+    }
+  }
+
+  Future<void>
       test_matchingContext_pattern_first_withoutGetter_afterColon() async {
     await computeSuggestions('''
 void f1(Object x0) {
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 31224db3..cd3e714 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -3460,7 +3460,9 @@
   DartType? matchedValueType;
 
   /// Returns the context for this pattern.
-  /// * Declaration context: [PatternVariableDeclarationImpl]
+  /// * Declaration context:
+  ///     [ForEachPartsWithPatternImpl]
+  ///     [PatternVariableDeclarationImpl]
   /// * Assignment context: [PatternAssignmentImpl]
   /// * Matching context: [GuardedPatternImpl]
   AstNodeImpl? get patternContext {
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
index 98055b9..71e5338 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
@@ -1753,6 +1753,7 @@
       final pattern = node.pattern;
       final patternContext = pattern.patternContext;
       if (pattern is DeclaredVariablePatternImpl ||
+          patternContext is ForEachPartsWithPattern ||
           patternContext is PatternVariableDeclaration) {
         optype.patternLocation = NamedPatternFieldWantsName(
           matchedType: parentMatchedValueType,