Version 2.15.0-243.0.dev

Merge commit '732224bcced01f4a95f90ffd4a8ccdcf34ebcbd3' into 'dev'
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index 9934b5b..b84e3fd 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -1528,6 +1528,8 @@
   
   
   
+  
+  
 <h3>Requests</h3><dl><dt class="request"><a name="request_completion.getSuggestions">completion.getSuggestions</a></dt><dd><div class="box"><pre>request: {
   "id": String
   "method": "completion.getSuggestions"
diff --git a/pkg/analysis_server/lib/protocol/protocol_constants.dart b/pkg/analysis_server/lib/protocol/protocol_constants.dart
index 84b3a5c..2689506 100644
--- a/pkg/analysis_server/lib/protocol/protocol_constants.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_constants.dart
@@ -137,10 +137,22 @@
     'replacementOffset';
 const String COMPLETION_NOTIFICATION_RESULTS_RESULTS = 'results';
 const String COMPLETION_REQUEST_GET_SUGGESTIONS = 'completion.getSuggestions';
+const String COMPLETION_REQUEST_GET_SUGGESTIONS2 = 'completion.getSuggestions2';
+const String COMPLETION_REQUEST_GET_SUGGESTIONS2_FILE = 'file';
+const String COMPLETION_REQUEST_GET_SUGGESTIONS2_MAX_RESULTS = 'maxResults';
+const String COMPLETION_REQUEST_GET_SUGGESTIONS2_OFFSET = 'offset';
 const String COMPLETION_REQUEST_GET_SUGGESTIONS_FILE = 'file';
 const String COMPLETION_REQUEST_GET_SUGGESTIONS_OFFSET = 'offset';
 const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS =
     'completion.getSuggestionDetails';
+const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS2 =
+    'completion.getSuggestionDetails2';
+const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS2_COMPLETION =
+    'completion';
+const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS2_FILE = 'file';
+const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS2_LIBRARY_URI =
+    'libraryUri';
+const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS2_OFFSET = 'offset';
 const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS_FILE = 'file';
 const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS_ID = 'id';
 const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS_LABEL = 'label';
@@ -152,7 +164,19 @@
     'completion.setSubscriptions';
 const String COMPLETION_REQUEST_SET_SUBSCRIPTIONS_SUBSCRIPTIONS =
     'subscriptions';
+const String COMPLETION_RESPONSE_GET_SUGGESTIONS2_IS_INCOMPLETE =
+    'isIncomplete';
+const String COMPLETION_RESPONSE_GET_SUGGESTIONS2_LIBRARY_URIS_TO_IMPORT =
+    'libraryUrisToImport';
+const String COMPLETION_RESPONSE_GET_SUGGESTIONS2_REPLACEMENT_LENGTH =
+    'replacementLength';
+const String COMPLETION_RESPONSE_GET_SUGGESTIONS2_REPLACEMENT_OFFSET =
+    'replacementOffset';
+const String COMPLETION_RESPONSE_GET_SUGGESTIONS2_SUGGESTIONS = 'suggestions';
 const String COMPLETION_RESPONSE_GET_SUGGESTIONS_ID = 'id';
+const String COMPLETION_RESPONSE_GET_SUGGESTION_DETAILS2_CHANGE = 'change';
+const String COMPLETION_RESPONSE_GET_SUGGESTION_DETAILS2_COMPLETION =
+    'completion';
 const String COMPLETION_RESPONSE_GET_SUGGESTION_DETAILS_CHANGE = 'change';
 const String COMPLETION_RESPONSE_GET_SUGGESTION_DETAILS_COMPLETION =
     'completion';
diff --git a/pkg/analysis_server/lib/protocol/protocol_generated.dart b/pkg/analysis_server/lib/protocol/protocol_generated.dart
index 301bfab..8cd904d 100644
--- a/pkg/analysis_server/lib/protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_generated.dart
@@ -4292,6 +4292,202 @@
       );
 }
 
+/// completion.getSuggestionDetails2 params
+///
+/// {
+///   "file": FilePath
+///   "offset": int
+///   "completion": String
+///   "libraryUri": String
+/// }
+///
+/// Clients may not extend, implement or mix-in this class.
+class CompletionGetSuggestionDetails2Params implements RequestParams {
+  /// The path of the file into which this completion is being inserted.
+  String file;
+
+  /// The offset in the file where the completion will be inserted.
+  int offset;
+
+  /// The completion from the selected CompletionSuggestion. It could be a name
+  /// of a class, or a name of a constructor in form
+  /// "typeName.constructorName()", or an enumeration constant in form
+  /// "enumName.constantName", etc.
+  String completion;
+
+  /// The URI of the library to import, so that the element referenced in the
+  /// completion becomes accessible.
+  String libraryUri;
+
+  CompletionGetSuggestionDetails2Params(
+      this.file, this.offset, this.completion, this.libraryUri);
+
+  factory CompletionGetSuggestionDetails2Params.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object? json) {
+    json ??= {};
+    if (json is Map) {
+      String file;
+      if (json.containsKey('file')) {
+        file = jsonDecoder.decodeString(jsonPath + '.file', json['file']);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, 'file');
+      }
+      int offset;
+      if (json.containsKey('offset')) {
+        offset = jsonDecoder.decodeInt(jsonPath + '.offset', json['offset']);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, 'offset');
+      }
+      String completion;
+      if (json.containsKey('completion')) {
+        completion = jsonDecoder.decodeString(
+            jsonPath + '.completion', json['completion']);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, 'completion');
+      }
+      String libraryUri;
+      if (json.containsKey('libraryUri')) {
+        libraryUri = jsonDecoder.decodeString(
+            jsonPath + '.libraryUri', json['libraryUri']);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, 'libraryUri');
+      }
+      return CompletionGetSuggestionDetails2Params(
+          file, offset, completion, libraryUri);
+    } else {
+      throw jsonDecoder.mismatch(
+          jsonPath, 'completion.getSuggestionDetails2 params', json);
+    }
+  }
+
+  factory CompletionGetSuggestionDetails2Params.fromRequest(Request request) {
+    return CompletionGetSuggestionDetails2Params.fromJson(
+        RequestDecoder(request), 'params', request.params);
+  }
+
+  @override
+  Map<String, Object> toJson() {
+    var result = <String, Object>{};
+    result['file'] = file;
+    result['offset'] = offset;
+    result['completion'] = completion;
+    result['libraryUri'] = libraryUri;
+    return result;
+  }
+
+  @override
+  Request toRequest(String id) {
+    return Request(id, 'completion.getSuggestionDetails2', toJson());
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is CompletionGetSuggestionDetails2Params) {
+      return file == other.file &&
+          offset == other.offset &&
+          completion == other.completion &&
+          libraryUri == other.libraryUri;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode => Object.hash(
+        file,
+        offset,
+        completion,
+        libraryUri,
+      );
+}
+
+/// completion.getSuggestionDetails2 result
+///
+/// {
+///   "completion": String
+///   "change": SourceChange
+/// }
+///
+/// Clients may not extend, implement or mix-in this class.
+class CompletionGetSuggestionDetails2Result implements ResponseResult {
+  /// The full text to insert, which possibly includes now an import prefix.
+  /// The client should insert this text, not the completion from the selected
+  /// CompletionSuggestion.
+  String completion;
+
+  /// A change for the client to apply to make the accepted completion
+  /// suggestion available. In most cases the change is to add a new import
+  /// directive to the file.
+  SourceChange change;
+
+  CompletionGetSuggestionDetails2Result(this.completion, this.change);
+
+  factory CompletionGetSuggestionDetails2Result.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object? json) {
+    json ??= {};
+    if (json is Map) {
+      String completion;
+      if (json.containsKey('completion')) {
+        completion = jsonDecoder.decodeString(
+            jsonPath + '.completion', json['completion']);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, 'completion');
+      }
+      SourceChange change;
+      if (json.containsKey('change')) {
+        change = SourceChange.fromJson(
+            jsonDecoder, jsonPath + '.change', json['change']);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, 'change');
+      }
+      return CompletionGetSuggestionDetails2Result(completion, change);
+    } else {
+      throw jsonDecoder.mismatch(
+          jsonPath, 'completion.getSuggestionDetails2 result', json);
+    }
+  }
+
+  factory CompletionGetSuggestionDetails2Result.fromResponse(
+      Response response) {
+    return CompletionGetSuggestionDetails2Result.fromJson(
+        ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
+        'result',
+        response.result);
+  }
+
+  @override
+  Map<String, Object> toJson() {
+    var result = <String, Object>{};
+    result['completion'] = completion;
+    result['change'] = change.toJson();
+    return result;
+  }
+
+  @override
+  Response toResponse(String id) {
+    return Response(id, result: toJson());
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is CompletionGetSuggestionDetails2Result) {
+      return completion == other.completion && change == other.change;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode => Object.hash(
+        completion,
+        change,
+      );
+}
+
 /// completion.getSuggestionDetails params
 ///
 /// {
@@ -4481,6 +4677,261 @@
       );
 }
 
+/// completion.getSuggestions2 params
+///
+/// {
+///   "file": FilePath
+///   "offset": int
+///   "maxResults": int
+/// }
+///
+/// Clients may not extend, implement or mix-in this class.
+class CompletionGetSuggestions2Params implements RequestParams {
+  /// The file containing the point at which suggestions are to be made.
+  String file;
+
+  /// The offset within the file at which suggestions are to be made.
+  int offset;
+
+  /// The maximum number of suggestions to return. If the number of suggestions
+  /// after filtering is greater than the maxResults, then isIncomplete is set
+  /// to true.
+  int maxResults;
+
+  CompletionGetSuggestions2Params(this.file, this.offset, this.maxResults);
+
+  factory CompletionGetSuggestions2Params.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object? json) {
+    json ??= {};
+    if (json is Map) {
+      String file;
+      if (json.containsKey('file')) {
+        file = jsonDecoder.decodeString(jsonPath + '.file', json['file']);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, 'file');
+      }
+      int offset;
+      if (json.containsKey('offset')) {
+        offset = jsonDecoder.decodeInt(jsonPath + '.offset', json['offset']);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, 'offset');
+      }
+      int maxResults;
+      if (json.containsKey('maxResults')) {
+        maxResults =
+            jsonDecoder.decodeInt(jsonPath + '.maxResults', json['maxResults']);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, 'maxResults');
+      }
+      return CompletionGetSuggestions2Params(file, offset, maxResults);
+    } else {
+      throw jsonDecoder.mismatch(
+          jsonPath, 'completion.getSuggestions2 params', json);
+    }
+  }
+
+  factory CompletionGetSuggestions2Params.fromRequest(Request request) {
+    return CompletionGetSuggestions2Params.fromJson(
+        RequestDecoder(request), 'params', request.params);
+  }
+
+  @override
+  Map<String, Object> toJson() {
+    var result = <String, Object>{};
+    result['file'] = file;
+    result['offset'] = offset;
+    result['maxResults'] = maxResults;
+    return result;
+  }
+
+  @override
+  Request toRequest(String id) {
+    return Request(id, 'completion.getSuggestions2', toJson());
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is CompletionGetSuggestions2Params) {
+      return file == other.file &&
+          offset == other.offset &&
+          maxResults == other.maxResults;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode => Object.hash(
+        file,
+        offset,
+        maxResults,
+      );
+}
+
+/// completion.getSuggestions2 result
+///
+/// {
+///   "replacementOffset": int
+///   "replacementLength": int
+///   "suggestions": List<CompletionSuggestion>
+///   "libraryUrisToImport": List<String>
+///   "isIncomplete": bool
+/// }
+///
+/// Clients may not extend, implement or mix-in this class.
+class CompletionGetSuggestions2Result implements ResponseResult {
+  /// The offset of the start of the text to be replaced. This will be
+  /// different from the offset used to request the completion suggestions if
+  /// there was a portion of an identifier before the original offset. In
+  /// particular, the replacementOffset will be the offset of the beginning of
+  /// said identifier.
+  int replacementOffset;
+
+  /// The length of the text to be replaced if the remainder of the identifier
+  /// containing the cursor is to be replaced when the suggestion is applied
+  /// (that is, the number of characters in the existing identifier).
+  int replacementLength;
+
+  /// The completion suggestions being reported. This list is filtered by the
+  /// already existing prefix, and sorted first by relevance, and (if the same)
+  /// by the suggestion text. The list will have at most maxResults items. If
+  /// the user types a new keystroke, the client is expected to either do local
+  /// filtering (when the returned list was complete), or ask the server again
+  /// (if isIncomplete was true).
+  ///
+  /// This list contains suggestions from both imported, and not yet imported
+  /// libraries. Items from not yet imported libraries will have
+  /// libraryUriToImportIndex set, which is an index into the
+  /// libraryUrisToImport in this response.
+  List<CompletionSuggestion> suggestions;
+
+  /// The list of libraries with declarations that are not yet available in the
+  /// file where completion was requested, most often because the library is
+  /// not yet imported. The declarations still might be included into the
+  /// suggestions, and the client should use getSuggestionDetails2 on selection
+  /// to make the library available in the file.
+  ///
+  /// Each item is the URI of a library, such as package:foo/bar.dart or
+  /// file:///home/me/workspace/foo/test/bar_test.dart.
+  List<String> libraryUrisToImport;
+
+  /// True if the number of suggestions after filtering was greater than the
+  /// requested maxResults.
+  bool isIncomplete;
+
+  CompletionGetSuggestions2Result(
+      this.replacementOffset,
+      this.replacementLength,
+      this.suggestions,
+      this.libraryUrisToImport,
+      this.isIncomplete);
+
+  factory CompletionGetSuggestions2Result.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object? json) {
+    json ??= {};
+    if (json is Map) {
+      int replacementOffset;
+      if (json.containsKey('replacementOffset')) {
+        replacementOffset = jsonDecoder.decodeInt(
+            jsonPath + '.replacementOffset', json['replacementOffset']);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, 'replacementOffset');
+      }
+      int replacementLength;
+      if (json.containsKey('replacementLength')) {
+        replacementLength = jsonDecoder.decodeInt(
+            jsonPath + '.replacementLength', json['replacementLength']);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, 'replacementLength');
+      }
+      List<CompletionSuggestion> suggestions;
+      if (json.containsKey('suggestions')) {
+        suggestions = jsonDecoder.decodeList(
+            jsonPath + '.suggestions',
+            json['suggestions'],
+            (String jsonPath, Object? json) =>
+                CompletionSuggestion.fromJson(jsonDecoder, jsonPath, json));
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, 'suggestions');
+      }
+      List<String> libraryUrisToImport;
+      if (json.containsKey('libraryUrisToImport')) {
+        libraryUrisToImport = jsonDecoder.decodeList(
+            jsonPath + '.libraryUrisToImport',
+            json['libraryUrisToImport'],
+            jsonDecoder.decodeString);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, 'libraryUrisToImport');
+      }
+      bool isIncomplete;
+      if (json.containsKey('isIncomplete')) {
+        isIncomplete = jsonDecoder.decodeBool(
+            jsonPath + '.isIncomplete', json['isIncomplete']);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, 'isIncomplete');
+      }
+      return CompletionGetSuggestions2Result(replacementOffset,
+          replacementLength, suggestions, libraryUrisToImport, isIncomplete);
+    } else {
+      throw jsonDecoder.mismatch(
+          jsonPath, 'completion.getSuggestions2 result', json);
+    }
+  }
+
+  factory CompletionGetSuggestions2Result.fromResponse(Response response) {
+    return CompletionGetSuggestions2Result.fromJson(
+        ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
+        'result',
+        response.result);
+  }
+
+  @override
+  Map<String, Object> toJson() {
+    var result = <String, Object>{};
+    result['replacementOffset'] = replacementOffset;
+    result['replacementLength'] = replacementLength;
+    result['suggestions'] = suggestions
+        .map((CompletionSuggestion value) => value.toJson())
+        .toList();
+    result['libraryUrisToImport'] = libraryUrisToImport;
+    result['isIncomplete'] = isIncomplete;
+    return result;
+  }
+
+  @override
+  Response toResponse(String id) {
+    return Response(id, result: toJson());
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is CompletionGetSuggestions2Result) {
+      return replacementOffset == other.replacementOffset &&
+          replacementLength == other.replacementLength &&
+          listEqual(suggestions, other.suggestions,
+              (CompletionSuggestion a, CompletionSuggestion b) => a == b) &&
+          listEqual(libraryUrisToImport, other.libraryUrisToImport,
+              (String a, String b) => a == b) &&
+          isIncomplete == other.isIncomplete;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode => Object.hash(
+        replacementOffset,
+        replacementLength,
+        suggestions,
+        libraryUrisToImport,
+        isIncomplete,
+      );
+}
+
 /// completion.getSuggestions params
 ///
 /// {
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/add_return_type.dart b/pkg/analysis_server/lib/src/services/correction/dart/add_return_type.dart
index a66c22c..9e06b2f 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/add_return_type.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/add_return_type.dart
@@ -21,9 +21,18 @@
   AssistKind get assistKind => DartAssistKind.ADD_RETURN_TYPE;
 
   @override
+  bool get canBeAppliedInBulk => true;
+
+  @override
+  bool get canBeAppliedToFile => true;
+
+  @override
   FixKind get fixKind => DartFixKind.ADD_RETURN_TYPE;
 
   @override
+  FixKind? get multiFixKind => DartFixKind.ADD_RETURN_TYPE_MULTI;
+
+  @override
   Future<void> compute(ChangeBuilder builder) async {
     SyntacticEntity? insertBeforeEntity;
     FunctionBody? body;
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/remove_unused_parameter.dart b/pkg/analysis_server/lib/src/services/correction/dart/remove_unused_parameter.dart
index 830345f..e18ebec 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/remove_unused_parameter.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/remove_unused_parameter.dart
@@ -12,9 +12,18 @@
 
 class RemoveUnusedParameter extends CorrectionProducer {
   @override
+  bool get canBeAppliedInBulk => true;
+
+  @override
+  bool get canBeAppliedToFile => true;
+
+  @override
   FixKind get fixKind => DartFixKind.REMOVE_UNUSED_PARAMETER;
 
   @override
+  FixKind? get multiFixKind => DartFixKind.REMOVE_UNUSED_PARAMETER_MULTI;
+
+  @override
   Future<void> compute(ChangeBuilder builder) async {
     var parameter = node;
     if (parameter is! FormalParameter) {
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_eight_digit_hex.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_eight_digit_hex.dart
index ff9e2eb..08271c9 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_eight_digit_hex.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_eight_digit_hex.dart
@@ -14,6 +14,12 @@
   String _replacement = '';
 
   @override
+  bool get canBeAppliedInBulk => true;
+
+  @override
+  bool get canBeAppliedToFile => true;
+
+  @override
   List<Object> get fixArguments => [_replacement];
 
   @override
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index e6be85e..04f4725 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -327,7 +327,6 @@
   /// are in the [nonLintProducerMap].
   static final Map<String, List<ProducerGenerator>> lintProducerMap = {
     LintNames.always_declare_return_types: [
-      // TODO(brianwilkerson) Consider applying in bulk.
       AddReturnType.newInstance,
     ],
     LintNames.always_require_non_null_named_parameters: [
@@ -393,7 +392,6 @@
       RemoveTypeAnnotation.newInstance,
     ],
     LintNames.avoid_unused_constructor_parameters: [
-      // TODO(brianwilkerson) Consider applying in bulk.
       RemoveUnusedParameter.newInstance,
     ],
     LintNames.avoid_unnecessary_containers: [
@@ -614,7 +612,6 @@
       RemoveThisExpression.newInstance,
     ],
     LintNames.use_full_hex_values_for_flutter_colors: [
-      // TODO(brianwilkerson) Consider applying in bulk.
       ReplaceWithEightDigitHex.newInstance,
     ],
     LintNames.use_function_type_syntax_for_parameters: [
diff --git a/pkg/analysis_server/test/integration/coverage.md b/pkg/analysis_server/test/integration/coverage.md
index 58d0edf..b91da0a 100644
--- a/pkg/analysis_server/test/integration/coverage.md
+++ b/pkg/analysis_server/test/integration/coverage.md
@@ -33,7 +33,9 @@
 - [ ] completion.availableSuggestions
 - [ ] completion.existingImports
 - [ ] completion.getSuggestionDetails
+- [ ] completion.getSuggestionDetails2
 - [x] completion.getSuggestions
+- [ ] completion.getSuggestions2
 - [ ] completion.registerLibraryPaths
 - [ ] completion.results
 - [ ] completion.setSubscriptions
diff --git a/pkg/analysis_server/test/integration/support/integration_test_methods.dart b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
index 5fd4d70..9a707cf 100644
--- a/pkg/analysis_server/test/integration/support/integration_test_methods.dart
+++ b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
@@ -953,6 +953,81 @@
     return CompletionGetSuggestionsResult.fromJson(decoder, 'result', result);
   }
 
+  /// Request that completion suggestions for the given offset in the given
+  /// file be returned. The suggestions will be filtered using fuzzy matching
+  /// with the already existing prefix.
+  ///
+  /// Parameters
+  ///
+  /// file: FilePath
+  ///
+  ///   The file containing the point at which suggestions are to be made.
+  ///
+  /// offset: int
+  ///
+  ///   The offset within the file at which suggestions are to be made.
+  ///
+  /// maxResults: int
+  ///
+  ///   The maximum number of suggestions to return. If the number of
+  ///   suggestions after filtering is greater than the maxResults, then
+  ///   isIncomplete is set to true.
+  ///
+  /// Returns
+  ///
+  /// replacementOffset: int
+  ///
+  ///   The offset of the start of the text to be replaced. This will be
+  ///   different from the offset used to request the completion suggestions if
+  ///   there was a portion of an identifier before the original offset. In
+  ///   particular, the replacementOffset will be the offset of the beginning
+  ///   of said identifier.
+  ///
+  /// replacementLength: int
+  ///
+  ///   The length of the text to be replaced if the remainder of the
+  ///   identifier containing the cursor is to be replaced when the suggestion
+  ///   is applied (that is, the number of characters in the existing
+  ///   identifier).
+  ///
+  /// suggestions: List<CompletionSuggestion>
+  ///
+  ///   The completion suggestions being reported. This list is filtered by the
+  ///   already existing prefix, and sorted first by relevance, and (if the
+  ///   same) by the suggestion text. The list will have at most maxResults
+  ///   items. If the user types a new keystroke, the client is expected to
+  ///   either do local filtering (when the returned list was complete), or ask
+  ///   the server again (if isIncomplete was true).
+  ///
+  ///   This list contains suggestions from both imported, and not yet imported
+  ///   libraries. Items from not yet imported libraries will have
+  ///   libraryUriToImportIndex set, which is an index into the
+  ///   libraryUrisToImport in this response.
+  ///
+  /// libraryUrisToImport: List<String>
+  ///
+  ///   The list of libraries with declarations that are not yet available in
+  ///   the file where completion was requested, most often because the library
+  ///   is not yet imported. The declarations still might be included into the
+  ///   suggestions, and the client should use getSuggestionDetails2 on
+  ///   selection to make the library available in the file.
+  ///
+  ///   Each item is the URI of a library, such as package:foo/bar.dart or
+  ///   file:///home/me/workspace/foo/test/bar_test.dart.
+  ///
+  /// isIncomplete: bool
+  ///
+  ///   True if the number of suggestions after filtering was greater than the
+  ///   requested maxResults.
+  Future<CompletionGetSuggestions2Result> sendCompletionGetSuggestions2(
+      String file, int offset, int maxResults) async {
+    var params =
+        CompletionGetSuggestions2Params(file, offset, maxResults).toJson();
+    var result = await server.send('completion.getSuggestions2', params);
+    var decoder = ResponseDecoder(null);
+    return CompletionGetSuggestions2Result.fromJson(decoder, 'result', result);
+  }
+
   /// Subscribe for completion services. All previous subscriptions are
   /// replaced by the given set of services.
   ///
@@ -1046,6 +1121,61 @@
         decoder, 'result', result);
   }
 
+  /// Clients must make this request when the user has selected a completion
+  /// suggestion with the libraryUriToImportIndex field set. The server will
+  /// respond with the text to insert, as well as any SourceChange that needs
+  /// to be applied in case the completion requires an additional import to be
+  /// added. The text to insert might be different from the original suggestion
+  /// to include an import prefix if the library will be imported with a prefix
+  /// to avoid shadowing conflicts in the file.
+  ///
+  /// Parameters
+  ///
+  /// file: FilePath
+  ///
+  ///   The path of the file into which this completion is being inserted.
+  ///
+  /// offset: int
+  ///
+  ///   The offset in the file where the completion will be inserted.
+  ///
+  /// completion: String
+  ///
+  ///   The completion from the selected CompletionSuggestion. It could be a
+  ///   name of a class, or a name of a constructor in form
+  ///   "typeName.constructorName()", or an enumeration constant in form
+  ///   "enumName.constantName", etc.
+  ///
+  /// libraryUri: String
+  ///
+  ///   The URI of the library to import, so that the element referenced in the
+  ///   completion becomes accessible.
+  ///
+  /// Returns
+  ///
+  /// completion: String
+  ///
+  ///   The full text to insert, which possibly includes now an import prefix.
+  ///   The client should insert this text, not the completion from the
+  ///   selected CompletionSuggestion.
+  ///
+  /// change: SourceChange
+  ///
+  ///   A change for the client to apply to make the accepted completion
+  ///   suggestion available. In most cases the change is to add a new import
+  ///   directive to the file.
+  Future<CompletionGetSuggestionDetails2Result>
+      sendCompletionGetSuggestionDetails2(
+          String file, int offset, String completion, String libraryUri) async {
+    var params = CompletionGetSuggestionDetails2Params(
+            file, offset, completion, libraryUri)
+        .toJson();
+    var result = await server.send('completion.getSuggestionDetails2', params);
+    var decoder = ResponseDecoder(null);
+    return CompletionGetSuggestionDetails2Result.fromJson(
+        decoder, 'result', result);
+  }
+
   /// Reports the completion suggestions that should be presented to the user.
   /// The set of suggestions included in the notification is always a complete
   /// list that supersedes any previously reported suggestions.
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index 8a094d4..5fd8c3c 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -295,7 +295,8 @@
           'requiredParameterCount': isInt,
           'hasNamedParameters': isBool,
           'parameterName': isString,
-          'parameterType': isString
+          'parameterType': isString,
+          'libraryUriToImportIndex': isInt
         }));
 
 /// CompletionSuggestionKind
@@ -2080,6 +2081,32 @@
     MatchesJsonObject('completion.existingImports params',
         {'file': isFilePath, 'imports': isExistingImports}));
 
+/// completion.getSuggestionDetails2 params
+///
+/// {
+///   "file": FilePath
+///   "offset": int
+///   "completion": String
+///   "libraryUri": String
+/// }
+final Matcher isCompletionGetSuggestionDetails2Params = LazyMatcher(
+    () => MatchesJsonObject('completion.getSuggestionDetails2 params', {
+          'file': isFilePath,
+          'offset': isInt,
+          'completion': isString,
+          'libraryUri': isString
+        }));
+
+/// completion.getSuggestionDetails2 result
+///
+/// {
+///   "completion": String
+///   "change": SourceChange
+/// }
+final Matcher isCompletionGetSuggestionDetails2Result = LazyMatcher(() =>
+    MatchesJsonObject('completion.getSuggestionDetails2 result',
+        {'completion': isString, 'change': isSourceChange}));
+
 /// completion.getSuggestionDetails params
 ///
 /// {
@@ -2103,6 +2130,35 @@
         'completion.getSuggestionDetails result', {'completion': isString},
         optionalFields: {'change': isSourceChange}));
 
+/// completion.getSuggestions2 params
+///
+/// {
+///   "file": FilePath
+///   "offset": int
+///   "maxResults": int
+/// }
+final Matcher isCompletionGetSuggestions2Params = LazyMatcher(() =>
+    MatchesJsonObject('completion.getSuggestions2 params',
+        {'file': isFilePath, 'offset': isInt, 'maxResults': isInt}));
+
+/// completion.getSuggestions2 result
+///
+/// {
+///   "replacementOffset": int
+///   "replacementLength": int
+///   "suggestions": List<CompletionSuggestion>
+///   "libraryUrisToImport": List<String>
+///   "isIncomplete": bool
+/// }
+final Matcher isCompletionGetSuggestions2Result =
+    LazyMatcher(() => MatchesJsonObject('completion.getSuggestions2 result', {
+          'replacementOffset': isInt,
+          'replacementLength': isInt,
+          'suggestions': isListOf(isCompletionSuggestion),
+          'libraryUrisToImport': isListOf(isString),
+          'isIncomplete': isBool
+        }));
+
 /// completion.getSuggestions params
 ///
 /// {
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_return_type_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_return_type_test.dart
index cfcabd6..1a40007 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/add_return_type_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_return_type_test.dart
@@ -12,10 +12,36 @@
 void main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(AddReturnTypeLintTest);
+    defineReflectiveTests(AddReturnTypeBulkTest);
   });
 }
 
 @reflectiveTest
+class AddReturnTypeBulkTest extends BulkFixProcessorTest {
+  @override
+  String get lintCode => LintNames.always_declare_return_types;
+
+  Future<void> test_singleFile() async {
+    await resolveTestCode('''
+class A {
+  get foo => 0;
+  m(p) {
+    return p;
+  }
+}
+''');
+    await assertHasFix('''
+class A {
+  int get foo => 0;
+  dynamic m(p) {
+    return p;
+  }
+}
+''');
+  }
+}
+
+@reflectiveTest
 class AddReturnTypeLintTest extends FixProcessorLintTest {
   @override
   FixKind get kind => DartFixKind.ADD_RETURN_TYPE;
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_unused_parameter_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_unused_parameter_test.dart
index e421d0e..fe01fbd 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/remove_unused_parameter_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_unused_parameter_test.dart
@@ -12,10 +12,32 @@
 void main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(RemoveUnusedParameterTest);
+    defineReflectiveTests(RemoveUnusedParameterBulkTest);
   });
 }
 
 @reflectiveTest
+class RemoveUnusedParameterBulkTest extends BulkFixProcessorTest {
+  @override
+  String get lintCode => LintNames.avoid_unused_constructor_parameters;
+
+  Future<void> test_singleFile() async {
+    await resolveTestCode('''
+class C {
+  int y;
+  C({int x = 0, this.y = 0, int z = 0});
+}
+''');
+    await assertHasFix('''
+class C {
+  int y;
+  C({this.y = 0});
+}
+''');
+  }
+}
+
+@reflectiveTest
 class RemoveUnusedParameterTest extends FixProcessorLintTest {
   @override
   FixKind get kind => DartFixKind.REMOVE_UNUSED_PARAMETER;
diff --git a/pkg/analysis_server/test/src/services/correction/fix/replace_with_eight_digit_hex_test.dart b/pkg/analysis_server/test/src/services/correction/fix/replace_with_eight_digit_hex_test.dart
index bd4e2e1..fb67e7a 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/replace_with_eight_digit_hex_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/replace_with_eight_digit_hex_test.dart
@@ -12,10 +12,40 @@
 void main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(ReplaceWithEightDigitHexTest);
+    defineReflectiveTests(ReplaceWithEightDigitHexBulkTest);
   });
 }
 
 @reflectiveTest
+class ReplaceWithEightDigitHexBulkTest extends BulkFixProcessorTest {
+  @override
+  String get lintCode => LintNames.use_full_hex_values_for_flutter_colors;
+
+  Future<void> test_singleFile() async {
+    await resolveTestCode('''
+library dart.ui;
+
+var c = Color(1);
+var c2 = Color(0x000001);
+
+class Color {
+  Color(int value);
+}
+''');
+    await assertHasFix('''
+library dart.ui;
+
+var c = Color(0x00000001);
+var c2 = Color(0x00000001);
+
+class Color {
+  Color(int value);
+}
+''');
+  }
+}
+
+@reflectiveTest
 class ReplaceWithEightDigitHexTest extends FixProcessorLintTest {
   @override
   FixKind get kind => DartFixKind.REPLACE_WITH_EIGHT_DIGIT_HEX;
diff --git a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
index 03b9cbe..9f7e268 100644
--- a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
+++ b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
@@ -402,6 +402,26 @@
   public void completion_getSuggestionDetails(String file, int id, String label, int offset, GetSuggestionDetailsConsumer consumer);
 
   /**
+   * {@code completion.getSuggestionDetails2}
+   *
+   * Clients must make this request when the user has selected a completion suggestion with the
+   * libraryUriToImportIndex field set. The server will respond with the text to insert, as well as
+   * any SourceChange that needs to be applied in case the completion requires an additional import
+   * to be added. The text to insert might be different from the original suggestion to include an
+   * import prefix if the library will be imported with a prefix to avoid shadowing conflicts in the
+   * file.
+   *
+   * @param file The path of the file into which this completion is being inserted.
+   * @param offset The offset in the file where the completion will be inserted.
+   * @param completion The completion from the selected CompletionSuggestion. It could be a name of a
+   *         class, or a name of a constructor in form "typeName.constructorName()", or an
+   *         enumeration constant in form "enumName.constantName", etc.
+   * @param libraryUri The URI of the library to import, so that the element referenced in the
+   *         completion becomes accessible.
+   */
+  public void completion_getSuggestionDetails2(String file, int offset, String completion, String libraryUri, GetSuggestionDetails2Consumer consumer);
+
+  /**
    * {@code completion.getSuggestions}
    *
    * Request that completion suggestions for the given offset in the given file be returned.
@@ -412,6 +432,19 @@
   public void completion_getSuggestions(String file, int offset, GetSuggestionsConsumer consumer);
 
   /**
+   * {@code completion.getSuggestions2}
+   *
+   * Request that completion suggestions for the given offset in the given file be returned. The
+   * suggestions will be filtered using fuzzy matching with the already existing prefix.
+   *
+   * @param file The file containing the point at which suggestions are to be made.
+   * @param offset The offset within the file at which suggestions are to be made.
+   * @param maxResults The maximum number of suggestions to return. If the number of suggestions
+   *         after filtering is greater than the maxResults, then isIncomplete is set to true.
+   */
+  public void completion_getSuggestions2(String file, int offset, int maxResults, GetSuggestions2Consumer consumer);
+
+  /**
    * {@code completion.registerLibraryPaths}
    *
    * The client can make this request to express interest in certain libraries to receive completion
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java b/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java
index c9ffeeb..bf8d912 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/CompletionSuggestion.java
@@ -176,9 +176,18 @@
   private final String parameterType;
 
   /**
+   * The index in the list of libraries that could be imported to make this suggestion accessible in
+   * the file where completion was requested. The server provides this list of libraries together
+   * with suggestions, so that information about the library can be shared for multiple suggestions.
+   * This field is omitted if the library is already imported, so that the suggestion can be inserted
+   * as is, or if getSuggestions was used rather than getSuggestions2.
+   */
+  private final Integer libraryUriToImportIndex;
+
+  /**
    * Constructor for {@link CompletionSuggestion}.
    */
-  public CompletionSuggestion(String kind, int relevance, String completion, String displayText, Integer replacementOffset, Integer replacementLength, int selectionOffset, int selectionLength, boolean isDeprecated, boolean isPotential, String docSummary, String docComplete, String declaringType, String defaultArgumentListString, int[] defaultArgumentListTextRanges, Element element, String returnType, List<String> parameterNames, List<String> parameterTypes, Integer requiredParameterCount, Boolean hasNamedParameters, String parameterName, String parameterType) {
+  public CompletionSuggestion(String kind, int relevance, String completion, String displayText, Integer replacementOffset, Integer replacementLength, int selectionOffset, int selectionLength, boolean isDeprecated, boolean isPotential, String docSummary, String docComplete, String declaringType, String defaultArgumentListString, int[] defaultArgumentListTextRanges, Element element, String returnType, List<String> parameterNames, List<String> parameterTypes, Integer requiredParameterCount, Boolean hasNamedParameters, String parameterName, String parameterType, Integer libraryUriToImportIndex) {
     this.kind = kind;
     this.relevance = relevance;
     this.completion = completion;
@@ -202,6 +211,7 @@
     this.hasNamedParameters = hasNamedParameters;
     this.parameterName = parameterName;
     this.parameterType = parameterType;
+    this.libraryUriToImportIndex = libraryUriToImportIndex;
   }
 
   @Override
@@ -231,7 +241,8 @@
         ObjectUtilities.equals(other.requiredParameterCount, requiredParameterCount) &&
         ObjectUtilities.equals(other.hasNamedParameters, hasNamedParameters) &&
         ObjectUtilities.equals(other.parameterName, parameterName) &&
-        ObjectUtilities.equals(other.parameterType, parameterType);
+        ObjectUtilities.equals(other.parameterType, parameterType) &&
+        ObjectUtilities.equals(other.libraryUriToImportIndex, libraryUriToImportIndex);
     }
     return false;
   }
@@ -260,7 +271,8 @@
     Boolean hasNamedParameters = jsonObject.get("hasNamedParameters") == null ? null : jsonObject.get("hasNamedParameters").getAsBoolean();
     String parameterName = jsonObject.get("parameterName") == null ? null : jsonObject.get("parameterName").getAsString();
     String parameterType = jsonObject.get("parameterType") == null ? null : jsonObject.get("parameterType").getAsString();
-    return new CompletionSuggestion(kind, relevance, completion, displayText, replacementOffset, replacementLength, selectionOffset, selectionLength, isDeprecated, isPotential, docSummary, docComplete, declaringType, defaultArgumentListString, defaultArgumentListTextRanges, element, returnType, parameterNames, parameterTypes, requiredParameterCount, hasNamedParameters, parameterName, parameterType);
+    Integer libraryUriToImportIndex = jsonObject.get("libraryUriToImportIndex") == null ? null : jsonObject.get("libraryUriToImportIndex").getAsInt();
+    return new CompletionSuggestion(kind, relevance, completion, displayText, replacementOffset, replacementLength, selectionOffset, selectionLength, isDeprecated, isPotential, docSummary, docComplete, declaringType, defaultArgumentListString, defaultArgumentListTextRanges, element, returnType, parameterNames, parameterTypes, requiredParameterCount, hasNamedParameters, parameterName, parameterType, libraryUriToImportIndex);
   }
 
   public static List<CompletionSuggestion> fromJsonArray(JsonArray jsonArray) {
@@ -372,6 +384,17 @@
   }
 
   /**
+   * The index in the list of libraries that could be imported to make this suggestion accessible in
+   * the file where completion was requested. The server provides this list of libraries together
+   * with suggestions, so that information about the library can be shared for multiple suggestions.
+   * This field is omitted if the library is already imported, so that the suggestion can be inserted
+   * as is, or if getSuggestions was used rather than getSuggestions2.
+   */
+  public Integer getLibraryUriToImportIndex() {
+    return libraryUriToImportIndex;
+  }
+
+  /**
    * The name of the optional parameter being suggested. This field is omitted if the suggestion is
    * not the addition of an optional argument within an argument list.
    */
@@ -486,6 +509,7 @@
     builder.append(hasNamedParameters);
     builder.append(parameterName);
     builder.append(parameterType);
+    builder.append(libraryUriToImportIndex);
     return builder.toHashCode();
   }
 
@@ -558,6 +582,9 @@
     if (parameterType != null) {
       jsonObject.addProperty("parameterType", parameterType);
     }
+    if (libraryUriToImportIndex != null) {
+      jsonObject.addProperty("libraryUriToImportIndex", libraryUriToImportIndex);
+    }
     return jsonObject;
   }
 
@@ -610,7 +637,9 @@
     builder.append("parameterName=");
     builder.append(parameterName + ", ");
     builder.append("parameterType=");
-    builder.append(parameterType);
+    builder.append(parameterType + ", ");
+    builder.append("libraryUriToImportIndex=");
+    builder.append(libraryUriToImportIndex);
     builder.append("]");
     return builder.toString();
   }
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index 7bb2fe0..aa08d74 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -1455,6 +1455,100 @@
       </field>
     </result>
   </request>
+  <request method="getSuggestions2" experimental="true">
+    <p>
+      Request that completion suggestions for the given offset in the given
+      file be returned. The suggestions will be filtered using fuzzy matching
+      with the already existing prefix.
+    </p>
+    <params>
+      <field name="file">
+        <ref>FilePath</ref>
+        <p>
+          The file containing the point at which suggestions are to be made.
+        </p>
+      </field>
+      <field name="offset">
+        <ref>int</ref>
+        <p>
+          The offset within the file at which suggestions are to be made.
+        </p>
+      </field>
+      <field name="maxResults">
+        <ref>int</ref>
+        <p>
+          The maximum number of suggestions to return. If the number of
+          suggestions after filtering is greater than the <tt>maxResults</tt>,
+          then <tt>isIncomplete</tt> is set to <tt>true</tt>.
+        </p>
+      </field>
+    </params>
+    <result>
+      <field name="replacementOffset">
+        <ref>int</ref>
+        <p>
+          The offset of the start of the text to be  replaced. This will be
+          different from the offset used  to request the completion suggestions
+          if there was a portion of an identifier before the original offset.
+          In particular, the replacementOffset will be the offset of the
+          beginning of said identifier.
+        </p>
+      </field>
+      <field name="replacementLength">
+        <ref>int</ref>
+        <p>
+          The length of the text to be replaced if the remainder of the
+          identifier containing the cursor is to be replaced when the
+          suggestion is applied (that is, the number of characters in the
+          existing identifier).
+        </p>
+      </field>
+      <field name="suggestions">
+        <list>
+          <ref>CompletionSuggestion</ref>
+        </list>
+        <p>
+          The completion suggestions being reported. This list is filtered
+          by the already existing prefix, and sorted first by relevance,
+          and (if the same) by the suggestion text. The list will have at
+          most <tt>maxResults</tt> items. If the user types a new keystroke,
+          the client is expected to either do local filtering (when the
+          returned list was complete), or ask the server again (if
+          <tt>isIncomplete</tt> was <tt>true</tt>).
+        </p>
+        <p>
+          This list contains suggestions from both imported, and not yet
+          imported libraries. Items from not yet imported libraries will
+          have <tt>libraryUriToImportIndex</tt> set, which is an index into
+          the <tt>libraryUrisToImport</tt> in this response.
+        </p>
+      </field>
+      <field name="libraryUrisToImport">
+        <list>
+          <ref>String</ref>
+        </list>
+        <p>
+          The list of libraries with declarations that are not yet available
+          in the file where completion was requested, most often because
+          the library is not yet imported. The declarations still might be
+          included into the <tt>suggestions</tt>, and the client should use
+          <tt>getSuggestionDetails2</tt> on selection to make the library
+          available in the file.
+        </p>
+        <p>
+          Each item is the URI of a library, such as <tt>package:foo/bar.dart</tt>
+          or <tt>file:///home/me/workspace/foo/test/bar_test.dart</tt>.
+        </p>
+      </field>
+      <field name="isIncomplete">
+        <ref>bool</ref>
+        <p>
+          True if the number of suggestions after filtering was greater than
+          the requested <tt>maxResults</tt>.
+        </p>
+      </field>
+    </result>
+  </request>
   <request method="setSubscriptions">
     <p>
       Subscribe for completion services. All previous subscriptions are
@@ -1551,6 +1645,66 @@
       </field>
     </result>
   </request>
+  <request method="getSuggestionDetails2" experimental="true">
+    <p>
+      Clients must make this request when the user has selected a completion
+      suggestion with the <tt>libraryUriToImportIndex</tt> field set.
+      The server will respond with the text to insert, as well as any
+      <tt>SourceChange</tt> that needs to be applied in case the completion
+      requires an additional import to be  added. The text to insert might be
+      different from the original suggestion to include an import prefix if the
+      library will be imported with a prefix to avoid shadowing
+      conflicts in the file.
+    </p>
+    <params>
+      <field name="file">
+        <ref>FilePath</ref>
+        <p>
+          The path of the file into which this completion is being inserted.
+        </p>
+      </field>
+      <field name="offset">
+        <ref>int</ref>
+        <p>
+          The offset in the file where the completion will be inserted.
+        </p>
+      </field>
+      <field name="completion">
+        <ref>String</ref>
+        <p>
+          The <tt>completion</tt> from the selected
+          <tt>CompletionSuggestion</tt>.  It could be a name of a class, or a
+          name of a constructor in form "typeName.constructorName()", or an
+          enumeration constant in form "enumName.constantName", etc.
+        </p>
+      </field>
+      <field name="libraryUri">
+        <ref>String</ref>
+        <p>
+          The URI of the library to import, so that the element referenced
+          in the <tt>completion</tt> becomes accessible.
+        </p>
+      </field>
+    </params>
+    <result>
+      <field name="completion">
+        <ref>String</ref>
+        <p>
+          The full text to insert, which possibly includes now an import prefix.
+          The client should insert this text, not the <tt>completion</tt> from
+          the selected <tt>CompletionSuggestion</tt>.
+        </p>
+      </field>
+      <field name="change">
+        <ref>SourceChange</ref>
+        <p>
+          A change for the client to apply to make the accepted completion
+          suggestion available. In most cases the change is to add a new
+          import directive to the file.
+        </p>
+      </field>
+    </result>
+  </request>
   <notification event="results">
     <p>
       Reports the completion suggestions that should be presented
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
index 4289f41..b2d7548 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_common.dart
@@ -612,6 +612,15 @@
   /// if the parameterName field is omitted.
   String? parameterType;
 
+  /// The index in the list of libraries that could be imported to make this
+  /// suggestion accessible in the file where completion was requested. The
+  /// server provides this list of libraries together with suggestions, so that
+  /// information about the library can be shared for multiple suggestions.
+  /// This field is omitted if the library is already imported, so that the
+  /// suggestion can be inserted as is, or if getSuggestions was used rather
+  /// than getSuggestions2.
+  int? libraryUriToImportIndex;
+
   CompletionSuggestion(
       this.kind,
       this.relevance,
@@ -635,7 +644,8 @@
       this.requiredParameterCount,
       this.hasNamedParameters,
       this.parameterName,
-      this.parameterType});
+      this.parameterType,
+      this.libraryUriToImportIndex});
 
   factory CompletionSuggestion.fromJson(
       JsonDecoder jsonDecoder, String jsonPath, Object? json) {
@@ -774,6 +784,12 @@
         parameterType = jsonDecoder.decodeString(
             jsonPath + '.parameterType', json['parameterType']);
       }
+      int? libraryUriToImportIndex;
+      if (json.containsKey('libraryUriToImportIndex')) {
+        libraryUriToImportIndex = jsonDecoder.decodeInt(
+            jsonPath + '.libraryUriToImportIndex',
+            json['libraryUriToImportIndex']);
+      }
       return CompletionSuggestion(kind, relevance, completion, selectionOffset,
           selectionLength, isDeprecated, isPotential,
           displayText: displayText,
@@ -791,7 +807,8 @@
           requiredParameterCount: requiredParameterCount,
           hasNamedParameters: hasNamedParameters,
           parameterName: parameterName,
-          parameterType: parameterType);
+          parameterType: parameterType,
+          libraryUriToImportIndex: libraryUriToImportIndex);
     } else {
       throw jsonDecoder.mismatch(jsonPath, 'CompletionSuggestion', json);
     }
@@ -871,6 +888,10 @@
     if (parameterType != null) {
       result['parameterType'] = parameterType;
     }
+    var libraryUriToImportIndex = this.libraryUriToImportIndex;
+    if (libraryUriToImportIndex != null) {
+      result['libraryUriToImportIndex'] = libraryUriToImportIndex;
+    }
     return result;
   }
 
@@ -905,7 +926,8 @@
           requiredParameterCount == other.requiredParameterCount &&
           hasNamedParameters == other.hasNamedParameters &&
           parameterName == other.parameterName &&
-          parameterType == other.parameterType;
+          parameterType == other.parameterType &&
+          libraryUriToImportIndex == other.libraryUriToImportIndex;
     }
     return false;
   }
@@ -935,6 +957,7 @@
         hasNamedParameters,
         parameterName,
         parameterType,
+        libraryUriToImportIndex,
       ]);
 }
 
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
index 84b3a5c..2689506 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
@@ -137,10 +137,22 @@
     'replacementOffset';
 const String COMPLETION_NOTIFICATION_RESULTS_RESULTS = 'results';
 const String COMPLETION_REQUEST_GET_SUGGESTIONS = 'completion.getSuggestions';
+const String COMPLETION_REQUEST_GET_SUGGESTIONS2 = 'completion.getSuggestions2';
+const String COMPLETION_REQUEST_GET_SUGGESTIONS2_FILE = 'file';
+const String COMPLETION_REQUEST_GET_SUGGESTIONS2_MAX_RESULTS = 'maxResults';
+const String COMPLETION_REQUEST_GET_SUGGESTIONS2_OFFSET = 'offset';
 const String COMPLETION_REQUEST_GET_SUGGESTIONS_FILE = 'file';
 const String COMPLETION_REQUEST_GET_SUGGESTIONS_OFFSET = 'offset';
 const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS =
     'completion.getSuggestionDetails';
+const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS2 =
+    'completion.getSuggestionDetails2';
+const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS2_COMPLETION =
+    'completion';
+const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS2_FILE = 'file';
+const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS2_LIBRARY_URI =
+    'libraryUri';
+const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS2_OFFSET = 'offset';
 const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS_FILE = 'file';
 const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS_ID = 'id';
 const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS_LABEL = 'label';
@@ -152,7 +164,19 @@
     'completion.setSubscriptions';
 const String COMPLETION_REQUEST_SET_SUBSCRIPTIONS_SUBSCRIPTIONS =
     'subscriptions';
+const String COMPLETION_RESPONSE_GET_SUGGESTIONS2_IS_INCOMPLETE =
+    'isIncomplete';
+const String COMPLETION_RESPONSE_GET_SUGGESTIONS2_LIBRARY_URIS_TO_IMPORT =
+    'libraryUrisToImport';
+const String COMPLETION_RESPONSE_GET_SUGGESTIONS2_REPLACEMENT_LENGTH =
+    'replacementLength';
+const String COMPLETION_RESPONSE_GET_SUGGESTIONS2_REPLACEMENT_OFFSET =
+    'replacementOffset';
+const String COMPLETION_RESPONSE_GET_SUGGESTIONS2_SUGGESTIONS = 'suggestions';
 const String COMPLETION_RESPONSE_GET_SUGGESTIONS_ID = 'id';
+const String COMPLETION_RESPONSE_GET_SUGGESTION_DETAILS2_CHANGE = 'change';
+const String COMPLETION_RESPONSE_GET_SUGGESTION_DETAILS2_COMPLETION =
+    'completion';
 const String COMPLETION_RESPONSE_GET_SUGGESTION_DETAILS_CHANGE = 'change';
 const String COMPLETION_RESPONSE_GET_SUGGESTION_DETAILS_COMPLETION =
     'completion';
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
index 616ff13..2dcbd32 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
@@ -4292,6 +4292,202 @@
       );
 }
 
+/// completion.getSuggestionDetails2 params
+///
+/// {
+///   "file": FilePath
+///   "offset": int
+///   "completion": String
+///   "libraryUri": String
+/// }
+///
+/// Clients may not extend, implement or mix-in this class.
+class CompletionGetSuggestionDetails2Params implements RequestParams {
+  /// The path of the file into which this completion is being inserted.
+  String file;
+
+  /// The offset in the file where the completion will be inserted.
+  int offset;
+
+  /// The completion from the selected CompletionSuggestion. It could be a name
+  /// of a class, or a name of a constructor in form
+  /// "typeName.constructorName()", or an enumeration constant in form
+  /// "enumName.constantName", etc.
+  String completion;
+
+  /// The URI of the library to import, so that the element referenced in the
+  /// completion becomes accessible.
+  String libraryUri;
+
+  CompletionGetSuggestionDetails2Params(
+      this.file, this.offset, this.completion, this.libraryUri);
+
+  factory CompletionGetSuggestionDetails2Params.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object? json) {
+    json ??= {};
+    if (json is Map) {
+      String file;
+      if (json.containsKey('file')) {
+        file = jsonDecoder.decodeString(jsonPath + '.file', json['file']);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, 'file');
+      }
+      int offset;
+      if (json.containsKey('offset')) {
+        offset = jsonDecoder.decodeInt(jsonPath + '.offset', json['offset']);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, 'offset');
+      }
+      String completion;
+      if (json.containsKey('completion')) {
+        completion = jsonDecoder.decodeString(
+            jsonPath + '.completion', json['completion']);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, 'completion');
+      }
+      String libraryUri;
+      if (json.containsKey('libraryUri')) {
+        libraryUri = jsonDecoder.decodeString(
+            jsonPath + '.libraryUri', json['libraryUri']);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, 'libraryUri');
+      }
+      return CompletionGetSuggestionDetails2Params(
+          file, offset, completion, libraryUri);
+    } else {
+      throw jsonDecoder.mismatch(
+          jsonPath, 'completion.getSuggestionDetails2 params', json);
+    }
+  }
+
+  factory CompletionGetSuggestionDetails2Params.fromRequest(Request request) {
+    return CompletionGetSuggestionDetails2Params.fromJson(
+        RequestDecoder(request), 'params', request.params);
+  }
+
+  @override
+  Map<String, Object> toJson() {
+    var result = <String, Object>{};
+    result['file'] = file;
+    result['offset'] = offset;
+    result['completion'] = completion;
+    result['libraryUri'] = libraryUri;
+    return result;
+  }
+
+  @override
+  Request toRequest(String id) {
+    return Request(id, 'completion.getSuggestionDetails2', toJson());
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is CompletionGetSuggestionDetails2Params) {
+      return file == other.file &&
+          offset == other.offset &&
+          completion == other.completion &&
+          libraryUri == other.libraryUri;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode => Object.hash(
+        file,
+        offset,
+        completion,
+        libraryUri,
+      );
+}
+
+/// completion.getSuggestionDetails2 result
+///
+/// {
+///   "completion": String
+///   "change": SourceChange
+/// }
+///
+/// Clients may not extend, implement or mix-in this class.
+class CompletionGetSuggestionDetails2Result implements ResponseResult {
+  /// The full text to insert, which possibly includes now an import prefix.
+  /// The client should insert this text, not the completion from the selected
+  /// CompletionSuggestion.
+  String completion;
+
+  /// A change for the client to apply to make the accepted completion
+  /// suggestion available. In most cases the change is to add a new import
+  /// directive to the file.
+  SourceChange change;
+
+  CompletionGetSuggestionDetails2Result(this.completion, this.change);
+
+  factory CompletionGetSuggestionDetails2Result.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object? json) {
+    json ??= {};
+    if (json is Map) {
+      String completion;
+      if (json.containsKey('completion')) {
+        completion = jsonDecoder.decodeString(
+            jsonPath + '.completion', json['completion']);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, 'completion');
+      }
+      SourceChange change;
+      if (json.containsKey('change')) {
+        change = SourceChange.fromJson(
+            jsonDecoder, jsonPath + '.change', json['change']);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, 'change');
+      }
+      return CompletionGetSuggestionDetails2Result(completion, change);
+    } else {
+      throw jsonDecoder.mismatch(
+          jsonPath, 'completion.getSuggestionDetails2 result', json);
+    }
+  }
+
+  factory CompletionGetSuggestionDetails2Result.fromResponse(
+      Response response) {
+    return CompletionGetSuggestionDetails2Result.fromJson(
+        ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
+        'result',
+        response.result);
+  }
+
+  @override
+  Map<String, Object> toJson() {
+    var result = <String, Object>{};
+    result['completion'] = completion;
+    result['change'] = change.toJson();
+    return result;
+  }
+
+  @override
+  Response toResponse(String id) {
+    return Response(id, result: toJson());
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is CompletionGetSuggestionDetails2Result) {
+      return completion == other.completion && change == other.change;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode => Object.hash(
+        completion,
+        change,
+      );
+}
+
 /// completion.getSuggestionDetails params
 ///
 /// {
@@ -4481,6 +4677,261 @@
       );
 }
 
+/// completion.getSuggestions2 params
+///
+/// {
+///   "file": FilePath
+///   "offset": int
+///   "maxResults": int
+/// }
+///
+/// Clients may not extend, implement or mix-in this class.
+class CompletionGetSuggestions2Params implements RequestParams {
+  /// The file containing the point at which suggestions are to be made.
+  String file;
+
+  /// The offset within the file at which suggestions are to be made.
+  int offset;
+
+  /// The maximum number of suggestions to return. If the number of suggestions
+  /// after filtering is greater than the maxResults, then isIncomplete is set
+  /// to true.
+  int maxResults;
+
+  CompletionGetSuggestions2Params(this.file, this.offset, this.maxResults);
+
+  factory CompletionGetSuggestions2Params.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object? json) {
+    json ??= {};
+    if (json is Map) {
+      String file;
+      if (json.containsKey('file')) {
+        file = jsonDecoder.decodeString(jsonPath + '.file', json['file']);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, 'file');
+      }
+      int offset;
+      if (json.containsKey('offset')) {
+        offset = jsonDecoder.decodeInt(jsonPath + '.offset', json['offset']);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, 'offset');
+      }
+      int maxResults;
+      if (json.containsKey('maxResults')) {
+        maxResults =
+            jsonDecoder.decodeInt(jsonPath + '.maxResults', json['maxResults']);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, 'maxResults');
+      }
+      return CompletionGetSuggestions2Params(file, offset, maxResults);
+    } else {
+      throw jsonDecoder.mismatch(
+          jsonPath, 'completion.getSuggestions2 params', json);
+    }
+  }
+
+  factory CompletionGetSuggestions2Params.fromRequest(Request request) {
+    return CompletionGetSuggestions2Params.fromJson(
+        RequestDecoder(request), 'params', request.params);
+  }
+
+  @override
+  Map<String, Object> toJson() {
+    var result = <String, Object>{};
+    result['file'] = file;
+    result['offset'] = offset;
+    result['maxResults'] = maxResults;
+    return result;
+  }
+
+  @override
+  Request toRequest(String id) {
+    return Request(id, 'completion.getSuggestions2', toJson());
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is CompletionGetSuggestions2Params) {
+      return file == other.file &&
+          offset == other.offset &&
+          maxResults == other.maxResults;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode => Object.hash(
+        file,
+        offset,
+        maxResults,
+      );
+}
+
+/// completion.getSuggestions2 result
+///
+/// {
+///   "replacementOffset": int
+///   "replacementLength": int
+///   "suggestions": List<CompletionSuggestion>
+///   "libraryUrisToImport": List<String>
+///   "isIncomplete": bool
+/// }
+///
+/// Clients may not extend, implement or mix-in this class.
+class CompletionGetSuggestions2Result implements ResponseResult {
+  /// The offset of the start of the text to be replaced. This will be
+  /// different from the offset used to request the completion suggestions if
+  /// there was a portion of an identifier before the original offset. In
+  /// particular, the replacementOffset will be the offset of the beginning of
+  /// said identifier.
+  int replacementOffset;
+
+  /// The length of the text to be replaced if the remainder of the identifier
+  /// containing the cursor is to be replaced when the suggestion is applied
+  /// (that is, the number of characters in the existing identifier).
+  int replacementLength;
+
+  /// The completion suggestions being reported. This list is filtered by the
+  /// already existing prefix, and sorted first by relevance, and (if the same)
+  /// by the suggestion text. The list will have at most maxResults items. If
+  /// the user types a new keystroke, the client is expected to either do local
+  /// filtering (when the returned list was complete), or ask the server again
+  /// (if isIncomplete was true).
+  ///
+  /// This list contains suggestions from both imported, and not yet imported
+  /// libraries. Items from not yet imported libraries will have
+  /// libraryUriToImportIndex set, which is an index into the
+  /// libraryUrisToImport in this response.
+  List<CompletionSuggestion> suggestions;
+
+  /// The list of libraries with declarations that are not yet available in the
+  /// file where completion was requested, most often because the library is
+  /// not yet imported. The declarations still might be included into the
+  /// suggestions, and the client should use getSuggestionDetails2 on selection
+  /// to make the library available in the file.
+  ///
+  /// Each item is the URI of a library, such as package:foo/bar.dart or
+  /// file:///home/me/workspace/foo/test/bar_test.dart.
+  List<String> libraryUrisToImport;
+
+  /// True if the number of suggestions after filtering was greater than the
+  /// requested maxResults.
+  bool isIncomplete;
+
+  CompletionGetSuggestions2Result(
+      this.replacementOffset,
+      this.replacementLength,
+      this.suggestions,
+      this.libraryUrisToImport,
+      this.isIncomplete);
+
+  factory CompletionGetSuggestions2Result.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object? json) {
+    json ??= {};
+    if (json is Map) {
+      int replacementOffset;
+      if (json.containsKey('replacementOffset')) {
+        replacementOffset = jsonDecoder.decodeInt(
+            jsonPath + '.replacementOffset', json['replacementOffset']);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, 'replacementOffset');
+      }
+      int replacementLength;
+      if (json.containsKey('replacementLength')) {
+        replacementLength = jsonDecoder.decodeInt(
+            jsonPath + '.replacementLength', json['replacementLength']);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, 'replacementLength');
+      }
+      List<CompletionSuggestion> suggestions;
+      if (json.containsKey('suggestions')) {
+        suggestions = jsonDecoder.decodeList(
+            jsonPath + '.suggestions',
+            json['suggestions'],
+            (String jsonPath, Object? json) =>
+                CompletionSuggestion.fromJson(jsonDecoder, jsonPath, json));
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, 'suggestions');
+      }
+      List<String> libraryUrisToImport;
+      if (json.containsKey('libraryUrisToImport')) {
+        libraryUrisToImport = jsonDecoder.decodeList(
+            jsonPath + '.libraryUrisToImport',
+            json['libraryUrisToImport'],
+            jsonDecoder.decodeString);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, 'libraryUrisToImport');
+      }
+      bool isIncomplete;
+      if (json.containsKey('isIncomplete')) {
+        isIncomplete = jsonDecoder.decodeBool(
+            jsonPath + '.isIncomplete', json['isIncomplete']);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, 'isIncomplete');
+      }
+      return CompletionGetSuggestions2Result(replacementOffset,
+          replacementLength, suggestions, libraryUrisToImport, isIncomplete);
+    } else {
+      throw jsonDecoder.mismatch(
+          jsonPath, 'completion.getSuggestions2 result', json);
+    }
+  }
+
+  factory CompletionGetSuggestions2Result.fromResponse(Response response) {
+    return CompletionGetSuggestions2Result.fromJson(
+        ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
+        'result',
+        response.result);
+  }
+
+  @override
+  Map<String, Object> toJson() {
+    var result = <String, Object>{};
+    result['replacementOffset'] = replacementOffset;
+    result['replacementLength'] = replacementLength;
+    result['suggestions'] = suggestions
+        .map((CompletionSuggestion value) => value.toJson())
+        .toList();
+    result['libraryUrisToImport'] = libraryUrisToImport;
+    result['isIncomplete'] = isIncomplete;
+    return result;
+  }
+
+  @override
+  Response toResponse(String id) {
+    return Response(id, result: toJson());
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is CompletionGetSuggestions2Result) {
+      return replacementOffset == other.replacementOffset &&
+          replacementLength == other.replacementLength &&
+          listEqual(suggestions, other.suggestions,
+              (CompletionSuggestion a, CompletionSuggestion b) => a == b) &&
+          listEqual(libraryUrisToImport, other.libraryUrisToImport,
+              (String a, String b) => a == b) &&
+          isIncomplete == other.isIncomplete;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode => Object.hash(
+        replacementOffset,
+        replacementLength,
+        suggestions,
+        libraryUrisToImport,
+        isIncomplete,
+      );
+}
+
 /// completion.getSuggestions params
 ///
 /// {
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 0c9499c..557a2e8 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -80,7 +80,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 = 189;
+  static const int DATA_VERSION = 190;
 
   /// 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/dart/analysis/experiments.g.dart b/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
index e4c3cc4..ce99ad0 100644
--- a/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/experiments.g.dart
@@ -28,6 +28,7 @@
       ExperimentalFeatures.nonfunction_type_aliases,
   EnableString.set_literals: ExperimentalFeatures.set_literals,
   EnableString.spread_collections: ExperimentalFeatures.spread_collections,
+  EnableString.super_parameters: ExperimentalFeatures.super_parameters,
   EnableString.test_experiment: ExperimentalFeatures.test_experiment,
   EnableString.triple_shift: ExperimentalFeatures.triple_shift,
   EnableString.value_class: ExperimentalFeatures.value_class,
@@ -76,6 +77,9 @@
   /// String to enable the experiment "spread-collections"
   static const String spread_collections = 'spread-collections';
 
+  /// String to enable the experiment "super-parameters"
+  static const String super_parameters = 'super-parameters';
+
   /// String to enable the experiment "test-experiment"
   static const String test_experiment = 'test-experiment';
 
@@ -223,8 +227,18 @@
     releaseVersion: Version.parse('2.0.0'),
   );
 
-  static final test_experiment = ExperimentalFeature(
+  static final super_parameters = ExperimentalFeature(
     index: 13,
+    enableString: EnableString.super_parameters,
+    isEnabledByDefault: IsEnabledByDefault.super_parameters,
+    isExpired: IsExpired.super_parameters,
+    documentation: 'Super-Initializer Parameters',
+    experimentalReleaseVersion: null,
+    releaseVersion: null,
+  );
+
+  static final test_experiment = ExperimentalFeature(
+    index: 14,
     enableString: EnableString.test_experiment,
     isEnabledByDefault: IsEnabledByDefault.test_experiment,
     isExpired: IsExpired.test_experiment,
@@ -235,7 +249,7 @@
   );
 
   static final triple_shift = ExperimentalFeature(
-    index: 14,
+    index: 15,
     enableString: EnableString.triple_shift,
     isEnabledByDefault: IsEnabledByDefault.triple_shift,
     isExpired: IsExpired.triple_shift,
@@ -245,7 +259,7 @@
   );
 
   static final value_class = ExperimentalFeature(
-    index: 15,
+    index: 16,
     enableString: EnableString.value_class,
     isEnabledByDefault: IsEnabledByDefault.value_class,
     isExpired: IsExpired.value_class,
@@ -255,7 +269,7 @@
   );
 
   static final variance = ExperimentalFeature(
-    index: 16,
+    index: 17,
     enableString: EnableString.variance,
     isEnabledByDefault: IsEnabledByDefault.variance,
     isExpired: IsExpired.variance,
@@ -307,6 +321,9 @@
   /// Default state of the experiment "spread-collections"
   static const bool spread_collections = true;
 
+  /// Default state of the experiment "super-parameters"
+  static const bool super_parameters = false;
+
   /// Default state of the experiment "test-experiment"
   static const bool test_experiment = false;
 
@@ -363,6 +380,9 @@
   /// Expiration status of the experiment "spread-collections"
   static const bool spread_collections = true;
 
+  /// Expiration status of the experiment "super-parameters"
+  static const bool super_parameters = false;
+
   /// Expiration status of the experiment "test-experiment"
   static const bool test_experiment = false;
 
@@ -423,6 +443,9 @@
   bool get spread_collections =>
       isEnabled(ExperimentalFeatures.spread_collections);
 
+  /// Current state for the flag "super-parameters"
+  bool get super_parameters => isEnabled(ExperimentalFeatures.super_parameters);
+
   /// Current state for the flag "test-experiment"
   bool get test_experiment => isEnabled(ExperimentalFeatures.test_experiment);
 
diff --git a/pkg/analyzer/lib/src/dart/ast/to_source_visitor.dart b/pkg/analyzer/lib/src/dart/ast/to_source_visitor.dart
index c32bd06..f9ac572 100644
--- a/pkg/analyzer/lib/src/dart/ast/to_source_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/ast/to_source_visitor.dart
@@ -54,7 +54,7 @@
       sink.write(', ');
       _visitNode(node.message);
     }
-    sink.write(');');
+    sink.write(')');
   }
 
   @override
@@ -565,6 +565,7 @@
     _visitNode(node.typeParameters);
     sink.write(' = ');
     _visitNode(node.type);
+    sink.write(';');
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index 17fa3c2..7561115 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -310,168 +310,6 @@
     }
   }
 
-  /// Compares two function types [t] and [s] to see if their corresponding
-  /// parameter types match [parameterRelation], return types match
-  /// [returnRelation], and type parameter bounds match [boundsRelation].
-  ///
-  /// Used for the various relations on function types which have the same
-  /// structural rules for handling optional parameters and arity, but use their
-  /// own relation for comparing corresponding parameters or return types.
-  ///
-  /// If [parameterRelation] is omitted, uses [returnRelation] for both. This
-  /// is convenient for Dart 1 type system methods.
-  ///
-  /// If [boundsRelation] is omitted, uses [returnRelation]. This is for
-  /// backwards compatibility, and convenience for Dart 1 type system methods.
-  static bool relate(FunctionType t, DartType? other,
-      bool Function(DartType t, DartType s) returnRelation,
-      {bool Function(ParameterElement t, ParameterElement s)? parameterRelation,
-      bool Function(DartType bound2, DartType bound1,
-              TypeParameterElement formal2, TypeParameterElement formal1)?
-          boundsRelation}) {
-    parameterRelation ??= (t, s) => returnRelation(t.type, s.type);
-    boundsRelation ??= (t, s, _, __) => returnRelation(t, s);
-
-    // Trivial base cases.
-    if (other == null) {
-      return false;
-    } else if (identical(t, other) ||
-        other.isDynamic ||
-        other.isDartCoreFunction ||
-        other.isDartCoreObject) {
-      return true;
-    } else if (other is! FunctionType) {
-      return false;
-    }
-
-    // This type cast is safe, because we checked it above.
-    FunctionType s = other;
-    if (t.typeFormals.isNotEmpty) {
-      var freshVariables = relateTypeFormals(t, s, boundsRelation);
-      if (freshVariables == null) {
-        return false;
-      }
-      t = t.instantiate(freshVariables);
-      s = s.instantiate(freshVariables);
-    } else if (s.typeFormals.isNotEmpty) {
-      return false;
-    }
-
-    // Test the return types.
-    DartType sRetType = s.returnType;
-    if (!sRetType.isVoid && !returnRelation(t.returnType, sRetType)) {
-      return false;
-    }
-
-    // Test the parameter types.
-    return relateParameters(t.parameters, s.parameters, parameterRelation);
-  }
-
-  /// Compares parameters [tParams] and [sParams] of two function types, taking
-  /// corresponding parameters from the lists, and see if they match
-  /// [parameterRelation].
-  ///
-  /// Corresponding parameters are defined as a pair `(t, s)` where `t` is a
-  /// parameter from [tParams] and `s` is a parameter from [sParams], and both
-  /// `t` and `s` are at the same position (for positional parameters)
-  /// or have the same name (for named parameters).
-  ///
-  /// Used for the various relations on function types which have the same
-  /// structural rules for handling optional parameters and arity, but use their
-  /// own relation for comparing the parameters.
-  static bool relateParameters(
-      List<ParameterElement> tParams,
-      List<ParameterElement> sParams,
-      bool Function(ParameterElement t, ParameterElement s) parameterRelation) {
-    // TODO(jmesserly): this could be implemented with less allocation if we
-    // wanted, by taking advantage of the fact that positional arguments must
-    // appear before named ones.
-    var tRequired = <ParameterElement>[];
-    var tOptional = <ParameterElement>[];
-    var tNamed = <String, ParameterElement>{};
-    for (var p in tParams) {
-      if (p.isRequiredPositional) {
-        tRequired.add(p);
-      } else if (p.isOptionalPositional) {
-        tOptional.add(p);
-      } else {
-        assert(p.isNamed);
-        tNamed[p.name] = p;
-      }
-    }
-
-    var sRequired = <ParameterElement>[];
-    var sOptional = <ParameterElement>[];
-    var sNamed = <String, ParameterElement>{};
-    for (var p in sParams) {
-      if (p.isRequiredPositional) {
-        sRequired.add(p);
-      } else if (p.isOptionalPositional) {
-        sOptional.add(p);
-      } else {
-        assert(p.isNamed);
-        sNamed[p.name] = p;
-      }
-    }
-
-    // If one function has positional and the other has named parameters,
-    // they don't relate.
-    if (sOptional.isNotEmpty && tNamed.isNotEmpty ||
-        tOptional.isNotEmpty && sNamed.isNotEmpty) {
-      return false;
-    }
-
-    // If the passed function includes more named parameters than we do, we
-    // don't relate.
-    if (tNamed.length < sNamed.length) {
-      return false;
-    }
-
-    // For each named parameter in s, make sure we have a corresponding one
-    // that relates.
-    for (String key in sNamed.keys) {
-      var tParam = tNamed[key];
-      if (tParam == null) {
-        return false;
-      }
-      var sParam = sNamed[key]!;
-      if (!parameterRelation(tParam, sParam)) {
-        return false;
-      }
-    }
-
-    // Make sure all of the positional parameters (both required and optional)
-    // relate to each other.
-    var tPositional = tRequired;
-    var sPositional = sRequired;
-
-    if (tOptional.isNotEmpty) {
-      tPositional = tPositional.toList()..addAll(tOptional);
-    }
-
-    if (sOptional.isNotEmpty) {
-      sPositional = sPositional.toList()..addAll(sOptional);
-    }
-
-    // Check that s has enough required parameters.
-    if (sRequired.length < tRequired.length) {
-      return false;
-    }
-
-    // Check that s does not include more positional parameters than we do.
-    if (tPositional.length < sPositional.length) {
-      return false;
-    }
-
-    for (int i = 0; i < sPositional.length; i++) {
-      if (!parameterRelation(tPositional[i], sPositional[i])) {
-        return false;
-      }
-    }
-
-    return true;
-  }
-
   /// Given two functions [f1] and [f2] where f1 and f2 are known to be
   /// generic function types (both have type formals), this checks that they
   /// have the same number of formals, and that those formals have bounds
diff --git a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
index 74e80c2..3833cc9 100644
--- a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
@@ -33,10 +33,6 @@
     return rootReference.getChild('dart:core').getChild('dynamic');
   }
 
-  bool get hasDartCore {
-    return _libraryReaders.containsKey('dart:core');
-  }
-
   void addBundle(BundleReader bundle) {
     addLibraries(bundle.libraryMap);
   }
@@ -161,6 +157,11 @@
   }
 
   bool hasLibrary(String uriStr) {
+    // We already have the element, linked or read.
+    if (rootReference[uriStr]?.element is LibraryElementImpl) {
+      return true;
+    }
+    // No element yet, but we know how to read it.
     return _libraryReaders[uriStr] != null;
   }
 
diff --git a/pkg/analyzer/test/src/dart/ast/to_source_visitor_test.dart b/pkg/analyzer/test/src/dart/ast/to_source_visitor_test.dart
index b14053b..70b153a 100644
--- a/pkg/analyzer/test/src/dart/ast/to_source_visitor_test.dart
+++ b/pkg/analyzer/test/src/dart/ast/to_source_visitor_test.dart
@@ -1925,7 +1925,7 @@
 
   void test_visitGenericTypeAlias() {
     _assertSource(
-        "typedef X<S> = S Function<T>(T)",
+        "typedef X<S> = S Function<T>(T);",
         AstTestFactory.genericTypeAlias(
             'X',
             AstTestFactory.typeParameterList2(['S']),
diff --git a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
index 8348e13..434f6bf 100644
--- a/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
+++ b/pkg/analyzer_plugin/lib/protocol/protocol_common.dart
@@ -612,6 +612,15 @@
   /// if the parameterName field is omitted.
   String? parameterType;
 
+  /// The index in the list of libraries that could be imported to make this
+  /// suggestion accessible in the file where completion was requested. The
+  /// server provides this list of libraries together with suggestions, so that
+  /// information about the library can be shared for multiple suggestions.
+  /// This field is omitted if the library is already imported, so that the
+  /// suggestion can be inserted as is, or if getSuggestions was used rather
+  /// than getSuggestions2.
+  int? libraryUriToImportIndex;
+
   CompletionSuggestion(
       this.kind,
       this.relevance,
@@ -635,7 +644,8 @@
       this.requiredParameterCount,
       this.hasNamedParameters,
       this.parameterName,
-      this.parameterType});
+      this.parameterType,
+      this.libraryUriToImportIndex});
 
   factory CompletionSuggestion.fromJson(
       JsonDecoder jsonDecoder, String jsonPath, Object? json) {
@@ -774,6 +784,12 @@
         parameterType = jsonDecoder.decodeString(
             jsonPath + '.parameterType', json['parameterType']);
       }
+      int? libraryUriToImportIndex;
+      if (json.containsKey('libraryUriToImportIndex')) {
+        libraryUriToImportIndex = jsonDecoder.decodeInt(
+            jsonPath + '.libraryUriToImportIndex',
+            json['libraryUriToImportIndex']);
+      }
       return CompletionSuggestion(kind, relevance, completion, selectionOffset,
           selectionLength, isDeprecated, isPotential,
           displayText: displayText,
@@ -791,7 +807,8 @@
           requiredParameterCount: requiredParameterCount,
           hasNamedParameters: hasNamedParameters,
           parameterName: parameterName,
-          parameterType: parameterType);
+          parameterType: parameterType,
+          libraryUriToImportIndex: libraryUriToImportIndex);
     } else {
       throw jsonDecoder.mismatch(jsonPath, 'CompletionSuggestion', json);
     }
@@ -871,6 +888,10 @@
     if (parameterType != null) {
       result['parameterType'] = parameterType;
     }
+    var libraryUriToImportIndex = this.libraryUriToImportIndex;
+    if (libraryUriToImportIndex != null) {
+      result['libraryUriToImportIndex'] = libraryUriToImportIndex;
+    }
     return result;
   }
 
@@ -905,7 +926,8 @@
           requiredParameterCount == other.requiredParameterCount &&
           hasNamedParameters == other.hasNamedParameters &&
           parameterName == other.parameterName &&
-          parameterType == other.parameterType;
+          parameterType == other.parameterType &&
+          libraryUriToImportIndex == other.libraryUriToImportIndex;
     }
     return false;
   }
@@ -935,6 +957,7 @@
         hasNamedParameters,
         parameterName,
         parameterType,
+        libraryUriToImportIndex,
       ]);
 }
 
diff --git a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
index bb1ed53..f49f000 100644
--- a/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
+++ b/pkg/analyzer_plugin/test/integration/support/protocol_matchers.dart
@@ -164,7 +164,8 @@
           'requiredParameterCount': isInt,
           'hasNamedParameters': isBool,
           'parameterName': isString,
-          'parameterType': isString
+          'parameterType': isString,
+          'libraryUriToImportIndex': isInt
         }));
 
 /// CompletionSuggestionKind
diff --git a/pkg/analyzer_plugin/tool/spec/common_types_spec.html b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
index bb13ac5..00b5663 100644
--- a/pkg/analyzer_plugin/tool/spec/common_types_spec.html
+++ b/pkg/analyzer_plugin/tool/spec/common_types_spec.html
@@ -380,6 +380,18 @@
           omitted if the parameterName field is omitted.
         </p>
       </field>
+      <field name="libraryUriToImportIndex" experimental="true" optional="true">
+        <ref>int</ref>
+        <p>
+          The index in the list of libraries that could be imported to make
+          this suggestion accessible in the file where completion was requested.
+          The server provides this list of libraries together with suggestions,
+          so that information about the library can be shared for multiple
+          suggestions. This field is omitted if the library is  already
+          imported, so that the suggestion can be inserted as is, or if
+          <tt>getSuggestions</tt> was used rather than <tt>getSuggestions2</tt>.
+        </p>
+      </field>
     </object>
   </type>
   <type name="CompletionSuggestionKind">
diff --git a/pkg/compiler/test/analyses/api_allowed.json b/pkg/compiler/test/analyses/api_allowed.json
index 69d4c13..7fe7b5a 100644
--- a/pkg/compiler/test/analyses/api_allowed.json
+++ b/pkg/compiler/test/analyses/api_allowed.json
@@ -94,36 +94,16 @@
   "org-dartlang-sdk:///lib/convert/json.dart": {
     "Dynamic invocation of 'toJson'.": 1
   },
-  "org-dartlang-sdk:///lib/_http/crypto.dart": {
-    "Dynamic invocation of '+'.": 2,
-    "Dynamic invocation of '&'.": 3,
-    "Dynamic invocation of 'unary-'.": 1,
-    "Dynamic invocation of '-'.": 2
-  },
-  "org-dartlang-sdk:///lib/_http/http_date.dart": {
-    "Dynamic access of 'length'.": 3,
-    "Dynamic invocation of '<'.": 1,
-    "Dynamic invocation of '>='.": 2,
-    "Dynamic invocation of '[]'.": 7
-  },
-  "org-dartlang-sdk:///lib/_http/http_headers.dart": {
-    "Dynamic invocation of 'toLowerCase'.": 1
-  },
   "org-dartlang-sdk:///lib/_http/http_impl.dart": {
-    "Dynamic access of 'headers'.": 1,
-    "Dynamic invocation of 'forEach'.": 1,
-    "Dynamic access of 'connectionInfo'.": 4,
-    "Dynamic access of 'localPort'.": 1,
-    "Dynamic access of 'remoteAddress'.": 2,
-    "Dynamic access of 'address'.": 4,
-    "Dynamic access of 'remotePort'.": 2,
     "Dynamic access of 'message'.": 3,
-    "Dynamic invocation of 'call'.": 1,
     "Dynamic invocation of 'destroy'.": 2,
+    "Dynamic access of 'address'.": 3,
     "Dynamic access of 'type'.": 1,
     "Dynamic invocation of 'setOption'.": 1,
     "Dynamic access of 'host'.": 2,
     "Dynamic access of 'port'.": 2,
+    "Dynamic access of 'remoteAddress'.": 1,
+    "Dynamic access of 'remotePort'.": 1,
     "Dynamic invocation of 'dart._http::_toJSON'.": 3,
     "Dynamic invocation of 'listen'.": 1,
     "Dynamic invocation of 'close'.": 1
diff --git a/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart b/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart
index 82414c9..4102f5a 100644
--- a/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart
+++ b/pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart
@@ -24,6 +24,7 @@
   nonfunctionTypeAliases,
   setLiterals,
   spreadCollections,
+  superParameters,
   testExperiment,
   tripleShift,
   valueClass,
@@ -45,6 +46,7 @@
 const Version enableNonfunctionTypeAliasesVersion = const Version(2, 13);
 const Version enableSetLiteralsVersion = const Version(2, 0);
 const Version enableSpreadCollectionsVersion = const Version(2, 0);
+const Version enableSuperParametersVersion = const Version(2, 15);
 const Version enableTestExperimentVersion = const Version(2, 15);
 const Version enableTripleShiftVersion = const Version(2, 14);
 const Version enableValueClassVersion = const Version(2, 15);
@@ -80,6 +82,8 @@
       return ExperimentalFlag.setLiterals;
     case "spread-collections":
       return ExperimentalFlag.spreadCollections;
+    case "super-parameters":
+      return ExperimentalFlag.superParameters;
     case "test-experiment":
       return ExperimentalFlag.testExperiment;
     case "triple-shift":
@@ -107,6 +111,7 @@
   ExperimentalFlag.nonfunctionTypeAliases: true,
   ExperimentalFlag.setLiterals: true,
   ExperimentalFlag.spreadCollections: true,
+  ExperimentalFlag.superParameters: false,
   ExperimentalFlag.testExperiment: false,
   ExperimentalFlag.tripleShift: true,
   ExperimentalFlag.valueClass: false,
@@ -128,6 +133,7 @@
   ExperimentalFlag.nonfunctionTypeAliases: false,
   ExperimentalFlag.setLiterals: true,
   ExperimentalFlag.spreadCollections: true,
+  ExperimentalFlag.superParameters: false,
   ExperimentalFlag.testExperiment: false,
   ExperimentalFlag.tripleShift: false,
   ExperimentalFlag.valueClass: false,
@@ -149,6 +155,7 @@
   ExperimentalFlag.nonfunctionTypeAliases: const Version(2, 13),
   ExperimentalFlag.setLiterals: const Version(2, 0),
   ExperimentalFlag.spreadCollections: const Version(2, 0),
+  ExperimentalFlag.superParameters: const Version(2, 15),
   ExperimentalFlag.testExperiment: const Version(2, 15),
   ExperimentalFlag.tripleShift: const Version(2, 14),
   ExperimentalFlag.valueClass: const Version(2, 15),
@@ -170,6 +177,7 @@
   ExperimentalFlag.nonfunctionTypeAliases: const Version(2, 13),
   ExperimentalFlag.setLiterals: const Version(2, 0),
   ExperimentalFlag.spreadCollections: const Version(2, 0),
+  ExperimentalFlag.superParameters: const Version(2, 15),
   ExperimentalFlag.testExperiment: const Version(2, 15),
   ExperimentalFlag.tripleShift: const Version(2, 14),
   ExperimentalFlag.valueClass: const Version(2, 15),
diff --git a/pkg/front_end/testcases/nnbd_mixed/mock_http_headers.dart.weak.outline.expect b/pkg/front_end/testcases/nnbd_mixed/mock_http_headers.dart.weak.outline.expect
index 4ba2007..4789762 100644
--- a/pkg/front_end/testcases/nnbd_mixed/mock_http_headers.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/nnbd_mixed/mock_http_headers.dart.weak.outline.expect
@@ -170,8 +170,8 @@
 Evaluated: SymbolLiteral @ org-dartlang-testcase:///mock_http_headers.dart:13:7 -> SymbolConstant(#noFolding)
 Evaluated: ListLiteral @ org-dartlang-testcase:///mock_http_headers.dart:13:7 -> ListConstant(const <Type*>[])
 Evaluated: MapLiteral @ org-dartlang-testcase:///mock_http_headers.dart:13:7 -> MapConstant(const <Symbol*, dynamic>{})
-Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/_http/http.dart:782:8 -> SymbolConstant(#clear)
-Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/_http/http.dart:782:8 -> ListConstant(const <Type*>[])
-Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/_http/http.dart:782:8 -> ListConstant(const <dynamic>[])
-Evaluated: MapLiteral @ org-dartlang-sdk:///sdk/lib/_http/http.dart:782:8 -> MapConstant(const <Symbol*, dynamic>{})
+Evaluated: SymbolLiteral @ org-dartlang-sdk:///sdk/lib/_http/http.dart:707:8 -> SymbolConstant(#clear)
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/_http/http.dart:707:8 -> ListConstant(const <Type*>[])
+Evaluated: ListLiteral @ org-dartlang-sdk:///sdk/lib/_http/http.dart:707:8 -> ListConstant(const <dynamic>[])
+Evaluated: MapLiteral @ org-dartlang-sdk:///sdk/lib/_http/http.dart:707:8 -> MapConstant(const <Symbol*, dynamic>{})
 Extra constant evaluation: evaluated: 268, effectively constant: 91
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart.expect
index ef7f8ee..463adf9 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart.expect
@@ -22,6 +22,6 @@
   synthetic constructor •() → self::Class
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3266,getterSelectorId:3267]  method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::Enum e) → core::int
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3252,getterSelectorId:3253]  method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::Enum e) → core::int
     return [@vm.inferred-type.metadata=!] e.{core::_Enum::index}{core::int};
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart.expect
index 4a68920..3a69351 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart.expect
@@ -51,6 +51,6 @@
   synthetic constructor •() → self::ConstClass
     : super core::Object::•()
     ;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3270,getterSelectorId:3271]  method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::ConstEnum e) → core::int
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3256,getterSelectorId:3257]  method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::ConstEnum e) → core::int
     return [@vm.inferred-type.metadata=!] e.{core::_Enum::index}{core::int};
 }
diff --git a/runtime/vm/heap/heap.cc b/runtime/vm/heap/heap.cc
index be2bfa6..7d4c1a4 100644
--- a/runtime/vm/heap/heap.cc
+++ b/runtime/vm/heap/heap.cc
@@ -445,7 +445,9 @@
     new_space_.Evacuate(reason);
     RecordAfterGC(GCType::kScavenge);
     PrintStats();
-    NOT_IN_PRODUCT(PrintStatsToTimeline(&tbes, reason));
+#if defined(SUPPORT_TIMELINE)
+    PrintStatsToTimeline(&tbes, reason);
+#endif
     last_gc_was_old_space_ = false;
   }
 }
@@ -473,7 +475,9 @@
       new_space_.Scavenge(reason);
       RecordAfterGC(GCType::kScavenge);
       PrintStats();
-      NOT_IN_PRODUCT(PrintStatsToTimeline(&tbes, reason));
+#if defined(SUPPORT_TIMELINE)
+      PrintStatsToTimeline(&tbes, reason);
+#endif
       last_gc_was_old_space_ = false;
     }
     if (reason == GCReason::kNewSpace) {
@@ -522,7 +526,9 @@
     old_space_.CollectGarbage(type == GCType::kMarkCompact, true /* finish */);
     RecordAfterGC(type);
     PrintStats();
-    NOT_IN_PRODUCT(PrintStatsToTimeline(&tbes, reason));
+#if defined(SUPPORT_TIMELINE)
+    PrintStatsToTimeline(&tbes, reason);
+#endif
 
     // Some Code objects may have been collected so invalidate handler cache.
     thread->isolate_group()->ForEachIsolate(
@@ -1176,7 +1182,7 @@
 }
 
 void Heap::PrintStatsToTimeline(TimelineEventScope* event, GCReason reason) {
-#if !defined(PRODUCT)
+#if defined(SUPPORT_TIMELINE)
   if ((event == NULL) || !event->enabled()) {
     return;
   }
@@ -1209,7 +1215,7 @@
                         RoundWordsToKB(stats_.before_.old_.external_in_words));
   event->FormatArgument(arguments + 12, "After.Old.External (kB)", "%" Pd "",
                         RoundWordsToKB(stats_.after_.old_.external_in_words));
-#endif  // !defined(PRODUCT)
+#endif  // defined(SUPPORT_TIMELINE)
 }
 
 Heap::Space Heap::SpaceForExternal(intptr_t size) const {
diff --git a/sdk/lib/_http/crypto.dart b/sdk/lib/_http/crypto.dart
index f29a15b..337f299 100644
--- a/sdk/lib/_http/crypto.dart
+++ b/sdk/lib/_http/crypto.dart
@@ -21,7 +21,7 @@
   // -1 : '\r' or '\n'
   //  0 : = (Padding character).
   // >0 : Base 64 alphabet index of given byte.
-  static const List<int> _decodeTable = const [
+  static const List<int> _decodeTable = [
     -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -1, -2, -2, -1, -2, -2, //
     -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, //
     -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, 62, -2, 62, -2, 63, //
@@ -40,18 +40,16 @@
     -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2
   ];
 
-  static Random _rng = new Random.secure();
-
   static Uint8List getRandomBytes(int count) {
-    final Uint8List result = new Uint8List(count);
+    final Uint8List result = Uint8List(count);
     for (int i = 0; i < count; i++) {
-      result[i] = _rng.nextInt(0xff);
+      result[i] = Random.secure().nextInt(0xff);
     }
     return result;
   }
 
   static String bytesToHex(List<int> bytes) {
-    var result = new StringBuffer();
+    var result = StringBuffer();
     for (var part in bytes) {
       result.write('${part < 16 ? '0' : ''}${part.toRadixString(16)}');
     }
@@ -66,7 +64,7 @@
     }
     final String lookup = urlSafe ? _encodeTableUrlSafe : _encodeTable;
     // Size of 24 bit chunks.
-    final int remainderLength = len.remainder(3) as int;
+    final int remainderLength = len.remainder(3);
     final int chunkLength = len - remainderLength;
     // Size of base output.
     int outputLen = ((len ~/ 3) * 4) + ((remainderLength > 0) ? 4 : 0);
@@ -74,7 +72,7 @@
     if (addLineSeparator) {
       outputLen += ((outputLen - 1) ~/ LINE_LENGTH) << 1;
     }
-    List<int> out = new List<int>.filled(outputLen, 0);
+    List<int> out = List<int>.filled(outputLen, 0);
 
     // Encode 24 bit chunks.
     int j = 0, i = 0, c = 0;
@@ -111,14 +109,14 @@
       out[j++] = PAD;
     }
 
-    return new String.fromCharCodes(out);
+    return String.fromCharCodes(out);
   }
 
   static List<int> base64StringToBytes(String input,
       [bool ignoreInvalidCharacters = true]) {
     int len = input.length;
     if (len == 0) {
-      return new List<int>.empty();
+      return List<int>.empty();
     }
 
     // Count '\r', '\n' and illegal characters, For illegal characters,
@@ -129,13 +127,13 @@
       if (c < 0) {
         extrasLen++;
         if (c == -2 && !ignoreInvalidCharacters) {
-          throw new FormatException('Invalid character: ${input[i]}');
+          throw FormatException('Invalid character: ${input[i]}');
         }
       }
     }
 
     if ((len - extrasLen) % 4 != 0) {
-      throw new FormatException('''Size of Base 64 characters in Input
+      throw FormatException('''Size of Base 64 characters in Input
           must be a multiple of 4. Input: $input''');
     }
 
@@ -147,7 +145,7 @@
       if (currentCodeUnit == PAD) padLength++;
     }
     int outputLen = (((len - extrasLen) * 6) >> 3) - padLength;
-    List<int> out = new List<int>.filled(outputLen, 0);
+    List<int> out = List<int>.filled(outputLen, 0);
 
     for (int i = 0, o = 0; o < outputLen;) {
       // Accumulate 4 valid 6 bit Base 64 characters into an int.
@@ -183,20 +181,19 @@
   final bool _bigEndianWords;
   int _lengthInBytes = 0;
   List<int> _pendingData;
-  List<int> _currentChunk;
-  List<int> _h;
+  final List<int> _currentChunk;
+  final List<int> _h;
   bool _digestCalled = false;
 
   _HashBase(this._chunkSizeInWords, int digestSizeInWords, this._bigEndianWords)
       : _pendingData = [],
-        _currentChunk = new List.filled(_chunkSizeInWords, 0),
-        _h = new List.filled(digestSizeInWords, 0);
+        _currentChunk = List.filled(_chunkSizeInWords, 0),
+        _h = List.filled(digestSizeInWords, 0);
 
   // Update the hasher with more data.
   add(List<int> data) {
     if (_digestCalled) {
-      throw new StateError(
-          'Hash update method called after digest was retrieved');
+      throw StateError('Hash update method called after digest was retrieved');
     }
     _lengthInBytes += data.length;
     _pendingData.addAll(data);
@@ -211,7 +208,7 @@
     _digestCalled = true;
     _finalizeData();
     _iterate();
-    assert(_pendingData.length == 0);
+    assert(_pendingData.isEmpty);
     return _resultAsBytes();
   }
 
@@ -227,8 +224,8 @@
   _updateHash(List<int> m);
 
   // Helper methods.
-  _add32(x, y) => (x + y) & _MASK_32;
-  _roundUp(val, n) => (val + n - 1) & -n;
+  int _add32(int x, int y) => (x + y) & _MASK_32;
+  int _roundUp(int val, int n) => (val + n - 1) & -n;
 
   // Rotate left limiting to unsigned 32-bit values.
   int _rotl32(int val, int shift) {
@@ -266,7 +263,7 @@
 
   // Convert a 32-bit word to four bytes.
   List<int> _wordToBytes(int word) {
-    List<int> bytes = new List.filled(_BYTES_PER_WORD, 0);
+    List<int> bytes = List.filled(_BYTES_PER_WORD, 0);
     bytes[0] = (word >> (_bigEndianWords ? 24 : 0)) & _MASK_8;
     bytes[1] = (word >> (_bigEndianWords ? 16 : 8)) & _MASK_8;
     bytes[2] = (word >> (_bigEndianWords ? 8 : 16)) & _MASK_8;
@@ -323,10 +320,10 @@
 
   // Returns a new instance of this Hash.
   _MD5 newInstance() {
-    return new _MD5();
+    return _MD5();
   }
 
-  static const _k = const [
+  static const _k = [
     0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, //
     0xa8304613, 0xfd469501, 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, //
     0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 0xf61e2562, 0xc040b340, //
@@ -340,7 +337,7 @@
     0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
   ];
 
-  static const _r = const [
+  static const _r = [
     7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, //
     20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4, 11, //
     16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15, 21, 6, //
@@ -357,8 +354,8 @@
     var c = _h[2];
     var d = _h[3];
 
-    var t0;
-    var t1;
+    int t0;
+    int t1;
 
     for (var i = 0; i < 64; i++) {
       if (i < 16) {
@@ -392,7 +389,7 @@
 
 // The SHA1 hasher is used to compute an SHA1 message digest.
 class _SHA1 extends _HashBase {
-  List<int> _w;
+  final List<int> _w;
 
   // Construct a SHA1 hasher object.
   _SHA1()
@@ -407,7 +404,7 @@
 
   // Returns a new instance of this Hash.
   _SHA1 newInstance() {
-    return new _SHA1();
+    return _SHA1();
   }
 
   // Compute one iteration of the SHA1 algorithm with a chunk of
diff --git a/sdk/lib/_http/http.dart b/sdk/lib/_http/http.dart
index bc88899..4193db2 100644
--- a/sdk/lib/_http/http.dart
+++ b/sdk/lib/_http/http.dart
@@ -9,7 +9,6 @@
     show
         HashMap,
         HashSet,
-        Queue,
         ListQueue,
         LinkedList,
         LinkedListEntry,
@@ -34,240 +33,226 @@
 part 'websocket.dart';
 part 'websocket_impl.dart';
 
-/**
- * A server that delivers content, such as web pages, using the HTTP protocol.
- *
- * The HttpServer is a [Stream] that provides [HttpRequest] objects. Each
- * HttpRequest has an associated [HttpResponse] object.
- * The server responds to a request by writing to that HttpResponse object.
- * The following example shows how to bind an HttpServer to an IPv6
- * [InternetAddress] on port 80 (the standard port for HTTP servers)
- * and how to listen for requests.
- * Port 80 is the default HTTP port. However, on most systems accessing
- * this requires super-user privileges. For local testing consider
- * using a non-reserved port (1024 and above).
- *
- *     import 'dart:io';
- *
- *     main() {
- *       HttpServer
- *           .bind(InternetAddress.anyIPv6, 80)
- *           .then((server) {
- *             server.listen((HttpRequest request) {
- *               request.response.write('Hello, world!');
- *               request.response.close();
- *             });
- *           });
- *     }
- *
- * Incomplete requests, in which all or part of the header is missing, are
- * ignored, and no exceptions or HttpRequest objects are generated for them.
- * Likewise, when writing to an HttpResponse, any [Socket] exceptions are
- * ignored and any future writes are ignored.
- *
- * The HttpRequest exposes the request headers and provides the request body,
- * if it exists, as a Stream of data. If the body is unread, it is drained
- * when the server writes to the HttpResponse or closes it.
- *
- * ## Bind with a secure HTTPS connection
- *
- * Use [bindSecure] to create an HTTPS server.
- *
- * The server presents a certificate to the client. The certificate
- * chain and the private key are set in the [SecurityContext]
- * object that is passed to [bindSecure].
- *
- *     import 'dart:io';
- *     import "dart:isolate";
- *
- *     main() {
- *       SecurityContext context = new SecurityContext();
- *       var chain =
- *           Platform.script.resolve('certificates/server_chain.pem')
- *           .toFilePath();
- *       var key =
- *           Platform.script.resolve('certificates/server_key.pem')
- *           .toFilePath();
- *       context.useCertificateChain(chain);
- *       context.usePrivateKey(key, password: 'dartdart');
- *
- *       HttpServer
- *           .bindSecure(InternetAddress.anyIPv6,
- *                       443,
- *                       context)
- *           .then((server) {
- *             server.listen((HttpRequest request) {
- *               request.response.write('Hello, world!');
- *               request.response.close();
- *             });
- *           });
- *     }
- *
- *  The certificates and keys are PEM files, which can be created and
- *  managed with the tools in OpenSSL.
- *
- * ## Connect to a server socket
- *
- * You can use the [listenOn] constructor to attach an HTTP server to
- * a [ServerSocket].
- *
- *     import 'dart:io';
- *
- *     main() {
- *       ServerSocket.bind(InternetAddress.anyIPv6, 80)
- *         .then((serverSocket) {
- *           HttpServer httpserver = new HttpServer.listenOn(serverSocket);
- *           serverSocket.listen((Socket socket) {
- *             socket.write('Hello, client.');
- *           });
- *         });
- *     }
- *
- * ## Other resources
- *
- * * HttpServer is a Stream. Refer to the [Stream] class for information
- * about the streaming qualities of an HttpServer.
- * Pausing the subscription of the stream, pauses at the OS level.
- *
- * * The [shelf](https://pub.dev/packages/shelf)
- * package on pub.dev contains a set of high-level classes that,
- * together with this class, makes it easy to provide content through HTTP
- * servers.
- */
+/// A server that delivers content, such as web pages, using the HTTP protocol.
+///
+/// The HttpServer is a [Stream] that provides [HttpRequest] objects. Each
+/// HttpRequest has an associated [HttpResponse] object.
+/// The server responds to a request by writing to that HttpResponse object.
+/// The following example shows how to bind an HttpServer to an IPv6
+/// [InternetAddress] on port 80 (the standard port for HTTP servers)
+/// and how to listen for requests.
+/// Port 80 is the default HTTP port. However, on most systems accessing
+/// this requires super-user privileges. For local testing consider
+/// using a non-reserved port (1024 and above).
+///
+///     import 'dart:io';
+///
+///     main() {
+///       HttpServer
+///           .bind(InternetAddress.anyIPv6, 80)
+///           .then((server) {
+///             server.listen((HttpRequest request) {
+///               request.response.write('Hello, world!');
+///               request.response.close();
+///             });
+///           });
+///     }
+///
+/// Incomplete requests, in which all or part of the header is missing, are
+/// ignored, and no exceptions or HttpRequest objects are generated for them.
+/// Likewise, when writing to an HttpResponse, any [Socket] exceptions are
+/// ignored and any future writes are ignored.
+///
+/// The HttpRequest exposes the request headers and provides the request body,
+/// if it exists, as a Stream of data. If the body is unread, it is drained
+/// when the server writes to the HttpResponse or closes it.
+///
+/// ## Bind with a secure HTTPS connection
+///
+/// Use [bindSecure] to create an HTTPS server.
+///
+/// The server presents a certificate to the client. The certificate
+/// chain and the private key are set in the [SecurityContext]
+/// object that is passed to [bindSecure].
+///
+///     import 'dart:io';
+///     import "dart:isolate";
+///
+///     main() {
+///       SecurityContext context = new SecurityContext();
+///       var chain =
+///           Platform.script.resolve('certificates/server_chain.pem')
+///           .toFilePath();
+///       var key =
+///           Platform.script.resolve('certificates/server_key.pem')
+///           .toFilePath();
+///       context.useCertificateChain(chain);
+///       context.usePrivateKey(key, password: 'dartdart');
+///
+///       HttpServer
+///           .bindSecure(InternetAddress.anyIPv6,
+///                       443,
+///                       context)
+///           .then((server) {
+///             server.listen((HttpRequest request) {
+///               request.response.write('Hello, world!');
+///               request.response.close();
+///             });
+///           });
+///     }
+///
+///  The certificates and keys are PEM files, which can be created and
+///  managed with the tools in OpenSSL.
+///
+/// ## Connect to a server socket
+///
+/// You can use the [listenOn] constructor to attach an HTTP server to
+/// a [ServerSocket].
+///
+///     import 'dart:io';
+///
+///     main() {
+///       ServerSocket.bind(InternetAddress.anyIPv6, 80)
+///         .then((serverSocket) {
+///           HttpServer httpserver = new HttpServer.listenOn(serverSocket);
+///           serverSocket.listen((Socket socket) {
+///             socket.write('Hello, client.');
+///           });
+///         });
+///     }
+///
+/// ## Other resources
+///
+/// * HttpServer is a Stream. Refer to the [Stream] class for information
+/// about the streaming qualities of an HttpServer.
+/// Pausing the subscription of the stream, pauses at the OS level.
+///
+/// * The [shelf](https://pub.dev/packages/shelf)
+/// package on pub.dev contains a set of high-level classes that,
+/// together with this class, makes it easy to provide content through HTTP
+/// servers.
 abstract class HttpServer implements Stream<HttpRequest> {
-  /**
-   * Gets and sets the default value of the `Server` header for all responses
-   * generated by this [HttpServer].
-   *
-   * If [serverHeader] is `null`, no `Server` header will be added to each
-   * response.
-   *
-   * The default value is `null`.
-   */
+  /// Gets and sets the default value of the `Server` header for all responses
+  /// generated by this [HttpServer].
+  ///
+  /// If [serverHeader] is `null`, no `Server` header will be added to each
+  /// response.
+  ///
+  /// The default value is `null`.
   String? serverHeader;
 
-  /**
-   * Default set of headers added to all response objects.
-   *
-   * By default the following headers are in this set:
-   *
-   *     Content-Type: text/plain; charset=utf-8
-   *     X-Frame-Options: SAMEORIGIN
-   *     X-Content-Type-Options: nosniff
-   *     X-XSS-Protection: 1; mode=block
-   *
-   * If the `Server` header is added here and the `serverHeader` is set as
-   * well then the value of `serverHeader` takes precedence.
-   */
+  /// Default set of headers added to all response objects.
+  ///
+  /// By default the following headers are in this set:
+  ///
+  ///     Content-Type: text/plain; charset=utf-8
+  ///     X-Frame-Options: SAMEORIGIN
+  ///     X-Content-Type-Options: nosniff
+  ///     X-XSS-Protection: 1; mode=block
+  ///
+  /// If the `Server` header is added here and the `serverHeader` is set as
+  /// well then the value of `serverHeader` takes precedence.
   HttpHeaders get defaultResponseHeaders;
 
-  /**
-   * Whether the [HttpServer] should compress the content, if possible.
-   *
-   * The content can only be compressed when the response is using
-   * chunked Transfer-Encoding and the incoming request has `gzip`
-   * as an accepted encoding in the Accept-Encoding header.
-   *
-   * The default value is `false` (compression disabled).
-   * To enable, set `autoCompress` to `true`.
-   */
+  /// Whether the [HttpServer] should compress the content, if possible.
+  ///
+  /// The content can only be compressed when the response is using
+  /// chunked Transfer-Encoding and the incoming request has `gzip`
+  /// as an accepted encoding in the Accept-Encoding header.
+  ///
+  /// The default value is `false` (compression disabled).
+  /// To enable, set `autoCompress` to `true`.
   bool autoCompress = false;
 
-  /**
-   * Gets or sets the timeout used for idle keep-alive connections. If no
-   * further request is seen within [idleTimeout] after the previous request was
-   * completed, the connection is dropped.
-   *
-   * Default is 120 seconds.
-   *
-   * Note that it may take up to `2 * idleTimeout` before a idle connection is
-   * aborted.
-   *
-   * To disable, set [idleTimeout] to `null`.
-   */
+  /// Gets or sets the timeout used for idle keep-alive connections. If no
+  /// further request is seen within [idleTimeout] after the previous request was
+  /// completed, the connection is dropped.
+  ///
+  /// Default is 120 seconds.
+  ///
+  /// Note that it may take up to `2 * idleTimeout` before a idle connection is
+  /// aborted.
+  ///
+  /// To disable, set [idleTimeout] to `null`.
   Duration? idleTimeout = const Duration(seconds: 120);
 
-  /**
-   * Starts listening for HTTP requests on the specified [address] and
-   * [port].
-   *
-   * The [address] can either be a [String] or an
-   * [InternetAddress]. If [address] is a [String], [bind] will
-   * perform a [InternetAddress.lookup] and use the first value in the
-   * list. To listen on the loopback adapter, which will allow only
-   * incoming connections from the local host, use the value
-   * [InternetAddress.loopbackIPv4] or
-   * [InternetAddress.loopbackIPv6]. To allow for incoming
-   * connection from the network use either one of the values
-   * [InternetAddress.anyIPv4] or [InternetAddress.anyIPv6] to
-   * bind to all interfaces or the IP address of a specific interface.
-   *
-   * If an IP version 6 (IPv6) address is used, both IP version 6
-   * (IPv6) and version 4 (IPv4) connections will be accepted. To
-   * restrict this to version 6 (IPv6) only, use [v6Only] to set
-   * version 6 only. However, if the address is
-   * [InternetAddress.loopbackIPv6], only IP version 6 (IPv6) connections
-   * will be accepted.
-   *
-   * If [port] has the value 0 an ephemeral port will be chosen by
-   * the system. The actual port used can be retrieved using the
-   * [port] getter.
-   *
-   * The optional argument [backlog] can be used to specify the listen
-   * backlog for the underlying OS listen setup. If [backlog] has the
-   * value of 0 (the default) a reasonable value will be chosen by
-   * the system.
-   *
-   * The optional argument [shared] specifies whether additional HttpServer
-   * objects can bind to the same combination of `address`, `port` and `v6Only`.
-   * If `shared` is `true` and more `HttpServer`s from this isolate or other
-   * isolates are bound to the port, then the incoming connections will be
-   * distributed among all the bound `HttpServer`s. Connections can be
-   * distributed over multiple isolates this way.
-   */
+  /// Starts listening for HTTP requests on the specified [address] and
+  /// [port].
+  ///
+  /// The [address] can either be a [String] or an
+  /// [InternetAddress]. If [address] is a [String], [bind] will
+  /// perform a [InternetAddress.lookup] and use the first value in the
+  /// list. To listen on the loopback adapter, which will allow only
+  /// incoming connections from the local host, use the value
+  /// [InternetAddress.loopbackIPv4] or
+  /// [InternetAddress.loopbackIPv6]. To allow for incoming
+  /// connection from the network use either one of the values
+  /// [InternetAddress.anyIPv4] or [InternetAddress.anyIPv6] to
+  /// bind to all interfaces or the IP address of a specific interface.
+  ///
+  /// If an IP version 6 (IPv6) address is used, both IP version 6
+  /// (IPv6) and version 4 (IPv4) connections will be accepted. To
+  /// restrict this to version 6 (IPv6) only, use [v6Only] to set
+  /// version 6 only. However, if the address is
+  /// [InternetAddress.loopbackIPv6], only IP version 6 (IPv6) connections
+  /// will be accepted.
+  ///
+  /// If [port] has the value 0 an ephemeral port will be chosen by
+  /// the system. The actual port used can be retrieved using the
+  /// [port] getter.
+  ///
+  /// The optional argument [backlog] can be used to specify the listen
+  /// backlog for the underlying OS listen setup. If [backlog] has the
+  /// value of 0 (the default) a reasonable value will be chosen by
+  /// the system.
+  ///
+  /// The optional argument [shared] specifies whether additional HttpServer
+  /// objects can bind to the same combination of `address`, `port` and `v6Only`.
+  /// If `shared` is `true` and more `HttpServer`s from this isolate or other
+  /// isolates are bound to the port, then the incoming connections will be
+  /// distributed among all the bound `HttpServer`s. Connections can be
+  /// distributed over multiple isolates this way.
   static Future<HttpServer> bind(address, int port,
           {int backlog = 0, bool v6Only = false, bool shared = false}) =>
       _HttpServer.bind(address, port, backlog, v6Only, shared);
 
-  /**
-   * The [address] can either be a [String] or an
-   * [InternetAddress]. If [address] is a [String], [bind] will
-   * perform a [InternetAddress.lookup] and use the first value in the
-   * list. To listen on the loopback adapter, which will allow only
-   * incoming connections from the local host, use the value
-   * [InternetAddress.loopbackIPv4] or
-   * [InternetAddress.loopbackIPv6]. To allow for incoming
-   * connection from the network use either one of the values
-   * [InternetAddress.anyIPv4] or [InternetAddress.anyIPv6] to
-   * bind to all interfaces or the IP address of a specific interface.
-   *
-   * If an IP version 6 (IPv6) address is used, both IP version 6
-   * (IPv6) and version 4 (IPv4) connections will be accepted. To
-   * restrict this to version 6 (IPv6) only, use [v6Only] to set
-   * version 6 only.
-   *
-   * If [port] has the value 0 an ephemeral port will be chosen by
-   * the system. The actual port used can be retrieved using the
-   * [port] getter.
-   *
-   * The optional argument [backlog] can be used to specify the listen
-   * backlog for the underlying OS listen setup. If [backlog] has the
-   * value of 0 (the default) a reasonable value will be chosen by
-   * the system.
-   *
-   * If [requestClientCertificate] is true, the server will
-   * request clients to authenticate with a client certificate.
-   * The server will advertise the names of trusted issuers of client
-   * certificates, getting them from a [SecurityContext], where they have been
-   * set using [SecurityContext.setClientAuthorities].
-   *
-   * The optional argument [shared] specifies whether additional HttpServer
-   * objects can bind to the same combination of `address`, `port` and `v6Only`.
-   * If `shared` is `true` and more `HttpServer`s from this isolate or other
-   * isolates are bound to the port, then the incoming connections will be
-   * distributed among all the bound `HttpServer`s. Connections can be
-   * distributed over multiple isolates this way.
-   */
+  /// The [address] can either be a [String] or an
+  /// [InternetAddress]. If [address] is a [String], [bind] will
+  /// perform a [InternetAddress.lookup] and use the first value in the
+  /// list. To listen on the loopback adapter, which will allow only
+  /// incoming connections from the local host, use the value
+  /// [InternetAddress.loopbackIPv4] or
+  /// [InternetAddress.loopbackIPv6]. To allow for incoming
+  /// connection from the network use either one of the values
+  /// [InternetAddress.anyIPv4] or [InternetAddress.anyIPv6] to
+  /// bind to all interfaces or the IP address of a specific interface.
+  ///
+  /// If an IP version 6 (IPv6) address is used, both IP version 6
+  /// (IPv6) and version 4 (IPv4) connections will be accepted. To
+  /// restrict this to version 6 (IPv6) only, use [v6Only] to set
+  /// version 6 only.
+  ///
+  /// If [port] has the value 0 an ephemeral port will be chosen by
+  /// the system. The actual port used can be retrieved using the
+  /// [port] getter.
+  ///
+  /// The optional argument [backlog] can be used to specify the listen
+  /// backlog for the underlying OS listen setup. If [backlog] has the
+  /// value of 0 (the default) a reasonable value will be chosen by
+  /// the system.
+  ///
+  /// If [requestClientCertificate] is true, the server will
+  /// request clients to authenticate with a client certificate.
+  /// The server will advertise the names of trusted issuers of client
+  /// certificates, getting them from a [SecurityContext], where they have been
+  /// set using [SecurityContext.setClientAuthorities].
+  ///
+  /// The optional argument [shared] specifies whether additional HttpServer
+  /// objects can bind to the same combination of `address`, `port` and `v6Only`.
+  /// If `shared` is `true` and more `HttpServer`s from this isolate or other
+  /// isolates are bound to the port, then the incoming connections will be
+  /// distributed among all the bound `HttpServer`s. Connections can be
+  /// distributed over multiple isolates this way.
 
   static Future<HttpServer> bindSecure(
           address, int port, SecurityContext context,
@@ -278,113 +263,89 @@
       _HttpServer.bindSecure(address, port, context, backlog, v6Only,
           requestClientCertificate, shared);
 
-  /**
-   * Attaches the HTTP server to an existing [ServerSocket]. When the
-   * [HttpServer] is closed, the [HttpServer] will just detach itself,
-   * closing current connections but not closing [serverSocket].
-   */
+  /// Attaches the HTTP server to an existing [ServerSocket]. When the
+  /// [HttpServer] is closed, the [HttpServer] will just detach itself,
+  /// closing current connections but not closing [serverSocket].
   factory HttpServer.listenOn(ServerSocket serverSocket) =>
-      new _HttpServer.listenOn(serverSocket);
+      _HttpServer.listenOn(serverSocket);
 
-  /**
-   * Permanently stops this [HttpServer] from listening for new
-   * connections.  This closes the [Stream] of [HttpRequest]s with a
-   * done event. The returned future completes when the server is
-   * stopped. For a server started using [bind] or [bindSecure] this
-   * means that the port listened on no longer in use.
-   *
-   * If [force] is `true`, active connections will be closed immediately.
-   */
+  /// Permanently stops this [HttpServer] from listening for new
+  /// connections.  This closes the [Stream] of [HttpRequest]s with a
+  /// done event. The returned future completes when the server is
+  /// stopped. For a server started using [bind] or [bindSecure] this
+  /// means that the port listened on no longer in use.
+  ///
+  /// If [force] is `true`, active connections will be closed immediately.
   Future close({bool force = false});
 
-  /**
-   * The port that the server is listening on.
-   *
-   * This is the actual port used when a port of zero is
-   * specified in the [bind] or [bindSecure] call.
-   */
+  /// The port that the server is listening on.
+  ///
+  /// This is the actual port used when a port of zero is
+  /// specified in the [bind] or [bindSecure] call.
   int get port;
 
-  /**
-   * The address that the server is listening on.
-   *
-   * This is the actual address used when the original address
-   * was specified as a hostname.
-   */
+  /// The address that the server is listening on.
+  ///
+  /// This is the actual address used when the original address
+  /// was specified as a hostname.
   InternetAddress get address;
 
-  /**
-   * Sets the timeout, in seconds, for sessions of this [HttpServer].
-   *
-   * The default timeout is 20 minutes.
-   */
+  /// Sets the timeout, in seconds, for sessions of this [HttpServer].
+  ///
+  /// The default timeout is 20 minutes.
   set sessionTimeout(int timeout);
 
-  /**
-   * A [HttpConnectionsInfo] object summarizing the number of
-   * current connections handled by the server.
-   */
+  /// A [HttpConnectionsInfo] object summarizing the number of
+  /// current connections handled by the server.
   HttpConnectionsInfo connectionsInfo();
 }
 
-/**
- * Summary statistics about an [HttpServer]s current socket connections.
- */
+/// Summary statistics about an [HttpServer]s current socket connections.
 class HttpConnectionsInfo {
-  /**
-   * Total number of socket connections.
-   */
+  /// Total number of socket connections.
   int total = 0;
 
-  /**
-   * Number of active connections where actual request/response
-   * processing is active.
-   */
+  /// Number of active connections where actual request/response
+  /// processing is active.
   int active = 0;
 
-  /**
-   * Number of idle connections held by clients as persistent connections.
-   */
+  /// Number of idle connections held by clients as persistent connections.
   int idle = 0;
 
-  /**
-   * Number of connections which are preparing to close.
-   *
-   * Note: These connections are also part of the [active] count as they might
-   * still be sending data to the client before finally closing.
-   */
+  /// Number of connections which are preparing to close.
+  ///
+  /// Note: These connections are also part of the [active] count as they might
+  /// still be sending data to the client before finally closing.
   int closing = 0;
 }
 
-/**
- * Headers for HTTP requests and responses.
- *
- * In some situations, headers are immutable:
- *
- * * [HttpRequest] and [HttpClientResponse] always have immutable headers.
- *
- * * [HttpResponse] and [HttpClientRequest] have immutable headers
- *   from the moment the body is written to.
- *
- * In these situations, the mutating methods throw exceptions.
- *
- * For all operations on HTTP headers the header name is
- * case-insensitive.
- *
- * To set the value of a header use the `set()` method:
- *
- *     request.headers.set(HttpHeaders.cacheControlHeader,
- *                         'max-age=3600, must-revalidate');
- *
- * To retrieve the value of a header use the `value()` method:
- *
- *     print(request.headers.value(HttpHeaders.userAgentHeader));
- *
- * An `HttpHeaders` object holds a list of values for each name
- * as the standard allows. In most cases a name holds only a single value,
- * The most common mode of operation is to use `set()` for setting a value,
- * and `value()` for retrieving a value.
- */
+/// Headers for HTTP requests and responses.
+///
+/// In some situations, headers are immutable:
+///
+/// * [HttpRequest] and [HttpClientResponse] always have immutable headers.
+///
+/// * [HttpResponse] and [HttpClientRequest] have immutable headers
+///   from the moment the body is written to.
+///
+/// In these situations, the mutating methods throw exceptions.
+///
+/// For all operations on HTTP headers the header name is
+/// case-insensitive.
+///
+/// To set the value of a header use the `set()` method:
+///
+///     request.headers.set(HttpHeaders.cacheControlHeader,
+///                         'max-age=3600, must-revalidate');
+///
+/// To retrieve the value of a header use the `value()` method:
+///
+///     print(request.headers.value(HttpHeaders.userAgentHeader));
+///
+/// An `HttpHeaders` object holds a list of values for each name
+/// as the standard allows. In most cases a name holds only a single value,
+/// The most common mode of operation is to use `set()` for setting a value,
+/// and `value()` for retrieving a value.
 abstract class HttpHeaders {
   static const acceptHeader = "accept";
   static const acceptCharsetHeader = "accept-charset";
@@ -559,7 +520,7 @@
   static const SET_COOKIE = setCookieHeader;
 
   // TODO(39783): Document this.
-  static const generalHeaders = const [
+  static const generalHeaders = [
     cacheControlHeader,
     connectionHeader,
     dateHeader,
@@ -574,7 +535,7 @@
   @Deprecated("Use generalHeaders instead")
   static const GENERAL_HEADERS = generalHeaders;
 
-  static const entityHeaders = const [
+  static const entityHeaders = [
     allowHeader,
     contentEncodingHeader,
     contentLanguageHeader,
@@ -590,7 +551,7 @@
   @Deprecated("Use entityHeaders instead")
   static const ENTITY_HEADERS = entityHeaders;
 
-  static const responseHeaders = const [
+  static const responseHeaders = [
     acceptRangesHeader,
     ageHeader,
     etagHeader,
@@ -605,7 +566,7 @@
   @Deprecated("Use responseHeaders instead")
   static const RESPONSE_HEADERS = responseHeaders;
 
-  static const requestHeaders = const [
+  static const requestHeaders = [
     acceptHeader,
     acceptCharsetHeader,
     acceptEncodingHeader,
@@ -630,207 +591,165 @@
   @Deprecated("Use requestHeaders instead")
   static const REQUEST_HEADERS = requestHeaders;
 
-  /**
-   * The date specified by the [dateHeader] header, if any.
-   */
+  /// The date specified by the [dateHeader] header, if any.
   DateTime? date;
 
-  /**
-   * The date and time specified by the [expiresHeader] header, if any.
-   */
+  /// The date and time specified by the [expiresHeader] header, if any.
   DateTime? expires;
 
-  /**
-   * The date and time specified by the [ifModifiedSinceHeader] header, if any.
-   */
+  /// The date and time specified by the [ifModifiedSinceHeader] header, if any.
   DateTime? ifModifiedSince;
 
-  /**
-   * The value of the [hostHeader] header, if any.
-   */
+  /// The value of the [hostHeader] header, if any.
   String? host;
 
-  /**
-   * The value of the port part of the [hostHeader] header, if any.
-   */
+  /// The value of the port part of the [hostHeader] header, if any.
   int? port;
 
-  /**
-   * The [ContentType] of the [contentTypeHeader] header, if any.
-   */
+  /// The [ContentType] of the [contentTypeHeader] header, if any.
   ContentType? contentType;
 
-  /**
-   * The value of the [contentLengthHeader] header, if any.
-   *
-   * The value is negative if there is no content length set.
-   */
+  /// The value of the [contentLengthHeader] header, if any.
+  ///
+  /// The value is negative if there is no content length set.
   int contentLength = -1;
 
-  /**
-   * Whether the connection is persistent (keep-alive).
-   */
+  /// Whether the connection is persistent (keep-alive).
   late bool persistentConnection;
 
-  /**
-   * Whether the connection uses chunked transfer encoding.
-   *
-   * Reflects and modifies the value of the [transferEncodingHeader] header.
-   */
+  /// Whether the connection uses chunked transfer encoding.
+  ///
+  /// Reflects and modifies the value of the [transferEncodingHeader] header.
   late bool chunkedTransferEncoding;
 
-  /**
-   * The values for the header named [name].
-   *
-   * Returns null if there is no header with the provided name,
-   * otherwise returns a new list containing the current values.
-   * Not that modifying the list does not change the header.
-   */
+  /// The values for the header named [name].
+  ///
+  /// Returns null if there is no header with the provided name,
+  /// otherwise returns a new list containing the current values.
+  /// Not that modifying the list does not change the header.
   List<String>? operator [](String name);
 
-  /**
-   * Convenience method for the value for a single valued header.
-   *
-   * The value must not have more than one value.
-   *
-   * Returns `null` if there is no header with the provided name.
-   */
+  /// Convenience method for the value for a single valued header.
+  ///
+  /// The value must not have more than one value.
+  ///
+  /// Returns `null` if there is no header with the provided name.
   String? value(String name);
 
-  /**
-   * Adds a header value.
-   *
-   * The header named [name] will have a string value derived from [value]
-   * added to its list of values.
-   *
-   * Some headers are single valued, and for these, adding a value will
-   * replace a previous value. If the [value] is a [DateTime], an
-   * HTTP date format will be applied. If the value is an [Iterable],
-   * each element will be added separately. For all other
-   * types the default [Object.toString] method will be used.
-   *
-   * Header names are converted to lower-case unless
-   * [preserveHeaderCase] is set to true. If two header names are
-   * the same when converted to lower-case, they are considered to be
-   * the same header, with one set of values.
-   *
-   * The current case of the a header name is that of the name used by
-   * the last [set] or [add] call for that header.
-   */
+  /// Adds a header value.
+  ///
+  /// The header named [name] will have a string value derived from [value]
+  /// added to its list of values.
+  ///
+  /// Some headers are single valued, and for these, adding a value will
+  /// replace a previous value. If the [value] is a [DateTime], an
+  /// HTTP date format will be applied. If the value is an [Iterable],
+  /// each element will be added separately. For all other
+  /// types the default [Object.toString] method will be used.
+  ///
+  /// Header names are converted to lower-case unless
+  /// [preserveHeaderCase] is set to true. If two header names are
+  /// the same when converted to lower-case, they are considered to be
+  /// the same header, with one set of values.
+  ///
+  /// The current case of the a header name is that of the name used by
+  /// the last [set] or [add] call for that header.
   void add(String name, Object value,
       {@Since("2.8") bool preserveHeaderCase = false});
 
-  /**
-   * Sets the header [name] to [value].
-   *
-   * Removes all existing values for the header named [name] and
-   * then [add]s [value] to it.
-   */
+  /// Sets the header [name] to [value].
+  ///
+  /// Removes all existing values for the header named [name] and
+  /// then [add]s [value] to it.
   void set(String name, Object value,
       {@Since("2.8") bool preserveHeaderCase = false});
 
-  /**
-   * Removes a specific value for a header name.
-   *
-   * Some headers have system supplied values which cannot be removed.
-   * For all other headers and values, the [value] is converted to a string
-   * in the same way as for [add], then that string value is removed from the
-   * current values of [name].
-   * If there are no remaining values for [name], the header is no longer
-   * considered present.
-   */
+  /// Removes a specific value for a header name.
+  ///
+  /// Some headers have system supplied values which cannot be removed.
+  /// For all other headers and values, the [value] is converted to a string
+  /// in the same way as for [add], then that string value is removed from the
+  /// current values of [name].
+  /// If there are no remaining values for [name], the header is no longer
+  /// considered present.
   void remove(String name, Object value);
 
-  /**
-   * Removes all values for the specified header name.
-   *
-   * Some headers have system supplied values which cannot be removed.
-   * All other values for [name] are removed.
-   * If there are no remaining values for [name], the header is no longer
-   * considered present.
-   */
+  /// Removes all values for the specified header name.
+  ///
+  /// Some headers have system supplied values which cannot be removed.
+  /// All other values for [name] are removed.
+  /// If there are no remaining values for [name], the header is no longer
+  /// considered present.
   void removeAll(String name);
 
-  /**
-   * Performs the [action] on each header.
-   *
-   * The [action] function is called with each header's name and a list
-   * of the header's values. The casing of the name string is determined by
-   * the last [add] or [set] operation for that particular header,
-   * which defaults to lower-casing the header name unless explicitly
-   * set to preserve the case.
-   */
-  void forEach(void action(String name, List<String> values));
+  /// Performs the [action] on each header.
+  ///
+  /// The [action] function is called with each header's name and a list
+  /// of the header's values. The casing of the name string is determined by
+  /// the last [add] or [set] operation for that particular header,
+  /// which defaults to lower-casing the header name unless explicitly
+  /// set to preserve the case.
+  void forEach(void Function(String name, List<String> values) action);
 
-  /**
-   * Disables folding for the header named [name] when sending the HTTP header.
-   *
-   * By default, multiple header values are folded into a
-   * single header line by separating the values with commas.
-   *
-   * The 'set-cookie' header has folding disabled by default.
-   */
+  /// Disables folding for the header named [name] when sending the HTTP header.
+  ///
+  /// By default, multiple header values are folded into a
+  /// single header line by separating the values with commas.
+  ///
+  /// The 'set-cookie' header has folding disabled by default.
   void noFolding(String name);
 
-  /**
-   * Removes all headers.
-   *
-   * Some headers have system supplied values which cannot be removed.
-   * All other header values are removed, and header names with not
-   * remaining values are no longer considered present.
-   */
+  /// Removes all headers.
+  ///
+  /// Some headers have system supplied values which cannot be removed.
+  /// All other header values are removed, and header names with not
+  /// remaining values are no longer considered present.
   void clear();
 }
 
-/**
- * Representation of a header value in the form:
- * ```plaintext
- * value; parameter1=value1; parameter2=value2
- * ```
- *
- * [HeaderValue] can be used to conveniently build and parse header
- * values on this form.
- *
- * Parameter values can be omitted, in which case the value is parsed as `null`.
- * Values can be doubled quoted to allow characters outside of the RFC 7230
- * token characters and backslash sequences can be used to represent the double
- * quote and backslash characters themselves.
- *
- * To build an "accepts" header with the value
- *
- *     text/plain; q=0.3, text/html
- *
- * use code like this:
- *
- *     HttpClientRequest request = ...;
- *     var v = new HeaderValue("text/plain", {"q": "0.3"});
- *     request.headers.add(HttpHeaders.acceptHeader, v);
- *     request.headers.add(HttpHeaders.acceptHeader, "text/html");
- *
- * To parse the header values use the [parse] static method.
- *
- *     HttpRequest request = ...;
- *     List<String> values = request.headers[HttpHeaders.acceptHeader];
- *     values.forEach((value) {
- *       HeaderValue v = HeaderValue.parse(value);
- *       // Use v.value and v.parameters
- *     });
- *
- * An instance of [HeaderValue] is immutable.
- */
+/// Representation of a header value in the form:
+/// ```plaintext
+/// value; parameter1=value1; parameter2=value2
+/// ```
+///
+/// [HeaderValue] can be used to conveniently build and parse header
+/// values on this form.
+///
+/// Parameter values can be omitted, in which case the value is parsed as `null`.
+/// Values can be doubled quoted to allow characters outside of the RFC 7230
+/// token characters and backslash sequences can be used to represent the double
+/// quote and backslash characters themselves.
+///
+/// To build an "accepts" header with the value
+///
+///     text/plain; q=0.3, text/html
+///
+/// use code like this:
+///
+///     HttpClientRequest request = ...;
+///     var v = new HeaderValue("text/plain", {"q": "0.3"});
+///     request.headers.add(HttpHeaders.acceptHeader, v);
+///     request.headers.add(HttpHeaders.acceptHeader, "text/html");
+///
+/// To parse the header values use the [parse] static method.
+///
+///     HttpRequest request = ...;
+///     List<String> values = request.headers[HttpHeaders.acceptHeader];
+///     values.forEach((value) {
+///       HeaderValue v = HeaderValue.parse(value);
+///       // Use v.value and v.parameters
+///     });
+///
+/// An instance of [HeaderValue] is immutable.
 abstract class HeaderValue {
-  /**
-   * Creates a new header value object setting the value and parameters.
-   */
+  /// Creates a new header value object setting the value and parameters.
   factory HeaderValue(
       [String value = "", Map<String, String?> parameters = const {}]) {
-    return new _HeaderValue(value, parameters);
+    return _HeaderValue(value, parameters);
   }
 
-  /**
-   * Creates a new header value object from parsing a header value
-   * string with both value and optional parameters.
-   */
+  /// Creates a new header value object from parsing a header value
+  /// string with both value and optional parameters.
   static HeaderValue parse(String value,
       {String parameterSeparator = ";",
       String? valueSeparator,
@@ -841,646 +760,534 @@
         preserveBackslash: preserveBackslash);
   }
 
-  /**
-   * The value of the header.
-   */
+  /// The value of the header.
   String get value;
 
-  /**
-   * A map of parameters.
-   *
-   * This map cannot be modified.
-   */
+  /// A map of parameters.
+  ///
+  /// This map cannot be modified.
   Map<String, String?> get parameters;
 
-  /**
-   * Returns the formatted string representation in the form:
-   * ```plaintext
-   * value; parameter1=value1; parameter2=value2
-   * ```
-   */
+  /// Returns the formatted string representation in the form:
+  /// ```plaintext
+  /// value; parameter1=value1; parameter2=value2
+  /// ```
   String toString();
 }
 
 abstract class HttpSession implements Map {
-  /**
-   * The id of the current session.
-   */
+  /// The id of the current session.
   String get id;
 
-  /**
-   * Destroys the session.
-   *
-   * This terminates the session and any further
-   * connections with this id will be given a new id and session.
-   */
+  /// Destroys the session.
+  ///
+  /// This terminates the session and any further
+  /// connections with this id will be given a new id and session.
   void destroy();
 
-  /**
-   * Sets a callback that will be called when the session is timed out.
-   *
-   * Calling this again will overwrite the previous value.
-   */
-  void set onTimeout(void callback());
+  /// Sets a callback that will be called when the session is timed out.
+  ///
+  /// Calling this again will overwrite the previous value.
+  void set onTimeout(void Function() callback);
 
-  /**
-   * Whether the session has not yet been sent to the client.
-   */
+  /// Whether the session has not yet been sent to the client.
   bool get isNew;
 }
 
-/**
- * A MIME/IANA media type used as the value of the
- * [HttpHeaders.contentTypeHeader] header.
- *
- * A [ContentType] is immutable.
- */
+/// A MIME/IANA media type used as the value of the
+/// [HttpHeaders.contentTypeHeader] header.
+///
+/// A [ContentType] is immutable.
 abstract class ContentType implements HeaderValue {
-  /**
-   * Content type for plain text using UTF-8 encoding.
-   *
-   *     text/plain; charset=utf-8
-   */
-  static final text = new ContentType("text", "plain", charset: "utf-8");
+  /// Content type for plain text using UTF-8 encoding.
+  ///
+  ///     text/plain; charset=utf-8
+  static final text = ContentType("text", "plain", charset: "utf-8");
   @Deprecated("Use text instead")
   static final TEXT = text;
 
-  /**
-   *  Content type for HTML using UTF-8 encoding.
-   *
-   *     text/html; charset=utf-8
-   */
-  static final html = new ContentType("text", "html", charset: "utf-8");
+  /// Content type for HTML using UTF-8 encoding.
+  ///
+  ///    text/html; charset=utf-8
+  static final html = ContentType("text", "html", charset: "utf-8");
   @Deprecated("Use html instead")
   static final HTML = html;
 
-  /**
-   *  Content type for JSON using UTF-8 encoding.
-   *
-   *     application/json; charset=utf-8
-   */
-  static final json = new ContentType("application", "json", charset: "utf-8");
+  /// Content type for JSON using UTF-8 encoding.
+  ///
+  ///    application/json; charset=utf-8
+  static final json = ContentType("application", "json", charset: "utf-8");
   @Deprecated("Use json instead")
   static final JSON = json;
 
-  /**
-   *  Content type for binary data.
-   *
-   *     application/octet-stream
-   */
-  static final binary = new ContentType("application", "octet-stream");
+  /// Content type for binary data.
+  ///
+  ///    application/octet-stream
+  static final binary = ContentType("application", "octet-stream");
   @Deprecated("Use binary instead")
   static final BINARY = binary;
 
-  /**
-   * Creates a new content type object setting the primary type and
-   * sub type. The charset and additional parameters can also be set
-   * using [charset] and [parameters]. If charset is passed and
-   * [parameters] contains charset as well the passed [charset] will
-   * override the value in parameters. Keys passed in parameters will be
-   * converted to lower case. The `charset` entry, whether passed as `charset`
-   * or in `parameters`, will have its value converted to lower-case.
-   */
+  /// Creates a new content type object setting the primary type and
+  /// sub type. The charset and additional parameters can also be set
+  /// using [charset] and [parameters]. If charset is passed and
+  /// [parameters] contains charset as well the passed [charset] will
+  /// override the value in parameters. Keys passed in parameters will be
+  /// converted to lower case. The `charset` entry, whether passed as `charset`
+  /// or in `parameters`, will have its value converted to lower-case.
   factory ContentType(String primaryType, String subType,
       {String? charset, Map<String, String?> parameters = const {}}) {
-    return new _ContentType(primaryType, subType, charset, parameters);
+    return _ContentType(primaryType, subType, charset, parameters);
   }
 
-  /**
-   * Creates a new content type object from parsing a Content-Type
-   * header value. As primary type, sub type and parameter names and
-   * values are not case sensitive all these values will be converted
-   * to lower case. Parsing this string
-   *
-   *     text/html; charset=utf-8
-   *
-   * will create a content type object with primary type "text",
-   * subtype "html" and parameter "charset" with value "utf-8".
-   * There may be more parameters supplied, but they are not recognized
-   * by this class.
-   */
+  /// Creates a new content type object from parsing a Content-Type
+  /// header value. As primary type, sub type and parameter names and
+  /// values are not case sensitive all these values will be converted
+  /// to lower case. Parsing this string
+  ///
+  ///     text/html; charset=utf-8
+  ///
+  /// will create a content type object with primary type "text",
+  /// subtype "html" and parameter "charset" with value "utf-8".
+  /// There may be more parameters supplied, but they are not recognized
+  /// by this class.
   static ContentType parse(String value) {
     return _ContentType.parse(value);
   }
 
-  /**
-   * Gets the MIME type and subtype, without any parameters.
-   *
-   * For the full content type `text/html;charset=utf-8`,
-   * the [mimeType] value is the string `text/html`.
-   */
+  /// Gets the MIME type and subtype, without any parameters.
+  ///
+  /// For the full content type `text/html;charset=utf-8`,
+  /// the [mimeType] value is the string `text/html`.
   String get mimeType;
 
-  /**
-   * Gets the primary type.
-   *
-   * For the full content type `text/html;charset=utf-8`,
-   * the [primaryType] value is the string `text`.
-   */
+  /// Gets the primary type.
+  ///
+  /// For the full content type `text/html;charset=utf-8`,
+  /// the [primaryType] value is the string `text`.
   String get primaryType;
 
-  /**
-   * Gets the subtype.
-   *
-   * For the full content type `text/html;charset=utf-8`,
-   * the [subType] value is the string `html`.
-   * May be the empty string.
-   */
+  /// Gets the subtype.
+  ///
+  /// For the full content type `text/html;charset=utf-8`,
+  /// the [subType] value is the string `html`.
+  /// May be the empty string.
   String get subType;
 
-  /**
-   * Gets the character set, if any.
-   *
-   * For the full content type `text/html;charset=utf-8`,
-   * the [charset] value is the string `utf-8`.
-   */
+  /// Gets the character set, if any.
+  ///
+  /// For the full content type `text/html;charset=utf-8`,
+  /// the [charset] value is the string `utf-8`.
   String? get charset;
 }
 
-/**
- * Representation of a cookie. For cookies received by the server as Cookie
- * header values only [name] and [value] properties will be set. When building a
- * cookie for the 'set-cookie' header in the server and when receiving cookies
- * in the client as 'set-cookie' headers all fields can be used.
- */
+/// Representation of a cookie. For cookies received by the server as Cookie
+/// header values only [name] and [value] properties will be set. When building a
+/// cookie for the 'set-cookie' header in the server and when receiving cookies
+/// in the client as 'set-cookie' headers all fields can be used.
 abstract class Cookie {
-  /**
-   * The name of the cookie.
-   *
-   * Must be a `token` as specified in RFC 6265.
-   *
-   * The allowed characters in a `token` are the visible ASCII characters,
-   * U+0021 (`!`) through U+007E (`~`), except the separator characters:
-   * `(`, `)`, `<`, `>`, `@`, `,`, `;`, `:`, `\`, `"`, `/`, `[`, `]`, `?`, `=`,
-   * `{`, and `}`.
-   */
+  /// The name of the cookie.
+  ///
+  /// Must be a `token` as specified in RFC 6265.
+  ///
+  /// The allowed characters in a `token` are the visible ASCII characters,
+  /// U+0021 (`!`) through U+007E (`~`), except the separator characters:
+  /// `(`, `)`, `<`, `>`, `@`, `,`, `;`, `:`, `\`, `"`, `/`, `[`, `]`, `?`, `=`,
+  /// `{`, and `}`.
   late String name;
 
-  /**
-   * The value of the cookie.
-   *
-   * Must be a `cookie-value` as specified in RFC 6265.
-   *
-   * The allowed characters in a cookie value are the visible ASCII characters,
-   * U+0021 (`!`) through U+007E (`~`) except the characters:
-   * `"`, `,`, `;` and `\`.
-   * Cookie values may be wrapped in a single pair of double quotes
-   * (U+0022, `"`).
-   */
+  /// The value of the cookie.
+  ///
+  /// Must be a `cookie-value` as specified in RFC 6265.
+  ///
+  /// The allowed characters in a cookie value are the visible ASCII characters,
+  /// U+0021 (`!`) through U+007E (`~`) except the characters:
+  /// `"`, `,`, `;` and `\`.
+  /// Cookie values may be wrapped in a single pair of double quotes
+  /// (U+0022, `"`).
   late String value;
 
-  /**
-   * The time at which the cookie expires.
-   */
+  /// The time at which the cookie expires.
   DateTime? expires;
 
-  /**
-   * The number of seconds until the cookie expires. A zero or negative value
-   * means the cookie has expired.
-   */
+  /// The number of seconds until the cookie expires. A zero or negative value
+  /// means the cookie has expired.
   int? maxAge;
 
-  /**
-   * The domain that the cookie applies to.
-   */
+  /// The domain that the cookie applies to.
   String? domain;
 
-  /**
-   * The path within the [domain] that the cookie applies to.
-   */
+  /// The path within the [domain] that the cookie applies to.
   String? path;
 
-  /**
-   * Whether to only send this cookie on secure connections.
-   */
+  /// Whether to only send this cookie on secure connections.
   bool secure = false;
 
-  /**
-   * Whether the cookie is only sent in the HTTP request and is not made
-   * available to client side scripts.
-   */
+  /// Whether the cookie is only sent in the HTTP request and is not made
+  /// available to client side scripts.
   bool httpOnly = false;
 
-  /**
-   * Creates a new cookie setting the name and value.
-   *
-   * [name] and [value] must be composed of valid characters according to RFC
-   * 6265.
-   *
-   * By default the value of `httpOnly` will be set to `true`.
-   */
-  factory Cookie(String name, String value) => new _Cookie(name, value);
+  /// Creates a new cookie setting the name and value.
+  ///
+  /// [name] and [value] must be composed of valid characters according to RFC
+  /// 6265.
+  ///
+  /// By default the value of `httpOnly` will be set to `true`.
+  factory Cookie(String name, String value) => _Cookie(name, value);
 
-  /**
-   * Creates a new cookie by parsing a header value from a 'set-cookie'
-   * header.
-   */
+  /// Creates a new cookie by parsing a header value from a 'set-cookie'
+  /// header.
   factory Cookie.fromSetCookieValue(String value) {
-    return new _Cookie.fromSetCookieValue(value);
+    return _Cookie.fromSetCookieValue(value);
   }
 
-  /**
-   * Returns the formatted string representation of the cookie. The
-   * string representation can be used for setting the Cookie or
-   * 'set-cookie' headers
-   */
+  /// Returns the formatted string representation of the cookie. The
+  /// string representation can be used for setting the Cookie or
+  /// 'set-cookie' headers
   String toString();
 }
 
-/**
- * A server-side object
- * that contains the content of and information about an HTTP request.
- *
- * __Note__: Check out the
- * [http_server](https://pub.dev/packages/http_server)
- * package, which makes working with the low-level
- * dart:io HTTP server subsystem easier.
- *
- * `HttpRequest` objects are generated by an [HttpServer],
- * which listens for HTTP requests on a specific host and port.
- * For each request received, the HttpServer, which is a [Stream],
- * generates an `HttpRequest` object and adds it to the stream.
- *
- * An `HttpRequest` object delivers the body content of the request
- * as a stream of byte lists.
- * The object also contains information about the request,
- * such as the method, URI, and headers.
- *
- * In the following code, an HttpServer listens
- * for HTTP requests. When the server receives a request,
- * it uses the HttpRequest object's `method` property to dispatch requests.
- *
- *     final HOST = InternetAddress.loopbackIPv4;
- *     final PORT = 80;
- *
- *     HttpServer.bind(HOST, PORT).then((_server) {
- *       _server.listen((HttpRequest request) {
- *         switch (request.method) {
- *           case 'GET':
- *             handleGetRequest(request);
- *             break;
- *           case 'POST':
- *             ...
- *         }
- *       },
- *       onError: handleError);    // listen() failed.
- *     }).catchError(handleError);
- *
- * An HttpRequest object provides access to the associated [HttpResponse]
- * object through the response property.
- * The server writes its response to the body of the HttpResponse object.
- * For example, here's a function that responds to a request:
- *
- *     void handleGetRequest(HttpRequest req) {
- *       HttpResponse res = req.response;
- *       res.write('Received request ${req.method}: ${req.uri.path}');
- *       res.close();
- *     }
- */
+/// A server-side object
+/// that contains the content of and information about an HTTP request.
+///
+/// __Note__: Check out the
+/// [http_server](https://pub.dev/packages/http_server)
+/// package, which makes working with the low-level
+/// dart:io HTTP server subsystem easier.
+///
+/// `HttpRequest` objects are generated by an [HttpServer],
+/// which listens for HTTP requests on a specific host and port.
+/// For each request received, the HttpServer, which is a [Stream],
+/// generates an `HttpRequest` object and adds it to the stream.
+///
+/// An `HttpRequest` object delivers the body content of the request
+/// as a stream of byte lists.
+/// The object also contains information about the request,
+/// such as the method, URI, and headers.
+///
+/// In the following code, an HttpServer listens
+/// for HTTP requests. When the server receives a request,
+/// it uses the HttpRequest object's `method` property to dispatch requests.
+///
+///     final HOST = InternetAddress.loopbackIPv4;
+///     final PORT = 80;
+///
+///     HttpServer.bind(HOST, PORT).then((_server) {
+///       _server.listen((HttpRequest request) {
+///         switch (request.method) {
+///           case 'GET':
+///             handleGetRequest(request);
+///             break;
+///           case 'POST':
+///             ...
+///         }
+///       },
+///       onError: handleError);    // listen() failed.
+///     }).catchError(handleError);
+///
+/// An HttpRequest object provides access to the associated [HttpResponse]
+/// object through the response property.
+/// The server writes its response to the body of the HttpResponse object.
+/// For example, here's a function that responds to a request:
+///
+///     void handleGetRequest(HttpRequest req) {
+///       HttpResponse res = req.response;
+///       res.write('Received request ${req.method}: ${req.uri.path}');
+///       res.close();
+///     }
 abstract class HttpRequest implements Stream<Uint8List> {
-  /**
-   * The content length of the request body.
-   *
-   * If the size of the request body is not known in advance,
-   * this value is -1.
-   */
+  /// The content length of the request body.
+  ///
+  /// If the size of the request body is not known in advance,
+  /// this value is -1.
   int get contentLength;
 
-  /**
-   * The method, such as 'GET' or 'POST', for the request.
-   */
+  /// The method, such as 'GET' or 'POST', for the request.
   String get method;
 
-  /**
-   * The URI for the request.
-   *
-   * This provides access to the
-   * path and query string for the request.
-   */
+  /// The URI for the request.
+  ///
+  /// This provides access to the
+  /// path and query string for the request.
   Uri get uri;
 
-  /**
-   * The requested URI for the request.
-   *
-   * The returned URI is reconstructed by using http-header fields, to access
-   * otherwise lost information, e.g. host and scheme.
-   *
-   * To reconstruct the scheme, first 'X-Forwarded-Proto' is checked, and then
-   * falling back to server type.
-   *
-   * To reconstruct the host, first 'X-Forwarded-Host' is checked, then 'Host'
-   * and finally calling back to server.
-   */
+  /// The requested URI for the request.
+  ///
+  /// The returned URI is reconstructed by using http-header fields, to access
+  /// otherwise lost information, e.g. host and scheme.
+  ///
+  /// To reconstruct the scheme, first 'X-Forwarded-Proto' is checked, and then
+  /// falling back to server type.
+  ///
+  /// To reconstruct the host, first 'X-Forwarded-Host' is checked, then 'Host'
+  /// and finally calling back to server.
   Uri get requestedUri;
 
-  /**
-   * The request headers.
-   *
-   * The returned [HttpHeaders] are immutable.
-   */
+  /// The request headers.
+  ///
+  /// The returned [HttpHeaders] are immutable.
   HttpHeaders get headers;
 
-  /**
-   * The cookies in the request, from the "Cookie" headers.
-   */
+  /// The cookies in the request, from the "Cookie" headers.
   List<Cookie> get cookies;
 
-  /**
-   * The persistent connection state signaled by the client.
-   */
+  /// The persistent connection state signaled by the client.
   bool get persistentConnection;
 
-  /**
-   * The client certificate of the client making the request.
-   *
-   * This value is null if the connection is not a secure TLS or SSL connection,
-   * or if the server does not request a client certificate, or if the client
-   * does not provide one.
-   */
+  /// The client certificate of the client making the request.
+  ///
+  /// This value is null if the connection is not a secure TLS or SSL connection,
+  /// or if the server does not request a client certificate, or if the client
+  /// does not provide one.
   X509Certificate? get certificate;
 
-  /**
-   * The session for the given request.
-   *
-   * If the session is being initialized by this call,
-   * [HttpSession.isNew] is true for the returned session.
-   * See [HttpServer.sessionTimeout] on how to change default timeout.
-   */
+  /// The session for the given request.
+  ///
+  /// If the session is being initialized by this call,
+  /// [HttpSession.isNew] is true for the returned session.
+  /// See [HttpServer.sessionTimeout] on how to change default timeout.
   HttpSession get session;
 
-  /**
-   * The HTTP protocol version used in the request,
-   * either "1.0" or "1.1".
-   */
+  /// The HTTP protocol version used in the request,
+  /// either "1.0" or "1.1".
   String get protocolVersion;
 
-  /**
-   * Information about the client connection.
-   *
-   * Returns `null` if the socket is not available.
-   */
+  /// Information about the client connection.
+  ///
+  /// Returns `null` if the socket is not available.
   HttpConnectionInfo? get connectionInfo;
 
-  /**
-   * The [HttpResponse] object, used for sending back the response to the
-   * client.
-   *
-   * If the [contentLength] of the body isn't 0, and the body isn't being read,
-   * any write calls on the [HttpResponse] automatically drain the request
-   * body.
-   */
+  /// The [HttpResponse] object, used for sending back the response to the
+  /// client.
+  ///
+  /// If the [contentLength] of the body isn't 0, and the body isn't being read,
+  /// any write calls on the [HttpResponse] automatically drain the request
+  /// body.
   HttpResponse get response;
 }
 
-/**
- * An HTTP response, which returns the headers and data
- * from the server to the client in response to an HTTP request.
- *
- * Every HttpRequest object provides access to the associated [HttpResponse]
- * object through the `response` property.
- * The server sends its response to the client by writing to the
- * HttpResponse object.
- *
- * ## Writing the response
- *
- * This class implements [IOSink].
- * After the header has been set up, the methods
- * from IOSink, such as `writeln()`, can be used to write
- * the body of the HTTP response.
- * Use the `close()` method to close the response and send it to the client.
- *
- *     server.listen((HttpRequest request) {
- *       request.response.write('Hello, world!');
- *       request.response.close();
- *     });
- *
- * When one of the IOSink methods is used for the
- * first time, the request header is sent. Calling any methods that
- * change the header after it is sent throws an exception.
- *
- * ## Setting the headers
- *
- * The HttpResponse object has a number of properties for setting up
- * the HTTP headers of the response.
- * When writing string data through the IOSink, the encoding used
- * is determined from the "charset" parameter of the
- * "Content-Type" header.
- *
- *     HttpResponse response = ...
- *     response.headers.contentType
- *         = new ContentType("application", "json", charset: "utf-8");
- *     response.write(...);  // Strings written will be UTF-8 encoded.
- *
- * If no charset is provided the default of ISO-8859-1 (Latin 1) will
- * be used.
- *
- *     HttpResponse response = ...
- *     response.headers.add(HttpHeaders.contentTypeHeader, "text/plain");
- *     response.write(...);  // Strings written will be ISO-8859-1 encoded.
- *
- * An exception is thrown if you use the `write()` method
- * while an unsupported content-type is set.
- */
+/// An HTTP response, which returns the headers and data
+/// from the server to the client in response to an HTTP request.
+///
+/// Every HttpRequest object provides access to the associated [HttpResponse]
+/// object through the `response` property.
+/// The server sends its response to the client by writing to the
+/// HttpResponse object.
+///
+/// ## Writing the response
+///
+/// This class implements [IOSink].
+/// After the header has been set up, the methods
+/// from IOSink, such as `writeln()`, can be used to write
+/// the body of the HTTP response.
+/// Use the `close()` method to close the response and send it to the client.
+///
+///     server.listen((HttpRequest request) {
+///       request.response.write('Hello, world!');
+///       request.response.close();
+///     });
+///
+/// When one of the IOSink methods is used for the
+/// first time, the request header is sent. Calling any methods that
+/// change the header after it is sent throws an exception.
+///
+/// ## Setting the headers
+///
+/// The HttpResponse object has a number of properties for setting up
+/// the HTTP headers of the response.
+/// When writing string data through the IOSink, the encoding used
+/// is determined from the "charset" parameter of the
+/// "Content-Type" header.
+///
+///     HttpResponse response = ...
+///     response.headers.contentType
+///         = new ContentType("application", "json", charset: "utf-8");
+///     response.write(...);  // Strings written will be UTF-8 encoded.
+///
+/// If no charset is provided the default of ISO-8859-1 (Latin 1) will
+/// be used.
+///
+///     HttpResponse response = ...
+///     response.headers.add(HttpHeaders.contentTypeHeader, "text/plain");
+///     response.write(...);  // Strings written will be ISO-8859-1 encoded.
+///
+/// An exception is thrown if you use the `write()` method
+/// while an unsupported content-type is set.
 abstract class HttpResponse implements IOSink {
   // TODO(ajohnsen): Add documentation of how to pipe a file to the response.
-  /**
-   * Gets and sets the content length of the response. If the size of
-   * the response is not known in advance set the content length to
-   * -1, which is also the default if not set.
-   */
+  /// Gets and sets the content length of the response. If the size of
+  /// the response is not known in advance set the content length to
+  /// -1, which is also the default if not set.
   int contentLength = -1;
 
-  /**
-   * The status code of the response.
-   *
-   * Any integer value is accepted. For
-   * the official HTTP status codes use the fields from
-   * [HttpStatus]. If no status code is explicitly set the default
-   * value [HttpStatus.ok] is used.
-   *
-   * The status code must be set before the body is written
-   * to. Setting the status code after writing to the response body or
-   * closing the response will throw a `StateError`.
-   */
+  /// The status code of the response.
+  ///
+  /// Any integer value is accepted. For
+  /// the official HTTP status codes use the fields from
+  /// [HttpStatus]. If no status code is explicitly set the default
+  /// value [HttpStatus.ok] is used.
+  ///
+  /// The status code must be set before the body is written
+  /// to. Setting the status code after writing to the response body or
+  /// closing the response will throw a `StateError`.
   int statusCode = HttpStatus.ok;
 
-  /**
-   * The reason phrase for the response.
-   *
-   * If no reason phrase is explicitly set, a default reason phrase is provided.
-   *
-   * The reason phrase must be set before the body is written
-   * to. Setting the reason phrase after writing to the response body
-   * or closing the response will throw a [StateError].
-   */
+  /// The reason phrase for the response.
+  ///
+  /// If no reason phrase is explicitly set, a default reason phrase is provided.
+  ///
+  /// The reason phrase must be set before the body is written
+  /// to. Setting the reason phrase after writing to the response body
+  /// or closing the response will throw a [StateError].
   late String reasonPhrase;
 
-  /**
-   * Gets and sets the persistent connection state. The initial value
-   * of this property is the persistent connection state from the
-   * request.
-   */
+  /// Gets and sets the persistent connection state. The initial value
+  /// of this property is the persistent connection state from the
+  /// request.
   late bool persistentConnection;
 
-  /**
-   * Set and get the [deadline] for the response. The deadline is timed from the
-   * time it's set. Setting a new deadline will override any previous deadline.
-   * When a deadline is exceeded, the response will be closed and any further
-   * data ignored.
-   *
-   * To disable a deadline, set the [deadline] to `null`.
-   *
-   * The [deadline] is `null` by default.
-   */
+  /// Set and get the [deadline] for the response. The deadline is timed from the
+  /// time it's set. Setting a new deadline will override any previous deadline.
+  /// When a deadline is exceeded, the response will be closed and any further
+  /// data ignored.
+  ///
+  /// To disable a deadline, set the [deadline] to `null`.
+  ///
+  /// The [deadline] is `null` by default.
   Duration? deadline;
 
-  /**
-   * Gets or sets if the [HttpResponse] should buffer output.
-   *
-   * Default value is `true`.
-   *
-   * __Note__: Disabling buffering of the output can result in very poor
-   * performance, when writing many small chunks.
-   */
+  /// Gets or sets if the [HttpResponse] should buffer output.
+  ///
+  /// Default value is `true`.
+  ///
+  /// __Note__: Disabling buffering of the output can result in very poor
+  /// performance, when writing many small chunks.
   bool bufferOutput = true;
 
-  /**
-   * Returns the response headers.
-   *
-   * The response headers can be modified until the response body is
-   * written to or closed. After that they become immutable.
-   */
+  /// Returns the response headers.
+  ///
+  /// The response headers can be modified until the response body is
+  /// written to or closed. After that they become immutable.
   HttpHeaders get headers;
 
-  /**
-   * Cookies to set in the client (in the 'set-cookie' header).
-   */
+  /// Cookies to set in the client (in the 'set-cookie' header).
   List<Cookie> get cookies;
 
-  /**
-   * Respond with a redirect to [location].
-   *
-   * The URI in [location] should be absolute, but there are no checks
-   * to enforce that.
-   *
-   * By default the HTTP status code `HttpStatus.movedTemporarily`
-   * (`302`) is used for the redirect, but an alternative one can be
-   * specified using the [status] argument.
-   *
-   * This method will also call `close`, and the returned future is
-   * the future returned by `close`.
-   */
+  /// Respond with a redirect to [location].
+  ///
+  /// The URI in [location] should be absolute, but there are no checks
+  /// to enforce that.
+  ///
+  /// By default the HTTP status code `HttpStatus.movedTemporarily`
+  /// (`302`) is used for the redirect, but an alternative one can be
+  /// specified using the [status] argument.
+  ///
+  /// This method will also call `close`, and the returned future is
+  /// the future returned by `close`.
   Future redirect(Uri location, {int status = HttpStatus.movedTemporarily});
 
-  /**
-   * Detaches the underlying socket from the HTTP server. When the
-   * socket is detached the HTTP server will no longer perform any
-   * operations on it.
-   *
-   * This is normally used when a HTTP upgrade request is received
-   * and the communication should continue with a different protocol.
-   *
-   * If [writeHeaders] is `true`, the status line and [headers] will be written
-   * to the socket before it's detached. If `false`, the socket is detached
-   * immediately, without any data written to the socket. Default is `true`.
-   */
+  /// Detaches the underlying socket from the HTTP server. When the
+  /// socket is detached the HTTP server will no longer perform any
+  /// operations on it.
+  ///
+  /// This is normally used when a HTTP upgrade request is received
+  /// and the communication should continue with a different protocol.
+  ///
+  /// If [writeHeaders] is `true`, the status line and [headers] will be written
+  /// to the socket before it's detached. If `false`, the socket is detached
+  /// immediately, without any data written to the socket. Default is `true`.
   Future<Socket> detachSocket({bool writeHeaders = true});
 
-  /**
-   * Gets information about the client connection. Returns `null` if the
-   * socket is not available.
-   */
+  /// Gets information about the client connection. Returns `null` if the
+  /// socket is not available.
   HttpConnectionInfo? get connectionInfo;
 }
 
-/**
- * A client that receives content, such as web pages, from
- * a server using the HTTP protocol.
- *
- * HttpClient contains a number of methods to send an [HttpClientRequest]
- * to an Http server and receive an [HttpClientResponse] back.
- * For example, you can use the [get], [getUrl], [post], and [postUrl] methods
- * for GET and POST requests, respectively.
- *
- * ## Making a simple GET request: an example
- *
- * A `getUrl` request is a two-step process, triggered by two [Future]s.
- * When the first future completes with a [HttpClientRequest], the underlying
- * network connection has been established, but no data has been sent.
- * In the callback function for the first future, the HTTP headers and body
- * can be set on the request. Either the first write to the request object
- * or a call to [close] sends the request to the server.
- *
- * When the HTTP response is received from the server,
- * the second future, which is returned by close,
- * completes with an [HttpClientResponse] object.
- * This object provides access to the headers and body of the response.
- * The body is available as a stream implemented by HttpClientResponse.
- * If a body is present, it must be read. Otherwise, it leads to resource
- * leaks. Consider using [HttpClientResponse.drain] if the body is unused.
- *
- *     HttpClient client = new HttpClient();
- *     client.getUrl(Uri.parse("http://www.example.com/"))
- *         .then((HttpClientRequest request) {
- *           // Optionally set up headers...
- *           // Optionally write to the request object...
- *           // Then call close.
- *           ...
- *           return request.close();
- *         })
- *         .then((HttpClientResponse response) {
- *           // Process the response.
- *           ...
- *         });
- *
- * The future for [HttpClientRequest] is created by methods such as
- * [getUrl] and [open].
- *
- * ## HTTPS connections
- *
- * An HttpClient can make HTTPS requests, connecting to a server using
- * the TLS (SSL) secure networking protocol. Calling [getUrl] with an
- * https: scheme will work automatically, if the server's certificate is
- * signed by a root CA (certificate authority) on the default list of
- * well-known trusted CAs, compiled by Mozilla.
- *
- * To add a custom trusted certificate authority, or to send a client
- * certificate to servers that request one, pass a [SecurityContext] object
- * as the optional `context` argument to the `HttpClient` constructor.
- * The desired security options can be set on the [SecurityContext] object.
- *
- * ## Headers
- *
- * All HttpClient requests set the following header by default:
- *
- *     Accept-Encoding: gzip
- *
- * This allows the HTTP server to use gzip compression for the body if
- * possible. If this behavior is not desired set the
- * `Accept-Encoding` header to something else.
- * To turn off gzip compression of the response, clear this header:
- *
- *      request.headers.removeAll(HttpHeaders.acceptEncodingHeader)
- *
- * ## Closing the HttpClient
- *
- * The HttpClient supports persistent connections and caches network
- * connections to reuse them for multiple requests whenever
- * possible. This means that network connections can be kept open for
- * some time after a request has completed. Use HttpClient.close
- * to force the HttpClient object to shut down and to close the idle
- * network connections.
- *
- * ## Turning proxies on and off
- *
- * By default the HttpClient uses the proxy configuration available
- * from the environment, see [findProxyFromEnvironment]. To turn off
- * the use of proxies set the [findProxy] property to
- * `null`.
- *
- *     HttpClient client = new HttpClient();
- *     client.findProxy = null;
- */
+/// A client that receives content, such as web pages, from
+/// a server using the HTTP protocol.
+///
+/// HttpClient contains a number of methods to send an [HttpClientRequest]
+/// to an Http server and receive an [HttpClientResponse] back.
+/// For example, you can use the [get], [getUrl], [post], and [postUrl] methods
+/// for GET and POST requests, respectively.
+///
+/// ## Making a simple GET request: an example
+///
+/// A `getUrl` request is a two-step process, triggered by two [Future]s.
+/// When the first future completes with a [HttpClientRequest], the underlying
+/// network connection has been established, but no data has been sent.
+/// In the callback function for the first future, the HTTP headers and body
+/// can be set on the request. Either the first write to the request object
+/// or a call to [close] sends the request to the server.
+///
+/// When the HTTP response is received from the server,
+/// the second future, which is returned by close,
+/// completes with an [HttpClientResponse] object.
+/// This object provides access to the headers and body of the response.
+/// The body is available as a stream implemented by HttpClientResponse.
+/// If a body is present, it must be read. Otherwise, it leads to resource
+/// leaks. Consider using [HttpClientResponse.drain] if the body is unused.
+///
+///     HttpClient client = new HttpClient();
+///     client.getUrl(Uri.parse("http://www.example.com/"))
+///         .then((HttpClientRequest request) {
+///           // Optionally set up headers...
+///           // Optionally write to the request object...
+///           // Then call close.
+///           ...
+///           return request.close();
+///         })
+///         .then((HttpClientResponse response) {
+///           // Process the response.
+///           ...
+///         });
+///
+/// The future for [HttpClientRequest] is created by methods such as
+/// [getUrl] and [open].
+///
+/// ## HTTPS connections
+///
+/// An HttpClient can make HTTPS requests, connecting to a server using
+/// the TLS (SSL) secure networking protocol. Calling [getUrl] with an
+/// https: scheme will work automatically, if the server's certificate is
+/// signed by a root CA (certificate authority) on the default list of
+/// well-known trusted CAs, compiled by Mozilla.
+///
+/// To add a custom trusted certificate authority, or to send a client
+/// certificate to servers that request one, pass a [SecurityContext] object
+/// as the optional `context` argument to the `HttpClient` constructor.
+/// The desired security options can be set on the [SecurityContext] object.
+///
+/// ## Headers
+///
+/// All HttpClient requests set the following header by default:
+///
+///     Accept-Encoding: gzip
+///
+/// This allows the HTTP server to use gzip compression for the body if
+/// possible. If this behavior is not desired set the
+/// `Accept-Encoding` header to something else.
+/// To turn off gzip compression of the response, clear this header:
+///
+///      request.headers.removeAll(HttpHeaders.acceptEncodingHeader)
+///
+/// ## Closing the HttpClient
+///
+/// The HttpClient supports persistent connections and caches network
+/// connections to reuse them for multiple requests whenever
+/// possible. This means that network connections can be kept open for
+/// some time after a request has completed. Use HttpClient.close
+/// to force the HttpClient object to shut down and to close the idle
+/// network connections.
+///
+/// ## Turning proxies on and off
+///
+/// By default the HttpClient uses the proxy configuration available
+/// from the environment, see [findProxyFromEnvironment]. To turn off
+/// the use of proxies set the [findProxy] property to
+/// `null`.
+///
+///     HttpClient client = new HttpClient();
+///     client.findProxy = null;
 abstract class HttpClient {
   static const int defaultHttpPort = 80;
   @Deprecated("Use defaultHttpPort instead")
@@ -1529,44 +1336,40 @@
   /// `null`.
   Duration? connectionTimeout;
 
-  /**
-   * Gets and sets the maximum number of live connections, to a single host.
-   *
-   * Increasing this number may lower performance and take up unwanted
-   * system resources.
-   *
-   * To disable, set to `null`.
-   *
-   * Default is `null`.
-   */
+  /// Gets and sets the maximum number of live connections, to a single host.
+  ///
+  /// Increasing this number may lower performance and take up unwanted
+  /// system resources.
+  ///
+  /// To disable, set to `null`.
+  ///
+  /// Default is `null`.
   int? maxConnectionsPerHost;
 
-  /**
-   * Gets and sets whether the body of a response will be automatically
-   * uncompressed.
-   *
-   * The body of an HTTP response can be compressed. In most
-   * situations providing the un-compressed body is most
-   * convenient. Therefore the default behavior is to un-compress the
-   * body. However in some situations (e.g. implementing a transparent
-   * proxy) keeping the uncompressed stream is required.
-   *
-   * NOTE: Headers in the response are never modified. This means
-   * that when automatic un-compression is turned on the value of the
-   * header `Content-Length` will reflect the length of the original
-   * compressed body. Likewise the header `Content-Encoding` will also
-   * have the original value indicating compression.
-   *
-   * NOTE: Automatic un-compression is only performed if the
-   * `Content-Encoding` header value is `gzip`.
-   *
-   * This value affects all responses produced by this client after the
-   * value is changed.
-   *
-   * To disable, set to `false`.
-   *
-   * Default is `true`.
-   */
+  /// Gets and sets whether the body of a response will be automatically
+  /// uncompressed.
+  ///
+  /// The body of an HTTP response can be compressed. In most
+  /// situations providing the un-compressed body is most
+  /// convenient. Therefore the default behavior is to un-compress the
+  /// body. However in some situations (e.g. implementing a transparent
+  /// proxy) keeping the uncompressed stream is required.
+  ///
+  /// NOTE: Headers in the response are never modified. This means
+  /// that when automatic un-compression is turned on the value of the
+  /// header `Content-Length` will reflect the length of the original
+  /// compressed body. Likewise the header `Content-Encoding` will also
+  /// have the original value indicating compression.
+  ///
+  /// NOTE: Automatic un-compression is only performed if the
+  /// `Content-Encoding` header value is `gzip`.
+  ///
+  /// This value affects all responses produced by this client after the
+  /// value is changed.
+  ///
+  /// To disable, set to `false`.
+  ///
+  /// Default is `true`.
   bool autoUncompress = true;
 
   /// Gets and sets the default value of the `User-Agent` header for all requests
@@ -1581,275 +1384,240 @@
   factory HttpClient({SecurityContext? context}) {
     HttpOverrides? overrides = HttpOverrides.current;
     if (overrides == null) {
-      return new _HttpClient(context);
+      return _HttpClient(context);
     }
     return overrides.createHttpClient(context);
   }
 
-  /**
-   * Opens a HTTP connection.
-   *
-   * The HTTP method to use is specified in [method], the server is
-   * specified using [host] and [port], and the path (including
-   * a possible query) is specified using [path].
-   * The path may also contain a URI fragment, which will be ignored.
-   *
-   * The `Host` header for the request will be set to the value [host]:[port]
-   * (if [host] is an IP address, it will still be used in the `Host` header).
-   * This can be overridden through the [HttpClientRequest] interface before
-   * the request is sent.
-   *
-   * For additional information on the sequence of events during an
-   * HTTP transaction, and the objects returned by the futures, see
-   * the overall documentation for the class [HttpClient].
-   */
+  /// Opens a HTTP connection.
+  ///
+  /// The HTTP method to use is specified in [method], the server is
+  /// specified using [host] and [port], and the path (including
+  /// a possible query) is specified using [path].
+  /// The path may also contain a URI fragment, which will be ignored.
+  ///
+  /// The `Host` header for the request will be set to the value [host]:[port]
+  /// (if [host] is an IP address, it will still be used in the `Host` header).
+  /// This can be overridden through the [HttpClientRequest] interface before
+  /// the request is sent.
+  ///
+  /// For additional information on the sequence of events during an
+  /// HTTP transaction, and the objects returned by the futures, see
+  /// the overall documentation for the class [HttpClient].
   Future<HttpClientRequest> open(
       String method, String host, int port, String path);
 
-  /**
-   * Opens a HTTP connection.
-   *
-   * The HTTP method is specified in [method] and the URL to use in
-   * [url].
-   *
-   * The `Host` header for the request will be set to the value
-   * [Uri.host]:[Uri.port] from [url] (if `url.host` is an IP address, it will
-   * still be used in the `Host` header). This can be overridden through the
-   * [HttpClientRequest] interface before the request is sent.
-   *
-   * For additional information on the sequence of events during an
-   * HTTP transaction, and the objects returned by the futures, see
-   * the overall documentation for the class [HttpClient].
-   */
+  /// Opens a HTTP connection.
+  ///
+  /// The HTTP method is specified in [method] and the URL to use in
+  /// [url].
+  ///
+  /// The `Host` header for the request will be set to the value
+  /// [Uri.host]:[Uri.port] from [url] (if `url.host` is an IP address, it will
+  /// still be used in the `Host` header). This can be overridden through the
+  /// [HttpClientRequest] interface before the request is sent.
+  ///
+  /// For additional information on the sequence of events during an
+  /// HTTP transaction, and the objects returned by the futures, see
+  /// the overall documentation for the class [HttpClient].
   Future<HttpClientRequest> openUrl(String method, Uri url);
 
-  /**
-   * Opens a HTTP connection using the GET method.
-   *
-   * The server is specified using [host] and [port], and the path
-   * (including a possible query) is specified using
-   * [path].
-   *
-   * See [open] for details.
-   */
+  /// Opens a HTTP connection using the GET method.
+  ///
+  /// The server is specified using [host] and [port], and the path
+  /// (including a possible query) is specified using
+  /// [path].
+  ///
+  /// See [open] for details.
   Future<HttpClientRequest> get(String host, int port, String path);
 
-  /**
-   * Opens a HTTP connection using the GET method.
-   *
-   * The URL to use is specified in [url].
-   *
-   * See [openUrl] for details.
-   */
+  /// Opens a HTTP connection using the GET method.
+  ///
+  /// The URL to use is specified in [url].
+  ///
+  /// See [openUrl] for details.
   Future<HttpClientRequest> getUrl(Uri url);
 
-  /**
-   * Opens a HTTP connection using the POST method.
-   *
-   * The server is specified using [host] and [port], and the path
-   * (including a possible query) is specified using
-   * [path].
-   *
-   * See [open] for details.
-   */
+  /// Opens a HTTP connection using the POST method.
+  ///
+  /// The server is specified using [host] and [port], and the path
+  /// (including a possible query) is specified using
+  /// [path].
+  ///
+  /// See [open] for details.
   Future<HttpClientRequest> post(String host, int port, String path);
 
-  /**
-   * Opens a HTTP connection using the POST method.
-   *
-   * The URL to use is specified in [url].
-   *
-   * See [openUrl] for details.
-   */
+  /// Opens a HTTP connection using the POST method.
+  ///
+  /// The URL to use is specified in [url].
+  ///
+  /// See [openUrl] for details.
   Future<HttpClientRequest> postUrl(Uri url);
 
-  /**
-   * Opens a HTTP connection using the PUT method.
-   *
-   * The server is specified using [host] and [port], and the path
-   * (including a possible query) is specified using [path].
-   *
-   * See [open] for details.
-   */
+  /// Opens a HTTP connection using the PUT method.
+  ///
+  /// The server is specified using [host] and [port], and the path
+  /// (including a possible query) is specified using [path].
+  ///
+  /// See [open] for details.
   Future<HttpClientRequest> put(String host, int port, String path);
 
-  /**
-   * Opens a HTTP connection using the PUT method.
-   *
-   * The URL to use is specified in [url].
-   *
-   * See [openUrl] for details.
-   */
+  /// Opens a HTTP connection using the PUT method.
+  ///
+  /// The URL to use is specified in [url].
+  ///
+  /// See [openUrl] for details.
   Future<HttpClientRequest> putUrl(Uri url);
 
-  /**
-   * Opens a HTTP connection using the DELETE method.
-   *
-   * The server is specified using [host] and [port], and the path
-   * (including a possible query) is specified using [path].
-   *
-   * See [open] for details.
-   */
+  /// Opens a HTTP connection using the DELETE method.
+  ///
+  /// The server is specified using [host] and [port], and the path
+  /// (including a possible query) is specified using [path].
+  ///
+  /// See [open] for details.
   Future<HttpClientRequest> delete(String host, int port, String path);
 
-  /**
-   * Opens a HTTP connection using the DELETE method.
-   *
-   * The URL to use is specified in [url].
-   *
-   * See [openUrl] for details.
-   */
+  /// Opens a HTTP connection using the DELETE method.
+  ///
+  /// The URL to use is specified in [url].
+  ///
+  /// See [openUrl] for details.
   Future<HttpClientRequest> deleteUrl(Uri url);
 
-  /**
-   * Opens a HTTP connection using the PATCH method.
-   *
-   * The server is specified using [host] and [port], and the path
-   * (including a possible query) is specified using [path].
-   *
-   * See [open] for details.
-   */
+  /// Opens a HTTP connection using the PATCH method.
+  ///
+  /// The server is specified using [host] and [port], and the path
+  /// (including a possible query) is specified using [path].
+  ///
+  /// See [open] for details.
   Future<HttpClientRequest> patch(String host, int port, String path);
 
-  /**
-   * Opens a HTTP connection using the PATCH method.
-   *
-   * The URL to use is specified in [url].
-   *
-   * See [openUrl] for details.
-   */
+  /// Opens a HTTP connection using the PATCH method.
+  ///
+  /// The URL to use is specified in [url].
+  ///
+  /// See [openUrl] for details.
   Future<HttpClientRequest> patchUrl(Uri url);
 
-  /**
-   * Opens a HTTP connection using the HEAD method.
-   *
-   * The server is specified using [host] and [port], and the path
-   * (including a possible query) is specified using [path].
-   *
-   * See [open] for details.
-   */
+  /// Opens a HTTP connection using the HEAD method.
+  ///
+  /// The server is specified using [host] and [port], and the path
+  /// (including a possible query) is specified using [path].
+  ///
+  /// See [open] for details.
   Future<HttpClientRequest> head(String host, int port, String path);
 
-  /**
-   * Opens a HTTP connection using the HEAD method.
-   *
-   * The URL to use is specified in [url].
-   *
-   * See [openUrl] for details.
-   */
+  /// Opens a HTTP connection using the HEAD method.
+  ///
+  /// The URL to use is specified in [url].
+  ///
+  /// See [openUrl] for details.
   Future<HttpClientRequest> headUrl(Uri url);
 
-  /**
-   * Sets the function to be called when a site is requesting
-   * authentication.
-   *
-   * The URL requested, the authentication scheme and the security realm
-   * from the server are passed in the arguments [f.url], [f.scheme] and
-   * [f.realm].
-   *
-   * The function returns a [Future] which should complete when the
-   * authentication has been resolved. If credentials cannot be
-   * provided the [Future] should complete with `false`. If
-   * credentials are available the function should add these using
-   * [addCredentials] before completing the [Future] with the value
-   * `true`.
-   *
-   * If the [Future] completes with `true` the request will be retried
-   * using the updated credentials, however, the retried request will not
-   * carry the original request payload. Otherwise response processing will
-   * continue normally.
-   *
-   * If it is known that the remote server requires authentication for all
-   * requests, it is advisable to use [addCredentials] directly, or manually
-   * set the `'authorization'` header on the request to avoid the overhead
-   * of a failed request, or issues due to missing request payload on retried
-   * request.
-   */
-  void set authenticate(Future<bool> f(Uri url, String scheme, String? realm)?);
+  /// Sets the function to be called when a site is requesting
+  /// authentication.
+  ///
+  /// The URL requested, the authentication scheme and the security realm
+  /// from the server are passed in the arguments [f.url], [f.scheme] and
+  /// [f.realm].
+  ///
+  /// The function returns a [Future] which should complete when the
+  /// authentication has been resolved. If credentials cannot be
+  /// provided the [Future] should complete with `false`. If
+  /// credentials are available the function should add these using
+  /// [addCredentials] before completing the [Future] with the value
+  /// `true`.
+  ///
+  /// If the [Future] completes with `true` the request will be retried
+  /// using the updated credentials, however, the retried request will not
+  /// carry the original request payload. Otherwise response processing will
+  /// continue normally.
+  ///
+  /// If it is known that the remote server requires authentication for all
+  /// requests, it is advisable to use [addCredentials] directly, or manually
+  /// set the `'authorization'` header on the request to avoid the overhead
+  /// of a failed request, or issues due to missing request payload on retried
+  /// request.
+  void set authenticate(
+      Future<bool> Function(Uri url, String scheme, String? realm)? f);
 
-  /**
-   * Add credentials to be used for authorizing HTTP requests.
-   */
+  /// Add credentials to be used for authorizing HTTP requests.
   void addCredentials(Uri url, String realm, HttpClientCredentials credentials);
 
-  /**
-   * Sets the function used to resolve the proxy server to be used for
-   * opening a HTTP connection to the specified [url]. If this
-   * function is not set, direct connections will always be used.
-   *
-   * The string returned by [f] must be in the format used by browser
-   * PAC (proxy auto-config) scripts. That is either
-   *
-   *     "DIRECT"
-   *
-   * for using a direct connection or
-   *
-   *     "PROXY host:port"
-   *
-   * for using the proxy server `host` on port `port`.
-   *
-   * A configuration can contain several configuration elements
-   * separated by semicolons, e.g.
-   *
-   *     "PROXY host:port; PROXY host2:port2; DIRECT"
-   *
-   * The static function [findProxyFromEnvironment] on this class can
-   * be used to implement proxy server resolving based on environment
-   * variables.
-   */
-  void set findProxy(String f(Uri url)?);
+  /// Sets the function used to resolve the proxy server to be used for
+  /// opening a HTTP connection to the specified [url]. If this
+  /// function is not set, direct connections will always be used.
+  ///
+  /// The string returned by [f] must be in the format used by browser
+  /// PAC (proxy auto-config) scripts. That is either
+  ///
+  ///     "DIRECT"
+  ///
+  /// for using a direct connection or
+  ///
+  ///     "PROXY host:port"
+  ///
+  /// for using the proxy server `host` on port `port`.
+  ///
+  /// A configuration can contain several configuration elements
+  /// separated by semicolons, e.g.
+  ///
+  ///     "PROXY host:port; PROXY host2:port2; DIRECT"
+  ///
+  /// The static function [findProxyFromEnvironment] on this class can
+  /// be used to implement proxy server resolving based on environment
+  /// variables.
+  void set findProxy(String Function(Uri url)? f);
 
-  /**
-   * Function for resolving the proxy server to be used for a HTTP
-   * connection from the proxy configuration specified through
-   * environment variables.
-   *
-   * The following environment variables are taken into account:
-   *
-   *     http_proxy
-   *     https_proxy
-   *     no_proxy
-   *     HTTP_PROXY
-   *     HTTPS_PROXY
-   *     NO_PROXY
-   *
-   * [:http_proxy:] and [:HTTP_PROXY:] specify the proxy server to use for
-   * http:// urls. Use the format [:hostname:port:]. If no port is used a
-   * default of 1080 will be used. If both are set the lower case one takes
-   * precedence.
-   *
-   * [:https_proxy:] and [:HTTPS_PROXY:] specify the proxy server to use for
-   * https:// urls. Use the format [:hostname:port:]. If no port is used a
-   * default of 1080 will be used. If both are set the lower case one takes
-   * precedence.
-   *
-   * [:no_proxy:] and [:NO_PROXY:] specify a comma separated list of
-   * postfixes of hostnames for which not to use the proxy
-   * server. E.g. the value "localhost,127.0.0.1" will make requests
-   * to both "localhost" and "127.0.0.1" not use a proxy. If both are set
-   * the lower case one takes precedence.
-   *
-   * To activate this way of resolving proxies assign this function to
-   * the [findProxy] property on the [HttpClient].
-   *
-   *     HttpClient client = new HttpClient();
-   *     client.findProxy = HttpClient.findProxyFromEnvironment;
-   *
-   * If you don't want to use the system environment you can use a
-   * different one by wrapping the function.
-   *
-   *     HttpClient client = new HttpClient();
-   *     client.findProxy = (url) {
-   *       return HttpClient.findProxyFromEnvironment(
-   *           url, environment: {"http_proxy": ..., "no_proxy": ...});
-   *     }
-   *
-   * If a proxy requires authentication it is possible to configure
-   * the username and password as well. Use the format
-   * [:username:password@hostname:port:] to include the username and
-   * password. Alternatively the API [addProxyCredentials] can be used
-   * to set credentials for proxies which require authentication.
-   */
+  /// Function for resolving the proxy server to be used for a HTTP
+  /// connection from the proxy configuration specified through
+  /// environment variables.
+  ///
+  /// The following environment variables are taken into account:
+  ///
+  ///     http_proxy
+  ///     https_proxy
+  ///     no_proxy
+  ///     HTTP_PROXY
+  ///     HTTPS_PROXY
+  ///     NO_PROXY
+  ///
+  /// [:http_proxy:] and [:HTTP_PROXY:] specify the proxy server to use for
+  /// http:// urls. Use the format [:hostname:port:]. If no port is used a
+  /// default of 1080 will be used. If both are set the lower case one takes
+  /// precedence.
+  ///
+  /// [:https_proxy:] and [:HTTPS_PROXY:] specify the proxy server to use for
+  /// https:// urls. Use the format [:hostname:port:]. If no port is used a
+  /// default of 1080 will be used. If both are set the lower case one takes
+  /// precedence.
+  ///
+  /// [:no_proxy:] and [:NO_PROXY:] specify a comma separated list of
+  /// postfixes of hostnames for which not to use the proxy
+  /// server. E.g. the value "localhost,127.0.0.1" will make requests
+  /// to both "localhost" and "127.0.0.1" not use a proxy. If both are set
+  /// the lower case one takes precedence.
+  ///
+  /// To activate this way of resolving proxies assign this function to
+  /// the [findProxy] property on the [HttpClient].
+  ///
+  ///     HttpClient client = new HttpClient();
+  ///     client.findProxy = HttpClient.findProxyFromEnvironment;
+  ///
+  /// If you don't want to use the system environment you can use a
+  /// different one by wrapping the function.
+  ///
+  ///     HttpClient client = new HttpClient();
+  ///     client.findProxy = (url) {
+  ///       return HttpClient.findProxyFromEnvironment(
+  ///           url, environment: {"http_proxy": ..., "no_proxy": ...});
+  ///     }
+  ///
+  /// If a proxy requires authentication it is possible to configure
+  /// the username and password as well. Use the format
+  /// [:username:password@hostname:port:] to include the username and
+  /// password. Alternatively the API [addProxyCredentials] can be used
+  /// to set credentials for proxies which require authentication.
   static String findProxyFromEnvironment(Uri url,
       {Map<String, String>? environment}) {
     HttpOverrides? overrides = HttpOverrides.current;
@@ -1859,58 +1627,54 @@
     return overrides.findProxyFromEnvironment(url, environment);
   }
 
-  /**
-   * Sets the function to be called when a proxy is requesting
-   * authentication.
-   *
-   * Information on the proxy in use, the authentication scheme
-   * and the security realm for the authentication
-   * are passed in the arguments [f.host], [f.port], [f.scheme] and [f.realm].
-   *
-   * The function returns a [Future] which should complete when the
-   * authentication has been resolved. If credentials cannot be
-   * provided the [Future] should complete with `false`. If
-   * credentials are available the function should add these using
-   * [addProxyCredentials] before completing the [Future] with the value
-   * `true`.
-   *
-   * If the [Future] completes with `true` the request will be retried
-   * using the updated credentials. Otherwise response processing will
-   * continue normally.
-   */
+  /// Sets the function to be called when a proxy is requesting
+  /// authentication.
+  ///
+  /// Information on the proxy in use, the authentication scheme
+  /// and the security realm for the authentication
+  /// are passed in the arguments [f.host], [f.port], [f.scheme] and [f.realm].
+  ///
+  /// The function returns a [Future] which should complete when the
+  /// authentication has been resolved. If credentials cannot be
+  /// provided the [Future] should complete with `false`. If
+  /// credentials are available the function should add these using
+  /// [addProxyCredentials] before completing the [Future] with the value
+  /// `true`.
+  ///
+  /// If the [Future] completes with `true` the request will be retried
+  /// using the updated credentials. Otherwise response processing will
+  /// continue normally.
   void set authenticateProxy(
-      Future<bool> f(String host, int port, String scheme, String? realm)?);
+      Future<bool> Function(
+              String host, int port, String scheme, String? realm)?
+          f);
 
-  /**
-   * Add credentials to be used for authorizing HTTP proxies.
-   */
+  /// Add credentials to be used for authorizing HTTP proxies.
   void addProxyCredentials(
       String host, int port, String realm, HttpClientCredentials credentials);
 
-  /**
-   * Sets a callback that will decide whether to accept a secure connection
-   * with a server certificate that cannot be authenticated by any of our
-   * trusted root certificates.
-   *
-   * When an secure HTTP request if made, using this HttpClient, and the
-   * server returns a server certificate that cannot be authenticated, the
-   * callback is called asynchronously with the [X509Certificate] object and
-   * the server's hostname and port.  If the value of [badCertificateCallback]
-   * is `null`, the bad certificate is rejected, as if the callback
-   * returned `false`
-   *
-   * If the callback returns true, the secure connection is accepted and the
-   * [:Future<HttpClientRequest>:] that was returned from the call making the
-   * request completes with a valid HttpRequest object. If the callback returns
-   * false, the [:Future<HttpClientRequest>:] completes with an exception.
-   *
-   * If a bad certificate is received on a connection attempt, the library calls
-   * the function that was the value of badCertificateCallback at the time
-   * the request is made, even if the value of badCertificateCallback
-   * has changed since then.
-   */
+  /// Sets a callback that will decide whether to accept a secure connection
+  /// with a server certificate that cannot be authenticated by any of our
+  /// trusted root certificates.
+  ///
+  /// When an secure HTTP request if made, using this HttpClient, and the
+  /// server returns a server certificate that cannot be authenticated, the
+  /// callback is called asynchronously with the [X509Certificate] object and
+  /// the server's hostname and port.  If the value of [badCertificateCallback]
+  /// is `null`, the bad certificate is rejected, as if the callback
+  /// returned `false`
+  ///
+  /// If the callback returns true, the secure connection is accepted and the
+  /// [:Future<HttpClientRequest>:] that was returned from the call making the
+  /// request completes with a valid HttpRequest object. If the callback returns
+  /// false, the [:Future<HttpClientRequest>:] completes with an exception.
+  ///
+  /// If a bad certificate is received on a connection attempt, the library calls
+  /// the function that was the value of badCertificateCallback at the time
+  /// the request is made, even if the value of badCertificateCallback
+  /// has changed since then.
   void set badCertificateCallback(
-      bool callback(X509Certificate cert, String host, int port)?);
+      bool Function(X509Certificate cert, String host, int port)? callback);
 
   /// Shuts down the HTTP client.
   ///
@@ -1923,84 +1687,72 @@
   void close({bool force = false});
 }
 
-/**
- * HTTP request for a client connection.
- *
- * To set up a request, set the headers using the headers property
- * provided in this class and write the data to the body of the request.
- * HttpClientRequest is an [IOSink]. Use the methods from IOSink,
- * such as writeCharCode(), to write the body of the HTTP
- * request. When one of the IOSink methods is used for the first
- * time, the request header is sent. Calling any methods that
- * change the header after it is sent throws an exception.
- *
- * When writing string data through the [IOSink] the
- * encoding used is determined from the "charset" parameter of
- * the "Content-Type" header.
- *
- *     HttpClientRequest request = ...
- *     request.headers.contentType
- *         = new ContentType("application", "json", charset: "utf-8");
- *     request.write(...);  // Strings written will be UTF-8 encoded.
- *
- * If no charset is provided the default of ISO-8859-1 (Latin 1) is
- * be used.
- *
- *     HttpClientRequest request = ...
- *     request.headers.add(HttpHeaders.contentTypeHeader, "text/plain");
- *     request.write(...);  // Strings written will be ISO-8859-1 encoded.
- *
- * An exception is thrown if you use an unsupported encoding and the
- * `write()` method being used takes a string parameter.
- */
+/// HTTP request for a client connection.
+///
+/// To set up a request, set the headers using the headers property
+/// provided in this class and write the data to the body of the request.
+/// HttpClientRequest is an [IOSink]. Use the methods from IOSink,
+/// such as writeCharCode(), to write the body of the HTTP
+/// request. When one of the IOSink methods is used for the first
+/// time, the request header is sent. Calling any methods that
+/// change the header after it is sent throws an exception.
+///
+/// When writing string data through the [IOSink] the
+/// encoding used is determined from the "charset" parameter of
+/// the "Content-Type" header.
+///
+///     HttpClientRequest request = ...
+///     request.headers.contentType
+///         = new ContentType("application", "json", charset: "utf-8");
+///     request.write(...);  // Strings written will be UTF-8 encoded.
+///
+/// If no charset is provided the default of ISO-8859-1 (Latin 1) is
+/// be used.
+///
+///     HttpClientRequest request = ...
+///     request.headers.add(HttpHeaders.contentTypeHeader, "text/plain");
+///     request.write(...);  // Strings written will be ISO-8859-1 encoded.
+///
+/// An exception is thrown if you use an unsupported encoding and the
+/// `write()` method being used takes a string parameter.
 abstract class HttpClientRequest implements IOSink {
-  /**
-   * The requested persistent connection state.
-   *
-   * The default value is `true`.
-   */
+  /// The requested persistent connection state.
+  ///
+  /// The default value is `true`.
   bool persistentConnection = true;
 
-  /**
-   * Whether to follow redirects automatically.
-   *
-   * Set this property to `false` if this request should not
-   * automatically follow redirects. The default is `true`.
-   *
-   * Automatic redirect will only happen for "GET" and "HEAD" requests
-   * and only for the status codes [HttpStatus.movedPermanently]
-   * (301), [HttpStatus.found] (302),
-   * [HttpStatus.movedTemporarily] (302, alias for
-   * [HttpStatus.found]), [HttpStatus.seeOther] (303),
-   * [HttpStatus.temporaryRedirect] (307) and
-   * [HttpStatus.permanentRedirect] (308). For
-   * [HttpStatus.seeOther] (303) automatic redirect will also happen
-   * for "POST" requests with the method changed to "GET" when
-   * following the redirect.
-   *
-   * All headers added to the request will be added to the redirection
-   * request(s). However, any body send with the request will not be
-   * part of the redirection request(s).
-   */
+  /// Whether to follow redirects automatically.
+  ///
+  /// Set this property to `false` if this request should not
+  /// automatically follow redirects. The default is `true`.
+  ///
+  /// Automatic redirect will only happen for "GET" and "HEAD" requests
+  /// and only for the status codes [HttpStatus.movedPermanently]
+  /// (301), [HttpStatus.found] (302),
+  /// [HttpStatus.movedTemporarily] (302, alias for
+  /// [HttpStatus.found]), [HttpStatus.seeOther] (303),
+  /// [HttpStatus.temporaryRedirect] (307) and
+  /// [HttpStatus.permanentRedirect] (308). For
+  /// [HttpStatus.seeOther] (303) automatic redirect will also happen
+  /// for "POST" requests with the method changed to "GET" when
+  /// following the redirect.
+  ///
+  /// All headers added to the request will be added to the redirection
+  /// request(s). However, any body send with the request will not be
+  /// part of the redirection request(s).
   bool followRedirects = true;
 
-  /**
-   * Set this property to the maximum number of redirects to follow
-   * when [followRedirects] is `true`. If this number is exceeded
-   * an error event will be added with a [RedirectException].
-   *
-   * The default value is 5.
-   */
+  /// Set this property to the maximum number of redirects to follow
+  /// when [followRedirects] is `true`. If this number is exceeded
+  /// an error event will be added with a [RedirectException].
+  ///
+  /// The default value is 5.
   int maxRedirects = 5;
 
-  /**
-   * The method of the request.
-   */
+  /// The method of the request.
   String get method;
 
-  /**
-   * The uri of the request.
-   */
+  /// The uri of the request.
   Uri get uri;
 
   /// Gets and sets the content length of the request.
@@ -2009,28 +1761,22 @@
   /// -1, which is also the default.
   int contentLength = -1;
 
-  /**
-   * Gets or sets if the [HttpClientRequest] should buffer output.
-   *
-   * Default value is `true`.
-   *
-   * __Note__: Disabling buffering of the output can result in very poor
-   * performance, when writing many small chunks.
-   */
+  /// Gets or sets if the [HttpClientRequest] should buffer output.
+  ///
+  /// Default value is `true`.
+  ///
+  /// __Note__: Disabling buffering of the output can result in very poor
+  /// performance, when writing many small chunks.
   bool bufferOutput = true;
 
-  /**
-   * Returns the client request headers.
-   *
-   * The client request headers can be modified until the client
-   * request body is written to or closed. After that they become
-   * immutable.
-   */
+  /// Returns the client request headers.
+  ///
+  /// The client request headers can be modified until the client
+  /// request body is written to or closed. After that they become
+  /// immutable.
   HttpHeaders get headers;
 
-  /**
-   * Cookies to present to the server (in the 'cookie' header).
-   */
+  /// Cookies to present to the server (in the 'cookie' header).
   List<Cookie> get cookies;
 
   /// A [HttpClientResponse] future that will complete once the response is
@@ -2040,9 +1786,7 @@
   /// complete with an error.
   Future<HttpClientResponse> get done;
 
-  /**
-   * Close the request for input. Returns the value of [done].
-   */
+  /// Close the request for input. Returns the value of [done].
   Future<HttpClientResponse> close();
 
   /// Gets information about the client connection.
@@ -2079,48 +1823,40 @@
   void abort([Object? exception, StackTrace? stackTrace]);
 }
 
-/**
- * HTTP response for a client connection.
- *
- * The body of a [HttpClientResponse] object is a
- * [Stream] of data from the server. Listen to the body to handle
- * the data and be notified when the entire body is received.
- *
- *     new HttpClient().get('localhost', 80, '/file.txt')
- *          .then((HttpClientRequest request) => request.close())
- *          .then((HttpClientResponse response) {
- *            response.transform(utf8.decoder).listen((contents) {
- *              // handle data
- *            });
- *          });
- */
+/// HTTP response for a client connection.
+///
+/// The body of a [HttpClientResponse] object is a
+/// [Stream] of data from the server. Listen to the body to handle
+/// the data and be notified when the entire body is received.
+///
+///     new HttpClient().get('localhost', 80, '/file.txt')
+///          .then((HttpClientRequest request) => request.close())
+///          .then((HttpClientResponse response) {
+///            response.transform(utf8.decoder).listen((contents) {
+///              // handle data
+///            });
+///          });
 abstract class HttpClientResponse implements Stream<List<int>> {
-  /**
-   * Returns the status code.
-   *
-   * The status code must be set before the body is written
-   * to. Setting the status code after writing to the body will throw
-   * a `StateError`.
-   */
+  /// Returns the status code.
+  ///
+  /// The status code must be set before the body is written
+  /// to. Setting the status code after writing to the body will throw
+  /// a `StateError`.
   int get statusCode;
 
-  /**
-   * Returns the reason phrase associated with the status code.
-   *
-   * The reason phrase must be set before the body is written
-   * to. Setting the reason phrase after writing to the body will throw
-   * a `StateError`.
-   */
+  /// Returns the reason phrase associated with the status code.
+  ///
+  /// The reason phrase must be set before the body is written
+  /// to. Setting the reason phrase after writing to the body will throw
+  /// a `StateError`.
   String get reasonPhrase;
 
-  /**
-   * Returns the content length of the response body. Returns -1 if the size of
-   * the response body is not known in advance.
-   *
-   * If the content length needs to be set, it must be set before the
-   * body is written to. Setting the content length after writing to the body
-   * will throw a `StateError`.
-   */
+  /// Returns the content length of the response body. Returns -1 if the size of
+  /// the response body is not known in advance.
+  ///
+  /// If the content length needs to be set, it must be set before the
+  /// body is written to. Setting the content length after writing to the body
+  /// will throw a `StateError`.
   int get contentLength;
 
   /// The compression state of the response.
@@ -2131,82 +1867,64 @@
   @Since("2.4")
   HttpClientResponseCompressionState get compressionState;
 
-  /**
-   * Gets the persistent connection state returned by the server.
-   *
-   * If the persistent connection state needs to be set, it must be
-   * set before the body is written to. Setting the persistent connection state
-   * after writing to the body will throw a `StateError`.
-   */
+  /// Gets the persistent connection state returned by the server.
+  ///
+  /// If the persistent connection state needs to be set, it must be
+  /// set before the body is written to. Setting the persistent connection state
+  /// after writing to the body will throw a `StateError`.
   bool get persistentConnection;
 
-  /**
-   * Returns whether the status code is one of the normal redirect
-   * codes [HttpStatus.movedPermanently], [HttpStatus.found],
-   * [HttpStatus.movedTemporarily], [HttpStatus.seeOther] and
-   * [HttpStatus.temporaryRedirect].
-   */
+  /// Returns whether the status code is one of the normal redirect
+  /// codes [HttpStatus.movedPermanently], [HttpStatus.found],
+  /// [HttpStatus.movedTemporarily], [HttpStatus.seeOther] and
+  /// [HttpStatus.temporaryRedirect].
   bool get isRedirect;
 
-  /**
-   * Returns the series of redirects this connection has been through. The
-   * list will be empty if no redirects were followed. [redirects] will be
-   * updated both in the case of an automatic and a manual redirect.
-   */
+  /// Returns the series of redirects this connection has been through. The
+  /// list will be empty if no redirects were followed. [redirects] will be
+  /// updated both in the case of an automatic and a manual redirect.
   List<RedirectInfo> get redirects;
 
-  /**
-   * Redirects this connection to a new URL. The default value for
-   * [method] is the method for the current request. The default value
-   * for [url] is the value of the [HttpHeaders.locationHeader] header of
-   * the current response. All body data must have been read from the
-   * current response before calling [redirect].
-   *
-   * All headers added to the request will be added to the redirection
-   * request. However, any body sent with the request will not be
-   * part of the redirection request.
-   *
-   * If [followLoops] is set to `true`, redirect will follow the redirect,
-   * even if the URL was already visited. The default value is `false`.
-   *
-   * The method will ignore [HttpClientRequest.maxRedirects]
-   * and will always perform the redirect.
-   */
+  /// Redirects this connection to a new URL. The default value for
+  /// [method] is the method for the current request. The default value
+  /// for [url] is the value of the [HttpHeaders.locationHeader] header of
+  /// the current response. All body data must have been read from the
+  /// current response before calling [redirect].
+  ///
+  /// All headers added to the request will be added to the redirection
+  /// request. However, any body sent with the request will not be
+  /// part of the redirection request.
+  ///
+  /// If [followLoops] is set to `true`, redirect will follow the redirect,
+  /// even if the URL was already visited. The default value is `false`.
+  ///
+  /// The method will ignore [HttpClientRequest.maxRedirects]
+  /// and will always perform the redirect.
   Future<HttpClientResponse> redirect(
       [String? method, Uri? url, bool? followLoops]);
 
-  /**
-   * Returns the client response headers.
-   *
-   * The client response headers are immutable.
-   */
+  /// Returns the client response headers.
+  ///
+  /// The client response headers are immutable.
   HttpHeaders get headers;
 
-  /**
-   * Detach the underlying socket from the HTTP client. When the
-   * socket is detached the HTTP client will no longer perform any
-   * operations on it.
-   *
-   * This is normally used when a HTTP upgrade is negotiated and the
-   * communication should continue with a different protocol.
-   */
+  /// Detach the underlying socket from the HTTP client. When the
+  /// socket is detached the HTTP client will no longer perform any
+  /// operations on it.
+  ///
+  /// This is normally used when a HTTP upgrade is negotiated and the
+  /// communication should continue with a different protocol.
   Future<Socket> detachSocket();
 
-  /**
-   * Cookies set by the server (from the 'set-cookie' header).
-   */
+  /// Cookies set by the server (from the 'set-cookie' header).
   List<Cookie> get cookies;
 
-  /**
-   * Returns the certificate of the HTTPS server providing the response.
-   * Returns null if the connection is not a secure TLS or SSL connection.
-   */
+  /// Returns the certificate of the HTTPS server providing the response.
+  /// Returns null if the connection is not a secure TLS or SSL connection.
   X509Certificate? get certificate;
 
-  /**
-   * Gets information about the client connection. Returns `null` if the socket
-   * is not available.
-   */
+  /// Gets information about the client connection. Returns `null` if the socket
+  /// is not available.
   HttpConnectionInfo? get connectionInfo;
 }
 
@@ -2255,62 +1973,46 @@
 
 abstract class HttpClientCredentials {}
 
-/**
- * Represents credentials for basic authentication.
- */
+/// Represents credentials for basic authentication.
 abstract class HttpClientBasicCredentials extends HttpClientCredentials {
   factory HttpClientBasicCredentials(String username, String password) =>
-      new _HttpClientBasicCredentials(username, password);
+      _HttpClientBasicCredentials(username, password);
 }
 
-/**
- * Represents credentials for digest authentication. Digest
- * authentication is only supported for servers using the MD5
- * algorithm and quality of protection (qop) of either "none" or
- * "auth".
- */
+/// Represents credentials for digest authentication. Digest
+/// authentication is only supported for servers using the MD5
+/// algorithm and quality of protection (qop) of either "none" or
+/// "auth".
 abstract class HttpClientDigestCredentials extends HttpClientCredentials {
   factory HttpClientDigestCredentials(String username, String password) =>
-      new _HttpClientDigestCredentials(username, password);
+      _HttpClientDigestCredentials(username, password);
 }
 
-/**
- * Information about an [HttpRequest], [HttpResponse], [HttpClientRequest], or
- * [HttpClientResponse] connection.
- */
+/// Information about an [HttpRequest], [HttpResponse], [HttpClientRequest], or
+/// [HttpClientResponse] connection.
 abstract class HttpConnectionInfo {
   InternetAddress get remoteAddress;
   int get remotePort;
   int get localPort;
 }
 
-/**
- * Redirect information.
- */
+/// Redirect information.
 abstract class RedirectInfo {
-  /**
-   * Returns the status code used for the redirect.
-   */
+  /// Returns the status code used for the redirect.
   int get statusCode;
 
-  /**
-   * Returns the method used for the redirect.
-   */
+  /// Returns the method used for the redirect.
   String get method;
 
-  /**
-   * Returns the location for the redirect.
-   */
+  /// Returns the location for the redirect.
   Uri get location;
 }
 
-/**
- * When detaching a socket from either the [:HttpServer:] or the
- * [:HttpClient:] due to a HTTP connection upgrade there might be
- * unparsed data already read from the socket. This unparsed data
- * together with the detached socket is returned in an instance of
- * this class.
- */
+/// When detaching a socket from either the [:HttpServer:] or the
+/// [:HttpClient:] due to a HTTP connection upgrade there might be
+/// unparsed data already read from the socket. This unparsed data
+/// together with the detached socket is returned in an instance of
+/// this class.
 abstract class DetachedSocket {
   Socket get socket;
   List<int> get unparsedData;
@@ -2323,7 +2025,7 @@
   const HttpException(this.message, {this.uri});
 
   String toString() {
-    var b = new StringBuffer()
+    var b = StringBuffer()
       ..write('HttpException: ')
       ..write(message);
     var uri = this.uri;
diff --git a/sdk/lib/_http/http_date.dart b/sdk/lib/_http/http_date.dart
index 5fd2f34..df8d643 100644
--- a/sdk/lib/_http/http_date.dart
+++ b/sdk/lib/_http/http_date.dart
@@ -4,10 +4,8 @@
 
 part of dart._http;
 
-/**
- * Utility functions for working with dates with HTTP specific date
- * formats.
- */
+/// Utility functions for working with dates with HTTP specific date
+/// formats.
 class HttpDate {
   // From RFC-2616 section "3.3.1 Full Date",
   // http://tools.ietf.org/html/rfc2616#section-3.3.1
@@ -32,14 +30,12 @@
   //              | "May" | "Jun" | "Jul" | "Aug"
   //              | "Sep" | "Oct" | "Nov" | "Dec"
 
-  /**
-   * Format a date according to
-   * [RFC-1123](http://tools.ietf.org/html/rfc1123 "RFC-1123"),
-   * e.g. `Thu, 1 Jan 1970 00:00:00 GMT`.
-   */
+  /// Format a date according to
+  /// [RFC-1123](http://tools.ietf.org/html/rfc1123 "RFC-1123"),
+  /// e.g. `Thu, 1 Jan 1970 00:00:00 GMT`.
   static String format(DateTime date) {
-    const List wkday = const ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
-    const List month = const [
+    const List wkday = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
+    const List month = [
       "Jan",
       "Feb",
       "Mar",
@@ -55,7 +51,7 @@
     ];
 
     DateTime d = date.toUtc();
-    StringBuffer sb = new StringBuffer()
+    StringBuffer sb = StringBuffer()
       ..write(wkday[d.weekday - 1])
       ..write(", ")
       ..write(d.day <= 9 ? "0" : "")
@@ -74,24 +70,22 @@
     return sb.toString();
   }
 
-  /**
-   * Parse a date string in either of the formats
-   * [RFC-1123](http://tools.ietf.org/html/rfc1123 "RFC-1123"),
-   * [RFC-850](http://tools.ietf.org/html/rfc850 "RFC-850") or
-   * ANSI C's asctime() format. These formats are listed here.
-   *
-   *     Thu, 1 Jan 1970 00:00:00 GMT
-   *     Thursday, 1-Jan-1970 00:00:00 GMT
-   *     Thu Jan  1 00:00:00 1970
-   *
-   * For more information see [RFC-2616 section
-   * 3.1.1](http://tools.ietf.org/html/rfc2616#section-3.3.1
-   * "RFC-2616 section 3.1.1").
-   */
+  /// Parse a date string in either of the formats
+  /// [RFC-1123](http://tools.ietf.org/html/rfc1123 "RFC-1123"),
+  /// [RFC-850](http://tools.ietf.org/html/rfc850 "RFC-850") or
+  /// ANSI C's asctime() format. These formats are listed here.
+  ///
+  ///     Thu, 1 Jan 1970 00:00:00 GMT
+  ///     Thursday, 1-Jan-1970 00:00:00 GMT
+  ///     Thu Jan  1 00:00:00 1970
+  ///
+  /// For more information see [RFC-2616 section
+  /// 3.1.1](http://tools.ietf.org/html/rfc2616#section-3.3.1
+  /// "RFC-2616 section 3.1.1").
   static DateTime parse(String date) {
     final int SP = 32;
-    const List wkdays = const ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
-    const List weekdays = const [
+    const List wkdays = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
+    const List weekdays = [
       "Monday",
       "Tuesday",
       "Wednesday",
@@ -100,7 +94,7 @@
       "Saturday",
       "Sunday"
     ];
-    const List months = const [
+    const List months = [
       "Jan",
       "Feb",
       "Mar",
@@ -124,11 +118,11 @@
 
     void expect(String s) {
       if (date.length - index < s.length) {
-        throw new HttpException("Invalid HTTP date $date");
+        throw HttpException("Invalid HTTP date $date");
       }
       String tmp = date.substring(index, index + s.length);
       if (tmp != s) {
-        throw new HttpException("Invalid HTTP date $date");
+        throw HttpException("Invalid HTTP date $date");
       }
       index += s.length;
     }
@@ -139,7 +133,7 @@
       int pos = date.indexOf(",", index);
       if (pos == -1) {
         int pos = date.indexOf(" ", index);
-        if (pos == -1) throw new HttpException("Invalid HTTP date $date");
+        if (pos == -1) throw HttpException("Invalid HTTP date $date");
         tmp = date.substring(index, pos);
         index = pos + 1;
         weekday = wkdays.indexOf(tmp);
@@ -158,22 +152,22 @@
           return formatRfc850;
         }
       }
-      throw new HttpException("Invalid HTTP date $date");
+      throw HttpException("Invalid HTTP date $date");
     }
 
     int expectMonth(String separator) {
       int pos = date.indexOf(separator, index);
-      if (pos - index != 3) throw new HttpException("Invalid HTTP date $date");
+      if (pos - index != 3) throw HttpException("Invalid HTTP date $date");
       tmp = date.substring(index, pos);
       index = pos + 1;
       int month = months.indexOf(tmp);
       if (month != -1) return month;
-      throw new HttpException("Invalid HTTP date $date");
+      throw HttpException("Invalid HTTP date $date");
     }
 
     int expectNum(String separator) {
       int pos;
-      if (separator.length > 0) {
+      if (separator.isNotEmpty) {
         pos = date.indexOf(separator, index);
       } else {
         pos = date.length;
@@ -184,13 +178,13 @@
         int value = int.parse(tmp);
         return value;
       } on FormatException {
-        throw new HttpException("Invalid HTTP date $date");
+        throw HttpException("Invalid HTTP date $date");
       }
     }
 
     void expectEnd() {
       if (index != date.length) {
-        throw new HttpException("Invalid HTTP date $date");
+        throw HttpException("Invalid HTTP date $date");
       }
     }
 
@@ -220,12 +214,12 @@
       expect("GMT");
     }
     expectEnd();
-    return new DateTime.utc(year, month + 1, day, hours, minutes, seconds, 0);
+    return DateTime.utc(year, month + 1, day, hours, minutes, seconds, 0);
   }
 
   // Parse a cookie date string.
   static DateTime _parseCookieDate(String date) {
-    const List monthsLowerCase = const [
+    const List monthsLowerCase = [
       "jan",
       "feb",
       "mar",
@@ -243,7 +237,7 @@
     int position = 0;
 
     Never error() {
-      throw new HttpException("Invalid cookie date $date");
+      throw HttpException("Invalid cookie date $date");
     }
 
     bool isEnd() => position == date.length;
@@ -287,7 +281,7 @@
       return int.parse(s.substring(0, index));
     }
 
-    var tokens = [];
+    var tokens = <String>[];
     while (!isEnd()) {
       while (!isEnd() && isDelimiter(date[position])) position++;
       int start = position;
@@ -302,7 +296,7 @@
     String? yearStr;
 
     for (var token in tokens) {
-      if (token.length < 1) continue;
+      if (token.isEmpty) continue;
       if (timeStr == null &&
           token.length >= 5 &&
           isDigit(token[0]) &&
@@ -347,6 +341,6 @@
     if (minute > 59) error();
     if (second > 59) error();
 
-    return new DateTime.utc(year, month, dayOfMonth, hour, minute, second, 0);
+    return DateTime.utc(year, month, dayOfMonth, hour, minute, second, 0);
   }
 }
diff --git a/sdk/lib/_http/http_headers.dart b/sdk/lib/_http/http_headers.dart
index 09e5748..2ccf23a 100644
--- a/sdk/lib/_http/http_headers.dart
+++ b/sdk/lib/_http/http_headers.dart
@@ -24,7 +24,7 @@
   _HttpHeaders(this.protocolVersion,
       {int defaultPortForScheme = HttpClient.defaultHttpPort,
       _HttpHeaders? initialHeaders})
-      : _headers = new HashMap<String, List<String>>(),
+      : _headers = HashMap<String, List<String>>(),
         _defaultPortForScheme = defaultPortForScheme {
     if (initialHeaders != null) {
       initialHeaders._headers.forEach((name, value) => _headers[name] = value);
@@ -48,7 +48,7 @@
     if (values == null) return null;
     assert(values.isNotEmpty);
     if (values.length > 1) {
-      throw new HttpException("More than one value for header $name");
+      throw HttpException("More than one value for header $name");
     }
     return values[0];
   }
@@ -99,7 +99,7 @@
     List<String>? values = _headers[name];
     if (values != null) {
       values.remove(_valueToString(value));
-      if (values.length == 0) {
+      if (values.isEmpty) {
         _headers.remove(name);
         _originalHeaderNames?.remove(name);
       }
@@ -116,7 +116,7 @@
     _originalHeaderNames?.remove(name);
   }
 
-  void forEach(void action(String name, List<String> values)) {
+  void forEach(void Function(String name, List<String> values) action) {
     _headers.forEach((String name, List<String> values) {
       String originalName = _originalHeaderName(name);
       action(originalName, values);
@@ -139,7 +139,7 @@
         remove(HttpHeaders.connectionHeader, "close");
       } else {
         if (_contentLength < 0) {
-          throw new HttpException(
+          throw HttpException(
               "Trying to set 'Connection: Keep-Alive' on HTTP 1.0 headers with "
               "no ContentLength");
         }
@@ -162,7 +162,7 @@
     if (protocolVersion == "1.0" &&
         persistentConnection &&
         contentLength == -1) {
-      throw new HttpException(
+      throw HttpException(
           "Trying to clear ContentLength on HTTP 1.0 headers with "
           "'Connection: Keep-Alive' set");
     }
@@ -184,7 +184,7 @@
   void set chunkedTransferEncoding(bool chunkedTransferEncoding) {
     _checkMutable();
     if (chunkedTransferEncoding && protocolVersion == "1.0") {
-      throw new HttpException(
+      throw HttpException(
           "Trying to set 'Transfer-Encoding: Chunked' on HTTP 1.0 headers");
     }
     if (chunkedTransferEncoding == _chunkedTransferEncoding) return;
@@ -377,7 +377,7 @@
     } else if (value is String) {
       contentLength = int.parse(value);
     } else {
-      throw new HttpException("Unexpected type for header named $name");
+      throw HttpException("Unexpected type for header named $name");
     }
   }
 
@@ -395,7 +395,7 @@
     } else if (value is String) {
       _set(HttpHeaders.dateHeader, value);
     } else {
-      throw new HttpException("Unexpected type for header named $name");
+      throw HttpException("Unexpected type for header named $name");
     }
   }
 
@@ -405,7 +405,7 @@
     } else if (value is String) {
       _set(HttpHeaders.expiresHeader, value);
     } else {
-      throw new HttpException("Unexpected type for header named $name");
+      throw HttpException("Unexpected type for header named $name");
     }
   }
 
@@ -415,7 +415,7 @@
     } else if (value is String) {
       _set(HttpHeaders.ifModifiedSinceHeader, value);
     } else {
-      throw new HttpException("Unexpected type for header named $name");
+      throw HttpException("Unexpected type for header named $name");
     }
   }
 
@@ -448,11 +448,11 @@
       }
       _set(HttpHeaders.hostHeader, value);
     } else {
-      throw new HttpException("Unexpected type for header named $name");
+      throw HttpException("Unexpected type for header named $name");
     }
   }
 
-  void _addConnection(String name, value) {
+  void _addConnection(String name, String value) {
     var lowerCaseValue = value.toLowerCase();
     if (lowerCaseValue == 'close') {
       _persistentConnection = false;
@@ -487,7 +487,7 @@
   }
 
   void _checkMutable() {
-    if (!_mutable) throw new HttpException("HTTP headers are not mutable");
+    if (!_mutable) throw HttpException("HTTP headers are not mutable");
   }
 
   void _updateHostHeader() {
@@ -548,17 +548,22 @@
   }
 
   String toString() {
-    StringBuffer sb = new StringBuffer();
+    StringBuffer sb = StringBuffer();
     _headers.forEach((String name, List<String> values) {
       String originalName = _originalHeaderName(name);
-      sb..write(originalName)..write(": ");
+      sb
+        ..write(originalName)
+        ..write(": ");
       bool fold = _foldHeader(name);
       for (int i = 0; i < values.length; i++) {
         if (i > 0) {
           if (fold) {
             sb.write(", ");
           } else {
-            sb..write("\n")..write(originalName)..write(": ");
+            sb
+              ..write("\n")
+              ..write(originalName)
+              ..write(": ");
           }
         }
         sb.write(values[i]);
@@ -620,7 +625,7 @@
         skipWS();
         String value = parseValue();
         try {
-          cookies.add(new _Cookie(name, value));
+          cookies.add(_Cookie(name, value));
         } catch (_) {
           // Skip it, invalid cookie data.
         }
@@ -635,7 +640,9 @@
 
     List<String>? values = _headers[HttpHeaders.cookieHeader];
     if (values != null) {
-      values.forEach((headerValue) => parseCookieString(headerValue));
+      for (var headerValue in values) {
+        parseCookieString(headerValue);
+      }
     }
     return cookies;
   }
@@ -643,7 +650,7 @@
   static String _validateField(String field) {
     for (var i = 0; i < field.length; i++) {
       if (!_HttpParser._isTokenChar(field.codeUnitAt(i))) {
-        throw new FormatException(
+        throw FormatException(
             "Invalid HTTP header field name: ${json.encode(field)}", field, i);
       }
     }
@@ -652,9 +659,9 @@
 
   static Object _validateValue(Object value) {
     if (value is! String) return value;
-    for (var i = 0; i < (value as String).length; i++) {
-      if (!_HttpParser._isValueChar((value as String).codeUnitAt(i))) {
-        throw new FormatException(
+    for (var i = 0; i < (value).length; i++) {
+      if (!_HttpParser._isValueChar((value).codeUnitAt(i))) {
+        throw FormatException(
             "Invalid HTTP header field value: ${json.encode(value)}", value, i);
       }
     }
@@ -675,7 +682,7 @@
     // TODO(40614): Remove once non-nullability is sound.
     Map<String, String?>? nullableParameters = parameters;
     if (nullableParameters != null && nullableParameters.isNotEmpty) {
-      _parameters = new HashMap<String, String?>.from(nullableParameters);
+      _parameters = HashMap<String, String?>.from(nullableParameters);
     }
   }
 
@@ -684,7 +691,7 @@
       String? valueSeparator,
       bool preserveBackslash = false}) {
     // Parse the string.
-    var result = new _HeaderValue();
+    var result = _HeaderValue();
     result._parse(value, parameterSeparator, valueSeparator, preserveBackslash);
     return result;
   }
@@ -701,12 +708,10 @@
     if (token.isEmpty) {
       return false;
     }
-    final delimiters = "\"(),/:;<=>?@[\]{}";
+    final delimiters = "\"(),/:;<=>?@[]{}";
     for (int i = 0; i < token.length; i++) {
       int codeUnit = token.codeUnitAt(i);
-      if (codeUnit <= 32 ||
-          codeUnit >= 127 ||
-          delimiters.indexOf(token[i]) >= 0) {
+      if (codeUnit <= 32 || codeUnit >= 127 || delimiters.contains(token[i])) {
         return false;
       }
     }
@@ -714,12 +719,14 @@
   }
 
   String toString() {
-    StringBuffer sb = new StringBuffer();
+    StringBuffer sb = StringBuffer();
     sb.write(_value);
-    var parameters = this._parameters;
-    if (parameters != null && parameters.length > 0) {
+    var parameters = _parameters;
+    if (parameters != null && parameters.isNotEmpty) {
       parameters.forEach((String name, String? value) {
-        sb..write("; ")..write(name);
+        sb
+          ..write("; ")
+          ..write(name);
         if (value != null) {
           sb.write("=");
           if (_isToken(value)) {
@@ -737,7 +744,9 @@
                 start = i;
               }
             }
-            sb..write(value.substring(start))..write('"');
+            sb
+              ..write(value.substring(start))
+              ..write('"');
           }
         }
       });
@@ -773,7 +782,7 @@
 
     void expect(String expected) {
       if (done() || s[index] != expected) {
-        throw new HttpException("Failed to parse header value");
+        throw HttpException("Failed to parse header value");
       }
       index++;
     }
@@ -806,13 +815,13 @@
       String parseParameterValue() {
         if (!done() && s[index] == "\"") {
           // Parse quoted value.
-          StringBuffer sb = new StringBuffer();
+          StringBuffer sb = StringBuffer();
           index++;
           while (!done()) {
             var char = s[index];
             if (char == "\\") {
               if (index + 1 == s.length) {
-                throw new HttpException("Failed to parse header value");
+                throw HttpException("Failed to parse header value");
               }
               if (preserveBackslash && s[index + 1] != "\"") {
                 sb.write(char);
@@ -826,7 +835,7 @@
             sb.write(char);
             index++;
           }
-          throw new HttpException("Failed to parse header value");
+          throw HttpException("Failed to parse header value");
         } else {
           // Parse non-quoted value.
           return parseValue();
@@ -901,7 +910,7 @@
   _ContentType._();
 
   static _ContentType parse(String value) {
-    var result = new _ContentType._();
+    var result = _ContentType._();
     result._parse(value, ";", null, false);
     int index = result._value.indexOf("/");
     if (index == -1 || index == (result._value.length - 1)) {
@@ -1033,8 +1042,8 @@
     }
 
     _name = _validateName(parseName());
-    if (done() || _name.length == 0) {
-      throw new HttpException("Failed to parse header value [$s]");
+    if (done() || _name.isEmpty) {
+      throw HttpException("Failed to parse header value [$s]");
     }
     index++; // Skip the = character.
     _value = _validateValue(parseValue());
@@ -1044,20 +1053,31 @@
   }
 
   String toString() {
-    StringBuffer sb = new StringBuffer();
-    sb..write(_name)..write("=")..write(_value);
+    StringBuffer sb = StringBuffer();
+    sb
+      ..write(_name)
+      ..write("=")
+      ..write(_value);
     var expires = this.expires;
     if (expires != null) {
-      sb..write("; Expires=")..write(HttpDate.format(expires));
+      sb
+        ..write("; Expires=")
+        ..write(HttpDate.format(expires));
     }
     if (maxAge != null) {
-      sb..write("; Max-Age=")..write(maxAge);
+      sb
+        ..write("; Max-Age=")
+        ..write(maxAge);
     }
     if (domain != null) {
-      sb..write("; Domain=")..write(domain);
+      sb
+        ..write("; Domain=")
+        ..write(domain);
     }
     if (path != null) {
-      sb..write("; Path=")..write(path);
+      sb
+        ..write("; Path=")
+        ..write(path);
     }
     if (secure) sb.write("; Secure");
     if (httpOnly) sb.write("; HttpOnly");
@@ -1065,7 +1085,7 @@
   }
 
   static String _validateName(String newName) {
-    const separators = const [
+    const separators = [
       "(",
       ")",
       "<",
@@ -1084,13 +1104,13 @@
       "{",
       "}"
     ];
-    if (newName == null) throw new ArgumentError.notNull("name");
+    if (newName == null) throw ArgumentError.notNull("name");
     for (int i = 0; i < newName.length; i++) {
       int codeUnit = newName.codeUnitAt(i);
       if (codeUnit <= 32 ||
           codeUnit >= 127 ||
-          separators.indexOf(newName[i]) >= 0) {
-        throw new FormatException(
+          separators.contains(newName[i])) {
+        throw FormatException(
             "Invalid character in cookie name, code unit: '$codeUnit'",
             newName,
             i);
@@ -1100,7 +1120,7 @@
   }
 
   static String _validateValue(String newValue) {
-    if (newValue == null) throw new ArgumentError.notNull("value");
+    if (newValue == null) throw ArgumentError.notNull("value");
     // Per RFC 6265, consider surrounding "" as part of the value, but otherwise
     // double quotes are not allowed.
     int start = 0;
@@ -1119,7 +1139,7 @@
           (codeUnit >= 0x2D && codeUnit <= 0x3A) ||
           (codeUnit >= 0x3C && codeUnit <= 0x5B) ||
           (codeUnit >= 0x5D && codeUnit <= 0x7E))) {
-        throw new FormatException(
+        throw FormatException(
             "Invalid character in cookie value, code unit: '$codeUnit'",
             newValue,
             i);
diff --git a/sdk/lib/_http/http_impl.dart b/sdk/lib/_http/http_impl.dart
index 6845f45..9ff1eef 100644
--- a/sdk/lib/_http/http_impl.dart
+++ b/sdk/lib/_http/http_impl.dart
@@ -7,7 +7,7 @@
 abstract class HttpProfiler {
   static const _kType = 'HttpProfile';
 
-  static Map<int, _HttpProfileData> _profile = {};
+  static final Map<int, _HttpProfileData> _profile = {};
 
   static _HttpProfileData startRequest(
     String method,
@@ -96,21 +96,22 @@
     _updated();
   }
 
-  Map formatHeaders(r) {
-    final headers = <String, List<String>>{};
-    r.headers.forEach((name, values) {
-      headers[name] = values;
+  Map formatHeaders(HttpHeaders headers) {
+    final newHeaders = <String, List<String>>{};
+    headers.forEach((name, values) {
+      newHeaders[name] = values;
     });
-    return headers;
+    return newHeaders;
   }
 
-  Map? formatConnectionInfo(r) => r.connectionInfo == null
-      ? null
-      : {
-          'localPort': r.connectionInfo?.localPort,
-          'remoteAddress': r.connectionInfo?.remoteAddress.address,
-          'remotePort': r.connectionInfo?.remotePort,
-        };
+  Map? formatConnectionInfo(HttpConnectionInfo? connectionInfo) =>
+      connectionInfo == null
+          ? null
+          : {
+              'localPort': connectionInfo.localPort,
+              'remoteAddress': connectionInfo.remoteAddress.address,
+              'remotePort': connectionInfo.remotePort,
+            };
 
   void finishRequest({
     required HttpClientRequest request,
@@ -121,8 +122,8 @@
     requestDetails = <String, dynamic>{
       // TODO(bkonyi): consider exposing certificate information?
       // 'certificate': response.certificate,
-      'headers': formatHeaders(request),
-      'connectionInfo': formatConnectionInfo(request),
+      'headers': formatHeaders(request.headers),
+      'connectionInfo': formatConnectionInfo(request.connectionInfo),
       'contentLength': request.contentLength,
       'cookies': [
         for (final cookie in request.cookies) cookie.toString(),
@@ -153,9 +154,9 @@
     }
 
     responseDetails = <String, dynamic>{
-      'headers': formatHeaders(response),
+      'headers': formatHeaders(response.headers),
       'compressionState': response.compressionState.toString(),
-      'connectionInfo': formatConnectionInfo(response),
+      'connectionInfo': formatConnectionInfo(response.connectionInfo),
       'contentLength': response.contentLength,
       'cookies': [
         for (final cookie in response.cookies) cookie.toString(),
@@ -281,7 +282,7 @@
   int get lastUpdateTime => _lastUpdateTime;
   int _lastUpdateTime = 0;
 
-  TimelineTask _timeline;
+  final TimelineTask _timeline;
   late TimelineTask _responseTimeline;
 }
 
@@ -313,7 +314,7 @@
   // Start with 1024 bytes.
   static const int _INIT_SIZE = 1024;
 
-  static final _emptyList = new Uint8List(0);
+  static final _emptyList = Uint8List(0);
 
   int _length = 0;
   Uint8List _buffer;
@@ -321,7 +322,7 @@
   _CopyingBytesBuilder([int initialCapacity = 0])
       : _buffer = (initialCapacity <= 0)
             ? _emptyList
-            : new Uint8List(_pow2roundup(initialCapacity));
+            : Uint8List(_pow2roundup(initialCapacity));
 
   void add(List<int> bytes) {
     int bytesLength = bytes.length;
@@ -361,23 +362,22 @@
     } else {
       newSize = _pow2roundup(newSize);
     }
-    var newBuffer = new Uint8List(newSize);
+    var newBuffer = Uint8List(newSize);
     newBuffer.setRange(0, _buffer.length, _buffer);
     _buffer = newBuffer;
   }
 
   Uint8List takeBytes() {
     if (_length == 0) return _emptyList;
-    var buffer =
-        new Uint8List.view(_buffer.buffer, _buffer.offsetInBytes, _length);
+    var buffer = Uint8List.view(_buffer.buffer, _buffer.offsetInBytes, _length);
     clear();
     return buffer;
   }
 
   Uint8List toBytes() {
     if (_length == 0) return _emptyList;
-    return new Uint8List.fromList(
-        new Uint8List.view(_buffer.buffer, _buffer.offsetInBytes, _length));
+    return Uint8List.fromList(
+        Uint8List.view(_buffer.buffer, _buffer.offsetInBytes, _length));
   }
 
   int get length => _length;
@@ -405,12 +405,12 @@
 
 const int _OUTGOING_BUFFER_SIZE = 8 * 1024;
 
-typedef void _BytesConsumer(List<int> bytes);
+typedef _BytesConsumer = void Function(List<int> bytes);
 
 class _HttpIncoming extends Stream<Uint8List> {
   final int _transferLength;
-  final Completer _dataCompleter = new Completer();
-  Stream<Uint8List> _stream;
+  final _dataCompleter = Completer<bool>();
+  final Stream<Uint8List> _stream;
 
   bool fullBodyRead = false;
 
@@ -436,17 +436,17 @@
 
   _HttpIncoming(this.headers, this._transferLength, this._stream);
 
-  StreamSubscription<Uint8List> listen(void onData(Uint8List event)?,
-      {Function? onError, void onDone()?, bool? cancelOnError}) {
+  StreamSubscription<Uint8List> listen(void Function(Uint8List event)? onData,
+      {Function? onError, void Function()? onDone, bool? cancelOnError}) {
     hasSubscriber = true;
     return _stream.handleError((error) {
-      throw new HttpException(error.message, uri: uri);
+      throw HttpException(error.message, uri: uri);
     }).listen(onData,
         onError: onError, onDone: onDone, cancelOnError: cancelOnError);
   }
 
   // Is completed once all data have been received.
-  Future get dataDone => _dataCompleter.future;
+  Future<bool> get dataDone => _dataCompleter.future;
 
   void close(bool closing) {
     fullBodyRead = true;
@@ -519,8 +519,8 @@
     }
   }
 
-  StreamSubscription<Uint8List> listen(void onData(Uint8List event)?,
-      {Function? onError, void onDone()?, bool? cancelOnError}) {
+  StreamSubscription<Uint8List> listen(void Function(Uint8List event)? onData,
+      {Function? onError, void Function()? onDone, bool? cancelOnError}) {
     return _incoming.listen(onData,
         onError: onError, onDone: onDone, cancelOnError: cancelOnError);
   }
@@ -621,7 +621,7 @@
     List<String>? values = headers[HttpHeaders.setCookieHeader];
     if (values != null) {
       for (var value in values) {
-        cookies.add(new Cookie.fromSetCookieValue(value));
+        cookies.add(Cookie.fromSetCookieValue(value));
       }
     }
     _cookies = cookies;
@@ -654,15 +654,15 @@
     if (url == null) {
       String? location = headers.value(HttpHeaders.locationHeader);
       if (location == null) {
-        throw new StateError("Response has no Location header for redirect");
+        throw StateError("Response has no Location header for redirect");
       }
       url = Uri.parse(location);
     }
     if (followLoops != true) {
       for (var redirect in redirects) {
         if (redirect.location == url) {
-          return new Future.error(
-              new RedirectException("Redirect loop detected", redirects));
+          return Future.error(
+              RedirectException("Redirect loop detected", redirects));
         }
       }
     }
@@ -670,21 +670,21 @@
         ._openUrlFromRequest(method, url, _httpRequest)
         .then((request) {
       request._responseRedirects
-        ..addAll(this.redirects)
-        ..add(new _RedirectInfo(statusCode, method!, url!));
+        ..addAll(redirects)
+        ..add(_RedirectInfo(statusCode, method!, url!));
       return request.close();
     });
   }
 
-  StreamSubscription<Uint8List> listen(void onData(Uint8List event)?,
-      {Function? onError, void onDone()?, bool? cancelOnError}) {
+  StreamSubscription<Uint8List> listen(void Function(Uint8List event)? onData,
+      {Function? onError, void Function()? onDone, bool? cancelOnError}) {
     if (_incoming.upgraded) {
       _profileData?.finishResponseWithError('Connection was upgraded');
       // If upgraded, the connection is already 'removed' form the client.
       // Since listening to upgraded data is 'bogus', simply close and
       // return empty stream subscription.
       _httpRequest._httpClientConnection.destroy();
-      return new Stream<Uint8List>.empty().listen(null, onDone: onDone);
+      return Stream<Uint8List>.empty().listen(null, onDone: onDone);
     }
     Stream<Uint8List> stream = _incoming;
     if (compressionState == HttpClientResponseCompressionState.decompressed) {
@@ -781,7 +781,7 @@
       if (proxyAuth) {
         var authenticateProxy = _httpClient._authenticateProxy;
         if (authenticateProxy == null) {
-          return new Future.value(false);
+          return Future.value(false);
         }
         var proxy = _httpRequest._proxy;
         if (!proxy.isDirect) {
@@ -791,7 +791,7 @@
       }
       var authenticate = _httpClient._authenticate;
       if (authenticate == null) {
-        return new Future.value(false);
+        return Future.value(false);
       }
       return authenticate(_httpRequest.uri, scheme.toString(), realm);
     }
@@ -801,7 +801,7 @@
     _HeaderValue header =
         _HeaderValue.parse(challenge[0], parameterSeparator: ",");
     _AuthenticationScheme scheme =
-        new _AuthenticationScheme.fromString(header.value);
+        _AuthenticationScheme.fromString(header.value);
     String? realm = header.parameters["realm"];
 
     // See if any matching credentials are available.
@@ -890,7 +890,7 @@
 
 class _StreamSinkImpl<T> implements StreamSink<T> {
   final StreamConsumer<T> _target;
-  final _doneCompleter = new Completer<void>();
+  final _doneCompleter = Completer<void>();
   StreamController<T>? _controllerInstance;
   Completer? _controllerCompleter;
   bool _isClosed = false;
@@ -915,7 +915,7 @@
 
   Future addStream(Stream<T> stream) {
     if (_isBound) {
-      throw new StateError("StreamSink is already bound to a stream");
+      throw StateError("StreamSink is already bound to a stream");
     }
     _isBound = true;
     if (_hasError) return done;
@@ -935,10 +935,10 @@
 
   Future flush() {
     if (_isBound) {
-      throw new StateError("StreamSink is bound to a stream");
+      throw StateError("StreamSink is bound to a stream");
     }
     var controller = _controllerInstance;
-    if (controller == null) return new Future.value(this);
+    if (controller == null) return Future.value(this);
     // Adding an empty stream-controller will return a future that will complete
     // when all data is done.
     _isBound = true;
@@ -951,7 +951,7 @@
 
   Future close() {
     if (_isBound) {
-      throw new StateError("StreamSink is bound to a stream");
+      throw StateError("StreamSink is bound to a stream");
     }
     if (!_isClosed) {
       _isClosed = true;
@@ -986,14 +986,14 @@
 
   StreamController<T> get _controller {
     if (_isBound) {
-      throw new StateError("StreamSink is bound to a stream");
+      throw StateError("StreamSink is bound to a stream");
     }
     if (_isClosed) {
-      throw new StateError("StreamSink is closed");
+      throw StateError("StreamSink is closed");
     }
     if (_controllerInstance == null) {
-      _controllerInstance = new StreamController<T>(sync: true);
-      _controllerCompleter = new Completer();
+      _controllerInstance = StreamController<T>(sync: true);
+      _controllerCompleter = Completer();
       _target.addStream(_controller.stream).then((_) {
         if (_isBound) {
           // A new stream takes over - forward values to that stream.
@@ -1034,7 +1034,7 @@
 
   void set encoding(Encoding value) {
     if (!_encodingMutable) {
-      throw new StateError("IOSink encoding is not mutable");
+      throw StateError("IOSink encoding is not mutable");
     }
     _encoding = value;
   }
@@ -1072,7 +1072,7 @@
   }
 
   void writeCharCode(int charCode) {
-    write(new String.fromCharCode(charCode));
+    write(String.fromCharCode(charCode));
   }
 }
 
@@ -1092,7 +1092,7 @@
       _HttpProfileData? profileData,
       {_HttpHeaders? initialHeaders})
       : _uri = uri,
-        headers = new _HttpHeaders(protocolVersion,
+        headers = _HttpHeaders(protocolVersion,
             defaultPortForScheme: uri.scheme == 'https'
                 ? HttpClient.defaultHttpsPort
                 : HttpClient.defaultHttpPort,
@@ -1115,7 +1115,7 @@
 
   bool get bufferOutput => _bufferOutput;
   void set bufferOutput(bool bufferOutput) {
-    if (_outgoing.headersWritten) throw new StateError("Header already sent");
+    if (_outgoing.headersWritten) throw StateError("Header already sent");
     _bufferOutput = bufferOutput;
   }
 
@@ -1134,7 +1134,7 @@
   }
 
   void add(List<int> data) {
-    if (data.length == 0) return;
+    if (data.isEmpty) return;
     _profileData?.appendRequestData(Uint8List.fromList(data));
     super.add(data);
   }
@@ -1186,25 +1186,25 @@
 
   int get statusCode => _statusCode;
   void set statusCode(int statusCode) {
-    if (_outgoing.headersWritten) throw new StateError("Header already sent");
+    if (_outgoing.headersWritten) throw StateError("Header already sent");
     _statusCode = statusCode;
   }
 
   String get reasonPhrase => _findReasonPhrase(statusCode);
   void set reasonPhrase(String reasonPhrase) {
-    if (_outgoing.headersWritten) throw new StateError("Header already sent");
+    if (_outgoing.headersWritten) throw StateError("Header already sent");
     _reasonPhrase = reasonPhrase;
   }
 
   Future redirect(Uri location, {int status = HttpStatus.movedTemporarily}) {
-    if (_outgoing.headersWritten) throw new StateError("Header already sent");
+    if (_outgoing.headersWritten) throw StateError("Header already sent");
     statusCode = status;
     headers.set(HttpHeaders.locationHeader, location.toString());
     return close();
   }
 
   Future<Socket> detachSocket({bool writeHeaders = true}) {
-    if (_outgoing.headersWritten) throw new StateError("Headers already sent");
+    if (_outgoing.headersWritten) throw StateError("Headers already sent");
     deadline = null; // Be sure to stop any deadline.
     var future = _httpRequest!._httpConnection.detachSocket();
     if (writeHeaders) {
@@ -1233,13 +1233,13 @@
     _deadline = d;
 
     if (d == null) return;
-    _deadlineTimer = new Timer(d, () {
+    _deadlineTimer = Timer(d, () {
       _httpRequest!._httpConnection.destroy();
     });
   }
 
   void _writeHeader() {
-    BytesBuilder buffer = new _CopyingBytesBuilder(_OUTGOING_BUFFER_SIZE);
+    BytesBuilder buffer = _CopyingBytesBuilder(_OUTGOING_BUFFER_SIZE);
 
     // Write status line.
     if (headers.protocolVersion == "1.1") {
@@ -1270,7 +1270,7 @@
         }
       }
       if (!found) {
-        var cookie = new Cookie(_DART_SESSION_ID, session.id);
+        var cookie = Cookie(_DART_SESSION_ID, session.id);
         cookies.add(cookie
           ..httpOnly = true
           ..path = "/");
@@ -1393,10 +1393,9 @@
   // The HttpClient this request belongs to.
   final _HttpClient _httpClient;
   final _HttpClientConnection _httpClientConnection;
-  final _HttpProfileData? _profileData;
 
   final Completer<HttpClientResponse> _responseCompleter =
-      new Completer<HttpClientResponse>();
+      Completer<HttpClientResponse>();
 
   final _Proxy _proxy;
 
@@ -1407,20 +1406,19 @@
 
   int _maxRedirects = 5;
 
-  List<RedirectInfo> _responseRedirects = [];
+  final List<RedirectInfo> _responseRedirects = [];
 
   bool _aborted = false;
 
   _HttpClientRequest(
     _HttpOutgoing outgoing,
-    Uri uri,
+    this.uri,
     this.method,
     this._proxy,
     this._httpClient,
     this._httpClientConnection,
-    this._profileData,
-  )   : uri = uri,
-        super(uri, "1.1", outgoing, _profileData) {
+    _HttpProfileData? _profileData,
+  ) : super(uri, "1.1", outgoing, _profileData) {
     _profileData?.requestEvent('Request sent');
     // GET and HEAD have 'content-length: 0' by default.
     if (method == "GET" || method == "HEAD") {
@@ -1453,13 +1451,13 @@
 
   int get maxRedirects => _maxRedirects;
   void set maxRedirects(int maxRedirects) {
-    if (_outgoing.headersWritten) throw new StateError("Request already sent");
+    if (_outgoing.headersWritten) throw StateError("Request already sent");
     _maxRedirects = maxRedirects;
   }
 
   bool get followRedirects => _followRedirects;
   void set followRedirects(bool followRedirects) {
-    if (_outgoing.headersWritten) throw new StateError("Request already sent");
+    if (_outgoing.headersWritten) throw StateError("Request already sent");
     _followRedirects = followRedirects;
   }
 
@@ -1482,8 +1480,8 @@
       } else {
         // End with exception, too many redirects.
         future = response.drain().then<HttpClientResponse>((_) {
-          return new Future<HttpClientResponse>.error(new RedirectException(
-              "Redirect limit exceeded", response.redirects));
+          return Future<HttpClientResponse>.error(
+              RedirectException("Redirect limit exceeded", response.redirects));
         });
       }
     } else if (response._shouldAuthenticateProxy) {
@@ -1491,7 +1489,7 @@
     } else if (response._shouldAuthenticate) {
       future = response._authenticate(false);
     } else {
-      future = new Future<HttpClientResponse>.value(response);
+      future = Future<HttpClientResponse>.value(response);
     }
     future.then((v) {
       if (!_responseCompleter.isCompleted) {
@@ -1517,7 +1515,7 @@
       String result = uri.path;
       if (result.isEmpty) result = "/";
       if (uri.hasQuery) {
-        result = "${result}?${uri.query}";
+        result = "$result?${uri.query}";
       }
       return result;
     }
@@ -1541,7 +1539,7 @@
   }
 
   void add(List<int> data) {
-    if (data.length == 0 || _aborted) return;
+    if (data.isEmpty || _aborted) return;
     super.add(data);
   }
 
@@ -1555,7 +1553,7 @@
       _outgoing.setHeader(Uint8List(0), 0);
       return;
     }
-    BytesBuilder buffer = new _CopyingBytesBuilder(_OUTGOING_BUFFER_SIZE);
+    BytesBuilder buffer = _CopyingBytesBuilder(_OUTGOING_BUFFER_SIZE);
 
     // Write the request method.
     buffer.add(method.codeUnits);
@@ -1569,11 +1567,14 @@
     buffer.addByte(_CharCode.LF);
 
     // Add the cookies to the headers.
-    if (!cookies.isEmpty) {
-      StringBuffer sb = new StringBuffer();
+    if (cookies.isNotEmpty) {
+      StringBuffer sb = StringBuffer();
       for (int i = 0; i < cookies.length; i++) {
         if (i > 0) sb.write("; ");
-        sb..write(cookies[i].name)..write("=")..write(cookies[i].value);
+        sb
+          ..write(cookies[i].name)
+          ..write("=")
+          ..write(cookies[i].value);
       }
       headers.add(HttpHeaders.cookieHeader, sb.toString());
     }
@@ -1614,7 +1615,7 @@
 
   void addSlice(List<int> chunk, int start, int end, bool isLast) {
     if (chunk is Uint8List) {
-      _consume(new Uint8List.view(
+      _consume(Uint8List.view(
           chunk.buffer, chunk.offsetInBytes + start, end - start));
     } else {
       _consume(chunk.sublist(start, end - start));
@@ -1633,7 +1634,7 @@
 // Most notable is the GZip compression, that uses a double-buffering system,
 // one before gzip (_gzipBuffer) and one after (_buffer).
 class _HttpOutgoing implements StreamConsumer<List<int>> {
-  static const List<int> _footerAndChunk0Length = const [
+  static const List<int> _footerAndChunk0Length = [
     _CharCode.CR,
     _CharCode.LF,
     0x30,
@@ -1643,7 +1644,7 @@
     _CharCode.LF
   ];
 
-  static const List<int> _chunk0Length = const [
+  static const List<int> _chunk0Length = [
     0x30,
     _CharCode.CR,
     _CharCode.LF,
@@ -1651,7 +1652,7 @@
     _CharCode.LF
   ];
 
-  final Completer<Socket> _doneCompleter = new Completer<Socket>();
+  final Completer<Socket> _doneCompleter = Completer<Socket>();
   final Socket socket;
 
   bool ignoreBody = false;
@@ -1736,7 +1737,7 @@
   Future addStream(Stream<List<int>> stream) {
     if (_socketError) {
       stream.listen(null).cancel();
-      return new Future.value(outbound);
+      return Future.value(outbound);
     }
     if (ignoreBody) {
       stream.drain().catchError((_) {});
@@ -1749,11 +1750,11 @@
     // Use new stream so we are able to pause (see below listen). The
     // alternative is to use stream.extand, but that won't give us a way of
     // pausing.
-    var controller = new StreamController<List<int>>(sync: true);
+    var controller = StreamController<List<int>>(sync: true);
 
     void onData(List<int> data) {
       if (_socketError) return;
-      if (data.length == 0) return;
+      if (data.isEmpty) return;
       if (chunked) {
         if (_gzip) {
           _gzipAdd = controller.add;
@@ -1768,11 +1769,11 @@
         if (contentLength != null) {
           _bytesWritten += data.length;
           if (_bytesWritten > contentLength) {
-            controller.addError(new HttpException(
-                "Content size exceeds specified contentLength. "
-                "$_bytesWritten bytes written while expected "
-                "$contentLength. "
-                "[${new String.fromCharCodes(data)}]"));
+            controller.addError(
+                HttpException("Content size exceeds specified contentLength. "
+                    "$_bytesWritten bytes written while expected "
+                    "$contentLength. "
+                    "[${String.fromCharCodes(data)}]"));
             return;
           }
         }
@@ -1818,8 +1819,8 @@
     var outbound = this.outbound!;
     // If we earlier saw an error, return immediate. The notification to
     // _Http*Connection is already done.
-    if (_socketError) return new Future.value(outbound);
-    if (outbound._isConnectionClosed) return new Future.value(outbound);
+    if (_socketError) return Future.value(outbound);
+    if (outbound._isConnectionClosed) return Future.value(outbound);
     if (!headersWritten && !ignoreBody) {
       if (outbound.headers.contentLength == -1) {
         // If no body was written, ignoreBody is false (it's not a HEAD
@@ -1828,25 +1829,25 @@
         outbound.headers.chunkedTransferEncoding = false;
         outbound.headers.contentLength = 0;
       } else if (outbound.headers.contentLength > 0) {
-        var error = new HttpException(
+        var error = HttpException(
             "No content even though contentLength was specified to be "
             "greater than 0: ${outbound.headers.contentLength}.",
             uri: outbound._uri);
         _doneCompleter.completeError(error);
-        return _closeFuture = new Future.error(error);
+        return _closeFuture = Future.error(error);
       }
     }
     // If contentLength was specified, validate it.
     var contentLength = this.contentLength;
     if (contentLength != null) {
       if (_bytesWritten < contentLength) {
-        var error = new HttpException(
+        var error = HttpException(
             "Content size below specified contentLength. "
             " $_bytesWritten bytes written but expected "
             "$contentLength.",
             uri: outbound._uri);
         _doneCompleter.completeError(error);
-        return _closeFuture = new Future.error(error);
+        return _closeFuture = Future.error(error);
       }
     }
 
@@ -1857,7 +1858,7 @@
         if (_gzip) {
           _gzipAdd = socket.add;
           if (_gzipBufferLength > 0) {
-            _gzipSink!.add(new Uint8List.view(_gzipBuffer!.buffer,
+            _gzipSink!.add(Uint8List.view(_gzipBuffer!.buffer,
                 _gzipBuffer!.offsetInBytes, _gzipBufferLength));
           }
           _gzipBuffer = null;
@@ -1868,8 +1869,8 @@
       }
       // Add any remaining data in the buffer.
       if (_length > 0) {
-        socket.add(new Uint8List.view(
-            _buffer!.buffer, _buffer!.offsetInBytes, _length));
+        socket.add(
+            Uint8List.view(_buffer!.buffer, _buffer!.offsetInBytes, _length));
       }
       // Clear references, for better GC.
       _buffer = null;
@@ -1907,10 +1908,10 @@
   void set gzip(bool value) {
     _gzip = value;
     if (value) {
-      _gzipBuffer = new Uint8List(_OUTGOING_BUFFER_SIZE);
+      _gzipBuffer = Uint8List(_OUTGOING_BUFFER_SIZE);
       assert(_gzipSink == null);
-      _gzipSink = new ZLibEncoder(gzip: true)
-          .startChunkedConversion(new _HttpGZipSink((data) {
+      _gzipSink =
+          ZLibEncoder(gzip: true).startChunkedConversion(_HttpGZipSink((data) {
         // We are closing down prematurely, due to an error. Discard.
         if (_gzipAdd == null) return;
         _addChunk(_chunkHeader(data.length), _gzipAdd!);
@@ -1924,7 +1925,7 @@
       (error is SocketException || error is TlsException) &&
       outbound is HttpResponse;
 
-  void _addGZipChunk(List<int> chunk, void add(List<int> data)) {
+  void _addGZipChunk(List<int> chunk, void Function(List<int> data) add) {
     var bufferOutput = outbound!.bufferOutput;
     if (!bufferOutput) {
       add(chunk);
@@ -1932,9 +1933,9 @@
     }
     var gzipBuffer = _gzipBuffer!;
     if (chunk.length > gzipBuffer.length - _gzipBufferLength) {
-      add(new Uint8List.view(
+      add(Uint8List.view(
           gzipBuffer.buffer, gzipBuffer.offsetInBytes, _gzipBufferLength));
-      _gzipBuffer = new Uint8List(_OUTGOING_BUFFER_SIZE);
+      _gzipBuffer = Uint8List(_OUTGOING_BUFFER_SIZE);
       _gzipBufferLength = 0;
     }
     if (chunk.length > _OUTGOING_BUFFER_SIZE) {
@@ -1947,14 +1948,13 @@
     }
   }
 
-  void _addChunk(List<int> chunk, void add(List<int> data)) {
+  void _addChunk(List<int> chunk, void Function(List<int> data) add) {
     var bufferOutput = outbound!.bufferOutput;
     if (!bufferOutput) {
       if (_buffer != null) {
         // If _buffer is not null, we have not written the header yet. Write
         // it now.
-        add(new Uint8List.view(
-            _buffer!.buffer, _buffer!.offsetInBytes, _length));
+        add(Uint8List.view(_buffer!.buffer, _buffer!.offsetInBytes, _length));
         _buffer = null;
         _length = 0;
       }
@@ -1962,8 +1962,8 @@
       return;
     }
     if (chunk.length > _buffer!.length - _length) {
-      add(new Uint8List.view(_buffer!.buffer, _buffer!.offsetInBytes, _length));
-      _buffer = new Uint8List(_OUTGOING_BUFFER_SIZE);
+      add(Uint8List.view(_buffer!.buffer, _buffer!.offsetInBytes, _length));
+      _buffer = Uint8List(_OUTGOING_BUFFER_SIZE);
       _length = 0;
     }
     if (chunk.length > _OUTGOING_BUFFER_SIZE) {
@@ -1975,7 +1975,7 @@
   }
 
   List<int> _chunkHeader(int length) {
-    const hexDigits = const [
+    const hexDigits = [
       0x30,
       0x31,
       0x32,
@@ -2004,7 +2004,7 @@
       size++;
       len >>= 4;
     }
-    var footerAndHeader = new Uint8List(size + 2);
+    var footerAndHeader = Uint8List(size + 2);
     if (_pendingChunkedFooter == 2) {
       footerAndHeader[0] = _CharCode.CR;
       footerAndHeader[1] = _CharCode.LF;
@@ -2038,7 +2038,7 @@
 
   _HttpClientConnection(this.key, this._socket, this._httpClient,
       [this._proxyTunnel = false, this._context])
-      : _httpParser = new _HttpParser.responseParser() {
+      : _httpParser = _HttpParser.responseParser() {
     _httpParser.listenToStream(_socket);
 
     // Set up handlers on the parser here, so we are sure to get 'onDone' from
@@ -2049,7 +2049,7 @@
       _subscription!.pause();
       // We assume the response is not here, until we have send the request.
       if (_nextResponseCompleter == null) {
-        throw new HttpException(
+        throw HttpException(
             "Unexpected response (unsolicited response without request).",
             uri: _currentUri);
       }
@@ -2063,7 +2063,7 @@
           _subscription!.resume();
         }).catchError((dynamic error, StackTrace stackTrace) {
           _nextResponseCompleter!.completeError(
-              new HttpException(error.message, uri: _currentUri), stackTrace);
+              HttpException(error.message, uri: _currentUri), stackTrace);
           _nextResponseCompleter = null;
         });
       } else {
@@ -2072,10 +2072,10 @@
       }
     }, onError: (dynamic error, StackTrace stackTrace) {
       _nextResponseCompleter?.completeError(
-          new HttpException(error.message, uri: _currentUri), stackTrace);
+          HttpException(error.message, uri: _currentUri), stackTrace);
       _nextResponseCompleter = null;
     }, onDone: () {
-      _nextResponseCompleter?.completeError(new HttpException(
+      _nextResponseCompleter?.completeError(HttpException(
           "Connection closed before response was received",
           uri: _currentUri));
       _nextResponseCompleter = null;
@@ -2086,8 +2086,7 @@
   _HttpClientRequest send(Uri uri, int port, String method, _Proxy proxy,
       _HttpProfileData? profileData) {
     if (closed) {
-      throw new HttpException("Socket closed before request was sent",
-          uri: uri);
+      throw HttpException("Socket closed before request was sent", uri: uri);
     }
     _currentUri = uri;
     // Start with pausing the parser.
@@ -2098,10 +2097,10 @@
     }
     _ProxyCredentials? proxyCreds; // Credentials used to authorize proxy.
     _SiteCredentials? creds; // Credentials used to authorize this request.
-    var outgoing = new _HttpOutgoing(_socket);
+    var outgoing = _HttpOutgoing(_socket);
 
     // Create new request object, wrapping the outgoing connection.
-    var request = new _HttpClientRequest(
+    var request = _HttpClientRequest(
         outgoing, uri, method, proxy, _httpClient, this, profileData);
     // For the Host header an IPv6 address must be enclosed in []'s.
     var host = uri.host;
@@ -2119,13 +2118,13 @@
       String auth = _CryptoUtils.bytesToBase64(
           utf8.encode("${proxy.username}:${proxy.password}"));
       request.headers.set(HttpHeaders.proxyAuthorizationHeader, "Basic $auth");
-    } else if (!proxy.isDirect && _httpClient._proxyCredentials.length > 0) {
+    } else if (!proxy.isDirect && _httpClient._proxyCredentials.isNotEmpty) {
       proxyCreds = _httpClient._findProxyCredentials(proxy);
       if (proxyCreds != null) {
         proxyCreds.authorize(request);
       }
     }
-    if (uri.userInfo != null && !uri.userInfo.isEmpty) {
+    if (uri.userInfo != null && uri.userInfo.isNotEmpty) {
       // If the URL contains user information use that for basic
       // authorization.
       String auth = _CryptoUtils.bytesToBase64(utf8.encode(uri.userInfo));
@@ -2146,7 +2145,7 @@
       profileData?.finishRequest(request: request);
 
       // Request sent, set up response completer.
-      var nextResponseCompleter = new Completer<_HttpIncoming>();
+      var nextResponseCompleter = Completer<_HttpIncoming>();
       _nextResponseCompleter = nextResponseCompleter;
 
       // Listen for response.
@@ -2203,7 +2202,7 @@
           // If we see a state error, we failed to get the 'first'
           // element.
           .catchError((error) {
-        throw new HttpException("Connection closed before data was received",
+        throw HttpException("Connection closed before data was received",
             uri: uri);
       }, test: (error) => error is StateError).catchError((error, stackTrace) {
         // We are done with the socket.
@@ -2222,8 +2221,8 @@
   }
 
   Future<Socket> detachSocket() {
-    return _streamFuture!.then(
-        (_) => new _DetachedSocket(_socket, _httpParser.detachIncoming()));
+    return _streamFuture!
+        .then((_) => _DetachedSocket(_socket, _httpParser.detachIncoming()));
   }
 
   void destroy() {
@@ -2258,7 +2257,7 @@
       String host,
       int port,
       _Proxy proxy,
-      bool callback(X509Certificate certificate),
+      bool Function(X509Certificate certificate) callback,
       _HttpProfileData? profileData) {
     final method = "CONNECT";
     final uri = Uri(host: host, port: port);
@@ -2288,7 +2287,7 @@
         final error = "Proxy failed to establish tunnel "
             "(${response.statusCode} ${response.reasonPhrase})";
         profileData?.requestEvent(error);
-        throw new HttpException(error, uri: request.uri);
+        throw HttpException(error, uri: request.uri);
       }
       var socket = (response as _HttpClientResponse)
           ._httpRequest
@@ -2299,7 +2298,7 @@
     }).then((secureSocket) {
       String key = _HttpClientConnection.makeKey(true, host, port);
       profileData?.requestEvent('Proxy tunnel established');
-      return new _HttpClientConnection(
+      return _HttpClientConnection(
           key, secureSocket, request._httpClient, true);
     });
   }
@@ -2317,7 +2316,7 @@
 
   void startTimer() {
     assert(_idleTimer == null);
-    _idleTimer = new Timer(_httpClient.idleTimeout, () {
+    _idleTimer = Timer(_httpClient.idleTimeout, () {
       _idleTimer = null;
       close();
     });
@@ -2338,10 +2337,10 @@
   final int port;
   final bool isSecure;
   final SecurityContext? context;
-  final Set<_HttpClientConnection> _idle = new HashSet();
-  final Set<_HttpClientConnection> _active = new HashSet();
-  final Set<ConnectionTask> _socketTasks = new HashSet();
-  final Queue _pending = new ListQueue();
+  final Set<_HttpClientConnection> _idle = HashSet();
+  final Set<_HttpClientConnection> _active = HashSet();
+  final Set<ConnectionTask> _socketTasks = HashSet();
+  final _pending = ListQueue<void Function()>();
   int _connecting = 0;
 
   _ConnectionTarget(
@@ -2415,12 +2414,12 @@
     if (hasIdle) {
       var connection = takeIdle();
       client._connectionsChanged();
-      return new Future.value(new _ConnectionInfo(connection, proxy));
+      return Future.value(_ConnectionInfo(connection, proxy));
     }
     var maxConnectionsPerHost = client.maxConnectionsPerHost;
     if (maxConnectionsPerHost != null &&
         _active.length + _connecting >= maxConnectionsPerHost) {
-      var completer = new Completer<_ConnectionInfo>();
+      var completer = Completer<_ConnectionInfo>();
       _pending.add(() {
         completer
             .complete(connect(uriHost, uriPort, proxy, client, profileData));
@@ -2452,7 +2451,7 @@
           socket.setOption(SocketOption.tcpNoDelay, true);
         }
         var connection =
-            new _HttpClientConnection(key, socket, client, false, context);
+            _HttpClientConnection(key, socket, client, false, context);
         if (isSecure && !proxy.isDirect) {
           connection._dispose = true;
           return connection
@@ -2462,12 +2461,12 @@
                 ._getConnectionTarget(uriHost, uriPort, true)
                 .addNewActive(tunnel);
             _socketTasks.remove(task);
-            return new _ConnectionInfo(tunnel, proxy);
+            return _ConnectionInfo(tunnel, proxy);
           });
         } else {
           addNewActive(connection);
           _socketTasks.remove(task);
-          return new _ConnectionInfo(connection, proxy);
+          return _ConnectionInfo(connection, proxy);
         }
       }, onError: (error) {
         // When there is a timeout, there is a race in which the connectionTask
@@ -2481,8 +2480,8 @@
           _socketTasks.remove(task);
           task.cancel();
           throw SocketException(
-              "HTTP connection timed out after ${connectionTimeout}, "
-              "host: ${host}, port: ${port}");
+              "HTTP connection timed out after $connectionTimeout, "
+              "host: $host, port: $port");
         }
         _socketTasks.remove(task);
         _checkPending();
@@ -2495,13 +2494,14 @@
   }
 }
 
-typedef bool BadCertificateCallback(X509Certificate cr, String host, int port);
+typedef BadCertificateCallback = bool Function(
+    X509Certificate cr, String host, int port);
 
 class _HttpClient implements HttpClient {
   bool _closing = false;
   bool _closingForcefully = false;
   final Map<String, _ConnectionTarget> _connectionTargets =
-      new HashMap<String, _ConnectionTarget>();
+      HashMap<String, _ConnectionTarget>();
   final List<_Credentials> _credentials = [];
   final List<_ProxyCredentials> _proxyCredentials = [];
   final SecurityContext? _context;
@@ -2536,7 +2536,7 @@
   }
 
   set badCertificateCallback(
-      bool callback(X509Certificate cert, String host, int port)?) {
+      bool Function(X509Certificate cert, String host, int port)? callback) {
     _badCertificateCallback = callback;
   }
 
@@ -2560,8 +2560,8 @@
       query = path.substring(queryStart + 1, fragmentStart);
       path = path.substring(0, queryStart);
     }
-    Uri uri = new Uri(
-        scheme: "http", host: host, port: port, path: path, query: query);
+    Uri uri =
+        Uri(scheme: "http", host: host, port: port, path: path, query: query);
     return _openUrl(method, uri);
   }
 
@@ -2607,27 +2607,30 @@
         !force || !_connectionTargets.values.any((s) => s._active.isNotEmpty));
   }
 
-  set authenticate(Future<bool> f(Uri url, String scheme, String? realm)?) {
+  set authenticate(
+      Future<bool> Function(Uri url, String scheme, String? realm)? f) {
     _authenticate = f;
   }
 
   void addCredentials(Uri url, String realm, HttpClientCredentials cr) {
     _credentials
-        .add(new _SiteCredentials(url, realm, cr as _HttpClientCredentials));
+        .add(_SiteCredentials(url, realm, cr as _HttpClientCredentials));
   }
 
   set authenticateProxy(
-      Future<bool> f(String host, int port, String scheme, String? realm)?) {
+      Future<bool> Function(
+              String host, int port, String scheme, String? realm)?
+          f) {
     _authenticateProxy = f;
   }
 
   void addProxyCredentials(
       String host, int port, String realm, HttpClientCredentials cr) {
     _proxyCredentials.add(
-        new _ProxyCredentials(host, port, realm, cr as _HttpClientCredentials));
+        _ProxyCredentials(host, port, realm, cr as _HttpClientCredentials));
   }
 
-  set findProxy(String f(Uri uri)?) => _findProxy = f;
+  set findProxy(String Function(Uri uri)? f) => _findProxy = f;
 
   static void _startRequestTimelineEvent(
       TimelineTask? timeline, String method, Uri uri) {
@@ -2649,21 +2652,20 @@
 
   Future<_HttpClientRequest> _openUrl(String method, Uri uri) {
     if (_closing) {
-      throw new StateError("Client is closed");
+      throw StateError("Client is closed");
     }
 
     // Ignore any fragments on the request URI.
     uri = uri.removeFragment();
 
     if (method == null) {
-      throw new ArgumentError(method);
+      throw ArgumentError(method);
     }
     if (method != "CONNECT") {
       if (uri.host.isEmpty) {
-        throw new ArgumentError("No host specified in URI $uri");
+        throw ArgumentError("No host specified in URI $uri");
       } else if (uri.scheme != "http" && uri.scheme != "https") {
-        throw new ArgumentError(
-            "Unsupported scheme '${uri.scheme}' in URI $uri");
+        throw ArgumentError("Unsupported scheme '${uri.scheme}' in URI $uri");
       }
     }
 
@@ -2683,9 +2685,9 @@
       // TODO(sgjesse): Keep a map of these as normally only a few
       // configuration strings will be used.
       try {
-        proxyConf = new _ProxyConfiguration(findProxy(uri));
+        proxyConf = _ProxyConfiguration(findProxy(uri));
       } catch (error, stackTrace) {
-        return new Future.error(error, stackTrace);
+        return Future.error(error, stackTrace);
       }
     }
     _HttpProfileData? profileData;
@@ -2784,7 +2786,7 @@
   _ConnectionTarget _getConnectionTarget(String host, int port, bool isSecure) {
     String key = _HttpClientConnection.makeKey(isSecure, host, port);
     return _connectionTargets.putIfAbsent(key, () {
-      return new _ConnectionTarget(key, host, port, isSecure, _context);
+      return _ConnectionTarget(key, host, port, isSecure, _context);
     });
   }
 
@@ -2798,7 +2800,7 @@
     Iterator<_Proxy> proxies = proxyConf.proxies.iterator;
 
     Future<_ConnectionInfo> connect(error, stackTrace) {
-      if (!proxies.moveNext()) return new Future.error(error, stackTrace);
+      if (!proxies.moveNext()) return Future.error(error, stackTrace);
       _Proxy proxy = proxies.current;
       String host = proxy.isDirect ? uriHost : proxy.host!;
       int port = proxy.isDirect ? uriPort : proxy.port!;
@@ -2808,7 +2810,7 @@
           .catchError(connect);
     }
 
-    return connect(new HttpException("No proxies given"), StackTrace.current);
+    return connect(HttpException("No proxies given"), StackTrace.current);
   }
 
   _SiteCredentials? _findCredentials(Uri url, [_AuthenticationScheme? scheme]) {
@@ -2884,13 +2886,13 @@
         var pos = option.lastIndexOf(":");
         if (option.indexOf("]") > pos) option = "$option:1080";
       } else {
-        if (option.indexOf(":") == -1) option = "$option:1080";
+        if (!option.contains(":")) option = "$option:1080";
       }
       return "PROXY $option";
     }
 
     // Default to using the process current environment.
-    if (environment == null) environment = _platformEnvironmentCache;
+    environment ??= _platformEnvironmentCache;
 
     String? proxyCfg;
 
@@ -2916,7 +2918,8 @@
     return "DIRECT";
   }
 
-  static Map<String, String> _platformEnvironmentCache = Platform.environment;
+  static final Map<String, String> _platformEnvironmentCache =
+      Platform.environment;
 }
 
 class _HttpConnection extends LinkedListEntry<_HttpConnection>
@@ -2927,8 +2930,8 @@
   static const _DETACHED = 3;
 
   // Use HashMap, as we don't need to keep order.
-  static Map<int, _HttpConnection> _connections =
-      new HashMap<int, _HttpConnection>();
+  static final Map<int, _HttpConnection> _connections =
+      HashMap<int, _HttpConnection>();
 
   final /*_ServerSocket*/ _socket;
   final _HttpServer _httpServer;
@@ -2939,7 +2942,7 @@
   Future? _streamFuture;
 
   _HttpConnection(this._socket, this._httpServer)
-      : _httpParser = new _HttpParser.requestParser() {
+      : _httpParser = _HttpParser.requestParser() {
     _connections[_serviceId] = this;
     _httpParser.listenToStream(_socket);
     _subscription = _httpParser.listen((incoming) {
@@ -2952,8 +2955,8 @@
       // stream paused until the request has been send.
       _subscription!.pause();
       _state = _ACTIVE;
-      var outgoing = new _HttpOutgoing(_socket);
-      var response = new _HttpResponse(
+      var outgoing = _HttpOutgoing(_socket);
+      var response = _HttpResponse(
           incoming.uri!,
           incoming.headers.protocolVersion,
           outgoing,
@@ -2963,7 +2966,7 @@
       if (incoming.statusCode == HttpStatus.badRequest) {
         response.statusCode = HttpStatus.badRequest;
       }
-      var request = new _HttpRequest(response, incoming, _httpServer, this);
+      var request = _HttpRequest(response, incoming, _httpServer, this);
       _streamFuture = outgoing.done.then((_) {
         response.deadline = null;
         if (_state == _DETACHED) return;
@@ -3020,7 +3023,7 @@
 
     return _streamFuture!.then((_) {
       _connections.remove(_serviceId);
-      return new _DetachedSocket(_socket, detachedIncoming);
+      return _DetachedSocket(_socket, detachedIncoming);
     });
   }
 
@@ -3083,7 +3086,7 @@
     with _ServiceObject
     implements HttpServer {
   // Use default Map so we keep order.
-  static Map<int, _HttpServer> _servers = new Map<int, _HttpServer>();
+  static final Map<int, _HttpServer> _servers = <int, _HttpServer>{};
 
   String? serverHeader;
   final HttpHeaders defaultResponseHeaders = _initDefaultResponseHeaders();
@@ -3097,7 +3100,7 @@
     return ServerSocket.bind(address, port,
             backlog: backlog, v6Only: v6Only, shared: shared)
         .then<HttpServer>((socket) {
-      return new _HttpServer._(socket, true);
+      return _HttpServer._(socket, true);
     });
   }
 
@@ -3115,12 +3118,12 @@
             requestClientCertificate: requestClientCertificate,
             shared: shared)
         .then<HttpServer>((socket) {
-      return new _HttpServer._(socket, true);
+      return _HttpServer._(socket, true);
     });
   }
 
   _HttpServer._(this._serverSocket, this._closeServer)
-      : _controller = new StreamController<HttpRequest>(sync: true) {
+      : _controller = StreamController<HttpRequest>(sync: true) {
     _controller.onCancel = close;
     idleTimeout = const Duration(seconds: 120);
     _servers[_serviceId] = this;
@@ -3128,14 +3131,14 @@
 
   _HttpServer.listenOn(this._serverSocket)
       : _closeServer = false,
-        _controller = new StreamController<HttpRequest>(sync: true) {
+        _controller = StreamController<HttpRequest>(sync: true) {
     _controller.onCancel = close;
     idleTimeout = const Duration(seconds: 120);
     _servers[_serviceId] = this;
   }
 
   static HttpHeaders _initDefaultResponseHeaders() {
-    var defaultResponseHeaders = new _HttpHeaders('1.1');
+    var defaultResponseHeaders = _HttpHeaders('1.1');
     defaultResponseHeaders.contentType = ContentType.text;
     defaultResponseHeaders.set('X-Frame-Options', 'SAMEORIGIN');
     defaultResponseHeaders.set('X-Content-Type-Options', 'nosniff');
@@ -3153,7 +3156,7 @@
     }
     _idleTimeout = duration;
     if (duration != null) {
-      _idleTimer = new Timer.periodic(duration, (_) {
+      _idleTimer = Timer.periodic(duration, (_) {
         for (var idle in _idleConnections.toList()) {
           if (idle.isMarkedIdle) {
             idle.destroy();
@@ -3165,14 +3168,17 @@
     }
   }
 
-  StreamSubscription<HttpRequest> listen(void onData(HttpRequest event)?,
-      {Function? onError, void onDone()?, bool? cancelOnError}) {
+  StreamSubscription<HttpRequest> listen(
+      void Function(HttpRequest event)? onData,
+      {Function? onError,
+      void Function()? onDone,
+      bool? cancelOnError}) {
     _serverSocket.listen((Socket socket) {
       if (socket.address.type != InternetAddressType.unix) {
         socket.setOption(SocketOption.tcpNoDelay, true);
       }
       // Accept the client connection.
-      _HttpConnection connection = new _HttpConnection(socket, this);
+      _HttpConnection connection = _HttpConnection(socket, this);
       _idleConnections.add(connection);
     }, onError: (error, stackTrace) {
       // Ignore HandshakeExceptions as they are bound to a single request,
@@ -3191,7 +3197,7 @@
     if (_serverSocket != null && _closeServer) {
       result = _serverSocket.close();
     } else {
-      result = new Future.value();
+      result = Future.value();
     }
     idleTimeout = null;
     if (force) {
@@ -3220,12 +3226,12 @@
   }
 
   int get port {
-    if (closed) throw new HttpException("HttpServer is not bound to a socket");
+    if (closed) throw HttpException("HttpServer is not bound to a socket");
     return _serverSocket.port;
   }
 
   InternetAddress get address {
-    if (closed) throw new HttpException("HttpServer is not bound to a socket");
+    if (closed) throw HttpException("HttpServer is not bound to a socket");
     return _serverSocket.address;
   }
 
@@ -3262,20 +3268,20 @@
       _sessionManagerInstance ??= _HttpSessionManager();
 
   HttpConnectionsInfo connectionsInfo() {
-    HttpConnectionsInfo result = new HttpConnectionsInfo();
+    HttpConnectionsInfo result = HttpConnectionsInfo();
     result.total = _activeConnections.length + _idleConnections.length;
-    _activeConnections.forEach((_HttpConnection conn) {
+    for (var conn in _activeConnections) {
       if (conn._isActive) {
         result.active++;
       } else {
         assert(conn._isClosing);
         result.closing++;
       }
-    });
-    _idleConnections.forEach((_HttpConnection conn) {
+    }
+    for (var conn in _idleConnections) {
       result.idle++;
       assert(conn._isIdle);
-    });
+    }
     return result;
   }
 
@@ -3322,10 +3328,10 @@
 
   // Set of currently connected clients.
   final LinkedList<_HttpConnection> _activeConnections =
-      new LinkedList<_HttpConnection>();
+      LinkedList<_HttpConnection>();
   final LinkedList<_HttpConnection> _idleConnections =
-      new LinkedList<_HttpConnection>();
-  StreamController<HttpRequest> _controller;
+      LinkedList<_HttpConnection>();
+  final StreamController<HttpRequest> _controller;
 }
 
 class _ProxyConfiguration {
@@ -3334,12 +3340,12 @@
 
   _ProxyConfiguration(String configuration) : proxies = <_Proxy>[] {
     if (configuration == null) {
-      throw new HttpException("Invalid proxy configuration $configuration");
+      throw HttpException("Invalid proxy configuration $configuration");
     }
     List<String> list = configuration.split(";");
-    list.forEach((String proxy) {
+    for (var proxy in list) {
       proxy = proxy.trim();
-      if (!proxy.isEmpty) {
+      if (proxy.isNotEmpty) {
         if (proxy.startsWith(PROXY_PREFIX)) {
           String? username;
           String? password;
@@ -3352,8 +3358,7 @@
             proxy = proxy.substring(at + 1).trim();
             int colon = userinfo.indexOf(":");
             if (colon == -1 || colon == 0 || colon == proxy.length - 1) {
-              throw new HttpException(
-                  "Invalid proxy configuration $configuration");
+              throw HttpException("Invalid proxy configuration $configuration");
             }
             username = userinfo.substring(0, colon).trim();
             password = userinfo.substring(colon + 1).trim();
@@ -3361,8 +3366,7 @@
           // Look for proxy host and port.
           int colon = proxy.lastIndexOf(":");
           if (colon == -1 || colon == 0 || colon == proxy.length - 1) {
-            throw new HttpException(
-                "Invalid proxy configuration $configuration");
+            throw HttpException("Invalid proxy configuration $configuration");
           }
           String host = proxy.substring(0, colon).trim();
           if (host.startsWith("[") && host.endsWith("]")) {
@@ -3372,22 +3376,21 @@
           int port;
           try {
             port = int.parse(portString);
-          } on FormatException catch (e) {
-            throw new HttpException(
-                "Invalid proxy configuration $configuration, "
+          } on FormatException {
+            throw HttpException("Invalid proxy configuration $configuration, "
                 "invalid port '$portString'");
           }
-          proxies.add(new _Proxy(host, port, username, password));
+          proxies.add(_Proxy(host, port, username, password));
         } else if (proxy.trim() == DIRECT_PREFIX) {
-          proxies.add(new _Proxy.direct());
+          proxies.add(_Proxy.direct());
         } else {
-          throw new HttpException("Invalid proxy configuration $configuration");
+          throw HttpException("Invalid proxy configuration $configuration");
         }
       }
-    });
+    }
   }
 
-  const _ProxyConfiguration.direct() : proxies = const [const _Proxy.direct()];
+  const _ProxyConfiguration.direct() : proxies = const [_Proxy.direct()];
 
   final List<_Proxy> proxies;
 }
@@ -3434,8 +3437,8 @@
 
   _DetachedSocket(this._socket, this._incoming);
 
-  StreamSubscription<Uint8List> listen(void onData(Uint8List event)?,
-      {Function? onError, void onDone()?, bool? cancelOnError}) {
+  StreamSubscription<Uint8List> listen(void Function(Uint8List event)? onData,
+      {Function? onError, void Function()? onDone, bool? cancelOnError}) {
     return _incoming.listen(onData,
         onError: onError, onDone: onDone, cancelOnError: cancelOnError);
   }
@@ -3511,9 +3514,9 @@
 class _AuthenticationScheme {
   final int _scheme;
 
-  static const UNKNOWN = const _AuthenticationScheme(-1);
-  static const BASIC = const _AuthenticationScheme(0);
-  static const DIGEST = const _AuthenticationScheme(1);
+  static const UNKNOWN = _AuthenticationScheme(-1);
+  static const BASIC = _AuthenticationScheme(0);
+  static const DIGEST = _AuthenticationScheme(1);
 
   const _AuthenticationScheme(this._scheme);
 
@@ -3551,7 +3554,7 @@
       // http://tools.ietf.org/html/draft-reschke-basicauth-enc-06. For
       // now always use UTF-8 encoding.
       var creds = credentials as _HttpClientDigestCredentials;
-      var hasher = new _MD5()
+      var hasher = _MD5()
         ..add(utf8.encode(creds.username))
         ..add([_CharCode.COLON])
         ..add(realm.codeUnits)
@@ -3662,7 +3665,7 @@
 
   String authorization(_Credentials credentials, _HttpClientRequest request) {
     String requestUri = request._requestUri();
-    _MD5 hasher = new _MD5()
+    _MD5 hasher = _MD5()
       ..add(request.method.codeUnits)
       ..add([_CharCode.COLON])
       ..add(requestUri.codeUnits);
@@ -3671,7 +3674,7 @@
     bool isAuth = false;
     String cnonce = "";
     String nc = "";
-    hasher = new _MD5()
+    hasher = _MD5()
       ..add(credentials.ha1!.codeUnits)
       ..add([_CharCode.COLON]);
     if (credentials.qop == "auth") {
@@ -3698,7 +3701,7 @@
     }
     var response = _CryptoUtils.bytesToHex(hasher.close());
 
-    StringBuffer buffer = new StringBuffer()
+    StringBuffer buffer = StringBuffer()
       ..write('Digest ')
       ..write('username="$username"')
       ..write(', realm="${credentials.realm}"')
diff --git a/sdk/lib/_http/http_parser.dart b/sdk/lib/_http/http_parser.dart
index 52b16ae..0a8bba4 100644
--- a/sdk/lib/_http/http_parser.dart
+++ b/sdk/lib/_http/http_parser.dart
@@ -7,18 +7,18 @@
 // Global constants.
 class _Const {
   // Bytes for "HTTP".
-  static const HTTP = const [72, 84, 84, 80];
+  static const HTTP = [72, 84, 84, 80];
   // Bytes for "HTTP/1.".
-  static const HTTP1DOT = const [72, 84, 84, 80, 47, 49, 46];
+  static const HTTP1DOT = [72, 84, 84, 80, 47, 49, 46];
   // Bytes for "HTTP/1.0".
-  static const HTTP10 = const [72, 84, 84, 80, 47, 49, 46, 48];
+  static const HTTP10 = [72, 84, 84, 80, 47, 49, 46, 48];
   // Bytes for "HTTP/1.1".
-  static const HTTP11 = const [72, 84, 84, 80, 47, 49, 46, 49];
+  static const HTTP11 = [72, 84, 84, 80, 47, 49, 46, 49];
 
   static const bool T = true;
   static const bool F = false;
   // Loopup-map for the following characters: '()<>@,;:\\"/[]?={} \t'.
-  static const SEPARATOR_MAP = const [
+  static const SEPARATOR_MAP = [
     F, F, F, F, F, F, F, F, F, T, F, F, F, F, F, F, F, F, F, F, F, F, F, F, //
     F, F, F, F, F, F, F, F, T, F, T, F, F, F, F, F, T, T, F, F, T, F, F, T, //
     F, F, F, F, F, F, F, F, F, F, T, T, T, T, T, T, T, F, F, F, F, F, F, F, //
@@ -39,15 +39,12 @@
   static const int LF = 10;
   static const int CR = 13;
   static const int SP = 32;
-  static const int AMPERSAND = 38;
   static const int COMMA = 44;
-  static const int DASH = 45;
   static const int SLASH = 47;
   static const int ZERO = 48;
   static const int ONE = 49;
   static const int COLON = 58;
   static const int SEMI_COLON = 59;
-  static const int EQUAL = 61;
 }
 
 // States of the HTTP parser state machine.
@@ -99,19 +96,17 @@
   static const int RESPONSE = 0;
 }
 
-/**
- * The _HttpDetachedStreamSubscription takes a subscription and some extra data,
- * and makes it possible to "inject" the data in from of other data events
- * from the subscription.
- *
- * It does so by overriding pause/resume, so that once the
- * _HttpDetachedStreamSubscription is resumed, it'll deliver the data before
- * resuming the underlying subscription.
- */
+/// The _HttpDetachedStreamSubscription takes a subscription and some extra data,
+/// and makes it possible to "inject" the data in from of other data events
+/// from the subscription.
+///
+/// It does so by overriding pause/resume, so that once the
+/// _HttpDetachedStreamSubscription is resumed, it'll deliver the data before
+/// resuming the underlying subscription.
 class _HttpDetachedStreamSubscription implements StreamSubscription<Uint8List> {
-  StreamSubscription<Uint8List> _subscription;
+  final StreamSubscription<Uint8List> _subscription;
   Uint8List? _injectData;
-  Function? _userOnData;
+  void Function(Uint8List data)? _userOnData;
   bool _isCanceled = false;
   bool _scheduled = false;
   int _pauseCount = 1;
@@ -130,12 +125,12 @@
     return _subscription.cancel();
   }
 
-  void onData(void handleData(Uint8List data)?) {
+  void onData(void Function(Uint8List data)? handleData) {
     _userOnData = handleData;
     _subscription.onData(handleData);
   }
 
-  void onDone(void handleDone()?) {
+  void onDone(void Function()? handleDone) {
     _subscription.onDone(handleDone);
   }
 
@@ -170,7 +165,7 @@
     scheduleMicrotask(() {
       _scheduled = false;
       if (_pauseCount > 0 || _isCanceled) return;
-      var data = _injectData;
+      var data = _injectData!;
       _injectData = null;
       // To ensure that 'subscription.isPaused' is false, we resume the
       // subscription here. This is fine as potential events are delayed.
@@ -186,8 +181,8 @@
 
   _HttpDetachedIncoming(this.subscription, this.bufferedData);
 
-  StreamSubscription<Uint8List> listen(void onData(Uint8List event)?,
-      {Function? onError, void onDone()?, bool? cancelOnError}) {
+  StreamSubscription<Uint8List> listen(void Function(Uint8List event)? onData,
+      {Function? onError, void Function()? onDone, bool? cancelOnError}) {
     var subscription = this.subscription;
     if (subscription != null) {
       subscription
@@ -197,37 +192,34 @@
       if (bufferedData == null) {
         return subscription..resume();
       }
-      return new _HttpDetachedStreamSubscription(
-          subscription, bufferedData, onData)
+      return _HttpDetachedStreamSubscription(subscription, bufferedData, onData)
         ..resume();
     } else {
       // TODO(26379): add test for this branch.
-      return new Stream<Uint8List>.fromIterable([bufferedData!]).listen(onData,
+      return Stream<Uint8List>.fromIterable([bufferedData!]).listen(onData,
           onError: onError, onDone: onDone, cancelOnError: cancelOnError);
     }
   }
 }
 
-/**
- * HTTP parser which parses the data stream given to [consume].
- *
- * If an HTTP parser error occurs, the parser will signal an error to either
- * the current _HttpIncoming or the _parser itself.
- *
- * The connection upgrades (e.g. switching from HTTP/1.1 to the
- * WebSocket protocol) is handled in a special way. If connection
- * upgrade is specified in the headers, then on the callback to
- * [:responseStart:] the [:upgrade:] property on the [:HttpParser:]
- * object will be [:true:] indicating that from now on the protocol is
- * not HTTP anymore and no more callbacks will happen, that is
- * [:dataReceived:] and [:dataEnd:] are not called in this case as
- * there is no more HTTP data. After the upgrade the method
- * [:readUnparsedData:] can be used to read any remaining bytes in the
- * HTTP parser which are part of the protocol the connection is
- * upgrading to. These bytes cannot be processed by the HTTP parser
- * and should be handled according to whatever protocol is being
- * upgraded to.
- */
+/// HTTP parser which parses the data stream given to [consume].
+///
+/// If an HTTP parser error occurs, the parser will signal an error to either
+/// the current _HttpIncoming or the _parser itself.
+///
+/// The connection upgrades (e.g. switching from HTTP/1.1 to the
+/// WebSocket protocol) is handled in a special way. If connection
+/// upgrade is specified in the headers, then on the callback to
+/// [:responseStart:] the [:upgrade:] property on the [:HttpParser:]
+/// object will be [:true:] indicating that from now on the protocol is
+/// not HTTP anymore and no more callbacks will happen, that is
+/// [:dataReceived:] and [:dataEnd:] are not called in this case as
+/// there is no more HTTP data. After the upgrade the method
+/// [:readUnparsedData:] can be used to read any remaining bytes in the
+/// HTTP parser which are part of the protocol the connection is
+/// upgrading to. These bytes cannot be processed by the HTTP parser
+/// and should be handled according to whatever protocol is being
+/// upgraded to.
 class _HttpParser extends Stream<_HttpIncoming> {
   // State.
   bool _parserCalled = false;
@@ -265,7 +257,7 @@
   _HttpHeaders? _headers;
 
   // The limit for parsing chunk size
-  int _chunkSizeLimit = 0x7FFFFFFF;
+  static const _chunkSizeLimit = 0x7FFFFFFF;
 
   // The current incoming connection.
   _HttpIncoming? _incoming;
@@ -276,15 +268,15 @@
   StreamController<Uint8List>? _bodyController;
 
   factory _HttpParser.requestParser() {
-    return new _HttpParser._(true);
+    return _HttpParser._(true);
   }
 
   factory _HttpParser.responseParser() {
-    return new _HttpParser._(false);
+    return _HttpParser._(false);
   }
 
   _HttpParser._(this._requestParser)
-      : _controller = new StreamController<_HttpIncoming>(sync: true) {
+      : _controller = StreamController<_HttpIncoming>(sync: true) {
     _controller
       ..onListen = () {
         _paused = false;
@@ -303,8 +295,11 @@
     _reset();
   }
 
-  StreamSubscription<_HttpIncoming> listen(void onData(_HttpIncoming event)?,
-      {Function? onError, void onDone()?, bool? cancelOnError}) {
+  StreamSubscription<_HttpIncoming> listen(
+      void Function(_HttpIncoming event)? onData,
+      {Function? onError,
+      void Function()? onDone,
+      bool? cancelOnError}) {
     return _controller.stream.listen(onData,
         onError: onError, onDone: onDone, cancelOnError: cancelOnError);
   }
@@ -372,11 +367,11 @@
     }
     var incoming = _createIncoming(_transferLength);
     if (_requestParser) {
-      incoming.method = new String.fromCharCodes(_method);
-      incoming.uri = Uri.parse(new String.fromCharCodes(_uriOrReasonPhrase));
+      incoming.method = String.fromCharCodes(_method);
+      incoming.uri = Uri.parse(String.fromCharCodes(_uriOrReasonPhrase));
     } else {
       incoming.statusCode = _statusCode;
-      incoming.reasonPhrase = new String.fromCharCodes(_uriOrReasonPhrase);
+      incoming.reasonPhrase = String.fromCharCodes(_uriOrReasonPhrase);
     }
     _method.clear();
     _uriOrReasonPhrase.clear();
@@ -539,7 +534,7 @@
 
         case _State.REQUEST_LINE_URI:
           if (byte == _CharCode.SP) {
-            if (_uriOrReasonPhrase.length == 0) {
+            if (_uriOrReasonPhrase.isEmpty) {
               throw HttpException("Invalid request, empty URI");
             }
             _state = _State.REQUEST_LINE_HTTP_VERSION;
@@ -632,7 +627,7 @@
           break;
 
         case _State.HEADER_START:
-          _headers = new _HttpHeaders(version!);
+          _headers = _HttpHeaders(version!);
           if (byte == _CharCode.CR) {
             _state = _State.HEADER_ENDING;
           } else if (byte == _CharCode.LF) {
@@ -687,8 +682,8 @@
           if (byte == _CharCode.SP || byte == _CharCode.HT) {
             _state = _State.HEADER_VALUE_START;
           } else {
-            String headerField = new String.fromCharCodes(_headerField);
-            String headerValue = new String.fromCharCodes(_headerValue);
+            String headerField = String.fromCharCodes(_headerField);
+            String headerValue = String.fromCharCodes(_headerValue);
             const errorIfBothText = "Both Content-Length and Transfer-Encoding "
                 "are specified, at most one is allowed";
             if (headerField == HttpHeaders.contentLengthHeader) {
@@ -829,7 +824,7 @@
           // Always present the data as a view. This way we can handle all
           // cases like this, and the user will not experience different data
           // typed (which could lead to polymorphic user code).
-          Uint8List data = new Uint8List.view(
+          Uint8List data = Uint8List.view(
               buffer.buffer, buffer.offsetInBytes + _index, dataAvailable);
           _bodyController!.add(data);
           if (_remainingContent != -1) {
@@ -953,7 +948,7 @@
   _HttpDetachedIncoming detachIncoming() {
     // Simulate detached by marking as upgraded.
     _state = _State.UPGRADED;
-    return new _HttpDetachedIncoming(_socketSubscription, readUnparsedData());
+    return _HttpDetachedIncoming(_socketSubscription, readUnparsedData());
   }
 
   Uint8List? readUnparsedData() {
@@ -1099,7 +1094,6 @@
 
       default:
         throw UnsupportedError("Unexpected state: $_state");
-        break;
     }
     throw HttpException(
         "$method exceeds the $_headerTotalSizeLimit size limit");
@@ -1109,10 +1103,9 @@
     assert(_incoming == null);
     assert(_bodyController == null);
     assert(!_bodyPaused);
-    var controller =
-        _bodyController = new StreamController<Uint8List>(sync: true);
-    var incoming = _incoming =
-        new _HttpIncoming(_headers!, transferLength, controller.stream);
+    var controller = _bodyController = StreamController<Uint8List>(sync: true);
+    var incoming =
+        _incoming = _HttpIncoming(_headers!, transferLength, controller.stream);
     controller
       ..onListen = () {
         if (incoming != _incoming) return;
diff --git a/sdk/lib/_http/http_session.dart b/sdk/lib/_http/http_session.dart
index 407192a..edf811f 100644
--- a/sdk/lib/_http/http_session.dart
+++ b/sdk/lib/_http/http_session.dart
@@ -13,16 +13,16 @@
   bool _destroyed = false;
   bool _isNew = true;
   DateTime _lastSeen;
-  Function? _timeoutCallback;
-  _HttpSessionManager _sessionManager;
+  void Function()? _timeoutCallback;
+  final _HttpSessionManager _sessionManager;
   // Pointers in timeout queue.
   _HttpSession? _prev;
   _HttpSession? _next;
   final String id;
 
-  final Map _data = new HashMap();
+  final Map _data = HashMap();
 
-  _HttpSession(this._sessionManager, this.id) : _lastSeen = new DateTime.now();
+  _HttpSession(this._sessionManager, this.id) : _lastSeen = DateTime.now();
 
   void destroy() {
     assert(!_destroyed);
@@ -34,7 +34,7 @@
   // Mark the session as seen. This will reset the timeout and move the node to
   // the end of the timeout queue.
   void _markSeen() {
-    _lastSeen = new DateTime.now();
+    _lastSeen = DateTime.now();
     _sessionManager._bumpToEnd(this);
   }
 
@@ -42,7 +42,7 @@
 
   bool get isNew => _isNew;
 
-  void set onTimeout(void callback()?) {
+  void set onTimeout(void Function()? callback) {
     _timeoutCallback = callback;
   }
 
@@ -79,7 +79,7 @@
   }
 
   Map<K, V> cast<K, V>() => _data.cast<K, V>();
-  update(key, update(value), {ifAbsent()?}) =>
+  update(key, update(value), {Function()? ifAbsent}) =>
       _data.update(key, update, ifAbsent: ifAbsent);
 
   void updateAll(update(key, value)) {
@@ -101,7 +101,7 @@
 //  * In a map, mapping from ID to HttpSession.
 //  * In a linked list, used as a timeout queue.
 class _HttpSessionManager {
-  Map<String, _HttpSession> _sessions;
+  final Map<String, _HttpSession> _sessions;
   int _sessionTimeout = 20 * 60; // 20 mins.
   _HttpSession? _head;
   _HttpSession? _tail;
@@ -124,7 +124,7 @@
     while (_sessions.containsKey(id)) {
       id = createSessionId();
     }
-    var session = _sessions[id] = new _HttpSession(this, id);
+    var session = _sessions[id] = _HttpSession(this, id);
     _addToTimeoutQueue(session);
     return session;
   }
@@ -187,9 +187,9 @@
     assert(_timer == null);
     var head = _head;
     if (head != null) {
-      int seconds = new DateTime.now().difference(head.lastSeen).inSeconds;
-      _timer = new Timer(
-          new Duration(seconds: _sessionTimeout - seconds), _timerTimeout);
+      int seconds = DateTime.now().difference(head.lastSeen).inSeconds;
+      _timer =
+          Timer(Duration(seconds: _sessionTimeout - seconds), _timerTimeout);
     }
   }
 
diff --git a/sdk/lib/_http/overrides.dart b/sdk/lib/_http/overrides.dart
index 1fcc81d..5c49590 100644
--- a/sdk/lib/_http/overrides.dart
+++ b/sdk/lib/_http/overrides.dart
@@ -4,7 +4,7 @@
 
 part of dart._http;
 
-final _httpOverridesToken = new Object();
+final _httpOverridesToken = Object();
 
 const _asyncRunZoned = runZoned;
 
@@ -46,12 +46,12 @@
   }
 
   /// Runs [body] in a fresh [Zone] using the provided overrides.
-  static R runZoned<R>(R body(),
+  static R runZoned<R>(R Function() body,
       {HttpClient Function(SecurityContext?)? createHttpClient,
       String Function(Uri uri, Map<String, String>? environment)?
           findProxyFromEnvironment}) {
     HttpOverrides overrides =
-        new _HttpOverridesScope(createHttpClient, findProxyFromEnvironment);
+        _HttpOverridesScope(createHttpClient, findProxyFromEnvironment);
     return _asyncRunZoned<R>(body,
         zoneValues: {_httpOverridesToken: overrides});
   }
@@ -60,7 +60,7 @@
   ///
   /// Note that [overrides] should be an instance of a class that extends
   /// [HttpOverrides].
-  static R runWithHttpOverrides<R>(R body(), HttpOverrides overrides) {
+  static R runWithHttpOverrides<R>(R Function() body, HttpOverrides overrides) {
     return _asyncRunZoned<R>(body,
         zoneValues: {_httpOverridesToken: overrides});
   }
@@ -70,7 +70,7 @@
   /// When this override is installed, this function overrides the behavior of
   /// `new HttpClient`.
   HttpClient createHttpClient(SecurityContext? context) {
-    return new _HttpClient(context);
+    return _HttpClient(context);
   }
 
   /// Resolves the proxy server to be used for HTTP connections.
diff --git a/sdk/lib/_http/websocket.dart b/sdk/lib/_http/websocket.dart
index 4b9bbff..9503ae3 100644
--- a/sdk/lib/_http/websocket.dart
+++ b/sdk/lib/_http/websocket.dart
@@ -4,9 +4,7 @@
 
 part of dart._http;
 
-/**
- * WebSocket status codes used when closing a WebSocket connection.
- */
+/// WebSocket status codes used when closing a WebSocket connection.
 abstract class WebSocketStatus {
   static const int normalClosure = 1000;
   static const int goingAway = 1001;
@@ -69,8 +67,7 @@
   /// * `serverNoContextTakeover`: false
   /// * `clientMaxWindowBits`: null (default maximal window size of 15 bits)
   /// * `serverMaxWindowBits`: null (default maximal window size of 15 bits)
-  static const CompressionOptions compressionDefault =
-      const CompressionOptions();
+  static const CompressionOptions compressionDefault = CompressionOptions();
   @Deprecated("Use compressionDefault instead")
   static const CompressionOptions DEFAULT = compressionDefault;
 
@@ -79,7 +76,7 @@
   /// Disables compression when used as compression configuration for a
   /// [WebSocket].
   static const CompressionOptions compressionOff =
-      const CompressionOptions(enabled: false);
+      CompressionOptions(enabled: false);
   @Deprecated("Use compressionOff instead")
   static const CompressionOptions OFF = compressionOff;
 
@@ -132,17 +129,17 @@
   /// negotiated max window bits.
   _CompressionMaxWindowBits _createServerResponseHeader(
       HeaderValue? requested) {
-    var info = new _CompressionMaxWindowBits("", 0);
+    var info = _CompressionMaxWindowBits("", 0);
 
     String? part = requested?.parameters[_serverMaxWindowBits];
     if (part != null) {
       if (part.length >= 2 && part.startsWith('0')) {
-        throw new ArgumentError("Illegal 0 padding on value.");
+        throw ArgumentError("Illegal 0 padding on value.");
       } else {
         int mwb = serverMaxWindowBits ??
             int.tryParse(part) ??
             _WebSocketImpl.DEFAULT_WINDOW_BITS;
-        info.headerValue = "; server_max_window_bits=${mwb}";
+        info.headerValue = "; server_max_window_bits=$mwb";
         info.maxWindowBits = mwb;
       }
     } else {
@@ -185,7 +182,7 @@
   /// [_CompressionMaxWindowBits] object with the response headers and
   /// negotiated `maxWindowBits` value.
   _CompressionMaxWindowBits _createHeader([HeaderValue? requested]) {
-    var info = new _CompressionMaxWindowBits("", 0);
+    var info = _CompressionMaxWindowBits("", 0);
     if (!enabled) {
       return info;
     }
@@ -194,15 +191,13 @@
 
     if (clientNoContextTakeover &&
         (requested == null ||
-            (requested != null &&
-                requested.parameters.containsKey(_clientNoContextTakeover)))) {
+            (requested.parameters.containsKey(_clientNoContextTakeover)))) {
       info.headerValue += "; client_no_context_takeover";
     }
 
     if (serverNoContextTakeover &&
         (requested == null ||
-            (requested != null &&
-                requested.parameters.containsKey(_serverNoContextTakeover)))) {
+            (requested.parameters.containsKey(_serverNoContextTakeover)))) {
       info.headerValue += "; server_no_context_takeover";
     }
 
@@ -217,100 +212,89 @@
   }
 }
 
-/**
- * The [WebSocketTransformer] provides the ability to upgrade a
- * [HttpRequest] to a [WebSocket] connection. It supports both
- * upgrading a single [HttpRequest] and upgrading a stream of
- * [HttpRequest]s.
- *
- * To upgrade a single [HttpRequest] use the static [upgrade] method.
- *
- *     HttpServer server;
- *     server.listen((request) {
- *       if (...) {
- *         WebSocketTransformer.upgrade(request).then((websocket) {
- *           ...
- *         });
- *       } else {
- *         // Do normal HTTP request processing.
- *       }
- *     });
- *
- * To transform a stream of [HttpRequest] events as it implements a
- * stream transformer that transforms a stream of HttpRequest into a
- * stream of WebSockets by upgrading each HttpRequest from the HTTP or
- * HTTPS server, to the WebSocket protocol.
- *
- *     server.transform(new WebSocketTransformer()).listen((webSocket) => ...);
- *
- * This transformer strives to implement WebSockets as specified by RFC6455.
- */
+/// The [WebSocketTransformer] provides the ability to upgrade a
+/// [HttpRequest] to a [WebSocket] connection. It supports both
+/// upgrading a single [HttpRequest] and upgrading a stream of
+/// [HttpRequest]s.
+///
+/// To upgrade a single [HttpRequest] use the static [upgrade] method.
+///
+///     HttpServer server;
+///     server.listen((request) {
+///       if (...) {
+///         WebSocketTransformer.upgrade(request).then((websocket) {
+///           ...
+///         });
+///       } else {
+///         // Do normal HTTP request processing.
+///       }
+///     });
+///
+/// To transform a stream of [HttpRequest] events as it implements a
+/// stream transformer that transforms a stream of HttpRequest into a
+/// stream of WebSockets by upgrading each HttpRequest from the HTTP or
+/// HTTPS server, to the WebSocket protocol.
+///
+///     server.transform(new WebSocketTransformer()).listen((webSocket) => ...);
+///
+/// This transformer strives to implement WebSockets as specified by RFC6455.
 abstract class WebSocketTransformer
     implements StreamTransformer<HttpRequest, WebSocket> {
-  /**
-   * Create a new [WebSocketTransformer].
-   *
-   * If [protocolSelector] is provided, [protocolSelector] will be called to
-   * select what protocol to use, if any were provided by the client.
-   * [protocolSelector] is should return either a [String] or a [Future]
-   * completing with a [String]. The [String] must exist in the list of
-   * protocols.
-   *
-   * If [compression] is provided, the [WebSocket] created will be configured
-   * to negotiate with the specified [CompressionOptions]. If none is specified
-   * then the [WebSocket] will be created with the default [CompressionOptions].
-   */
+  /// Create a new [WebSocketTransformer].
+  ///
+  /// If [protocolSelector] is provided, [protocolSelector] will be called to
+  /// select what protocol to use, if any were provided by the client.
+  /// [protocolSelector] is should return either a [String] or a [Future]
+  /// completing with a [String]. The [String] must exist in the list of
+  /// protocols.
+  ///
+  /// If [compression] is provided, the [WebSocket] created will be configured
+  /// to negotiate with the specified [CompressionOptions]. If none is specified
+  /// then the [WebSocket] will be created with the default [CompressionOptions].
   factory WebSocketTransformer(
-      {/*String|Future<String>*/ protocolSelector(List<String> protocols)?,
+      {/*String|Future<String>*/ Function(List<String> protocols)?
+          protocolSelector,
       CompressionOptions compression = CompressionOptions.compressionDefault}) {
-    return new _WebSocketTransformerImpl(protocolSelector, compression);
+    return _WebSocketTransformerImpl(protocolSelector, compression);
   }
 
-  /**
-   * Upgrades a [HttpRequest] to a [WebSocket] connection. If the
-   * request is not a valid WebSocket upgrade request an HTTP response
-   * with status code 500 will be returned. Otherwise the returned
-   * future will complete with the [WebSocket] when the upgrade process
-   * is complete.
-   *
-   * If [protocolSelector] is provided, [protocolSelector] will be called to
-   * select what protocol to use, if any were provided by the client.
-   * [protocolSelector] is should return either a [String] or a [Future]
-   * completing with a [String]. The [String] must exist in the list of
-   * protocols.
-   *
-   * If [compression] is provided, the [WebSocket] created will be configured
-   * to negotiate with the specified [CompressionOptions]. If none is specified
-   * then the [WebSocket] will be created with the default [CompressionOptions].
-   */
+  /// Upgrades a [HttpRequest] to a [WebSocket] connection. If the
+  /// request is not a valid WebSocket upgrade request an HTTP response
+  /// with status code 500 will be returned. Otherwise the returned
+  /// future will complete with the [WebSocket] when the upgrade process
+  /// is complete.
+  ///
+  /// If [protocolSelector] is provided, [protocolSelector] will be called to
+  /// select what protocol to use, if any were provided by the client.
+  /// [protocolSelector] is should return either a [String] or a [Future]
+  /// completing with a [String]. The [String] must exist in the list of
+  /// protocols.
+  ///
+  /// If [compression] is provided, the [WebSocket] created will be configured
+  /// to negotiate with the specified [CompressionOptions]. If none is specified
+  /// then the [WebSocket] will be created with the default [CompressionOptions].
   static Future<WebSocket> upgrade(HttpRequest request,
-      {protocolSelector(List<String> protocols)?,
+      {Function(List<String> protocols)? protocolSelector,
       CompressionOptions compression = CompressionOptions.compressionDefault}) {
     return _WebSocketTransformerImpl._upgrade(
         request, protocolSelector, compression);
   }
 
-  /**
-   * Checks whether the request is a valid WebSocket upgrade request.
-   */
+  /// Checks whether the request is a valid WebSocket upgrade request.
   static bool isUpgradeRequest(HttpRequest request) {
     return _WebSocketTransformerImpl._isUpgradeRequest(request);
   }
 }
 
-/**
- * A two-way HTTP communication object for client or server applications.
- *
- * The stream exposes the messages received. A text message will be of type
- * `String` and a binary message will be of type `List<int>`.
- */
+/// A two-way HTTP communication object for client or server applications.
+///
+/// The stream exposes the messages received. A text message will be of type
+/// `String` and a binary message will be of type `List<int>`.
 abstract class WebSocket
     implements
         Stream<dynamic /*String|List<int>*/ >,
         StreamSink<dynamic /*String|List<int>*/ > {
-  /**
-   * Possible states of the connection.
-   */
+  /// Possible states of the connection.
   static const int connecting = 0;
   static const int open = 1;
   static const int closing = 2;
@@ -325,52 +309,48 @@
   @Deprecated("Use closed instead")
   static const int CLOSED = closed;
 
-  /**
-   * The interval between ping signals.
-   *
-   * A ping message is sent every [pingInterval], starting at the first
-   * [pingInterval] after a new value has been assigned or a pong message has
-   * been received. If a ping message is not answered by a pong message from the
-   * peer, the `WebSocket` is assumed disconnected and the connection is closed
-   * with a [WebSocketStatus.goingAway] close code. When a ping signal is sent,
-   * the pong message must be received within [pingInterval].
-   *
-   * There are never two outstanding pings at any given time, and the next ping
-   * timer starts when the pong is received.
-   *
-   * Set the [pingInterval] to `null` to disable sending ping messages.
-   *
-   * The default value is `null`.
-   */
+  /// The interval between ping signals.
+  ///
+  /// A ping message is sent every [pingInterval], starting at the first
+  /// [pingInterval] after a new value has been assigned or a pong message has
+  /// been received. If a ping message is not answered by a pong message from the
+  /// peer, the `WebSocket` is assumed disconnected and the connection is closed
+  /// with a [WebSocketStatus.goingAway] close code. When a ping signal is sent,
+  /// the pong message must be received within [pingInterval].
+  ///
+  /// There are never two outstanding pings at any given time, and the next ping
+  /// timer starts when the pong is received.
+  ///
+  /// Set the [pingInterval] to `null` to disable sending ping messages.
+  ///
+  /// The default value is `null`.
   Duration? pingInterval;
 
-  /**
-   * Create a new WebSocket connection. The URL supplied in [url]
-   * must use the scheme `ws` or `wss`.
-   *
-   * The [protocols] argument is specifying the subprotocols the
-   * client is willing to speak.
-   *
-   * The [headers] argument is specifying additional HTTP headers for
-   * setting up the connection. This would typically be the `Origin`
-   * header and potentially cookies. The keys of the map are the header
-   * fields and the values are either String or List<String>.
-   *
-   * If [headers] is provided, there are a number of headers
-   * which are controlled by the WebSocket connection process. These
-   * headers are:
-   *
-   *   - `connection`
-   *   - `sec-websocket-key`
-   *   - `sec-websocket-protocol`
-   *   - `sec-websocket-version`
-   *   - `upgrade`
-   *
-   * If any of these are passed in the `headers` map they will be ignored.
-   *
-   * If the `url` contains user information this will be passed as basic
-   * authentication when setting up the connection.
-   */
+  /// Create a new WebSocket connection. The URL supplied in [url]
+  /// must use the scheme `ws` or `wss`.
+  ///
+  /// The [protocols] argument is specifying the subprotocols the
+  /// client is willing to speak.
+  ///
+  /// The [headers] argument is specifying additional HTTP headers for
+  /// setting up the connection. This would typically be the `Origin`
+  /// header and potentially cookies. The keys of the map are the header
+  /// fields and the values are either String or List<String>.
+  ///
+  /// If [headers] is provided, there are a number of headers
+  /// which are controlled by the WebSocket connection process. These
+  /// headers are:
+  ///
+  ///   - `connection`
+  ///   - `sec-websocket-key`
+  ///   - `sec-websocket-protocol`
+  ///   - `sec-websocket-version`
+  ///   - `upgrade`
+  ///
+  /// If any of these are passed in the `headers` map they will be ignored.
+  ///
+  /// If the `url` contains user information this will be passed as basic
+  /// authentication when setting up the connection.
   static Future<WebSocket> connect(String url,
           {Iterable<String>? protocols,
           Map<String, dynamic>? headers,
@@ -384,106 +364,82 @@
       ' instead of `extends` if implementing this abstract class.')
   WebSocket();
 
-  /**
-   * Creates a WebSocket from an already-upgraded socket.
-   *
-   * The initial WebSocket handshake must have occurred prior to this call. A
-   * WebSocket client can automatically perform the handshake using
-   * [WebSocket.connect], while a server can do so using
-   * [WebSocketTransformer.upgrade]. To manually upgrade an [HttpRequest],
-   * [HttpResponse.detachSocket] may be called.
-   *
-   * [protocol] should be the protocol negotiated by this handshake, if any.
-   *
-   * [serverSide] must be passed explicitly. If it's `false`, the WebSocket will
-   * act as the client and mask the messages it sends. If it's `true`, it will
-   * act as the server and will not mask its messages.
-   *
-   * If [compression] is provided, the [WebSocket] created will be configured
-   * to negotiate with the specified [CompressionOptions]. If none is specified
-   * then the [WebSocket] will be created with the default [CompressionOptions].
-   */
+  /// Creates a WebSocket from an already-upgraded socket.
+  ///
+  /// The initial WebSocket handshake must have occurred prior to this call. A
+  /// WebSocket client can automatically perform the handshake using
+  /// [WebSocket.connect], while a server can do so using
+  /// [WebSocketTransformer.upgrade]. To manually upgrade an [HttpRequest],
+  /// [HttpResponse.detachSocket] may be called.
+  ///
+  /// [protocol] should be the protocol negotiated by this handshake, if any.
+  ///
+  /// [serverSide] must be passed explicitly. If it's `false`, the WebSocket will
+  /// act as the client and mask the messages it sends. If it's `true`, it will
+  /// act as the server and will not mask its messages.
+  ///
+  /// If [compression] is provided, the [WebSocket] created will be configured
+  /// to negotiate with the specified [CompressionOptions]. If none is specified
+  /// then the [WebSocket] will be created with the default [CompressionOptions].
   factory WebSocket.fromUpgradedSocket(Socket socket,
       {String? protocol,
       bool? serverSide,
       CompressionOptions compression = CompressionOptions.compressionDefault}) {
     if (serverSide == null) {
-      throw new ArgumentError("The serverSide argument must be passed "
+      throw ArgumentError("The serverSide argument must be passed "
           "explicitly to WebSocket.fromUpgradedSocket.");
     }
-    return new _WebSocketImpl._fromSocket(
+    return _WebSocketImpl._fromSocket(
         socket, protocol, compression, serverSide);
   }
 
-  /**
-   * Returns the current state of the connection.
-   */
+  /// Returns the current state of the connection.
   int get readyState;
 
-  /**
-   * The extensions property is initially the empty string. After the
-   * WebSocket connection is established this string reflects the
-   * extensions used by the server.
-   */
+  /// The extensions property is initially the empty string. After the
+  /// WebSocket connection is established this string reflects the
+  /// extensions used by the server.
   String get extensions;
 
-  /**
-   * The protocol property is initially the empty string. After the
-   * WebSocket connection is established the value is the subprotocol
-   * selected by the server. If no subprotocol is negotiated the
-   * value will remain [:null:].
-   */
+  /// The protocol property is initially the empty string. After the
+  /// WebSocket connection is established the value is the subprotocol
+  /// selected by the server. If no subprotocol is negotiated the
+  /// value will remain [:null:].
   String? get protocol;
 
-  /**
-   * The close code set when the WebSocket connection is closed. If
-   * there is no close code available this property will be [:null:]
-   */
+  /// The close code set when the WebSocket connection is closed. If
+  /// there is no close code available this property will be [:null:]
   int? get closeCode;
 
-  /**
-   * The close reason set when the WebSocket connection is closed. If
-   * there is no close reason available this property will be [:null:]
-   */
+  /// The close reason set when the WebSocket connection is closed. If
+  /// there is no close reason available this property will be [:null:]
   String? get closeReason;
 
-  /**
-   * Closes the WebSocket connection. Set the optional [code] and [reason]
-   * arguments to send close information to the remote peer. If they are
-   * omitted, the peer will see [WebSocketStatus.noStatusReceived] code
-   * with no reason.
-   */
+  /// Closes the WebSocket connection. Set the optional [code] and [reason]
+  /// arguments to send close information to the remote peer. If they are
+  /// omitted, the peer will see [WebSocketStatus.noStatusReceived] code
+  /// with no reason.
   Future close([int? code, String? reason]);
 
-  /**
-   * Sends data on the WebSocket connection. The data in [data] must
-   * be either a `String`, or a `List<int>` holding bytes.
-   */
+  /// Sends data on the WebSocket connection. The data in [data] must
+  /// be either a `String`, or a `List<int>` holding bytes.
   void add(/*String|List<int>*/ data);
 
-  /**
-   * Sends data from a stream on WebSocket connection. Each data event from
-   * [stream] will be send as a single WebSocket frame. The data from [stream]
-   * must be either `String`s, or `List<int>`s holding bytes.
-   */
+  /// Sends data from a stream on WebSocket connection. Each data event from
+  /// [stream] will be send as a single WebSocket frame. The data from [stream]
+  /// must be either `String`s, or `List<int>`s holding bytes.
   Future addStream(Stream stream);
 
-  /**
-   * Sends a text message with the text represented by [bytes].
-   *
-   * The [bytes] should be valid UTF-8 encoded Unicode characters. If they are
-   * not, the receiving end will close the connection.
-   */
+  /// Sends a text message with the text represented by [bytes].
+  ///
+  /// The [bytes] should be valid UTF-8 encoded Unicode characters. If they are
+  /// not, the receiving end will close the connection.
   void addUtf8Text(List<int> bytes);
 
-  /**
-   * Gets the user agent used for WebSocket connections.
-   */
+  /// Gets the user agent used for WebSocket connections.
   static String? get userAgent => _WebSocketImpl.userAgent;
 
-  /**
-   * Sets the user agent to use for WebSocket connections.
-   */
+  /// Sets the user agent to use for WebSocket connections.
   static set userAgent(String? userAgent) {
     _WebSocketImpl.userAgent = userAgent;
   }
diff --git a/sdk/lib/_http/websocket_impl.dart b/sdk/lib/_http/websocket_impl.dart
index fe2c5a7..e43c3e5 100644
--- a/sdk/lib/_http/websocket_impl.dart
+++ b/sdk/lib/_http/websocket_impl.dart
@@ -41,11 +41,9 @@
   _EncodedString(this.bytes);
 }
 
-/**
- *  Stores the header and integer value derived from negotiation of
- *  client_max_window_bits and server_max_window_bits. headerValue will be
- *  set in the Websocket response headers.
- */
+/// Stores the header and integer value derived from negotiation of
+/// client_max_window_bits and server_max_window_bits. headerValue will be
+/// set in the Websocket response headers.
 class _CompressionMaxWindowBits {
   String headerValue;
   int maxWindowBits;
@@ -53,15 +51,13 @@
   String toString() => headerValue;
 }
 
-/**
- * The web socket protocol transformer handles the protocol byte stream
- * which is supplied through the `handleData`. As the protocol is processed,
- * it'll output frame data as either a List<int> or String.
- *
- * Important information about usage: Be sure you use cancelOnError, so the
- * socket will be closed when the processor encounter an error. Not using it
- * will lead to undefined behaviour.
- */
+/// The web socket protocol transformer handles the protocol byte stream
+/// which is supplied through the `handleData`. As the protocol is processed,
+/// it'll output frame data as either a List<int> or String.
+///
+/// Important information about usage: Be sure you use cancelOnError, so the
+/// socket will be closed when the processor encounter an error. Not using it
+/// will lead to undefined behaviour.
 class _WebSocketProtocolTransformer extends StreamTransformerBase<List<int>,
         dynamic /*List<int>|_WebSocketPing|_WebSocketPong*/ >
     implements EventSink<List<int>> {
@@ -89,23 +85,23 @@
   int _remainingPayloadBytes = -1;
   int _unmaskingIndex = 0;
   int _currentMessageType = _WebSocketMessageType.NONE;
-  int closeCode = WebSocketStatus.NO_STATUS_RECEIVED;
+  int closeCode = WebSocketStatus.noStatusReceived;
   String closeReason = "";
 
   EventSink<dynamic /*List<int>|_WebSocketPing|_WebSocketPong*/ >? _eventSink;
 
   final bool _serverSide;
   final Uint8List _maskingBytes = Uint8List(4);
-  final BytesBuilder _payload = new BytesBuilder(copy: false);
+  final BytesBuilder _payload = BytesBuilder(copy: false);
 
-  _WebSocketPerMessageDeflate? _deflate;
+  final _WebSocketPerMessageDeflate? _deflate;
   _WebSocketProtocolTransformer([this._serverSide = false, this._deflate]);
 
   Stream<dynamic /*List<int>|_WebSocketPing|_WebSocketPong*/ > bind(
       Stream<List<int>> stream) {
-    return new Stream.eventTransformed(stream, (EventSink eventSink) {
+    return Stream.eventTransformed(stream, (EventSink eventSink) {
       if (_eventSink != null) {
-        throw new StateError("WebSocket transformer already used.");
+        throw StateError("WebSocket transformer already used.");
       }
       _eventSink = eventSink;
       return this;
@@ -122,18 +118,16 @@
     _eventSink!.close();
   }
 
-  /**
-   * Process data received from the underlying communication channel.
-   */
+  /// Process data received from the underlying communication channel.
   void add(List<int> bytes) {
-    var buffer = bytes is Uint8List ? bytes : new Uint8List.fromList(bytes);
+    var buffer = bytes is Uint8List ? bytes : Uint8List.fromList(bytes);
     int index = 0;
     int lastIndex = buffer.length;
     if (_state == CLOSED) {
-      throw new WebSocketException("Data on closed connection");
+      throw WebSocketException("Data on closed connection");
     }
     if (_state == FAILURE) {
-      throw new WebSocketException("Data on failed connection");
+      throw WebSocketException("Data on failed connection");
     }
     while ((index < lastIndex) && _state != CLOSED && _state != FAILURE) {
       int byte = buffer[index];
@@ -143,7 +137,7 @@
 
           if ((byte & (RSV2 | RSV3)) != 0) {
             // The RSV2, RSV3 bits must both be zero.
-            throw new WebSocketException("Protocol error");
+            throw WebSocketException("Protocol error");
           }
 
           _opcode = (byte & OPCODE);
@@ -159,29 +153,29 @@
           if (_opcode <= _WebSocketOpcode.BINARY) {
             if (_opcode == _WebSocketOpcode.CONTINUATION) {
               if (_currentMessageType == _WebSocketMessageType.NONE) {
-                throw new WebSocketException("Protocol error");
+                throw WebSocketException("Protocol error");
               }
             } else {
               assert(_opcode == _WebSocketOpcode.TEXT ||
                   _opcode == _WebSocketOpcode.BINARY);
               if (_currentMessageType != _WebSocketMessageType.NONE) {
-                throw new WebSocketException("Protocol error");
+                throw WebSocketException("Protocol error");
               }
               _currentMessageType = _opcode;
             }
           } else if (_opcode >= _WebSocketOpcode.CLOSE &&
               _opcode <= _WebSocketOpcode.PONG) {
             // Control frames cannot be fragmented.
-            if (!_fin) throw new WebSocketException("Protocol error");
+            if (!_fin) throw WebSocketException("Protocol error");
           } else {
-            throw new WebSocketException("Protocol error");
+            throw WebSocketException("Protocol error");
           }
           _state = LEN_FIRST;
         } else if (_state == LEN_FIRST) {
           _masked = (byte & 0x80) != 0;
           _len = byte & 0x7F;
           if (_isControlFrame() && _len > 125) {
-            throw new WebSocketException("Protocol error");
+            throw WebSocketException("Protocol error");
           }
           if (_len == 126) {
             _len = 0;
@@ -219,7 +213,7 @@
             _unmask(index, payloadLength, buffer);
           }
           // Control frame and data frame share _payloads.
-          _payload.add(new Uint8List.view(
+          _payload.add(Uint8List.view(
               buffer.buffer, buffer.offsetInBytes + index, payloadLength));
           index += payloadLength;
           if (_isControlFrame()) {
@@ -227,7 +221,7 @@
           } else {
             if (_currentMessageType != _WebSocketMessageType.TEXT &&
                 _currentMessageType != _WebSocketMessageType.BINARY) {
-              throw new WebSocketException("Protocol error");
+              throw WebSocketException("Protocol error");
             }
             if (_remainingPayloadBytes == 0) _messageFrameEnd();
           }
@@ -261,8 +255,8 @@
         for (int i = 3; i >= 0; i--) {
           mask = (mask << 8) | _maskingBytes[(_unmaskingIndex + i) & 3];
         }
-        Int32x4 blockMask = new Int32x4(mask, mask, mask, mask);
-        Int32x4List blockBuffer = new Int32x4List.view(
+        Int32x4 blockMask = Int32x4(mask, mask, mask, mask);
+        Int32x4List blockBuffer = Int32x4List.view(
             buffer.buffer, buffer.offsetInBytes + index, blockCount);
         for (int i = 0; i < blockBuffer.length; i++) {
           blockBuffer[i] ^= blockMask;
@@ -282,12 +276,12 @@
   void _lengthDone() {
     if (_masked) {
       if (!_serverSide) {
-        throw new WebSocketException("Received masked frame from server");
+        throw WebSocketException("Received masked frame from server");
       }
       _state = MASK;
     } else {
       if (_serverSide) {
-        throw new WebSocketException("Received unmasked frame from client");
+        throw WebSocketException("Received unmasked frame from client");
       }
       _remainingPayloadBytes = _len;
       _startPayload();
@@ -310,10 +304,10 @@
             _eventSink!.close();
             break;
           case _WebSocketOpcode.PING:
-            _eventSink!.add(new _WebSocketPing());
+            _eventSink!.add(_WebSocketPing());
             break;
           case _WebSocketOpcode.PONG:
-            _eventSink!.add(new _WebSocketPong());
+            _eventSink!.add(_WebSocketPong());
             break;
         }
         _prepareForNextFrame();
@@ -351,13 +345,13 @@
       case _WebSocketOpcode.CLOSE:
         closeCode = WebSocketStatus.noStatusReceived;
         var payload = _payload.takeBytes();
-        if (payload.length > 0) {
+        if (payload.isNotEmpty) {
           if (payload.length == 1) {
-            throw new WebSocketException("Protocol error");
+            throw WebSocketException("Protocol error");
           }
           closeCode = payload[0] << 8 | payload[1];
           if (closeCode == WebSocketStatus.noStatusReceived) {
-            throw new WebSocketException("Protocol error");
+            throw WebSocketException("Protocol error");
           }
           if (payload.length > 2) {
             closeReason = utf8.decode(payload.sublist(2));
@@ -368,11 +362,11 @@
         break;
 
       case _WebSocketOpcode.PING:
-        _eventSink!.add(new _WebSocketPing(_payload.takeBytes()));
+        _eventSink!.add(_WebSocketPing(_payload.takeBytes()));
         break;
 
       case _WebSocketOpcode.PONG:
-        _eventSink!.add(new _WebSocketPong(_payload.takeBytes()));
+        _eventSink!.add(_WebSocketPong(_payload.takeBytes()));
         break;
     }
     _prepareForNextFrame();
@@ -398,21 +392,22 @@
 
 class _WebSocketPing {
   final List<int>? payload;
-  _WebSocketPing([this.payload = null]);
+  _WebSocketPing([this.payload]);
 }
 
 class _WebSocketPong {
   final List<int>? payload;
-  _WebSocketPong([this.payload = null]);
+  _WebSocketPong([this.payload]);
 }
 
-typedef /*String|Future<String>*/ _ProtocolSelector(List<String> protocols);
+typedef /*String|Future<String>*/ _ProtocolSelector = Function(
+    List<String> protocols);
 
 class _WebSocketTransformerImpl
     extends StreamTransformerBase<HttpRequest, WebSocket>
     implements WebSocketTransformer {
   final StreamController<WebSocket> _controller =
-      new StreamController<WebSocket>(sync: true);
+      StreamController<WebSocket>(sync: true);
   final _ProtocolSelector? _protocolSelector;
   final CompressionOptions _compression;
 
@@ -455,8 +450,8 @@
       response
         ..statusCode = HttpStatus.badRequest
         ..close();
-      return new Future.error(
-          new WebSocketException("Invalid WebSocket upgrade request"));
+      return Future.error(
+          WebSocketException("Invalid WebSocket upgrade request"));
     }
 
     Future<WebSocket> upgrade(String? protocol) {
@@ -466,7 +461,7 @@
         ..headers.add(HttpHeaders.connectionHeader, "Upgrade")
         ..headers.add(HttpHeaders.upgradeHeader, "websocket");
       String key = request.headers.value("Sec-WebSocket-Key")!;
-      _SHA1 sha1 = new _SHA1();
+      _SHA1 sha1 = _SHA1();
       sha1.add("$key$_webSocketGUID".codeUnits);
       String accept = _CryptoUtils.bytesToBase64(sha1.close());
       response.headers.add("Sec-WebSocket-Accept", accept);
@@ -478,7 +473,7 @@
 
       response.headers.contentLength = 0;
       return response.detachSocket().then<WebSocket>((socket) =>
-          new _WebSocketImpl._fromSocket(
+          _WebSocketImpl._fromSocket(
               socket, protocol, compression, true, deflate));
     }
 
@@ -488,10 +483,10 @@
       // consisting of multiple protocols. To unify all of them, first join
       // the lists with ', ' and then tokenize.
       var tokenizedProtocols = _tokenizeFieldValue(protocols.join(', '));
-      return new Future<String>(() => protocolSelector(tokenizedProtocols))
+      return Future<String>(() => protocolSelector(tokenizedProtocols))
           .then<String>((protocol) {
-        if (tokenizedProtocols.indexOf(protocol) < 0) {
-          throw new WebSocketException(
+        if (!tokenizedProtocols.contains(protocol)) {
+          throw WebSocketException(
               "Selected protocol is not in the list of available protocols");
         }
         return protocol;
@@ -523,7 +518,7 @@
       var clientNoContextTakeover =
           (hv.parameters.containsKey(_clientNoContextTakeover) &&
               compression.clientNoContextTakeover);
-      var deflate = new _WebSocketPerMessageDeflate(
+      var deflate = _WebSocketPerMessageDeflate(
           serverNoContextTakeover: serverNoContextTakeover,
           clientNoContextTakeover: clientNoContextTakeover,
           serverMaxWindowBits: info.maxWindowBits,
@@ -585,11 +580,11 @@
       this.clientNoContextTakeover = false,
       this.serverSide = false});
 
-  RawZLibFilter _ensureDecoder() => decoder ??= new RawZLibFilter.inflateFilter(
+  RawZLibFilter _ensureDecoder() => decoder ??= RawZLibFilter.inflateFilter(
       windowBits: serverSide ? clientMaxWindowBits : serverMaxWindowBits,
       raw: true);
 
-  RawZLibFilter _ensureEncoder() => encoder ??= new RawZLibFilter.deflateFilter(
+  RawZLibFilter _ensureEncoder() => encoder ??= RawZLibFilter.deflateFilter(
       windowBits: serverSide ? serverMaxWindowBits : clientMaxWindowBits,
       raw: true);
 
@@ -601,8 +596,7 @@
     data.addAll(const [0x00, 0x00, 0xff, 0xff]);
 
     decoder.process(data, 0, data.length);
-    final result = new BytesBuilder();
-    List<int> out;
+    final result = BytesBuilder();
 
     while (true) {
       final out = decoder.processed();
@@ -626,11 +620,11 @@
     if (msg is! Uint8List) {
       for (var i = 0; i < msg.length; i++) {
         if (msg[i] < 0 || 255 < msg[i]) {
-          throw new ArgumentError("List element is not a byte value "
+          throw ArgumentError("List element is not a byte value "
               "(value ${msg[i]} at index $i)");
         }
       }
-      buffer = new Uint8List.fromList(msg);
+      buffer = Uint8List.fromList(msg);
     } else {
       buffer = msg;
     }
@@ -657,7 +651,7 @@
     // then an empty uncompressed deflate block is used for this purpose. The
     // 0x00 block has the BFINAL header bit set to 0 and the BTYPE header set to
     // 00 along with 5 bits of padding. This block decodes to zero bytes.
-    if (result.length == 0) {
+    if (result.isEmpty) {
       return [0x00];
     }
 
@@ -671,16 +665,16 @@
   final _WebSocketImpl webSocket;
   EventSink<List<int>>? _eventSink;
 
-  _WebSocketPerMessageDeflate? _deflateHelper;
+  final _WebSocketPerMessageDeflate? _deflateHelper;
 
   _WebSocketOutgoingTransformer(this.webSocket)
       : _deflateHelper = webSocket._deflate;
 
   Stream<List<int>> bind(Stream stream) {
-    return new Stream<List<int>>.eventTransformed(stream,
+    return Stream<List<int>>.eventTransformed(stream,
         (EventSink<List<int>> eventSink) {
       if (_eventSink != null) {
-        throw new StateError("WebSocket transformer already used");
+        throw StateError("WebSocket transformer already used");
       }
       _eventSink = eventSink;
       return this;
@@ -710,7 +704,7 @@
         opcode = _WebSocketOpcode.TEXT;
         messageData = message.bytes;
       } else {
-        throw new ArgumentError(message);
+        throw ArgumentError(message);
       }
       var deflateHelper = _deflateHelper;
       if (deflateHelper != null) {
@@ -768,7 +762,7 @@
     } else if (dataLength > 125) {
       headerSize += 2;
     }
-    Uint8List header = new Uint8List(headerSize);
+    Uint8List header = Uint8List(headerSize);
     int index = 0;
 
     // Set FIN and opcode.
@@ -803,12 +797,12 @@
           list = data;
         } else {
           if (data is Uint8List) {
-            list = new Uint8List.fromList(data);
+            list = Uint8List.fromList(data);
           } else {
-            list = new Uint8List(data.length);
+            list = Uint8List(data.length);
             for (int i = 0; i < data.length; i++) {
               if (data[i] < 0 || 255 < data[i]) {
-                throw new ArgumentError("List element is not a byte value "
+                throw ArgumentError("List element is not a byte value "
                     "(value ${data[i]} at index $i)");
               }
               list[i] = data[i];
@@ -823,9 +817,9 @@
           for (int i = 3; i >= 0; i--) {
             mask = (mask << 8) | maskBytes[i];
           }
-          Int32x4 blockMask = new Int32x4(mask, mask, mask, mask);
+          Int32x4 blockMask = Int32x4(mask, mask, mask, mask);
           Int32x4List blockBuffer =
-              new Int32x4List.view(list.buffer, list.offsetInBytes, blockCount);
+              Int32x4List.view(list.buffer, list.offsetInBytes, blockCount);
           for (int i = 0; i < blockBuffer.length; i++) {
             blockBuffer[i] ^= blockMask;
           }
@@ -853,7 +847,7 @@
   StreamSubscription? _subscription;
   bool _issuedPause = false;
   bool _closed = false;
-  Completer _closeCompleter = new Completer<WebSocket>();
+  final Completer _closeCompleter = Completer<WebSocket>();
   Completer? _completer;
 
   _WebSocketConsumer(this.webSocket, this.socket);
@@ -891,13 +885,13 @@
   StreamController _ensureController() {
     var controller = _controller;
     if (controller != null) return controller;
-    controller = _controller = new StreamController(
+    controller = _controller = StreamController(
         sync: true,
         onPause: _onPause,
         onResume: _onResume,
         onCancel: _onListen);
-    var stream = controller.stream
-        .transform(new _WebSocketOutgoingTransformer(webSocket));
+    var stream =
+        controller.stream.transform(_WebSocketOutgoingTransformer(webSocket));
     socket.addStream(stream).then((_) {
       _done();
       _closeCompleter.complete(webSocket);
@@ -931,10 +925,10 @@
   Future addStream(Stream stream) {
     if (_closed) {
       stream.listen(null).cancel();
-      return new Future.value(webSocket);
+      return Future.value(webSocket);
     }
     _ensureController();
-    var completer = _completer = new Completer();
+    var completer = _completer = Completer();
     var subscription = _subscription = stream.listen((data) {
       _controller!.add(data);
     }, onDone: _done, onError: _done, cancelOnError: true);
@@ -970,7 +964,7 @@
 
 class _WebSocketImpl extends Stream with _ServiceObject implements WebSocket {
   // Use default Map so we keep order.
-  static Map<int, _WebSocketImpl> _webSockets = new Map<int, _WebSocketImpl>();
+  static final Map<int, _WebSocketImpl> _webSockets = <int, _WebSocketImpl>{};
   static const int DEFAULT_WINDOW_BITS = 15;
   static const String PER_MESSAGE_DEFLATE = "permessage-deflate";
 
@@ -995,7 +989,7 @@
   Timer? _closeTimer;
   _WebSocketPerMessageDeflate? _deflate;
 
-  static final HttpClient _httpClient = new HttpClient();
+  static final HttpClient _httpClient = HttpClient();
 
   static Future<WebSocket> connect(
       String url, Iterable<String>? protocols, Map<String, dynamic>? headers,
@@ -1003,12 +997,12 @@
       HttpClient? customClient}) {
     Uri uri = Uri.parse(url);
     if (uri.scheme != "ws" && uri.scheme != "wss") {
-      throw new WebSocketException("Unsupported URL scheme '${uri.scheme}'");
+      throw WebSocketException("Unsupported URL scheme '${uri.scheme}'");
     }
 
-    Random random = new Random();
+    Random random = Random();
     // Generate 16 random bytes.
-    Uint8List nonceData = new Uint8List(16);
+    Uint8List nonceData = Uint8List(16);
     for (int i = 0; i < 16; i++) {
       nonceData[i] = random.nextInt(256);
     }
@@ -1016,7 +1010,7 @@
 
     final callerStackTrace = StackTrace.current;
 
-    uri = new Uri(
+    uri = Uri(
         scheme: uri.scheme == "wss" ? "https" : "http",
         userInfo: uri.userInfo,
         host: uri.host,
@@ -1025,7 +1019,7 @@
         query: uri.query,
         fragment: uri.fragment);
     return (customClient ?? _httpClient).openUrl("GET", uri).then((request) {
-      if (uri.userInfo != null && !uri.userInfo.isEmpty) {
+      if (uri.userInfo != null && uri.userInfo.isNotEmpty) {
         // If the URL contains user information use that for basic
         // authorization.
         String auth = _CryptoUtils.bytesToBase64(utf8.encode(uri.userInfo));
@@ -1058,7 +1052,7 @@
           socket.destroy();
         });
         return Future<WebSocket>.error(
-            new WebSocketException(message), callerStackTrace);
+            WebSocketException(message), callerStackTrace);
       }
 
       var connectionHeader = response.headers[HttpHeaders.connectionHeader];
@@ -1074,7 +1068,7 @@
         return error(
             "Response did not contain a 'Sec-WebSocket-Accept' header");
       }
-      _SHA1 sha1 = new _SHA1();
+      _SHA1 sha1 = _SHA1();
       sha1.add("$nonce$_webSocketGUID".codeUnits);
       List<int> expectedAccept = sha1.close();
       List<int> receivedAccept = _CryptoUtils.base64StringToBytes(accept);
@@ -1093,7 +1087,7 @@
           negotiateClientCompression(response, compression);
 
       return response.detachSocket().then<WebSocket>((socket) =>
-          new _WebSocketImpl._fromSocket(
+          _WebSocketImpl._fromSocket(
               socket, protocol, compression, false, deflate));
     });
   }
@@ -1120,7 +1114,7 @@
         return int.tryParse(o) ?? DEFAULT_WINDOW_BITS;
       }
 
-      return new _WebSocketPerMessageDeflate(
+      return _WebSocketPerMessageDeflate(
           clientMaxWindowBits: getWindowBits(_clientMaxWindowBits),
           serverMaxWindowBits: getWindowBits(_serverMaxWindowBits),
           clientNoContextTakeover: clientNoContextTakeover,
@@ -1133,16 +1127,16 @@
   _WebSocketImpl._fromSocket(
       this._socket, this.protocol, CompressionOptions compression,
       [this._serverSide = false, _WebSocketPerMessageDeflate? deflate])
-      : _controller = new StreamController(sync: true) {
-    _consumer = new _WebSocketConsumer(this, _socket);
-    _sink = new _StreamSinkImpl(_consumer);
+      : _controller = StreamController(sync: true) {
+    _consumer = _WebSocketConsumer(this, _socket);
+    _sink = _StreamSinkImpl(_consumer);
     _readyState = WebSocket.open;
     _deflate = deflate;
 
-    var transformer = new _WebSocketProtocolTransformer(_serverSide, deflate);
+    var transformer = _WebSocketProtocolTransformer(_serverSide, deflate);
     var subscription = _subscription = transformer.bind(_socket).listen((data) {
       if (data is _WebSocketPing) {
-        if (!_writeClosed) _consumer.add(new _WebSocketPong(data.payload));
+        if (!_writeClosed) _consumer.add(_WebSocketPong(data.payload));
       } else if (data is _WebSocketPong) {
         // Simply set pingInterval, as it'll cancel any timers.
         pingInterval = _pingInterval;
@@ -1190,7 +1184,7 @@
   }
 
   StreamSubscription listen(void onData(message)?,
-      {Function? onError, void onDone()?, bool? cancelOnError}) {
+      {Function? onError, void Function()? onDone, bool? cancelOnError}) {
     return _controller.stream.listen(onData,
         onError: onError, onDone: onDone, cancelOnError: cancelOnError);
   }
@@ -1204,10 +1198,10 @@
 
     if (interval == null) return;
 
-    _pingTimer = new Timer(interval, () {
+    _pingTimer = Timer(interval, () {
       if (_writeClosed) return;
-      _consumer.add(new _WebSocketPing());
-      _pingTimer = new Timer(interval, () {
+      _consumer.add(_WebSocketPing());
+      _pingTimer = Timer(interval, () {
         _closeTimer?.cancel();
         // No pong received.
         _close(WebSocketStatus.goingAway);
@@ -1231,7 +1225,7 @@
   void addUtf8Text(List<int> bytes) {
     // TODO(40614): Remove once non-nullability is sound.
     ArgumentError.checkNotNull(bytes, "bytes");
-    _sink.add(new _EncodedString(bytes));
+    _sink.add(_EncodedString(bytes));
   }
 
   void addError(Object error, [StackTrace? stackTrace]) {
@@ -1243,7 +1237,7 @@
 
   Future close([int? code, String? reason]) {
     if (_isReservedStatusCode(code)) {
-      throw new WebSocketException("Reserved status code $code");
+      throw WebSocketException("Reserved status code $code");
     }
     if (_outCloseCode == null) {
       _outCloseCode = code;
@@ -1258,17 +1252,14 @@
       if (!_controller.hasListener && _subscription != null) {
         _controller.stream.drain().catchError((_) => {});
       }
-      if (_closeTimer == null) {
-        // When closing the web-socket, we no longer accept data.
-        _closeTimer = new Timer(const Duration(seconds: 5), () {
-          // Reuse code and reason from the local close.
-          _closeCode = _outCloseCode;
-          _closeReason = _outCloseReason;
-          _subscription?.cancel();
-          _controller.close();
-          _webSockets.remove(_serviceId);
-        });
-      }
+      _closeTimer ??= Timer(const Duration(seconds: 5), () {
+        // Reuse code and reason from the local close.
+        _closeCode = _outCloseCode;
+        _closeReason = _outCloseReason;
+        _subscription?.cancel();
+        _controller.close();
+        _webSockets.remove(_serviceId);
+      });
     }
     return _sink.close();
   }
diff --git a/tools/VERSION b/tools/VERSION
index 5f2e7ac..f7fff19 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 15
 PATCH 0
-PRERELEASE 242
+PRERELEASE 243
 PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/experimental_features.yaml b/tools/experimental_features.yaml
index bf28d56..3c3b0a7 100644
--- a/tools/experimental_features.yaml
+++ b/tools/experimental_features.yaml
@@ -128,6 +128,9 @@
   named-arguments-anywhere:
     help: "Named Arguments Anywhere"
 
+  super-parameters:
+    help: "Super-Initializer Parameters"
+
 # Experiment flag only used for testing.
   test-experiment:
     help: >-