Suggest constructor tearoffs in const context.

Fixes https://github.com/dart-lang/sdk/issues/42264.

Change-Id: I19767d9afffd9270dedde71cad695ec439279674
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/357240
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Keerti Parthasarathy <keertip@google.com>
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/declaration_helper.dart b/pkg/analysis_server/lib/src/services/completion/dart/declaration_helper.dart
index 231a82a..30ec817 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/declaration_helper.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/declaration_helper.dart
@@ -141,7 +141,9 @@
       {required InterfaceType type, String? exclude}) {
     for (var constructor in type.constructors) {
       var name = constructor.name;
-      if (name.isNotEmpty && name != exclude) {
+      if (name.isNotEmpty &&
+          name != exclude &&
+          !(mustBeConstant && !constructor.isConst)) {
         _suggestConstructor(
           constructor,
           hasClassName: true,
@@ -1050,7 +1052,7 @@
     required bool hasClassName,
     required bool isConstructorRedirect,
   }) {
-    if (mustBeAssignable || (mustBeConstant && !element.isConst)) {
+    if (mustBeAssignable) {
       return;
     }
 
@@ -1058,11 +1060,13 @@
       return;
     }
 
+    var isTearOff = preferNonInvocation || (mustBeConstant && !element.isConst);
+
     var suggestion = ConstructorSuggestion(
       importData: importData,
       element: element,
       hasClassName: hasClassName,
-      isTearOff: preferNonInvocation,
+      isTearOff: isTearOff,
       isRedirect: isConstructorRedirect,
     );
     collector.addSuggestion(suggestion);
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/in_scope_completion_pass.dart b/pkg/analysis_server/lib/src/services/completion/dart/in_scope_completion_pass.dart
index 6ab6819..2a275a9 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/in_scope_completion_pass.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/in_scope_completion_pass.dart
@@ -2444,11 +2444,12 @@
   void _forCollectionElement(
       TypedLiteral literal, NodeList<CollectionElement> elements) {
     var mustBeStatic = literal.inStaticContext;
+    var mustBeConst = literal.inConstantContext;
     keywordHelper.addCollectionElementKeywords(literal, elements,
-        mustBeStatic: mustBeStatic);
-    var preceedingElement = elements.elementBefore(offset);
-    declarationHelper(mustBeStatic: mustBeStatic)
-        .addLexicalDeclarations(preceedingElement ?? literal);
+        mustBeConst: mustBeConst, mustBeStatic: mustBeStatic);
+    var precedingElement = elements.elementBefore(offset);
+    declarationHelper(mustBeStatic: mustBeStatic, mustBeConstant: mustBeConst)
+        .addLexicalDeclarations(precedingElement ?? literal);
   }
 
   /// Add the suggestions that are appropriate when completing in the given
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/keyword_helper.dart b/pkg/analysis_server/lib/src/services/completion/dart/keyword_helper.dart
index 92a5c2c..a139527 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/keyword_helper.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/keyword_helper.dart
@@ -103,7 +103,7 @@
   /// beginning of an element in a collection [literal].
   void addCollectionElementKeywords(
       TypedLiteral literal, NodeList<CollectionElement> elements,
-      {bool mustBeStatic = false}) {
+      {bool mustBeConst = false, bool mustBeStatic = false}) {
     // TODO(brianwilkerson): Consider determining whether there is a comma before
     //  the selection and inserting the comma if there isn't one.
     addKeyword(Keyword.FOR);
@@ -126,7 +126,8 @@
         }
       }
     }
-    addExpressionKeywords(literal, mustBeStatic: mustBeStatic);
+    addExpressionKeywords(literal,
+        mustBeConstant: mustBeConst, mustBeStatic: mustBeStatic);
   }
 
   /// Add the keywords that are appropriate when the selection is after the
