Version 2.16.0-142.0.dev

Merge commit '4b16e02a96512df2f3e615fb929e909cf4294656' into 'dev'
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index 661049b..71fad87 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -3,7 +3,6 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:async';
-import 'dart:collection';
 
 import 'package:analysis_server/protocol/protocol.dart';
 import 'package:analysis_server/protocol/protocol_constants.dart';
@@ -76,7 +75,7 @@
     Set<ElementKind>? includedElementKinds,
     Set<String>? includedElementNames,
     List<IncludedSuggestionRelevanceTag>? includedSuggestionRelevanceTags,
-    Map<CompletionSuggestion, Uri>? notImportedSuggestions,
+    NotImportedSuggestions? notImportedSuggestions,
   }) async {
     //
     // Allow plugins to start computing fixes.
@@ -358,8 +357,7 @@
         );
         setNewRequest(completionRequest);
 
-        var notImportedSuggestions =
-            HashMap<CompletionSuggestion, Uri>.identity();
+        var notImportedSuggestions = NotImportedSuggestions();
         var suggestions = <CompletionSuggestion>[];
         try {
           suggestions = await computeSuggestions(
@@ -390,7 +388,6 @@
         });
 
         var lengthRestricted = suggestions.take(params.maxResults).toList();
-        var isIncomplete = lengthRestricted.length < suggestions.length;
         completionPerformance.suggestionCount = lengthRestricted.length;
 
         // Update `libraryUriToImportIndex` for not yet imported.