diff --git a/pkg/analysis_server/test/services/completion/dart/declaration/constructor_test.dart b/pkg/analysis_server/test/services/completion/dart/declaration/constructor_test.dart
index 3ea727b..7a8013f 100644
--- a/pkg/analysis_server/test/services/completion/dart/declaration/constructor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/declaration/constructor_test.dart
@@ -18,6 +18,34 @@
     with ConstructorTestCases {}
 
 mixin ConstructorTestCases on AbstractCompletionDriverTest {
+  Future<void> test_constContext_constructorTearOff() async {
+    allowedIdentifiers = const {'NotAConst'};
+    newFile('$testPackageLibPath/a.dart', '''
+class A {
+  const A(List<Object> any);
+}
+
+class NotAConst {}
+''');
+    await computeSuggestions('''
+import 'a.dart';
+
+ @A([
+   N^
+ ])
+ class E {}
+''');
+    assertResponse(r'''
+replacement
+  left: 1
+suggestions
+  NotAConst.new
+    kind: constructor
+  null
+    kind: keyword
+''');
+  }
+
   Future<void> test_noKeyword() async {
     newFile('$testPackageLibPath/a.dart', '''
 class A0 {
diff --git a/pkg/analysis_server/test/services/completion/dart/declaration/imported_reference_test.dart b/pkg/analysis_server/test/services/completion/dart/declaration/imported_reference_test.dart
index 2c12cff..1176744 100644
--- a/pkg/analysis_server/test/services/completion/dart/declaration/imported_reference_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/declaration/imported_reference_test.dart
@@ -1742,8 +1742,12 @@
 suggestions
   B0
     kind: constructorInvocation
+  B0.named
+    kind: constructor
   B0.namedConst
     kind: constructorInvocation
+  C0.new
+    kind: constructor
   b0
     kind: topLevelVariable
 ''');
@@ -2305,6 +2309,12 @@
     kind: class
   A0
     kind: constructorInvocation
+  A0.new
+    kind: constructor
+  String.fromCharCode
+    kind: constructor
+  String.fromCharCodes
+    kind: constructor
   String.fromEnvironment
     kind: constructorInvocation
   f0
diff --git a/pkg/analysis_server/test/services/completion/dart/declaration/local_reference_test.dart b/pkg/analysis_server/test/services/completion/dart/declaration/local_reference_test.dart
index 759e938..979835c 100644
--- a/pkg/analysis_server/test/services/completion/dart/declaration/local_reference_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/declaration/local_reference_test.dart
@@ -2741,6 +2741,8 @@
     kind: class
   A0
     kind: constructorInvocation
+  A0.new
+    kind: constructor
   f0
     kind: functionInvocation
 ''');
diff --git a/pkg/analysis_server/test/services/completion/dart/declaration/type_member_test.dart b/pkg/analysis_server/test/services/completion/dart/declaration/type_member_test.dart
index 583900b..897be50 100644
--- a/pkg/analysis_server/test/services/completion/dart/declaration/type_member_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/declaration/type_member_test.dart
@@ -1898,6 +1898,8 @@
     kind: class
   A0
     kind: constructorInvocation
+  A0.new
+    kind: constructor
   f0
     kind: functionInvocation
 ''');
diff --git a/pkg/analysis_server/test/services/completion/dart/location/if_statement_test.dart b/pkg/analysis_server/test/services/completion/dart/location/if_statement_test.dart
index 73f10e9..421792f 100644
--- a/pkg/analysis_server/test/services/completion/dart/location/if_statement_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/location/if_statement_test.dart
@@ -38,7 +38,7 @@
   A1
     kind: class
   A1.named
-    kind: constructorInvocation
+    kind: constructor
   c01
     kind: topLevelVariable
   const
diff --git a/pkg/analysis_server/test/services/completion/dart/location/switch_expression_test.dart b/pkg/analysis_server/test/services/completion/dart/location/switch_expression_test.dart
index 24ea2c2..128a942 100644
--- a/pkg/analysis_server/test/services/completion/dart/location/switch_expression_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/location/switch_expression_test.dart
@@ -59,6 +59,8 @@
     kind: class
   A1
     kind: constructorInvocation
+  A1.new
+    kind: constructor
   const
     kind: keyword
   false
@@ -97,7 +99,7 @@
   A1
     kind: class
   A1.named
-    kind: constructorInvocation
+    kind: constructor
   c01
     kind: topLevelVariable
   const