@@ -398,7 +395,7 @@
         var librariesToImport = <Uri, int>{};
         for (var i = 0; i < lengthRestricted.length; i++) {
           var suggestion = lengthRestricted[i];
-          var libraryToImport = notImportedSuggestions[suggestion];
+          var libraryToImport = notImportedSuggestions.map[suggestion];
           if (libraryToImport != null) {
             var index = librariesToImport.putIfAbsent(
               libraryToImport,
@@ -410,6 +407,9 @@
           }
         }
 
+        var isIncomplete = notImportedSuggestions.isIncomplete ||
+            lengthRestricted.length < suggestions.length;
+
         performance.run('sendResponse', (_) {
           server.sendResponse(
             CompletionGetSuggestions2Result(
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
index 4193128..c3a351b 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/completion_manager.dart
@@ -2,6 +2,8 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:collection';
+
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:analysis_server/src/provisional/completion/completion_core.dart';
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
@@ -96,7 +98,7 @@
   /// that are not yet imported, but could be imported into the requested
   /// target. It is up to the client to make copies of [CompletionSuggestion]s
   /// with the import index property updated.
-  final Map<protocol.CompletionSuggestion, Uri>? notImportedSuggestions;
+  final NotImportedSuggestions? notImportedSuggestions;
 
   /// Initialize a newly created completion manager. The parameters
   /// [includedElementKinds], [includedElementNames], and
@@ -498,3 +500,12 @@
     }
   }
 }
+
+/// Information provided by [NotImportedContributor] in addition to suggestions.
+class NotImportedSuggestions {
+  final Map<protocol.CompletionSuggestion, Uri> map = HashMap.identity();
+
+  /// This flag is set to `true` if the contributor decided to stop before it
+  /// processed all available libraries, e.g. we ran out of budget.
+  bool isIncomplete = false;
+}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/not_imported_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/not_imported_contributor.dart
index 070294f..4046262 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/not_imported_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/not_imported_contributor.dart
@@ -4,7 +4,6 @@
 
 import 'dart:async';
 
-import 'package:analysis_server/src/protocol_server.dart' as protocol;
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
 import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
 import 'package:analysis_server/src/services/completion/dart/extension_member_contributor.dart';
@@ -16,13 +15,13 @@
 /// A contributor of suggestions from not yet imported libraries.
 class NotImportedContributor extends DartCompletionContributor {
   final CompletionBudget budget;
-  final Map<protocol.CompletionSuggestion, Uri> notImportedSuggestions;
+  final NotImportedSuggestions additionalData;
 
   NotImportedContributor(
     DartCompletionRequest request,
     SuggestionBuilder builder,
     this.budget,
-    this.notImportedSuggestions,
+    this.additionalData,
   ) : super(request, builder);
 
   @override
@@ -37,6 +36,7 @@
     try {
       await analysisDriver.discoverAvailableFiles().timeout(budget.left);
     } on TimeoutException {
+      additionalData.isIncomplete = true;
       return;
     }
 
@@ -46,6 +46,7 @@
     var knownFiles = fsState.knownFiles.toList();
     for (var file in knownFiles) {
       if (budget.isEmpty) {
+        additionalData.isIncomplete = true;
         return;
       }
 
@@ -63,7 +64,7 @@
 
       builder.laterReplacesEarlier = false;
       builder.suggestionAdded = (suggestion) {
-        notImportedSuggestions[suggestion] = file.uri;
+        additionalData.map[suggestion] = file.uri;
       };
 
       if (request.includeIdentifiers) {
diff --git a/pkg/analysis_server/test/domain_completion_test.dart b/pkg/analysis_server/test/domain_completion_test.dart
index e3a94a0..2a94276 100644
--- a/pkg/analysis_server/test/domain_completion_test.dart
+++ b/pkg/analysis_server/test/domain_completion_test.dart
@@ -335,7 +335,7 @@
 ''');
 
     responseValidator
-      ..assertComplete()
+      ..assertIncomplete()
       ..assertReplacementBack(4)
       ..assertLibrariesToImport(includes: [], excludes: [
         'dart:core',
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 8b728b5..598631f 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -83,7 +83,7 @@
 /// TODO(scheglov) Clean up the list of implicitly analyzed files.
 class AnalysisDriver implements AnalysisDriverGeneric {
   /// The version of data format, should be incremented on every format change.
-  static const int DATA_VERSION = 193;
+  static const int DATA_VERSION = 194;
 
   /// The number of exception contexts allowed to write. Once this field is
   /// zero, we stop writing any new exception contexts in this process.
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
index c7c08cf..114c5ec 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
@@ -95,6 +95,8 @@
         return _readGenericFunctionType();
       case Tag.IfElement:
         return _readIfElement();
+      case Tag.ImplicitCallReference:
+        return _readImplicitCallReference();
       case Tag.IndexExpression:
         return _readIndexExpression();
       case Tag.IntegerLiteralNegative1:
@@ -647,6 +649,22 @@
     );
   }
 
+  ImplicitCallReference _readImplicitCallReference() {
+    var expression = readNode() as Expression;
+    var typeArguments = _readOptionalNode() as TypeArgumentList?;
+    var typeArgumentTypes = _reader.readOptionalTypeList()!;
+    var staticElement = _reader.readElement() as MethodElement;
+
+    var node = astFactory.implicitCallReference(
+      expression: expression,
+      staticElement: staticElement,
+      typeArguments: typeArguments,
+      typeArgumentTypes: typeArgumentTypes,
+    );
+    _readExpressionResolution(node);
+    return node;
+  }
+
   IndexExpression _readIndexExpression() {
     var flags = _readByte();
     var target = _readOptionalNode() as Expression?;
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_tag.dart b/pkg/analyzer/lib/src/summary2/ast_binary_tag.dart
index a8033ec..38aa374 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_tag.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_tag.dart
@@ -45,6 +45,7 @@
   static const int GenericFunctionType = 21;
   static const int HideCombinator = 48;
   static const int IfElement = 63;
+  static const int ImplicitCallReference = 104;
   static const int IndexExpression = 98;
   static const int InstanceCreationExpression = 25;
   static const int IntegerLiteralNegative = 73;
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
index 446308d..e03af22 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
@@ -359,6 +359,18 @@
   }
 
   @override
+  void visitImplicitCallReference(ImplicitCallReference node) {
+    _writeByte(Tag.ImplicitCallReference);
+    _writeNode(node.expression);
+    _writeOptionalNode(node.typeArguments);
+    _sink.writeOptionalTypeList(node.typeArgumentTypes);
+
+    _sink.writeElement(node.staticElement);
+
+    _storeExpression(node);
+  }
+
+  @override
   void visitIndexExpression(IndexExpression node) {
     _writeByte(Tag.IndexExpression);
     _writeByte(
diff --git a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
index 3f5806f..3ca0b95 100644
--- a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
+++ b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
@@ -821,6 +821,19 @@
   }
 
   @override
+  void visitImplicitCallReference(ImplicitCallReference node) {
+    _writeln('ImplicitCallReference');
+    _withIndent(() {
+      var properties = _Properties();
+      properties.addNode('expression', node.expression);
+      properties.addNode('typeArguments', node.typeArguments);
+      properties.addTypeList('typeArgumentTypes', node.typeArgumentTypes);
+      _addExpression(properties, node);
+      _writeProperties(properties);
+    });
+  }
+
+  @override
   void visitImportDirective(ImportDirective node) {
     _writeNextCodeLine(node);
     _writeln('ImportDirective');
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 3d50b66..9ab1bc5 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -19495,6 +19495,63 @@
 ''');
   }
 
+  test_implicitCallTearoff() async {
+    var library = await checkLibrary(r'''
+class C {
+  void call() {}
+}
+
+class D {
+  const D(C c) : this.named(c);
+
+  const D.named(void Function() f);
+}
+''');
+    checkElementText(library, r'''
+library
+  definingUnit
+    classes
+      class C @6
+        constructors
+          synthetic @-1
+        methods
+          call @17
+            returnType: void
+      class D @36
+        constructors
+          const @48
+            parameters
+              requiredPositional c @52
+                type: C
+            constantInitializers
+              RedirectingConstructorInvocation
+                argumentList: ArgumentList
+                  arguments
+                    ImplicitCallReference
+                      expression: SimpleIdentifier
+                        staticElement: c@52
+                        staticType: C
+                        token: c @68
+                      staticType: void Function()
+                  leftParenthesis: ( @67
+                  rightParenthesis: ) @69
+                constructorName: SimpleIdentifier
+                  staticElement: self::@class::D::@constructor::named
+                  staticType: null
+                  token: named @62
+                period: . @61
+                staticElement: self::@class::D::@constructor::named
+                thisKeyword: this @57
+            redirectedConstructor: self::@class::D::@constructor::named
+          const named @83
+            periodOffset: 82
+            nameEnd: 88
+            parameters
+              requiredPositional f @105
+                type: void Function()
+''');
+  }
+
   test_implicitConstructor_named_const() async {
     var library = await checkLibrary('''
 class C {
diff --git a/tools/VERSION b/tools/VERSION
index a94e232..0557489 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 16
 PATCH 0
-PRERELEASE 141
+PRERELEASE 142
 PRERELEASE_PATCH 0
\ No newline at end of file