Version 2.13.0-212.0.dev

Merge commit '0fa7878d561398d6d4df75c230deaec13a8f65a2' into 'dev'
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index 4064188..b5ad7d0 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -11,7 +11,7 @@
     "constraint, update this by running tools/generate_package_config.dart."
   ],
   "configVersion": 2,
-  "generated": "2021-04-06T14:39:06.316531",
+  "generated": "2021-04-06T11:20:39.965073",
   "generator": "tools/generate_package_config.dart",
   "packages": [
     {
@@ -728,6 +728,12 @@
       "languageVersion": "2.12"
     },
     {
+      "name": "uuid",
+      "rootUri": "../third_party/pkg/uuid",
+      "packageUri": "lib/",
+      "languageVersion": "2.0"
+    },
+    {
       "name": "vector_math",
       "rootUri": "../third_party/pkg/vector_math",
       "packageUri": "lib/",
diff --git a/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart b/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
index c456641..f8bdd41 100644
--- a/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
+++ b/pkg/analysis_server/lib/plugin/protocol/protocol_dart.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 /// Utilities for converting Dart entities into analysis server's protocol
 /// entities.
 import 'package:analysis_server/src/protocol_server.dart';
@@ -130,7 +128,7 @@
   }
 }
 
-String _getParametersString(engine.Element element) {
+String? _getParametersString(engine.Element element) {
   // TODO(scheglov) expose the corresponding feature from ExecutableElement
   List<engine.ParameterElement> parameters;
   if (element is engine.ExecutableElement) {
@@ -179,8 +177,8 @@
   return '(' + sb.toString() + ')';
 }
 
-String _getTypeParametersString(engine.Element element) {
-  List<engine.TypeParameterElement> typeParameters;
+String? _getTypeParametersString(engine.Element element) {
+  List<engine.TypeParameterElement>? typeParameters;
   if (element is engine.ClassElement) {
     typeParameters = element.typeParameters;
   } else if (element is engine.TypeAliasElement) {
diff --git a/pkg/analysis_server/lib/src/channel/byte_stream_channel.dart b/pkg/analysis_server/lib/src/channel/byte_stream_channel.dart
index f9abadf..bfbc6ba 100644
--- a/pkg/analysis_server/lib/src/channel/byte_stream_channel.dart
+++ b/pkg/analysis_server/lib/src/channel/byte_stream_channel.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'dart:async';
 import 'dart:convert';
 import 'dart:io';
@@ -17,7 +15,6 @@
 /// [ClientCommunicationChannel] that uses a stream and a sink (typically,
 /// standard input and standard output) to communicate with servers.
 class ByteStreamClientChannel implements ClientCommunicationChannel {
-  final Stream input;
   final IOSink output;
 
   @override
@@ -26,23 +23,37 @@
   @override
   Stream<Notification> notificationStream;
 
-  ByteStreamClientChannel(this.input, this.output) {
-    Stream jsonStream = input
+  factory ByteStreamClientChannel(Stream<List<int>> input, IOSink output) {
+    var jsonStream = input
         .transform(const Utf8Decoder())
         .transform(LineSplitter())
         .transform(JsonStreamDecoder())
-        .where((json) => json is Map)
+        .where((json) => json is Map<String, Object?>)
+        .cast<Map<String, Object?>>()
         .asBroadcastStream();
-    responseStream = jsonStream
+    var responseStream = jsonStream
         .where((json) => json[Notification.EVENT] == null)
         .transform(ResponseConverter())
+        .where((response) => response != null)
+        .cast<Response>()
         .asBroadcastStream();
-    notificationStream = jsonStream
+    var notificationStream = jsonStream
         .where((json) => json[Notification.EVENT] != null)
         .transform(NotificationConverter())
         .asBroadcastStream();
+    return ByteStreamClientChannel._(
+      output,
+      responseStream,
+      notificationStream,
+    );
   }
 
+  ByteStreamClientChannel._(
+    this.output,
+    this.responseStream,
+    this.notificationStream,
+  );
+
   @override
   Future close() {
     return output.close();
@@ -69,7 +80,7 @@
   final InstrumentationService _instrumentationService;
 
   /// The helper for recording request / response statistics.
-  final RequestStatisticsHelper _requestStatistics;
+  final RequestStatisticsHelper? _requestStatistics;
 
   /// Completer that will be signalled when the input stream is closed.
   final Completer _closed = Completer();
@@ -79,7 +90,7 @@
 
   ByteStreamServerChannel(
       this._input, this._output, this._instrumentationService,
-      {RequestStatisticsHelper requestStatistics})
+      {RequestStatisticsHelper? requestStatistics})
       : _requestStatistics = requestStatistics {
     _requestStatistics?.serverChannel = this;
   }
@@ -100,12 +111,12 @@
 
   @override
   void listen(void Function(Request request) onRequest,
-      {Function onError, void Function() onDone}) {
+      {Function? onError, void Function()? onDone}) {
     _input.transform(const Utf8Decoder()).transform(LineSplitter()).listen(
         (String data) => _readRequest(data, onRequest),
         onError: onError, onDone: () {
       close();
-      onDone();
+      onDone?.call();
     });
   }
 
@@ -148,7 +159,7 @@
 
   /// Read a request from the given [data] and use the given function to handle
   /// the request.
-  void _readRequest(Object data, void Function(Request request) onRequest) {
+  void _readRequest(String data, void Function(Request request) onRequest) {
     // Ignore any further requests after the communication channel is closed.
     if (_closed.isCompleted) {
       return;
diff --git a/pkg/analysis_server/lib/src/channel/channel.dart b/pkg/analysis_server/lib/src/channel/channel.dart
index 627db8a..6b5e95f 100644
--- a/pkg/analysis_server/lib/src/channel/channel.dart
+++ b/pkg/analysis_server/lib/src/channel/channel.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'dart:convert';
 
 import 'package:analysis_server/protocol/protocol.dart';
@@ -46,10 +44,10 @@
 /// receive both [Response]s and [Notification]s.
 abstract class ClientCommunicationChannel {
   /// The stream of notifications from the server.
-  Stream<Notification> notificationStream;
+  Stream<Notification> get notificationStream;
 
   /// The stream of responses from the server.
-  Stream<Response> responseStream;
+  Stream<Response> get responseStream;
 
   /// Close the channel to the server. Once called, all future communication
   /// with the server via [sendRequest] will silently be ignored.
@@ -60,36 +58,40 @@
   Future<Response> sendRequest(Request request);
 }
 
-/// Instances of the class [JsonStreamDecoder] convert JSON strings to JSON
-/// maps.
-class JsonStreamDecoder extends Converter<String, Map> {
+/// Instances of the class [JsonStreamDecoder] convert JSON strings to values.
+class JsonStreamDecoder extends Converter<String, Object?> {
   @override
-  Map convert(String text) => json.decode(text);
+  Object? convert(String text) => json.decode(text);
 
   @override
-  ChunkedConversionSink<String> startChunkedConversion(Sink<Map> sink) =>
-      ChannelChunkSink<String, Map>(this, sink);
+  ChunkedConversionSink<String> startChunkedConversion(Sink<Object?> sink) =>
+      ChannelChunkSink<String, Object?>(this, sink);
 }
 
 /// Instances of the class [NotificationConverter] convert JSON maps to
 /// [Notification]s.
-class NotificationConverter extends Converter<Map, Notification> {
+class NotificationConverter
+    extends Converter<Map<String, Object?>, Notification> {
   @override
   Notification convert(Map json) => Notification.fromJson(json);
 
   @override
-  ChunkedConversionSink<Map> startChunkedConversion(Sink<Notification> sink) =>
-      ChannelChunkSink<Map, Notification>(this, sink);
+  ChunkedConversionSink<Map<String, Object?>> startChunkedConversion(
+          Sink<Notification> sink) =>
+      ChannelChunkSink<Map<String, Object?>, Notification>(this, sink);
 }
 
 /// Instances of the class [ResponseConverter] convert JSON maps to [Response]s.
-class ResponseConverter extends Converter<Map, Response> {
+class ResponseConverter extends Converter<Map<String, Object?>, Response?> {
   @override
-  Response convert(Map json) => Response.fromJson(json);
+  Response? convert(Map<String, Object?> json) => Response.fromJson(json);
 
   @override
-  ChunkedConversionSink<Map> startChunkedConversion(Sink<Response> sink) =>
-      ChannelChunkSink<Map, Response>(this, sink);
+  ChunkedConversionSink<Map<String, Object?>> startChunkedConversion(
+    Sink<Response?> sink,
+  ) {
+    return ChannelChunkSink<Map<String, Object?>, Response?>(this, sink);
+  }
 }
 
 /// The abstract class [ServerCommunicationChannel] defines the behavior of
diff --git a/pkg/analysis_server/lib/src/protocol_server.dart b/pkg/analysis_server/lib/src/protocol_server.dart
index dda065c..d84f9cb 100644
--- a/pkg/analysis_server/lib/src/protocol_server.dart
+++ b/pkg/analysis_server/lib/src/protocol_server.dart
@@ -2,13 +2,12 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analysis_server/plugin/protocol/protocol_dart.dart';
 import 'package:analysis_server/protocol/protocol_generated.dart';
 import 'package:analysis_server/src/services/correction/fix.dart';
 import 'package:analysis_server/src/services/search/search_engine.dart'
     as engine;
+import 'package:analysis_server/src/utilities/extensions/element.dart';
 import 'package:analyzer/dart/analysis/results.dart' as engine;
 import 'package:analyzer/dart/ast/ast.dart' as engine;
 import 'package:analyzer/dart/element/element.dart' as engine;
@@ -35,7 +34,7 @@
 /// Adds [edit] to the file containing the given [element].
 void doSourceChange_addElementEdit(
     SourceChange change, engine.Element element, SourceEdit edit) {
-  var source = element.source;
+  var source = element.source!;
   doSourceChange_addSourceEdit(change, source, edit);
 }
 
@@ -47,7 +46,7 @@
   change.addEdit(file, isNewFile ? -1 : 0, edit);
 }
 
-String getAliasedTypeString(engine.Element element) {
+String? getAliasedTypeString(engine.Element element) {
   if (element is engine.TypeAliasElement) {
     var aliasedType = element.aliasedType;
     return aliasedType.getDisplayString(withNullability: false);
@@ -55,18 +54,16 @@
   return null;
 }
 
-String getReturnTypeString(engine.Element element) {
+String? getReturnTypeString(engine.Element element) {
   if (element is engine.ExecutableElement) {
     if (element.kind == engine.ElementKind.SETTER) {
       return null;
     } else {
-      return element.returnType?.getDisplayString(withNullability: false);
+      return element.returnType.getDisplayString(withNullability: false);
     }
   } else if (element is engine.VariableElement) {
     var type = element.type;
-    return type != null
-        ? type.getDisplayString(withNullability: false)
-        : 'dynamic';
+    return type.getDisplayString(withNullability: false);
   } else if (element is engine.TypeAliasElement) {
     var aliasedType = element.aliasedType;
     if (aliasedType is FunctionType) {
@@ -107,7 +104,7 @@
 /// If an [errorSeverity] is specified, it will override the one in [error].
 AnalysisError newAnalysisError_fromEngine(
     engine.ResolvedUnitResult result, engine.AnalysisError error,
-    [engine.ErrorSeverity errorSeverity]) {
+    [engine.ErrorSeverity? errorSeverity]) {
   var errorCode = error.errorCode;
   // prepare location
   Location location;
@@ -115,23 +112,16 @@
     var file = error.source.fullName;
     var offset = error.offset;
     var length = error.length;
-    var startLine = -1;
-    var startColumn = -1;
-    var endLine = -1;
-    var endColumn = -1;
     var lineInfo = result.lineInfo;
-    if (lineInfo != null) {
-      var startLocation = lineInfo.getLocation(offset);
-      if (startLocation != null) {
-        startLine = startLocation.lineNumber;
-        startColumn = startLocation.columnNumber;
-      }
-      var endLocation = lineInfo.getLocation(offset + length);
-      if (endLocation != null) {
-        endLine = endLocation.lineNumber;
-        endColumn = endLocation.columnNumber;
-      }
-    }
+
+    var startLocation = lineInfo.getLocation(offset);
+    var startLine = startLocation.lineNumber;
+    var startColumn = startLocation.columnNumber;
+
+    var endLocation = lineInfo.getLocation(offset + length);
+    var endLine = endLocation.lineNumber;
+    var endColumn = endLocation.columnNumber;
+
     location = Location(
         file, offset, length, startLine, startColumn, endLine, endColumn);
   }
@@ -144,7 +134,7 @@
   var type = AnalysisErrorType(errorCode.type.name);
   var message = error.message;
   var code = errorCode.name.toLowerCase();
-  List<DiagnosticMessage> contextMessages;
+  List<DiagnosticMessage>? contextMessages;
   if (error.contextMessages.isNotEmpty) {
     contextMessages = error.contextMessages
         .map((message) => newDiagnosticMessage(result, message))
@@ -182,7 +172,7 @@
 }
 
 /// Create a Location based on an [engine.Element].
-Location newLocation_fromElement(engine.Element element) {
+Location? newLocation_fromElement(engine.Element? element) {
   if (element == null || element.source == null) {
     return null;
   }
@@ -206,8 +196,8 @@
 
 /// Create a Location based on an [engine.AstNode].
 Location newLocation_fromNode(engine.AstNode node) {
-  var unit = node.thisOrAncestorOfType<engine.CompilationUnit>();
-  var unitElement = unit.declaredElement;
+  var unit = node.thisOrAncestorOfType<engine.CompilationUnit>()!;
+  var unitElement = unit.declaredElement!;
   var range = engine.SourceRange(node.offset, node.length);
   return _locationForArgs(unitElement, range);
 }
@@ -215,13 +205,13 @@
 /// Create a Location based on an [engine.CompilationUnit].
 Location newLocation_fromUnit(
     engine.CompilationUnit unit, engine.SourceRange range) {
-  return _locationForArgs(unit.declaredElement, range);
+  return _locationForArgs(unit.declaredElement!, range);
 }
 
 /// Construct based on an element from the analyzer engine.
 OverriddenMember newOverriddenMember_fromEngine(engine.Element member) {
   var element = convertElement(member);
-  var className = member.enclosingElement.displayName;
+  var className = member.enclosingElement!.displayName;
   return OverriddenMember(element, className);
 }
 
@@ -258,22 +248,19 @@
 
 /// Construct based on a SourceRange.
 SourceEdit newSourceEdit_range(engine.SourceRange range, String replacement,
-    {String id}) {
+    {String? id}) {
   return SourceEdit(range.offset, range.length, replacement, id: id);
 }
 
 List<Element> _computePath(engine.Element element) {
   var path = <Element>[];
-  while (element != null) {
-    path.add(convertElement(element));
-    // go up
-    if (element is engine.PrefixElement) {
-      // imports are library children, but they are physically in the unit
-      engine.LibraryElement library = element.enclosingElement;
-      element = library.definingCompilationUnit;
-    } else {
-      element = element.enclosingElement;
-    }
+
+  if (element is engine.PrefixElement) {
+    element = element.enclosingElement.definingCompilationUnit;
+  }
+
+  for (var e in element.withAncestors) {
+    path.add(convertElement(e));
   }
   return path;
 }
@@ -282,18 +269,23 @@
   if (element is engine.CompilationUnitElement) {
     return element;
   }
-  if (element?.enclosingElement is engine.LibraryElement) {
-    element = element.enclosingElement;
+
+  var enclosingElement = element.enclosingElement;
+  if (enclosingElement is engine.LibraryElement) {
+    element = enclosingElement;
   }
+
   if (element is engine.LibraryElement) {
     return element.definingCompilationUnit;
   }
-  for (; element != null; element = element.enclosingElement) {
-    if (element is engine.CompilationUnitElement) {
-      return element;
+
+  for (var e in element.withAncestors) {
+    if (e is engine.CompilationUnitElement) {
+      return e;
     }
   }
-  return null;
+
+  throw StateError('No unit: $element');
 }
 
 /// Creates a new [Location].
diff --git a/pkg/analysis_server/lib/src/search/element_references.dart b/pkg/analysis_server/lib/src/search/element_references.dart
index 9cee80a..e2bf228 100644
--- a/pkg/analysis_server/lib/src/search/element_references.dart
+++ b/pkg/analysis_server/lib/src/search/element_references.dart
@@ -28,7 +28,6 @@
     if (withPotential && _isMemberElement(element)) {
       var name = element.displayName;
       var matches = await searchEngine.searchMemberReferences(name);
-      matches = SearchMatch.withNotNullElement(matches);
       results.addAll(matches.where((match) => !match.isResolved).map(toResult));
     }
 
@@ -51,7 +50,6 @@
   Future<List<SearchResult>> _findSingleElementReferences(
       Element element) async {
     var matches = await searchEngine.searchReferences(element);
-    matches = SearchMatch.withNotNullElement(matches);
     return matches.map(toResult).toList();
   }
 
diff --git a/pkg/analysis_server/lib/src/search/search_domain.dart b/pkg/analysis_server/lib/src/search/search_domain.dart
index 80b84ce..1317e40 100644
--- a/pkg/analysis_server/lib/src/search/search_domain.dart
+++ b/pkg/analysis_server/lib/src/search/search_domain.dart
@@ -70,7 +70,6 @@
         request, protocol.SearchFindMemberDeclarationsResult(searchId));
     // search
     var matches = await searchEngine.searchMemberDeclarations(params.name);
-    matches = SearchMatch.withNotNullElement(matches);
     _sendSearchNotification(searchId, true, matches.map(toResult));
   }
 
@@ -83,7 +82,6 @@
         request, protocol.SearchFindMemberReferencesResult(searchId));
     // search
     var matches = await searchEngine.searchMemberReferences(params.name);
-    matches = SearchMatch.withNotNullElement(matches);
     _sendSearchNotification(searchId, true, matches.map(toResult));
   }
 
@@ -106,7 +104,6 @@
         request, protocol.SearchFindTopLevelDeclarationsResult(searchId));
     // search
     var matches = await searchEngine.searchTopLevelDeclarations(params.pattern);
-    matches = SearchMatch.withNotNullElement(matches);
     _sendSearchNotification(searchId, true, matches.map(toResult));
   }
 
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index a2190f6..98dfce5 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analysis_server/plugin/edit/fix/fix_dart.dart';
 import 'package:analysis_server/src/services/correction/fix/dart/top_level_declarations.dart';
 import 'package:analysis_server/src/services/linter/lint_names.dart';
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/accessor.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/accessor.dart
index bbfdd2a..bd0dde1 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/accessor.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/accessor.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analysis_server/src/services/correction/fix/data_driven/parameter_reference.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 
@@ -11,7 +9,7 @@
 abstract class Accessor {
   /// Return the result of using this accessor to access a value from the
   /// [target].
-  AccessorResult getValue(Object target);
+  AccessorResult getValue(Object? target);
 }
 
 /// The result of using an accessor to get a result.
@@ -35,10 +33,10 @@
 
   /// Initialize a newly created accessor to access the argument that
   /// corresponds to the given [parameter].
-  ArgumentAccessor(this.parameter) : assert(parameter != null);
+  ArgumentAccessor(this.parameter);
 
   @override
-  AccessorResult getValue(Object target) {
+  AccessorResult getValue(Object? target) {
     if (target is AstNode) {
       var argumentList = _getArgumentList(target);
       if (argumentList != null) {
@@ -55,7 +53,7 @@
   String toString() => 'arguments[$parameter]';
 
   /// Return the argument list associated with the [node].
-  ArgumentList _getArgumentList(AstNode node) {
+  ArgumentList? _getArgumentList(AstNode node) {
     if (node is Annotation) {
       return node.arguments;
     } else if (node is ExtensionOverride) {
@@ -92,19 +90,16 @@
 
   /// Initialize a newly created accessor to access the type argument at the
   /// given [index].
-  TypeArgumentAccessor(this.index) : assert(index != null);
+  TypeArgumentAccessor(this.index);
 
   @override
-  AccessorResult getValue(Object target) {
+  AccessorResult getValue(Object? target) {
     if (target is AstNode) {
       var typeArgumentList = _getTypeArgumentList(target);
       if (typeArgumentList != null) {
         var arguments = typeArgumentList.arguments;
         if (arguments.length > index) {
-          var argument = arguments[index];
-          if (argument != null) {
-            return ValidResult(argument);
-          }
+          return ValidResult(arguments[index]);
         }
       }
     }
@@ -115,7 +110,7 @@
   String toString() => 'typeArguments[$index]';
 
   /// Return the type argument list associated with the [node].
-  TypeArgumentList _getTypeArgumentList(AstNode node) {
+  TypeArgumentList? _getTypeArgumentList(AstNode node) {
     if (node is ExtensionOverride) {
       return node.typeArguments;
     } else if (node is InstanceCreationExpression) {
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_descriptor.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_descriptor.dart
index 9eeedf3..1c24767 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_descriptor.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_descriptor.dart
@@ -2,13 +2,10 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analysis_server/src/services/correction/fix/data_driven/element_kind.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart' show ClassElement;
 import 'package:analyzer/dart/element/type.dart';
-import 'package:meta/meta.dart';
 
 /// The path to an element.
 class ElementDescriptor {
@@ -27,9 +24,9 @@
   /// within the library is given by the list of [components]. The [kind] of the
   /// element is represented by the key used in the data file.
   ElementDescriptor(
-      {@required this.libraryUris,
-      @required this.kind,
-      @required this.components});
+      {required this.libraryUris,
+      required this.kind,
+      required this.components});
 
   /// Return `true` if the described element is a constructor.
   bool get isConstructor => kind == ElementKind.constructorKind;
@@ -118,7 +115,7 @@
                 // that the method might have been in the element's class.
                 return true;
               }
-              if (components[1] == type.element.name) {
+              if (components[1] == type.element?.name) {
                 return true;
               }
               if (type is InterfaceType) {
@@ -145,7 +142,6 @@
         // TODO: Handle this case.
         return false;
     }
-    return false;
   }
 
   String _nameFromIdentifier(Identifier identifier) {
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_kind.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_kind.dart
index be3d61e..a3fb8b1 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_kind.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_kind.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 /// An indication of the kind of an element.
 enum ElementKind {
   classKind,
@@ -23,7 +21,7 @@
 
 extension ElementKindUtilities on ElementKind {
   /// Return the element kind corresponding to the given [name].
-  static ElementKind fromName(String name) {
+  static ElementKind? fromName(String name) {
     for (var kind in ElementKind.values) {
       if (kind.toString() == 'ElementKind.${name}Kind') {
         return kind;
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_matcher.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_matcher.dart
index fe8ba62..51b100f 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_matcher.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/element_matcher.dart
@@ -2,15 +2,12 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analysis_server/src/services/correction/fix/data_driven/element_descriptor.dart';
 import 'package:analysis_server/src/services/correction/fix/data_driven/element_kind.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart'
     show ClassElement, ExtensionElement;
 import 'package:analyzer/dart/element/type.dart';
-import 'package:meta/meta.dart';
 
 /// An object that can be used to determine whether an element is appropriate
 /// for a given reference.
@@ -31,10 +28,10 @@
   /// Initialize a newly created matcher representing a reference to an element
   /// with the given [name] in a library that imports the [importedUris].
   ElementMatcher(
-      {@required this.importedUris,
-      @required this.components,
-      List<ElementKind> kinds})
-      : assert(components != null && components.isNotEmpty),
+      {required this.importedUris,
+      required this.components,
+      List<ElementKind>? kinds})
+      : assert(components.isNotEmpty),
         validKinds = kinds ?? const [];
 
   /// Return `true` if this matcher matches the given [element].
@@ -99,7 +96,7 @@
   /// Return an element matcher that will match the element that is, or should
   /// be, associated with the given [node], or `null` if there is no appropriate
   /// matcher for the node.
-  static ElementMatcher forNode(AstNode node) {
+  static ElementMatcher? forNode(AstNode? node) {
     if (node == null) {
       return null;
     }
@@ -122,14 +119,14 @@
   /// For example, for a constructor this would be the name of the constructor
   /// followed by the name of the class in which the constructor is declared
   /// (with an empty string for the unnamed constructor).
-  static List<String> _componentsForNode(AstNode node) {
+  static List<String>? _componentsForNode(AstNode? node) {
     if (node is SimpleIdentifier) {
       var parent = node.parent;
       if (parent is Label && parent.parent is NamedExpression) {
         // The parent of the named expression is an argument list. Because we
         // don't represent parameters as elements, the element we need to match
         // against is the invocation containing those arguments.
-        return _componentsFromParent(parent.parent.parent);
+        return _componentsFromParent(parent.parent!.parent!);
       } else if (parent is TypeName && parent.parent is ConstructorName) {
         return ['', node.name];
       } else if (parent is MethodDeclaration && node == parent.name) {
@@ -147,15 +144,20 @@
       }
       return [node.identifier.name];
     } else if (node is ConstructorName) {
-      return [node.name.name];
+      var constructorName = node.name;
+      if (constructorName != null) {
+        return [constructorName.name];
+      }
     } else if (node is NamedType) {
       return [node.name.name];
     } else if (node is TypeArgumentList) {
       return _componentsFromParent(node);
     } else if (node is ArgumentList) {
       return _componentsFromParent(node);
-    } else if (node?.parent is ArgumentList) {
-      return _componentsFromParent(node.parent);
+    }
+    var parent = node?.parent;
+    if (parent is ArgumentList) {
+      return _componentsFromParent(parent);
     }
     return null;
   }
@@ -172,9 +174,13 @@
     }
     if (element != null) {
       var enclosingElement = element.enclosingElement;
-      if (enclosingElement is ClassElement ||
-          enclosingElement is ExtensionElement) {
+      if (enclosingElement is ClassElement) {
         return [identifier.name, enclosingElement.name];
+      } else if (enclosingElement is ExtensionElement) {
+        var name = enclosingElement.name;
+        if (name != null) {
+          return [identifier.name, name];
+        }
       }
     }
     return [identifier.name];
@@ -182,7 +188,7 @@
 
   /// Return the components for the element associated with the given [node] by
   /// looking at the parent of the [node].
-  static List<String> _componentsFromParent(AstNode node) {
+  static List<String>? _componentsFromParent(AstNode node) {
     var parent = node.parent;
     if (parent is ArgumentList) {
       parent = parent.parent;
@@ -231,17 +237,20 @@
 
   /// Return the URIs of the imports in the library containing the [node], or
   /// `null` if the imports can't be determined.
-  static List<Uri> _importElementsForNode(AstNode node) {
+  static List<Uri>? _importElementsForNode(AstNode node) {
     var root = node.root;
     if (root is! CompilationUnit) {
       return null;
     }
     var importedUris = <Uri>[];
-    var library = (root as CompilationUnit).declaredElement.library;
+    var library = root.declaredElement?.library;
+    if (library == null) {
+      return null;
+    }
     for (var importElement in library.imports) {
       // TODO(brianwilkerson) Filter based on combinators to help avoid making
       //  invalid suggestions.
-      var uri = importElement.importedLibrary?.source?.uri;
+      var uri = importElement.importedLibrary?.source.uri;
       if (uri != null) {
         // The [uri] is `null` if the literal string is not a valid URI.
         importedUris.add(uri);
@@ -251,9 +260,9 @@
   }
 
   /// Return the kinds of elements that could reasonably be referenced at the
-  /// location of the [node]. If [child] is no `null` then the [node] is a
-  /// parent of the original node.
-  static List<ElementKind> _kindsForNode(AstNode node, {AstNode child}) {
+  /// location of the [node]. If [child] is not `null` then the [node] is a
+  /// parent of the [child].
+  static List<ElementKind>? _kindsForNode(AstNode? node, {AstNode? child}) {
     if (node is ConstructorName) {
       return const [ElementKind.constructorKind];
     } else if (node is ExtensionOverride) {
@@ -261,8 +270,8 @@
     } else if (node is InstanceCreationExpression) {
       return const [ElementKind.constructorKind];
     } else if (node is Label) {
-      var argumentList = node.parent.parent;
-      return _kindsForNode(argumentList.parent, child: argumentList);
+      var argumentList = node.parent?.parent;
+      return _kindsForNode(argumentList?.parent, child: argumentList);
     } else if (node is MethodInvocation) {
       assert(child != null);
       if (node.target == child) {
@@ -315,7 +324,7 @@
   }
 
   /// Return the name of the class associated with the given [target].
-  static String _nameOfTarget(Expression target) {
+  static String? _nameOfTarget(Expression? target) {
     if (target is SimpleIdentifier) {
       var type = target.staticType;
       if (type != null) {
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/parameter_reference.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/parameter_reference.dart
index 662a953..ffd9683 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/parameter_reference.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/parameter_reference.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analyzer/dart/ast/ast.dart';
 
 /// A reference to a named parameter.
@@ -16,7 +14,7 @@
   NamedParameterReference(this.name) : assert(name.isNotEmpty);
 
   @override
-  Expression argumentFrom(ArgumentList argumentList) {
+  Expression? argumentFrom(ArgumentList argumentList) {
     for (var argument in argumentList.arguments) {
       if (argument is NamedExpression && argument.name.label.name == name) {
         return argument.expression;
@@ -35,7 +33,7 @@
   /// parameter, or `null` if there is no argument corresponding to the
   /// parameter. Note that for named parameters this will be an expression whose
   /// parent is a named expression.
-  Expression argumentFrom(ArgumentList argumentList);
+  Expression? argumentFrom(ArgumentList argumentList);
 }
 
 /// A reference to a positional parameter.
@@ -48,7 +46,7 @@
   PositionalParameterReference(this.index) : assert(index >= 0);
 
   @override
-  Expression argumentFrom(ArgumentList argumentList) {
+  Expression? argumentFrom(ArgumentList argumentList) {
     var arguments = argumentList.arguments;
     if (index >= arguments.length) {
       return null;
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_override.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_override.dart
index b873aba..857336c 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_override.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_override.dart
@@ -2,10 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
-import 'package:meta/meta.dart';
-
 /// A description of a set of changes to a single transform.
 class TransformOverride {
   /// The title of the transform being overridden.
@@ -13,12 +9,12 @@
 
   /// The overridden value of the `bulkApply` property of the transform, or
   /// `null` if the property should not be overridden.
-  final bool bulkApply;
+  final bool? bulkApply;
 
   /// Initialize a newly created transform override to override the transform
   /// with the given [title]. The remaining parameters correspond to properties
   /// of the transform. They should have non-null values when the property is to
   /// be overridden, and a value of `null` when the property should be
   /// unchanged.
-  TransformOverride({@required this.title, this.bulkApply});
+  TransformOverride({required this.title, this.bulkApply});
 }
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_override_set.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_override_set.dart
index 9b18a0f..14d186a 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_override_set.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_override_set.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analysis_server/src/services/correction/fix/data_driven/transform_override.dart';
 
 /// A description of a set of transform overrides.
@@ -24,5 +22,5 @@
 
   /// Return the override for the transform with the given [title] or `null` if
   /// there is no such override in this set.
-  TransformOverride overrideForTransform(String title) => overrideMap[title];
+  TransformOverride? overrideForTransform(String title) => overrideMap[title];
 }
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_error_code.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_error_code.dart
index 10a8af9..1f68a5c 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_error_code.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_error_code.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 // ignore_for_file: prefer_single_quotes, slash_for_doc_comments
 import 'package:analyzer/error/error.dart';
 
@@ -160,7 +158,7 @@
   const TransformSetErrorCode(
     String name,
     String message, {
-    String correction,
+    String? correction,
     bool hasPublishedDocs = false,
   }) : super(
           correction: correction,
diff --git a/pkg/analysis_server/lib/src/services/correction/status.dart b/pkg/analysis_server/lib/src/services/correction/status.dart
index d552874..d148d34 100644
--- a/pkg/analysis_server/lib/src/services/correction/status.dart
+++ b/pkg/analysis_server/lib/src/services/correction/status.dart
@@ -2,15 +2,13 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 
 /// An outcome of a condition checking operation.
 class RefactoringStatus {
   /// The current severity of this [RefactoringStatus] - the maximum of the
   /// severities of its [entries].
-  RefactoringProblemSeverity _severity;
+  RefactoringProblemSeverity? _severity;
 
   /// A list of [RefactoringProblem]s.
   final List<RefactoringProblem> problems = [];
@@ -19,21 +17,21 @@
   RefactoringStatus();
 
   /// Creates a new [RefactoringStatus] with the ERROR severity.
-  factory RefactoringStatus.error(String msg, [Location location]) {
+  factory RefactoringStatus.error(String msg, [Location? location]) {
     var status = RefactoringStatus();
     status.addError(msg, location);
     return status;
   }
 
   /// Creates a new [RefactoringStatus] with the FATAL severity.
-  factory RefactoringStatus.fatal(String msg, [Location location]) {
+  factory RefactoringStatus.fatal(String msg, [Location? location]) {
     var status = RefactoringStatus();
     status.addFatalError(msg, location);
     return status;
   }
 
   /// Creates a new [RefactoringStatus] with the WARNING severity.
-  factory RefactoringStatus.warning(String msg, [Location location]) {
+  factory RefactoringStatus.warning(String msg, [Location? location]) {
     var status = RefactoringStatus();
     status.addWarning(msg, location);
     return status;
@@ -56,7 +54,7 @@
 
   /// Returns the message of the [RefactoringProblem] with highest severity;
   /// may be `null` if no problems.
-  String get message {
+  String? get message {
     var problem = this.problem;
     if (problem == null) {
       return null;
@@ -67,7 +65,7 @@
   /// Returns the first [RefactoringProblem] with the highest severity.
   ///
   /// Returns `null` if no entries.
-  RefactoringProblem get problem {
+  RefactoringProblem? get problem {
     for (var problem in problems) {
       if (problem.severity == _severity) {
         return problem;
@@ -77,16 +75,16 @@
   }
 
   /// Returns the current severity of this [RefactoringStatus].
-  RefactoringProblemSeverity get severity => _severity;
+  RefactoringProblemSeverity? get severity => _severity;
 
   /// Adds an ERROR problem with the given message and location.
-  void addError(String msg, [Location location]) {
+  void addError(String msg, [Location? location]) {
     _addProblem(RefactoringProblem(RefactoringProblemSeverity.ERROR, msg,
         location: location));
   }
 
   /// Adds a FATAL problem with the given message and location.
-  void addFatalError(String msg, [Location location]) {
+  void addFatalError(String msg, [Location? location]) {
     _addProblem(RefactoringProblem(RefactoringProblemSeverity.FATAL, msg,
         location: location));
   }
@@ -98,7 +96,7 @@
   /// The resulting severity is the more severe of this and [other] severities.
   ///
   /// Merging with `null` is allowed - it has no effect.
-  void addStatus(RefactoringStatus other) {
+  void addStatus(RefactoringStatus? other) {
     if (other == null) {
       return;
     }
@@ -107,7 +105,7 @@
   }
 
   /// Adds a WARNING problem with the given message and location.
-  void addWarning(String msg, [Location location]) {
+  void addWarning(String msg, [Location? location]) {
     _addProblem(RefactoringProblem(RefactoringProblemSeverity.WARNING, msg,
         location: location));
   }
@@ -116,10 +114,11 @@
   String toString() {
     var sb = StringBuffer();
     sb.write('<');
-    if (_severity == null) {
+    var severity = _severity;
+    if (severity == null) {
       sb.write('OK');
     } else {
-      sb.write(_severity.name);
+      sb.write(severity.name);
     }
     if (!isOK) {
       sb.write('\n');
diff --git a/pkg/analysis_server/lib/src/services/pub/pub_api.dart b/pkg/analysis_server/lib/src/services/pub/pub_api.dart
index a9e504a..2ba45d0 100644
--- a/pkg/analysis_server/lib/src/services/pub/pub_api.dart
+++ b/pkg/analysis_server/lib/src/services/pub/pub_api.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'dart:async';
 import 'dart:convert';
 import 'dart:io';
@@ -42,7 +40,7 @@
         ' (+https://github.com/dart-lang/sdk)',
   };
 
-  PubApi(this.instrumentationService, http.Client httpClient,
+  PubApi(this.instrumentationService, http.Client? httpClient,
       String envPubHostedUrl)
       : httpClient =
             httpClient != null ? _NoCloseHttpClient(httpClient) : http.Client(),
@@ -52,7 +50,7 @@
   ///
   /// Failed requests will be retried a number of times. If no successful response
   /// is received, will return null.
-  Future<List<PubApiPackage>> allPackages() async {
+  Future<List<PubApiPackage>?> allPackages() async {
     final json = await _getJson('$_pubHostedUrl$packageNameListPath');
     if (json == null) {
       return null;
@@ -73,7 +71,7 @@
   /// Automatically retries the request for specific types of failures after
   /// [_failedRetryInitialDelaySeconds] doubling each time. After [maxFailedRequests]
   /// requests or upon a 4XX response, will return `null` and not retry.
-  Future<Map<String, dynamic>> _getJson(String url) async {
+  Future<Map<String, Object?>?> _getJson(String url) async {
     var requestCount = 0;
     var retryAfterSeconds = _failedRetryInitialDelaySeconds;
     while (requestCount++ < maxFailedRequests) {
@@ -115,7 +113,7 @@
 
   /// Returns a valid Pub base URL from [envPubHostedUrl] if valid, otherwise using
   /// the default 'https://pub.dartlang.org'.
-  static String _validPubHostedUrl(String envPubHostedUrl) {
+  static String _validPubHostedUrl(String? envPubHostedUrl) {
     final validUrl = envPubHostedUrl != null &&
             (Uri.tryParse(envPubHostedUrl)?.isAbsolute ?? false)
         ? envPubHostedUrl
diff --git a/pkg/analysis_server/lib/src/services/pub/pub_package_service.dart b/pkg/analysis_server/lib/src/services/pub/pub_package_service.dart
index 09d0c80..e958542 100644
--- a/pkg/analysis_server/lib/src/services/pub/pub_package_service.dart
+++ b/pkg/analysis_server/lib/src/services/pub/pub_package_service.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'dart:async';
 import 'dart:convert';
 
@@ -51,20 +49,47 @@
     return PackageDetailsCache._(packages, DateTime.now().toUtc());
   }
 
-  /// Deserialises cached package data from JSON.
+  /// Deserializes cached package data from JSON.
   ///
   /// If the JSON version does not match the current version, will return null.
-  static PackageDetailsCache fromJson(Map<String, Object> json) {
+  static PackageDetailsCache? fromJson(Map<String, Object?> json) {
     if (json['version'] != cacheVersion) {
       return null;
     }
 
-    final packagesJson = json['packages'] as List<Object>;
-    final packages = packagesJson.map((json) => PubPackage.fromJson(json));
+    final packagesJson = json['packages'];
+    if (packagesJson is! List<Object>) {
+      return null;
+    }
+
+    final packages = <PubPackage>[];
+    for (final packageJson in packagesJson) {
+      if (packageJson is! Map<String, Object?>) {
+        return null;
+      }
+      final nameJson = packageJson['packageName'];
+      if (nameJson is! String) {
+        return null;
+      }
+      packages.add(PubPackage.fromJson(nameJson));
+    }
+
     final packageMap = Map.fromEntries(
-        packages.map((package) => MapEntry(package.packageName, package)));
-    return PackageDetailsCache._(
-        packageMap, DateTime.parse(json['lastUpdated']));
+      packages.map(
+        (package) => MapEntry(package.packageName, package),
+      ),
+    );
+
+    final lastUpdatedJson = json['lastUpdated'];
+    if (lastUpdatedJson is! String) {
+      return null;
+    }
+    final lastUpdated = DateTime.tryParse(lastUpdatedJson);
+    if (lastUpdated == null) {
+      return null;
+    }
+
+    return PackageDetailsCache._(packageMap, lastUpdated);
   }
 }
 
@@ -72,15 +97,14 @@
 class PubPackage {
   String packageName;
 
-  PubPackage.fromJson(Map<String, Object> json)
-      : packageName = json['packageName'];
+  PubPackage.fromJson(this.packageName);
 
   PubPackage.fromName(PubApiPackage package)
       : packageName = package.packageName;
 
   Map<String, Object> toJson() {
     return {
-      if (packageName != null) 'packageName': packageName,
+      'packageName': packageName,
     };
   }
 }
@@ -91,57 +115,60 @@
 class PubPackageService {
   final InstrumentationService _instrumentationService;
   final PubApi _api;
-  Timer _nextRequestTimer;
+  Timer? _nextRequestTimer;
 
   /// [ResourceProvider] used for caching. This should generally be a
   /// [PhysicalResourceProvider] outside of tests.
   final ResourceProvider cacheResourceProvider;
 
-  /// The current cache of package information. Initiailly null, but overwritten
-  /// after first read of cache from disk or fetch from the API.
+  /// The current cache of package information. Initially `null`, but
+  /// overwritten after first read of cache from disk or fetch from the API.
   @visibleForTesting
-  PackageDetailsCache packageCache;
+  PackageDetailsCache? packageCache;
 
   PubPackageService(
       this._instrumentationService, this.cacheResourceProvider, this._api);
 
   /// Gets the last set of package results or an empty List if no results.
   List<PubPackage> get cachedPackages =>
-      packageCache?.packages?.values?.toList() ?? [];
+      packageCache?.packages.values.toList() ?? [];
 
   bool get isRunning => _nextRequestTimer != null;
 
   @visibleForTesting
   File get packageCacheFile {
     final cacheFolder = cacheResourceProvider
-        .getStateLocation('.pub-package-details-cache')
-          ..create();
+        .getStateLocation('.pub-package-details-cache')!
+      ..create();
     return cacheFolder.getChildAssumingFile('packages.json');
   }
 
   /// Begin a request to pre-load the package name list.
   void beginPackageNamePreload() {
     // If first time, try to read from disk.
-    packageCache ??= readDiskCache() ?? PackageDetailsCache.empty();
+    var packageCache = this.packageCache;
+    if (packageCache == null) {
+      packageCache ??= readDiskCache() ?? PackageDetailsCache.empty();
+      this.packageCache = packageCache;
+    }
 
     // If there is no queued request, initialize one when the current cache expires.
     _nextRequestTimer ??=
         Timer(packageCache.cacheTimeRemaining, _fetchFromServer);
   }
 
-  PubPackage cachedPackageDetails(String packageName) =>
-      packageCache.packages[packageName];
-
   @visibleForTesting
-  PackageDetailsCache readDiskCache() {
+  PackageDetailsCache? readDiskCache() {
     final file = packageCacheFile;
     if (!file.exists) {
       return null;
     }
     try {
       final contents = file.readAsStringSync();
-      final json = jsonDecode(contents) as Map<String, Object>;
-      return PackageDetailsCache.fromJson(json);
+      final json = jsonDecode(contents);
+      if (json is Map<String, Object?>) {
+        return PackageDetailsCache.fromJson(json);
+      }
     } catch (e) {
       _instrumentationService.logError('Error reading pub cache file: $e');
       return null;
@@ -159,11 +186,14 @@
   Future<void> _fetchFromServer() async {
     try {
       final packages = await _api.allPackages();
+
+      // If we never got a valid response, just skip until the next refresh.
       if (packages == null) {
-        // If we never got a valid response, just skip until the next refresh.
         return;
       }
-      packageCache = PackageDetailsCache.fromApiResults(packages);
+
+      final packageCache = PackageDetailsCache.fromApiResults(packages);
+      this.packageCache = packageCache;
       writeDiskCache(packageCache);
     } catch (e) {
       _instrumentationService.logError('Failed to fetch packages from Pub: $e');
diff --git a/pkg/analysis_server/lib/src/services/search/element_visitors.dart b/pkg/analysis_server/lib/src/services/search/element_visitors.dart
index de03c6f..06ec9b2 100644
--- a/pkg/analysis_server/lib/src/services/search/element_visitors.dart
+++ b/pkg/analysis_server/lib/src/services/search/element_visitors.dart
@@ -2,14 +2,12 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/visitor.dart';
 
 /// Return the [Element] that is either [root], or one of its direct or
 /// indirect children, and has the given [nameOffset].
-Element findElementByNameOffset(Element root, int nameOffset) {
+Element? findElementByNameOffset(Element? root, int nameOffset) {
   if (root == null) {
     return null;
   }
diff --git a/pkg/analysis_server/lib/src/services/search/hierarchy.dart b/pkg/analysis_server/lib/src/services/search/hierarchy.dart
index 6d30c6b..7189bd6 100644
--- a/pkg/analysis_server/lib/src/services/search/hierarchy.dart
+++ b/pkg/analysis_server/lib/src/services/search/hierarchy.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'dart:collection';
 
 import 'package:analysis_server/src/services/search/element_visitors.dart';
@@ -11,7 +9,7 @@
 import 'package:analyzer/dart/element/element.dart';
 
 /// Returns direct children of [parent].
-List<Element> getChildren(Element parent, [String name]) {
+List<Element> getChildren(Element parent, [String? name]) {
   var children = <Element>[];
   visitChildren(parent, (Element element) {
     if (name == null || element.displayName == name) {
@@ -26,7 +24,7 @@
 ///
 /// Includes: fields, accessors and methods.
 /// Excludes: constructors and synthetic elements.
-List<Element> getClassMembers(ClassElement clazz, [String name]) {
+List<Element> getClassMembers(ClassElement clazz, [String? name]) {
   var members = <Element>[];
   visitChildren(clazz, (Element element) {
     if (element.isSynthetic) {
@@ -58,7 +56,7 @@
 
 /// Return the non-synthetic children of the given [extension]. This includes
 /// fields, accessors and methods, but excludes synthetic elements.
-List<Element> getExtensionMembers(ExtensionElement extension, [String name]) {
+List<Element> getExtensionMembers(ExtensionElement extension, [String? name]) {
   var members = <Element>[];
   visitChildren(extension, (Element element) {
     if (element.isSynthetic) {
@@ -84,7 +82,8 @@
     SearchEngine searchEngine, ClassMemberElement member) async {
   Set<ClassMemberElement> result = HashSet<ClassMemberElement>();
   // extension member
-  if (member.enclosingElement is ExtensionElement) {
+  var enclosingElement = member.enclosingElement;
+  if (enclosingElement is ExtensionElement) {
     result.add(member);
     return Future.value(result);
   }
@@ -94,27 +93,29 @@
     return Future.value(result);
   }
   // method, field, etc
-  var name = member.displayName;
-  ClassElement memberClass = member.enclosingElement;
-  var searchClasses = getSuperClasses(memberClass);
-  searchClasses.add(memberClass);
-  for (var superClass in searchClasses) {
-    // ignore if super- class does not declare member
-    if (getClassMembers(superClass, name).isEmpty) {
-      continue;
-    }
-    // check all sub- classes
-    var subClasses = await searchEngine.searchAllSubtypes(superClass);
-    subClasses.add(superClass);
-    for (var subClass in subClasses) {
-      var subClassMembers = getChildren(subClass, name);
-      for (var member in subClassMembers) {
-        if (member is ClassMemberElement) {
-          result.add(member);
+  if (enclosingElement is ClassElement) {
+    var name = member.displayName;
+    var searchClasses = getSuperClasses(enclosingElement);
+    searchClasses.add(enclosingElement);
+    for (var superClass in searchClasses) {
+      // ignore if super- class does not declare member
+      if (getClassMembers(superClass, name).isEmpty) {
+        continue;
+      }
+      // check all sub- classes
+      var subClasses = await searchEngine.searchAllSubtypes(superClass);
+      subClasses.add(superClass);
+      for (var subClass in subClasses) {
+        var subClassMembers = getChildren(subClass, name);
+        for (var member in subClassMembers) {
+          if (member is ClassMemberElement) {
+            result.add(member);
+          }
         }
       }
     }
   }
+
   return result;
 }
 
diff --git a/pkg/analysis_server/lib/src/services/search/search_engine.dart b/pkg/analysis_server/lib/src/services/search/search_engine.dart
index 8addf0a..4b61420 100644
--- a/pkg/analysis_server/lib/src/services/search/search_engine.dart
+++ b/pkg/analysis_server/lib/src/services/search/search_engine.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/generated/source.dart';
 
@@ -42,7 +40,7 @@
   /// If the [type] has subtypes, return the set of names of members which these
   /// subtypes declare, possibly empty.  If the [type] does not have subtypes,
   /// return `null`.
-  Future<Set<String>> membersOfSubtypes(ClassElement type);
+  Future<Set<String>?> membersOfSubtypes(ClassElement type);
 
   /// Returns all subtypes of the given [type].
   ///
@@ -108,12 +106,4 @@
 
   /// The unit [Source] of the reference.
   Source get unitSource;
-
-  /// Return elements of [matches] which has not-null elements.
-  ///
-  /// When [SearchMatch.element] is not `null` we cache its value, so it cannot
-  /// become `null` later.
-  static List<SearchMatch> withNotNullElement(List<SearchMatch> matches) {
-    return matches.where((match) => match.element != null).toList();
-  }
 }
diff --git a/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart b/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart
index 3f5cd22..d4247e1 100644
--- a/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart
+++ b/pkg/analysis_server/lib/src/services/search/search_engine_internal.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analysis_server/src/services/search/search_engine.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
@@ -17,7 +15,7 @@
   SearchEngineImpl(this._drivers);
 
   @override
-  Future<Set<String>> membersOfSubtypes(ClassElement type) async {
+  Future<Set<String>?> membersOfSubtypes(ClassElement type) async {
     var drivers = _drivers.toList();
     var searchedFiles = _createSearchedFiles(drivers);
 
@@ -26,7 +24,7 @@
     var visitedIds = <String>{};
     var members = <String>{};
 
-    Future<void> addMembers(ClassElement type, SubtypeResult subtype) async {
+    Future<void> addMembers(ClassElement? type, SubtypeResult? subtype) async {
       if (subtype != null && !visitedIds.add(subtype.id)) {
         return;
       }
@@ -206,10 +204,10 @@
 
   static SearchMatchImpl forElement(Element element) {
     return SearchMatchImpl(
-        element.source.fullName,
-        element.librarySource,
-        element.source,
-        element.library,
+        element.source!.fullName,
+        element.librarySource!,
+        element.source!,
+        element.library!,
         element,
         true,
         true,
@@ -220,10 +218,10 @@
   static SearchMatchImpl forSearchResult(SearchResult result) {
     var enclosingElement = result.enclosingElement;
     return SearchMatchImpl(
-        enclosingElement.source.fullName,
-        enclosingElement.librarySource,
-        enclosingElement.source,
-        enclosingElement.library,
+        enclosingElement.source!.fullName,
+        enclosingElement.librarySource!,
+        enclosingElement.source!,
+        enclosingElement.library!,
         enclosingElement,
         result.isResolved,
         result.isQualified,
diff --git a/pkg/analysis_server/lib/src/utilities/extensions/element.dart b/pkg/analysis_server/lib/src/utilities/extensions/element.dart
index 440d3ef..73e8eb8 100644
--- a/pkg/analysis_server/lib/src/utilities/extensions/element.dart
+++ b/pkg/analysis_server/lib/src/utilities/extensions/element.dart
@@ -40,6 +40,19 @@
     return ancestor is CompilationUnitElement &&
         ancestor.enclosingElement.hasDeprecated;
   }
+
+  /// Return this element and all its enclosing elements.
+  Iterable<Element> get withAncestors sync* {
+    var current = this;
+    while (true) {
+      yield current;
+      var enclosing = current.enclosingElement;
+      if (enclosing == null) {
+        break;
+      }
+      current = enclosing;
+    }
+  }
 }
 
 extension MethodElementExtensions on MethodElement {
diff --git a/pkg/analysis_server/lib/src/utilities/request_statistics.dart b/pkg/analysis_server/lib/src/utilities/request_statistics.dart
index 044be84..3921409 100644
--- a/pkg/analysis_server/lib/src/utilities/request_statistics.dart
+++ b/pkg/analysis_server/lib/src/utilities/request_statistics.dart
@@ -2,9 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
-import 'dart:convert';
 import 'dart:io';
 
 import 'package:analysis_server/protocol/protocol.dart';
@@ -20,17 +17,16 @@
   final Map<String, _RequestStatistics> _statisticsMap = {};
 
   /// The [StringSink] to which performance logger should copy its output.
-  _ServerLogStringSink _perfLoggerStringSink;
+  late final _ServerLogStringSink _perfLoggerStringSink =
+      _ServerLogStringSink(this);
 
   /// The channel to send 'server.log' notifications to.
-  ByteStreamServerChannel _serverChannel;
+  ByteStreamServerChannel? _serverChannel;
 
   /// Is `true` if the client subscribed for "server.log" notification.
   bool _isNotificationSubscribed = false;
 
-  RequestStatisticsHelper() {
-    _perfLoggerStringSink = _ServerLogStringSink(this);
-  }
+  RequestStatisticsHelper();
 
   /// Set whether the client subscribed for "server.log" notification.
   set isNotificationSubscribed(bool value) {
@@ -93,8 +89,8 @@
     var id = response.id;
     var stat = _statisticsMap.remove(id);
     if (stat != null) {
-      stat.responseTime = DateTime.now();
-      _sendLogEntry(ServerLogEntryKind.RESPONSE, stat.toJson());
+      var responseTime = DateTime.now();
+      _sendLogEntry(ServerLogEntryKind.RESPONSE, stat.toJson(responseTime));
     }
   }
 
@@ -110,6 +106,11 @@
       return;
     }
 
+    var params = notification.params;
+    if (params == null) {
+      return;
+    }
+
     var map = <String, Object>{
       'event': event,
     };
@@ -119,13 +120,13 @@
         event == 'analysis.navigation' ||
         event == 'analysis.outline' ||
         event == 'analysis.overrides') {
-      map['file'] = notification.params['file'];
+      map['file'] = params['file'] as String;
     }
 
     if (event == 'server.status') {
-      var analysis = notification.params['analysis'];
-      if (analysis is Map<String, Object>) {
-        map['isAnalyzing'] = analysis['isAnalyzing'];
+      var analysis = params['analysis'];
+      if (analysis is Map<String, Object?>) {
+        map['isAnalyzing'] = analysis['isAnalyzing'] as bool;
       }
     }
 
@@ -163,9 +164,11 @@
 
   void _sendLogEntry(ServerLogEntryKind kind, Object data) {
     if (!_isNotificationSubscribed) return;
-    if (_serverChannel == null) return;
 
-    _serverChannel.sendNotification(
+    var serverChannel = _serverChannel;
+    if (serverChannel == null) return;
+
+    serverChannel.sendNotification(
       Notification(
         'server.log',
         <String, Object>{
@@ -185,7 +188,6 @@
   final DateTime clientRequestTime;
   final DateTime serverRequestTime;
   final List<_RequestStatisticsItem> items = [];
-  DateTime responseTime;
 
   _RequestStatistics(
     this.id,
@@ -194,7 +196,7 @@
     this.serverRequestTime,
   );
 
-  Map<String, Object> toJson() {
+  Map<String, Object> toJson(DateTime responseTime) {
     var map = {
       'id': id,
       'method': method,
@@ -207,21 +209,16 @@
     }
     return map;
   }
-
-  @override
-  String toString() {
-    var map = toJson();
-    return json.encode(map);
-  }
 }
 
 class _RequestStatisticsItem {
   final String name;
-  final DateTime timeValue;
+  final DateTime? timeValue;
 
   _RequestStatisticsItem(this.name, {this.timeValue});
 
   Map<String, Object> toJson() {
+    var timeValue = this.timeValue;
     if (timeValue != null) {
       return {
         'name': name,
@@ -238,7 +235,7 @@
   _ServerLogStringSink(this.helper);
 
   @override
-  void write(Object obj) {
+  void write(Object? obj) {
     throw UnimplementedError();
   }
 
@@ -253,7 +250,7 @@
   }
 
   @override
-  void writeln([Object obj = '']) {
+  void writeln([Object? obj = '']) {
     helper._sendLogEntry(ServerLogEntryKind.RAW, '$obj');
   }
 }
diff --git a/pkg/analysis_server/test/channel/byte_stream_channel_test.dart b/pkg/analysis_server/test/channel/byte_stream_channel_test.dart
index 5d80b9b..0724bfe 100644
--- a/pkg/analysis_server/test/channel/byte_stream_channel_test.dart
+++ b/pkg/analysis_server/test/channel/byte_stream_channel_test.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'dart:async';
 import 'dart:convert';
 import 'dart:io';
@@ -23,17 +21,17 @@
 
 @reflectiveTest
 class ByteStreamClientChannelTest {
-  ByteStreamClientChannel channel;
+  late ByteStreamClientChannel channel;
 
   /// Sink that may be used to deliver data to the channel, as though it's
   /// coming from the server.
-  IOSink inputSink;
+  late IOSink inputSink;
 
   /// Sink through which the channel delivers data to the server.
-  IOSink outputSink;
+  late IOSink outputSink;
 
   /// Stream of lines sent back to the client by the channel.
-  Stream<String> outputLineStream;
+  late Stream<String> outputLineStream;
 
   void setUp() {
     var inputStream = StreamController<List<int>>();
@@ -103,23 +101,23 @@
 
 @reflectiveTest
 class ByteStreamServerChannelTest {
-  ByteStreamServerChannel channel;
+  late ByteStreamServerChannel channel;
 
   /// Sink that may be used to deliver data to the channel, as though it's
   /// coming from the client.
-  IOSink inputSink;
+  late IOSink inputSink;
 
   /// Stream of lines sent back to the client by the channel.
-  Stream<String> outputLineStream;
+  late Stream<String> outputLineStream;
 
   /// Stream of requests received from the channel via [listen()].
-  Stream<Request> requestStream;
+  late Stream<Request> requestStream;
 
   /// Stream of errors received from the channel via [listen()].
-  Stream errorStream;
+  late Stream errorStream;
 
   /// Future which is completed when then [listen()] reports [onDone].
-  Future doneFuture;
+  late Future doneFuture;
 
   void setUp() {
     var inputStream = StreamController<List<int>>();
@@ -220,10 +218,10 @@
 
   Future<void> test_sendNotification_exceptionInSink() async {
     // This IOSink asynchronously throws an exception on any writeln().
-    var outputSink = _IOSinkMock();
+    var outputSink = _IOSinkThatAsyncThrowsOnWrite();
 
-    var channel = ByteStreamServerChannel(
-        null, outputSink, InstrumentationService.NULL_SERVICE);
+    var channel = ByteStreamServerChannel(StreamController<List<int>>().stream,
+        outputSink, InstrumentationService.NULL_SERVICE);
 
     // Attempt to send a notification.
     channel.sendNotification(Notification('foo'));
@@ -245,39 +243,14 @@
   }
 }
 
-class _IOSinkMock implements IOSink {
+class _IOSinkThatAsyncThrowsOnWrite implements IOSink {
   @override
-  Encoding encoding;
+  dynamic noSuchMethod(Invocation invocation) {
+    return super.noSuchMethod(invocation);
+  }
 
   @override
-  Future done;
-
-  @override
-  void add(List<int> data) {}
-
-  @override
-  void addError(Object error, [StackTrace stackTrace]) {}
-
-  @override
-  Future addStream(Stream<List<int>> stream) => null;
-
-  @override
-  Future close() => null;
-
-  @override
-  Future flush() => null;
-
-  @override
-  void write(Object obj) {}
-
-  @override
-  void writeAll(Iterable objects, [String separator = '']) {}
-
-  @override
-  void writeCharCode(int charCode) {}
-
-  @override
-  void writeln([Object obj = '']) {
+  void writeln([Object? obj = '']) {
     Timer(Duration(milliseconds: 10), () {
       throw '42';
     });
diff --git a/pkg/analysis_server/test/channel/test_all.dart b/pkg/analysis_server/test/channel/test_all.dart
index 689c931..b712e00 100644
--- a/pkg/analysis_server/test/channel/test_all.dart
+++ b/pkg/analysis_server/test/channel/test_all.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:test/test.dart';
 
 import 'byte_stream_channel_test.dart' as byte_stream_channel_test;
diff --git a/pkg/analysis_server/test/lsp/server_abstract.dart b/pkg/analysis_server/test/lsp/server_abstract.dart
index 663687b..1f18e72 100644
--- a/pkg/analysis_server/test/lsp/server_abstract.dart
+++ b/pkg/analysis_server/test/lsp/server_abstract.dart
@@ -32,6 +32,7 @@
 import 'package:test/test.dart' as test show expect;
 
 import '../mocks.dart';
+import '../mocks_lsp.dart';
 import '../src/utilities/mock_packages.dart';
 
 const dartLanguageId = 'dart';
diff --git a/pkg/analysis_server/test/mocks.dart b/pkg/analysis_server/test/mocks.dart
index f0ca226..d6cfa2c 100644
--- a/pkg/analysis_server/test/mocks.dart
+++ b/pkg/analysis_server/test/mocks.dart
@@ -2,27 +2,17 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'dart:async';
-import 'dart:convert';
 
-import 'package:analysis_server/lsp_protocol/protocol_generated.dart' as lsp;
-import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
-import 'package:analysis_server/lsp_protocol/protocol_special.dart' as lsp;
 import 'package:analysis_server/protocol/protocol.dart';
 import 'package:analysis_server/protocol/protocol_generated.dart';
-import 'package:analysis_server/src/lsp/channel/lsp_channel.dart';
 import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/timestamped_data.dart';
 import 'package:http/http.dart' as http;
 import 'package:test/test.dart';
 
-const _jsonEncoder = JsonEncoder.withIndent('    ');
-
 /// A [Matcher] that check that the given [Response] has an expected identifier
 /// and has an error.  The error code may optionally be checked.
-Matcher isResponseFailure(String id, [RequestErrorCode code]) =>
+Matcher isResponseFailure(String id, [RequestErrorCode? code]) =>
     _IsResponseFailure(id, code);
 
 /// A [Matcher] that check that the given [Response] has an expected identifier
@@ -30,7 +20,7 @@
 Matcher isResponseSuccess(String id) => _IsResponseSuccess(id);
 
 class MockHttpClient extends http.BaseClient {
-  Future<http.Response> Function(http.BaseRequest request) sendHandler;
+  late Future<http.Response> Function(http.BaseRequest request) sendHandler;
   int sendHandlerCalls = 0;
   bool wasClosed = false;
 
@@ -57,242 +47,36 @@
   }
 }
 
-/// A mock [LspServerCommunicationChannel] for testing [LspAnalysisServer].
-class MockLspServerChannel implements LspServerCommunicationChannel {
-  final StreamController<lsp.Message> _clientToServer =
-      StreamController<lsp.Message>.broadcast();
-  final StreamController<lsp.Message> _serverToClient =
-      StreamController<lsp.Message>.broadcast();
-
-  String name;
-
-  /// Completer that will be signalled when the input stream is closed.
-  final Completer _closed = Completer();
-
-  /// Errors popups sent to the user.
-  final shownErrors = <lsp.ShowMessageParams>[];
-
-  /// Warning popups sent to the user.
-  final shownWarnings = <lsp.ShowMessageParams>[];
-
-  MockLspServerChannel(bool _printMessages) {
-    if (_printMessages) {
-      _serverToClient.stream
-          .listen((message) => print('<== ' + jsonEncode(message)));
-      _clientToServer.stream
-          .listen((message) => print('==> ' + jsonEncode(message)));
-    }
-
-    // Keep track of any errors/warnings that are sent to the user with
-    // `window/showMessage`.
-    _serverToClient.stream.listen((message) {
-      if (message is lsp.NotificationMessage &&
-          message.method == Method.window_showMessage &&
-          message.params is lsp.ShowMessageParams) {
-        if (message.params?.type == MessageType.Error) {
-          shownErrors.add(message.params);
-        } else if (message.params?.type == MessageType.Warning) {
-          shownWarnings.add(message.params);
-        }
-      }
-    });
-  }
-
-  /// Future that will be completed when the input stream is closed.
+class MockSource implements Source {
   @override
-  Future get closed {
-    return _closed.future;
-  }
+  final String fullName;
 
-  Stream<lsp.Message> get serverToClient => _serverToClient.stream;
+  MockSource({
+    this.fullName = 'mocked.dart',
+  });
 
   @override
-  void close() {
-    if (!_closed.isCompleted) {
-      _closed.complete();
-    }
-    if (!_serverToClient.isClosed) {
-      _serverToClient.close();
-    }
-    if (!_clientToServer.isClosed) {
-      _clientToServer.close();
-    }
-  }
+  dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
 
   @override
-  void listen(void Function(lsp.Message message) onMessage,
-      {Function onError, void Function() onDone}) {
-    _clientToServer.stream.listen(onMessage, onError: onError, onDone: onDone);
-  }
-
-  @override
-  void sendNotification(lsp.NotificationMessage notification) {
-    // Don't deliver notifications after the connection is closed.
-    if (_closed.isCompleted) {
-      return;
-    }
-
-    notification = _convertJson(notification, lsp.NotificationMessage.fromJson);
-
-    _serverToClient.add(notification);
-  }
-
-  void sendNotificationToServer(lsp.NotificationMessage notification) {
-    // Don't deliver notifications after the connection is closed.
-    if (_closed.isCompleted) {
-      return;
-    }
-
-    notification = _convertJson(notification, lsp.NotificationMessage.fromJson);
-
-    // Wrap send request in future to simulate WebSocket.
-    Future(() => _clientToServer.add(notification));
-  }
-
-  @override
-  void sendRequest(lsp.RequestMessage request) {
-    // Don't deliver notifications after the connection is closed.
-    if (_closed.isCompleted) {
-      return;
-    }
-
-    request = _convertJson(request, lsp.RequestMessage.fromJson);
-
-    _serverToClient.add(request);
-  }
-
-  /// Send the given [request] to the server and return a future that will
-  /// complete when a response associated with the [request] has been received.
-  /// The value of the future will be the received response.
-  Future<lsp.ResponseMessage> sendRequestToServer(lsp.RequestMessage request) {
-    // No further requests should be sent after the connection is closed.
-    if (_closed.isCompleted) {
-      throw Exception('sendLspRequest after connection closed');
-    }
-
-    request = _convertJson(request, lsp.RequestMessage.fromJson);
-
-    // Wrap send request in future to simulate WebSocket.
-    Future(() => _clientToServer.add(request));
-    return waitForResponse(request);
-  }
-
-  @override
-  void sendResponse(lsp.ResponseMessage response) {
-    // Don't deliver responses after the connection is closed.
-    if (_closed.isCompleted) {
-      return;
-    }
-
-    response = _convertJson(response, lsp.ResponseMessage.fromJson);
-
-    // Wrap send response in future to simulate WebSocket.
-    Future(() => _serverToClient.add(response));
-  }
-
-  void sendResponseToServer(lsp.ResponseMessage response) {
-    // Don't deliver notifications after the connection is closed.
-    if (_closed.isCompleted) {
-      return;
-    }
-
-    response = _convertJson(response, lsp.ResponseMessage.fromJson);
-
-    _clientToServer.add(response);
-  }
-
-  /// Return a future that will complete when a response associated with the
-  /// given [request] has been received. The value of the future will be the
-  /// received response. The returned future will throw an exception if a server
-  /// error is reported before the response has been received.
-  ///
-  /// Unlike [sendLspRequest], this method assumes that the [request] has
-  /// already been sent to the server.
-  Future<lsp.ResponseMessage> waitForResponse(
-    lsp.RequestMessage request, {
-    bool throwOnError = true,
-  }) async {
-    final response = await _serverToClient.stream.firstWhere((message) =>
-        (message is lsp.ResponseMessage && message.id == request.id) ||
-        (throwOnError &&
-            message is lsp.NotificationMessage &&
-            message.method == Method.window_showMessage &&
-            lsp.ShowMessageParams.fromJson(message.params).type ==
-                MessageType.Error));
-
-    if (response is lsp.ResponseMessage) {
-      return response;
-    } else {
-      throw 'An error occurred while waiting for a response to ${request.method}: '
-          '${_jsonEncoder.convert(response.toJson())}';
-    }
-  }
-
-  /// Round trips the object to JSON and back to ensure it behaves the same as
-  /// when running over the real STDIO server. Without this, the object passed
-  /// to the handlers will have concrete types as constructed in tests rather
-  /// than the maps as they would be (the server expects to do the conversion).
-  T _convertJson<T>(
-      lsp.ToJsonable message, T Function(Map<String, dynamic>) constructor) {
-    return constructor(jsonDecode(jsonEncode(message.toJson())));
-  }
-}
-
-class MockSource extends StringTypedMock implements Source {
-  @override
-  TimestampedData<String> contents;
-
-  @override
-  String encoding;
-
-  @override
-  String fullName;
-
-  @override
-  bool isInSystemLibrary;
-
-  @override
-  Source librarySource;
-
-  @override
-  int modificationStamp;
-
-  @override
-  String shortName;
-
-  @override
-  Source source;
-
-  @override
-  Uri uri;
-
-  @override
-  UriKind uriKind;
-
-  MockSource([String name = 'mocked.dart']) : super(name);
-
-  @override
-  bool exists() => null;
+  String toString() => fullName;
 }
 
 class StringTypedMock {
-  final String _toString;
+  final String? _toString;
 
   StringTypedMock(this._toString);
 
   @override
   String toString() {
-    if (_toString != null) {
-      return _toString;
-    }
-    return super.toString();
+    return _toString ?? super.toString();
   }
 }
 
 /// A [Matcher] that check that there are no `error` in a given [Response].
 class _IsResponseFailure extends Matcher {
   final String _id;
-  final RequestErrorCode _code;
+  final RequestErrorCode? _code;
 
   _IsResponseFailure(this._id, this._code);
 
@@ -300,8 +84,9 @@
   Description describe(Description description) {
     description =
         description.add('response with identifier "$_id" and an error');
-    if (_code != null) {
-      description = description.add(' with code ${_code.name}');
+    var code = _code;
+    if (code != null) {
+      description = description.add(' with code ${code.name}');
     }
     return description;
   }
@@ -316,8 +101,7 @@
     if (error == null) {
       mismatchDescription.add(' and has no error');
     } else {
-      mismatchDescription
-          .add(' and has error code ${response.error.code.name}');
+      mismatchDescription.add(' and has error code ${error.code.name}');
     }
     return mismatchDescription;
   }
@@ -325,10 +109,11 @@
   @override
   bool matches(item, Map matchState) {
     Response response = item;
-    if (response.id != _id || response.error == null) {
+    var error = response.error;
+    if (response.id != _id || error == null) {
       return false;
     }
-    if (_code != null && response.error.code != _code) {
+    if (_code != null && error.code != _code) {
       return false;
     }
     return true;
@@ -350,7 +135,7 @@
   @override
   Description describeMismatch(
       item, Description mismatchDescription, Map matchState, bool verbose) {
-    Response response = item;
+    Response? response = item;
     if (response == null) {
       mismatchDescription.add('is null response');
     } else {
@@ -366,7 +151,7 @@
 
   @override
   bool matches(item, Map matchState) {
-    Response response = item;
+    Response? response = item;
     return response != null && response.id == _id && response.error == null;
   }
 }
diff --git a/pkg/analysis_server/test/mocks_lsp.dart b/pkg/analysis_server/test/mocks_lsp.dart
new file mode 100644
index 0000000..868b648
--- /dev/null
+++ b/pkg/analysis_server/test/mocks_lsp.dart
@@ -0,0 +1,196 @@
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart = 2.9
+
+import 'dart:async';
+import 'dart:convert';
+
+import 'package:analysis_server/lsp_protocol/protocol_generated.dart' as lsp;
+import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analysis_server/lsp_protocol/protocol_special.dart' as lsp;
+import 'package:analysis_server/src/lsp/channel/lsp_channel.dart';
+
+const _jsonEncoder = JsonEncoder.withIndent('    ');
+
+/// A mock [LspServerCommunicationChannel] for testing [LspAnalysisServer].
+class MockLspServerChannel implements LspServerCommunicationChannel {
+  final StreamController<lsp.Message> _clientToServer =
+      StreamController<lsp.Message>.broadcast();
+  final StreamController<lsp.Message> _serverToClient =
+      StreamController<lsp.Message>.broadcast();
+
+  String name;
+
+  /// Completer that will be signalled when the input stream is closed.
+  final Completer _closed = Completer();
+
+  /// Errors popups sent to the user.
+  final shownErrors = <lsp.ShowMessageParams>[];
+
+  /// Warning popups sent to the user.
+  final shownWarnings = <lsp.ShowMessageParams>[];
+
+  MockLspServerChannel(bool _printMessages) {
+    if (_printMessages) {
+      _serverToClient.stream
+          .listen((message) => print('<== ' + jsonEncode(message)));
+      _clientToServer.stream
+          .listen((message) => print('==> ' + jsonEncode(message)));
+    }
+
+    // Keep track of any errors/warnings that are sent to the user with
+    // `window/showMessage`.
+    _serverToClient.stream.listen((message) {
+      if (message is lsp.NotificationMessage &&
+          message.method == Method.window_showMessage &&
+          message.params is lsp.ShowMessageParams) {
+        if (message.params?.type == MessageType.Error) {
+          shownErrors.add(message.params);
+        } else if (message.params?.type == MessageType.Warning) {
+          shownWarnings.add(message.params);
+        }
+      }
+    });
+  }
+
+  /// Future that will be completed when the input stream is closed.
+  @override
+  Future get closed {
+    return _closed.future;
+  }
+
+  Stream<lsp.Message> get serverToClient => _serverToClient.stream;
+
+  @override
+  void close() {
+    if (!_closed.isCompleted) {
+      _closed.complete();
+    }
+    if (!_serverToClient.isClosed) {
+      _serverToClient.close();
+    }
+    if (!_clientToServer.isClosed) {
+      _clientToServer.close();
+    }
+  }
+
+  @override
+  void listen(void Function(lsp.Message message) onMessage,
+      {Function onError, void Function() onDone}) {
+    _clientToServer.stream.listen(onMessage, onError: onError, onDone: onDone);
+  }
+
+  @override
+  void sendNotification(lsp.NotificationMessage notification) {
+    // Don't deliver notifications after the connection is closed.
+    if (_closed.isCompleted) {
+      return;
+    }
+
+    notification = _convertJson(notification, lsp.NotificationMessage.fromJson);
+
+    _serverToClient.add(notification);
+  }
+
+  void sendNotificationToServer(lsp.NotificationMessage notification) {
+    // Don't deliver notifications after the connection is closed.
+    if (_closed.isCompleted) {
+      return;
+    }
+
+    notification = _convertJson(notification, lsp.NotificationMessage.fromJson);
+
+    // Wrap send request in future to simulate WebSocket.
+    Future(() => _clientToServer.add(notification));
+  }
+
+  @override
+  void sendRequest(lsp.RequestMessage request) {
+    // Don't deliver notifications after the connection is closed.
+    if (_closed.isCompleted) {
+      return;
+    }
+
+    request = _convertJson(request, lsp.RequestMessage.fromJson);
+
+    _serverToClient.add(request);
+  }
+
+  /// Send the given [request] to the server and return a future that will
+  /// complete when a response associated with the [request] has been received.
+  /// The value of the future will be the received response.
+  Future<lsp.ResponseMessage> sendRequestToServer(lsp.RequestMessage request) {
+    // No further requests should be sent after the connection is closed.
+    if (_closed.isCompleted) {
+      throw Exception('sendLspRequest after connection closed');
+    }
+
+    request = _convertJson(request, lsp.RequestMessage.fromJson);
+
+    // Wrap send request in future to simulate WebSocket.
+    Future(() => _clientToServer.add(request));
+    return waitForResponse(request);
+  }
+
+  @override
+  void sendResponse(lsp.ResponseMessage response) {
+    // Don't deliver responses after the connection is closed.
+    if (_closed.isCompleted) {
+      return;
+    }
+
+    response = _convertJson(response, lsp.ResponseMessage.fromJson);
+
+    // Wrap send response in future to simulate WebSocket.
+    Future(() => _serverToClient.add(response));
+  }
+
+  void sendResponseToServer(lsp.ResponseMessage response) {
+    // Don't deliver notifications after the connection is closed.
+    if (_closed.isCompleted) {
+      return;
+    }
+
+    response = _convertJson(response, lsp.ResponseMessage.fromJson);
+
+    _clientToServer.add(response);
+  }
+
+  /// Return a future that will complete when a response associated with the
+  /// given [request] has been received. The value of the future will be the
+  /// received response. The returned future will throw an exception if a server
+  /// error is reported before the response has been received.
+  ///
+  /// Unlike [sendLspRequest], this method assumes that the [request] has
+  /// already been sent to the server.
+  Future<lsp.ResponseMessage> waitForResponse(
+    lsp.RequestMessage request, {
+    bool throwOnError = true,
+  }) async {
+    final response = await _serverToClient.stream.firstWhere((message) =>
+        (message is lsp.ResponseMessage && message.id == request.id) ||
+        (throwOnError &&
+            message is lsp.NotificationMessage &&
+            message.method == Method.window_showMessage &&
+            lsp.ShowMessageParams.fromJson(message.params).type ==
+                MessageType.Error));
+
+    if (response is lsp.ResponseMessage) {
+      return response;
+    } else {
+      throw 'An error occurred while waiting for a response to ${request.method}: '
+          '${_jsonEncoder.convert(response.toJson())}';
+    }
+  }
+
+  /// Round trips the object to JSON and back to ensure it behaves the same as
+  /// when running over the real STDIO server. Without this, the object passed
+  /// to the handlers will have concrete types as constructed in tests rather
+  /// than the maps as they would be (the server expects to do the conversion).
+  T _convertJson<T>(
+      lsp.ToJsonable message, T Function(Map<String, dynamic>) constructor) {
+    return constructor(jsonDecode(jsonEncode(message.toJson())));
+  }
+}
diff --git a/pkg/analysis_server/test/protocol_server_test.dart b/pkg/analysis_server/test/protocol_server_test.dart
index 65df4b5..850b29a 100644
--- a/pkg/analysis_server/test/protocol_server_test.dart
+++ b/pkg/analysis_server/test/protocol_server_test.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'dart:mirrors';
 
 import 'package:analysis_server/src/protocol_server.dart'
@@ -34,37 +32,45 @@
 
 @reflectiveTest
 class AnalysisErrorTest {
-  MockSource source = MockSource();
-  MockAnalysisError engineError;
-  ResolvedUnitResult result;
+  late MockSource source;
+  late MockAnalysisError engineError;
+  late ResolvedUnitResult result;
 
   void setUp() {
     // prepare Source
-    source.fullName = 'foo.dart';
+    source = MockSource(fullName: 'foo.dart');
     // prepare AnalysisError
-    engineError = MockAnalysisError(source,
-        engine.CompileTimeErrorCode.AMBIGUOUS_EXPORT, 10, 20, 'my message');
+    engineError = MockAnalysisError(
+      source: source,
+      errorCode: engine.CompileTimeErrorCode.AMBIGUOUS_EXPORT,
+      offset: 10,
+      length: 20,
+      message: 'my message',
+    );
     // prepare ResolvedUnitResult
     var lineInfo = engine.LineInfo([0, 5, 9, 20]);
-    result = engine.ResolvedUnitResultImpl(null, 'foo.dart', null, true, null,
-        lineInfo, false, null, [engineError]);
-  }
-
-  void tearDown() {
-    source = null;
-    engineError = null;
+    result = _ResolvedUnitResultImplMock(
+      lineInfo: lineInfo,
+      errors: [engineError],
+    );
   }
 
   void test_fromEngine_hasContextMessage() {
-    engineError.contextMessages.add(engine.DiagnosticMessageImpl(
-        filePath: 'bar.dart', offset: 30, length: 5, message: 'context'));
-    var session = MockAnalysisSession();
-    session.addFileResult(engine.FileResultImpl(
-        session, 'bar.dart', null, engine.LineInfo([0, 5, 9, 20]), false));
+    engineError.contextMessages.add(
+      engine.DiagnosticMessageImpl(
+        filePath: 'bar.dart',
+        offset: 30,
+        length: 5,
+        message: 'context',
+      ),
+    );
     var error = newAnalysisError_fromEngine(
-        engine.ResolvedUnitResultImpl(session, 'foo.dart', null, true, null,
-            engine.LineInfo([0, 5, 9, 20]), false, null, [engineError]),
-        engineError);
+      _ResolvedUnitResultImplMock(
+        lineInfo: engine.LineInfo([0, 5, 9, 20]),
+        errors: [engineError],
+      ),
+      engineError,
+    );
     expect(error.toJson(), {
       SEVERITY: 'ERROR',
       TYPE: 'COMPILE_TIME_ERROR',
@@ -99,7 +105,14 @@
   }
 
   void test_fromEngine_hasCorrection() {
-    engineError.correction = 'my correction';
+    engineError = MockAnalysisError(
+      source: source,
+      errorCode: engine.CompileTimeErrorCode.AMBIGUOUS_EXPORT,
+      offset: 10,
+      length: 20,
+      message: 'my message',
+      correction: 'my correction',
+    );
     var error = newAnalysisError_fromEngine(result, engineError);
     expect(error.toJson(), {
       SEVERITY: 'ERROR',
@@ -123,11 +136,12 @@
 
   void test_fromEngine_hasUrl() {
     engineError = MockAnalysisError(
-        source,
-        MockErrorCode(url: 'http://codes.dartlang.org/TEST_ERROR'),
-        10,
-        20,
-        'my message');
+      source: source,
+      errorCode: MockErrorCode(url: 'http://codes.dartlang.org/TEST_ERROR'),
+      offset: 10,
+      length: 20,
+      message: 'my message',
+    );
     var error = newAnalysisError_fromEngine(result, engineError);
     expect(error.toJson(), {
       SEVERITY: 'ERROR',
@@ -150,11 +164,12 @@
 
   void test_fromEngine_lint() {
     engineError = MockAnalysisError(
-        source,
-        LintCode('my_lint', 'my message', correction: 'correction'),
-        10,
-        20,
-        'my message');
+      source: source,
+      errorCode: LintCode('my_lint', 'my message', correction: 'correction'),
+      offset: 10,
+      length: 20,
+      message: 'my message',
+    );
     var error = newAnalysisError_fromEngine(result, engineError);
     expect(error.toJson(), {
       SEVERITY: 'INFO',
@@ -176,7 +191,13 @@
   }
 
   void test_fromEngine_noCorrection() {
-    engineError.correction = null;
+    engineError = MockAnalysisError(
+      source: source,
+      errorCode: engine.CompileTimeErrorCode.AMBIGUOUS_EXPORT,
+      offset: 10,
+      length: 20,
+      message: 'my message',
+    );
     var error = newAnalysisError_fromEngine(result, engineError);
     expect(error.toJson(), {
       SEVERITY: 'ERROR',
@@ -196,31 +217,6 @@
       HAS_FIX: false
     });
   }
-
-  void test_fromEngine_noLineInfo() {
-    engineError.correction = null;
-    var error = newAnalysisError_fromEngine(
-        engine.ResolvedUnitResultImpl(null, 'foo.dart', null, true, null, null,
-            false, null, [engineError]),
-        engineError);
-    expect(error.toJson(), {
-      SEVERITY: 'ERROR',
-      TYPE: 'COMPILE_TIME_ERROR',
-      LOCATION: {
-        FILE: 'foo.dart',
-        OFFSET: 10,
-        LENGTH: 20,
-        START_LINE: -1,
-        START_COLUMN: -1,
-        END_LINE: -1,
-        END_COLUMN: -1,
-      },
-      MESSAGE: 'my message',
-      CODE: 'ambiguous_export',
-      URL: 'https://dart.dev/tools/diagnostic-messages#ambiguous_export',
-      HAS_FIX: false
-    });
-  }
 }
 
 @reflectiveTest
@@ -271,7 +267,7 @@
   /// If the corresponding value is an [ApiEnum], then we check that converting
   /// the given key results in the given value.
   void run(ApiEnum Function(EngineEnum) convert,
-      {Map<EngineEnum, ApiEnum> exceptions = const {}}) {
+      {Map<EngineEnum, ApiEnum?> exceptions = const {}}) {
     var engineClass = reflectClass(EngineEnum);
     engineClass.staticMembers.forEach((Symbol symbol, MethodMirror method) {
       if (symbol == #values) {
@@ -302,49 +298,73 @@
 }
 
 class MockAnalysisError implements engine.AnalysisError {
-  @override
-  MockSource source;
-
-  @override
-  engine.ErrorCode errorCode;
-
-  @override
-  int offset;
-
-  @override
-  String message;
-
-  @override
-  String correction;
-
-  @override
-  int length;
+  final MockSource? _source;
+  final engine.ErrorCode? _errorCode;
+  final int? _offset;
+  final int? _length;
+  final String? _message;
+  final String? _correction;
+  final DiagnosticMessage? _problemMessage;
+  final String? _correctionMessage;
 
   @override
   List<DiagnosticMessage> contextMessages = <DiagnosticMessage>[];
 
-  MockAnalysisError(
-      this.source, this.errorCode, this.offset, this.length, this.message);
+  MockAnalysisError({
+    MockSource? source,
+    engine.ErrorCode? errorCode,
+    int? offset,
+    int? length,
+    String? message,
+    String? correction,
+    DiagnosticMessage? problemMessage,
+    String? correctionMessage,
+  })  : _source = source,
+        _errorCode = errorCode,
+        _offset = offset,
+        _length = length,
+        _message = message,
+        _correction = correction,
+        _problemMessage = problemMessage,
+        _correctionMessage = correctionMessage;
 
   @override
-  String get correctionMessage => null;
+  String? get correction => _correction;
 
   @override
-  DiagnosticMessage get problemMessage => null;
+  String? get correctionMessage => _correctionMessage;
 
   @override
-  Severity get severity => null;
+  engine.ErrorCode get errorCode => _errorCode!;
+
+  @override
+  int get length => _length!;
+
+  @override
+  String get message => _message!;
+
+  @override
+  int get offset => _offset!;
+
+  @override
+  DiagnosticMessage get problemMessage => _problemMessage!;
+
+  @override
+  Severity get severity => throw UnimplementedError();
+
+  @override
+  engine.Source get source => _source!;
 }
 
 class MockAnalysisSession implements AnalysisSession {
   Map<String, FileResult> fileResults = {};
 
   void addFileResult(FileResult result) {
-    fileResults[result.path] = result;
+    fileResults[result.path!] = result;
   }
 
   @override
-  FileResult getFile(String path) => fileResults[path];
+  FileResult getFile(String path) => fileResults[path]!;
 
   @override
   dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
@@ -361,7 +381,7 @@
   String name;
 
   @override
-  String url;
+  String? url;
 
   MockErrorCode(
       {this.type = engine.ErrorType.COMPILE_TIME_ERROR,
@@ -393,3 +413,19 @@
     throw StateError('Unexpected invocation of uniqueName');
   }
 }
+
+class _ResolvedUnitResultImplMock implements engine.ResolvedUnitResultImpl {
+  @override
+  final engine.LineInfo lineInfo;
+
+  @override
+  final List<engine.AnalysisError> errors;
+
+  _ResolvedUnitResultImplMock({
+    required this.lineInfo,
+    required this.errors,
+  });
+
+  @override
+  dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
+}
diff --git a/pkg/analysis_server/test/services/search/element_visitors_test.dart b/pkg/analysis_server/test/services/search/element_visitors_test.dart
index 3f2b9e4..0de43dd0 100644
--- a/pkg/analysis_server/test/services/search/element_visitors_test.dart
+++ b/pkg/analysis_server/test/services/search/element_visitors_test.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analysis_server/src/services/search/element_visitors.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:test/test.dart';
@@ -62,8 +60,7 @@
   }
 
   void _assertElement(int nameOffset, ElementKind kind, String name) {
-    var element = findElementByNameOffset(testUnitElement, nameOffset);
-    expect(element, isNotNull);
+    var element = findElementByNameOffset(testUnitElement, nameOffset)!;
     expect(element.kind, kind);
     expect(element.name, name);
   }
diff --git a/pkg/analysis_server/test/services/search/hierarchy_test.dart b/pkg/analysis_server/test/services/search/hierarchy_test.dart
index fc72aa4..0280926 100644
--- a/pkg/analysis_server/test/services/search/hierarchy_test.dart
+++ b/pkg/analysis_server/test/services/search/hierarchy_test.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analysis_server/src/services/search/hierarchy.dart';
 import 'package:analysis_server/src/services/search/search_engine_internal.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -20,7 +18,7 @@
 
 @reflectiveTest
 class HierarchyTest extends AbstractSingleUnitTest {
-  SearchEngineImpl searchEngine;
+  late SearchEngineImpl searchEngine;
 
   @override
   void setUp() {
@@ -73,7 +71,7 @@
     var futureB = getHierarchyMembers(searchEngine, memberB).then((members) {
       expect(members, unorderedEquals([memberB]));
     });
-    return Future.wait([futureA, futureB]);
+    await Future.wait([futureA, futureB]);
   }
 
   Future<void> test_getHierarchyMembers_fields() async {
@@ -111,7 +109,7 @@
     var futureD = getHierarchyMembers(searchEngine, memberD).then((members) {
       expect(members, unorderedEquals([memberD]));
     });
-    return Future.wait([futureA, futureB, futureC, futureD]);
+    await Future.wait([futureA, futureB, futureC, futureD]);
   }
 
   Future<void> test_getHierarchyMembers_fields_static() async {
@@ -189,7 +187,7 @@
     var futureE = getHierarchyMembers(searchEngine, memberE).then((members) {
       expect(members, unorderedEquals([memberD, memberE]));
     });
-    return Future.wait([futureA, futureB, futureC, futureD, futureE]);
+    await Future.wait([futureA, futureB, futureC, futureD, futureE]);
   }
 
   Future<void> test_getHierarchyMembers_methods_static() async {
@@ -247,7 +245,7 @@
     var futureD = getHierarchyMembers(searchEngine, memberD).then((members) {
       expect(members, unorderedEquals([memberA, memberB, memberD]));
     });
-    return Future.wait([futureA, futureB, futureD]);
+    await Future.wait([futureA, futureB, futureD]);
   }
 
   Future<void> test_getHierarchyNamedParameters() async {
@@ -403,7 +401,7 @@
     var classD = findElement.class_('D');
     var classE = findElement.class_('E');
     var classF = findElement.class_('F');
-    var objectElement = classA.supertype.element;
+    var objectElement = classA.supertype!.element;
     // Object
     {
       var supers = getSuperClasses(objectElement);
@@ -461,7 +459,7 @@
     var m3 = findElement.mixin('M3');
     var m4 = findElement.mixin('M4');
     var m5 = findElement.mixin('M5');
-    var object = a.supertype.element;
+    var object = a.supertype!.element;
 
     _assertSuperClasses(object, []);
     _assertSuperClasses(a, [object]);
diff --git a/pkg/analysis_server/test/services/search/search_engine_test.dart b/pkg/analysis_server/test/services/search/search_engine_test.dart
index 593f483..664c8fd 100644
--- a/pkg/analysis_server/test/services/search/search_engine_test.dart
+++ b/pkg/analysis_server/test/services/search/search_engine_test.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analysis_server/src/services/search/search_engine.dart';
 import 'package:analysis_server/src/services/search/search_engine_internal.dart';
 import 'package:analyzer/dart/analysis/results.dart';
@@ -26,9 +24,9 @@
 /// TODO(scheglov) This class does not really belong here.
 /// Consider merging it into [AbstractContextTest].
 class PubPackageResolutionTest extends AbstractContextTest {
-  ResolvedUnitResult result;
-  FindNode findNode;
-  FindElement findElement;
+  late ResolvedUnitResult result;
+  late FindNode findNode;
+  late FindElement findElement;
 
   String get testFilePath => '$testPackageLibPath/test.dart';
 
@@ -43,8 +41,8 @@
     result = await resolveFile(path);
     expect(result.state, ResultState.VALID);
 
-    findNode = FindNode(result.content, result.unit);
-    findElement = FindElement(result.unit);
+    findNode = FindNode(result.content!, result.unit!);
+    findElement = FindElement(result.unit!);
   }
 
   /// Put the [code] into the test file, and resolve it.
@@ -331,14 +329,14 @@
 ''').path;
 
     var coreLib = await driverFor(testFilePath).getLibraryByUri('dart:core');
-    var intElement = coreLib.getType('int');
+    var intElement = coreLib.getType('int')!;
 
     var matches = await searchEngine.searchReferences(intElement);
 
     void assertHasOne(String path, String name) {
       expect(matches.where((m) {
         var element = m.element;
-        return element.name == name && element.source.fullName == path;
+        return element.name == name && element.source!.fullName == path;
       }), hasLength(1));
     }
 
@@ -426,7 +424,7 @@
 
   Future _ensureContainedFilesKnown() async {
     for (var driver in allDrivers) {
-      var contextRoot = driver.analysisContext.contextRoot;
+      var contextRoot = driver.analysisContext!.contextRoot;
       for (var file in contextRoot.analyzedFiles()) {
         if (file.endsWith('.dart')) {
           await driver.getUnitElement(file);
diff --git a/pkg/analysis_server/test/services/search/test_all.dart b/pkg/analysis_server/test/services/search/test_all.dart
index 123f0cf..c3f8f91 100644
--- a/pkg/analysis_server/test/services/search/test_all.dart
+++ b/pkg/analysis_server/test/services/search/test_all.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'element_visitors_test.dart' as element_visitors;
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_override_set_parser_test.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_override_set_parser_test.dart
index a219dbc..99e8f93 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_override_set_parser_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_override_set_parser_test.dart
@@ -59,7 +59,8 @@
 
   void parse(String content) {
     errorListener = GatheringErrorListener();
-    var errorReporter = ErrorReporter(errorListener, MockSource('data.yaml'));
+    var errorReporter =
+        ErrorReporter(errorListener, MockSource(fullName: 'data.yaml'));
     var parser = TransformOverrideSetParser(errorReporter);
     result = parser.parse(content);
   }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test_support.dart b/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test_support.dart
index a18e9be..8a790402 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test_support.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/data_driven/transform_set_parser_test_support.dart
@@ -42,7 +42,8 @@
 
   void parse(String content) {
     errorListener = GatheringErrorListener();
-    var errorReporter = ErrorReporter(errorListener, MockSource('data.yaml'));
+    var errorReporter =
+        ErrorReporter(errorListener, MockSource(fullName: 'data.yaml'));
     var parser = TransformSetParser(errorReporter, 'myPackage');
     result = parser.parse(content);
   }
diff --git a/pkg/analysis_server/test/tool/completion_metrics/metrics_util_test.dart b/pkg/analysis_server/test/tool/completion_metrics/metrics_util_test.dart
index 9b0865d..8c83b04 100644
--- a/pkg/analysis_server/test/tool/completion_metrics/metrics_util_test.dart
+++ b/pkg/analysis_server/test/tool/completion_metrics/metrics_util_test.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:test/test.dart';
 
 import '../../../tool/code_completion/metrics_util.dart';
@@ -172,8 +170,6 @@
   @override
   bool matches(item, Map matchState) {
     return item is num &&
-        item != null &&
-        _value != null &&
         num.parse(item.toStringAsFixed(fractionDigits)) ==
             num.parse(_value.toStringAsFixed(fractionDigits));
   }
diff --git a/pkg/analysis_server/test/tool/completion_metrics/test_all.dart b/pkg/analysis_server/test/tool/completion_metrics/test_all.dart
index 2a7e8b3..8ca30d9 100644
--- a/pkg/analysis_server/test/tool/completion_metrics/test_all.dart
+++ b/pkg/analysis_server/test/tool/completion_metrics/test_all.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'metrics_util_test.dart' as metrics_util_test;
diff --git a/pkg/analysis_server/tool/code_completion/implicit_type_declarations.dart b/pkg/analysis_server/tool/code_completion/implicit_type_declarations.dart
index 3204eeb..baa7300 100644
--- a/pkg/analysis_server/tool/code_completion/implicit_type_declarations.dart
+++ b/pkg/analysis_server/tool/code_completion/implicit_type_declarations.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'dart:io' as io;
 
 import 'package:analysis_server/src/status/pages.dart';
@@ -17,7 +15,6 @@
 import 'package:analyzer/file_system/physical_file_system.dart';
 import 'package:analyzer/src/util/file_paths.dart' as file_paths;
 import 'package:args/args.dart';
-import 'package:meta/meta.dart';
 
 /// Compute metrics to determine which untyped variable declarations can be used
 /// to imply an expected context type, i.e. the RHS of 'var string = ^' could be
@@ -63,7 +60,7 @@
 }
 
 /// Print usage information for this tool.
-void printUsage(ArgParser parser, {String error}) {
+void printUsage(ArgParser parser, {String? error}) {
   if (error != null) {
     print(error);
     print('');
@@ -104,7 +101,7 @@
   /// [data].
   ImpliedTypeCollector(this.data);
 
-  void handleVariableDeclaration(VariableDeclaration node, DartType dartType) {
+  void handleVariableDeclaration(VariableDeclaration node, DartType? dartType) {
     // If some untyped variable declaration
     if (node.equals != null && dartType == null ||
         (dartType != null && (dartType.isDynamic || dartType.isVoid))) {
@@ -141,7 +138,7 @@
   /// Compute the metrics for the file(s) in the [rootPath].
   /// If [corpus] is true, treat rootPath as a container of packages, creating
   /// a new context collection for each subdirectory.
-  Future<void> compute(String rootPath, {@required bool verbose}) async {
+  Future<void> compute(String rootPath, {required bool verbose}) async {
     final collection = AnalysisContextCollection(
       includedPaths: [rootPath],
       resourceProvider: PhysicalResourceProvider.INSTANCE,
@@ -174,7 +171,7 @@
   /// output if [verbose] is `true`.
   Future<void> _computeInContext(
       ContextRoot root, ImpliedTypeCollector collector,
-      {@required bool verbose}) async {
+      {required bool verbose}) async {
     // Create a new collection to avoid consuming large quantities of memory.
     final collection = AnalysisContextCollection(
       includedPaths: root.includedPaths.toList(),
@@ -191,13 +188,7 @@
           //
           // Check for errors that cause the file to be skipped.
           //
-          if (resolvedUnitResult == null) {
-            print('File $filePath skipped because resolved unit was null.');
-            if (verbose) {
-              print('');
-            }
-            continue;
-          } else if (resolvedUnitResult.state != ResultState.VALID) {
+          if (resolvedUnitResult.state != ResultState.VALID) {
             print('File $filePath skipped because it could not be analyzed.');
             if (verbose) {
               print('');
@@ -217,7 +208,7 @@
             continue;
           }
 
-          resolvedUnitResult.unit.accept(collector);
+          resolvedUnitResult.unit!.accept(collector);
         } catch (exception, stacktrace) {
           print('Exception caught analyzing: "$filePath"');
           print(exception);
@@ -243,8 +234,6 @@
 
   /// Record the variable name with the type.
   void recordImpliedType(String name, String displayString) {
-    assert(name != null);
-    assert(displayString != null);
     var nameMap = impliedTypesMap.putIfAbsent(name, () => {});
     nameMap[displayString] = (nameMap[displayString] ?? 0) + 1;
   }
diff --git a/pkg/analysis_server/tool/code_completion/metrics_util.dart b/pkg/analysis_server/tool/code_completion/metrics_util.dart
index 47671f0..00364e9 100644
--- a/pkg/analysis_server/tool/code_completion/metrics_util.dart
+++ b/pkg/analysis_server/tool/code_completion/metrics_util.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-// @dart = 2.9
-
 import 'package:analysis_server/src/status/pages.dart';
 import 'package:analyzer/src/generated/utilities_general.dart';
 
@@ -96,12 +94,12 @@
   }
 
   void count(String id, [int countNumber = 1]) {
-    assert(id != null && id.isNotEmpty && 1 <= countNumber);
-    if (_buckets.containsKey(id)) {
-      _buckets[id] += countNumber;
-    } else {
-      _buckets.putIfAbsent(id, () => countNumber);
-    }
+    assert(id.isNotEmpty && 1 <= countNumber);
+    _buckets.update(
+      id,
+      (value) => value + countNumber,
+      ifAbsent: () => countNumber,
+    );
     _totalCount += countNumber;
   }
 
diff --git a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
index 03b5275..e7dff9b 100644
--- a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
+++ b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
@@ -489,9 +489,6 @@
         }
       });
 
-      results.forEach((key, value) {
-        print('$key: $value');
-      });
       var resolvedUnits = results.values.map((fileResult) {
         var file = fileResult.file;
         return ResolvedUnitResultImpl(
diff --git a/pkg/dartdev/test/commands/format_test.dart b/pkg/dartdev/test/commands/format_test.dart
index 6f36795..82e68d2 100644
--- a/pkg/dartdev/test/commands/format_test.dart
+++ b/pkg/dartdev/test/commands/format_test.dart
@@ -62,6 +62,33 @@
             'Formatted lib/main.dart\nFormatted 1 file (1 changed) in '));
   });
 
+  test('formatted with exit code set', () {
+    p = project(mainSrc: 'int get foo =>       1;\n');
+    ProcessResult result = p.runSync([
+      'format',
+      '--set-exit-if-changed',
+      p.relativeFilePath,
+    ]);
+    expect(result.exitCode, isNot(0));
+    expect(result.stderr, isEmpty);
+    expect(
+        result.stdout,
+        startsWith(
+            'Formatted lib/main.dart\nFormatted 1 file (1 changed) in '));
+  });
+
+  test('not formatted with exit code set', () {
+    p = project(mainSrc: 'int get foo => 1;\n');
+    ProcessResult result = p.runSync([
+      'format',
+      '--set-exit-if-changed',
+      p.relativeFilePath,
+    ]);
+    expect(result.exitCode, 0);
+    expect(result.stderr, isEmpty);
+    expect(result.stdout, startsWith('Formatted 1 file (0 changed) in '));
+  });
+
   test('unknown file', () {
     p = project(mainSrc: 'int get foo => 1;\n');
     var unknownFilePath = '${p.relativeFilePath}-unknown-file.dart';
diff --git a/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart b/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart
index 9ae2415..6fd9bb0 100644
--- a/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart
+++ b/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_shared.dart
@@ -963,4 +963,99 @@
           breakpointId: 'bp', expression: 'e', expectedResult: '1');
     });
   });
+
+  group('Expression compiler tests in generic method:', () {
+    var source = '''
+        class C<T1> {
+          void generic<T2>(T1 a, T2 b) {
+            // Breakpoint: bp
+            print(a);
+            print(b);
+          }
+        }
+
+        void main() => C<int>().generic<String>(0, 'hi');
+        ''';
+
+    setUpAll(() async {
+      await driver.initSource(setup, source);
+    });
+
+    tearDownAll(() {
+      driver.cleanupTest();
+    });
+
+    test('evaluate formals', () async {
+      await driver.check(
+          breakpointId: 'bp',
+          expression: "'\${a} \$b'",
+          expectedResult: '0 hi');
+    });
+
+    test('evaluate class type parameters', () async {
+      await driver.check(
+          breakpointId: 'bp', expression: "'\$T1'", expectedResult: 'int');
+    });
+
+    test('evaluate method type parameters', () async {
+      await driver.check(
+          breakpointId: 'bp', expression: "'\$T2'", expectedResult: 'String');
+    });
+  });
+
+  group('Expression compiler tests for interactions with module containers:',
+      () {
+    var source = '''
+        class A {
+          const A();
+        }
+        class B {
+          const B();
+        }
+        void foo() {
+          const a = A();
+          var check = a is int;
+          // Breakpoint: bp
+          return;
+        }
+
+        void main() => foo();
+        ''';
+
+    setUpAll(() async {
+      await driver.initSource(setup, source);
+    });
+
+    tearDownAll(() {
+      driver.cleanupTest();
+    });
+
+    test('evaluation that non-destructively appends to the type container',
+        () async {
+      await driver.check(
+          breakpointId: 'bp',
+          expression: 'a is String',
+          expectedResult: 'false');
+    });
+
+    test('evaluation that reuses the type container', () async {
+      await driver.check(
+          breakpointId: 'bp', expression: 'a is int', expectedResult: 'false');
+    });
+
+    test('evaluation that non-destructively appends to the constant container',
+        () async {
+      await driver.check(
+          breakpointId: 'bp',
+          expression: 'const B() == const B()',
+          expectedResult: 'true');
+    });
+
+    test('evaluation that properly canonicalizes constants', () async {
+      await driver.check(
+          breakpointId: 'bp',
+          expression: 'a == const A()',
+          expectedResult: 'true');
+    });
+  });
 }
diff --git a/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_sound_test.dart b/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_sound_test.dart
index f67ae6a9..9db3279 100644
--- a/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_sound_test.dart
+++ b/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_sound_test.dart
@@ -6,19 +6,29 @@
 
 library dev_compiler.test.expression_compiler;
 
+import 'package:dev_compiler/dev_compiler.dart' show ModuleFormat;
 import 'package:test/test.dart';
 import 'expression_compiler_e2e_shared.dart';
 import 'expression_compiler_e2e_suite.dart';
 
 void main() async {
   var driver = await TestDriver.init();
-  var setup = SetupCompilerOptions(soundNullSafety: true);
 
   group('(Sound null safety)', () {
     tearDownAll(() {
       driver.finish();
     });
 
-    runSharedTests(setup, driver);
+    group('(AMD module system)', () {
+      var setup = SetupCompilerOptions(
+          soundNullSafety: true, moduleFormat: ModuleFormat.amd);
+      runSharedTests(setup, driver);
+    });
+
+    group('(DDC module system)', () {
+      var setup = SetupCompilerOptions(
+          soundNullSafety: true, moduleFormat: ModuleFormat.ddc);
+      runSharedTests(setup, driver);
+    });
   });
 }
diff --git a/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_suite.dart b/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_suite.dart
index 1dceafe..7f79898 100644
--- a/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_suite.dart
+++ b/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_suite.dart
@@ -314,7 +314,7 @@
             'dart_sdk.js'));
         var dartLibraryPath =
             escaped(p.join(ddcPath, 'lib', 'js', 'legacy', 'dart_library.js'));
-        var outputPath = escaped(output.toFilePath());
+        var outputPath = output.toFilePath();
         bootstrapFile.writeAsStringSync('''
 <script src='$dartLibraryPath'></script>
 <script src='$dartSdkPath'></script>
@@ -542,7 +542,12 @@
       for (var prop in response) {
         var propKey = '${prop.name}';
         var propValue = '${prop.value.value}';
-        jsScope[propKey] = propValue == 'null' ? propKey : propValue;
+        if (prop.value.type == 'string') {
+          propValue = "'$propValue'";
+        } else if (propValue == 'null') {
+          propValue = propKey;
+        }
+        jsScope[propKey] = propValue;
       }
     }
     return jsScope;
diff --git a/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_unsound_test.dart b/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_unsound_test.dart
index 7ac4ce7..72df6f5 100644
--- a/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_unsound_test.dart
+++ b/pkg/dev_compiler/test/expression_compiler/expression_compiler_e2e_unsound_test.dart
@@ -6,19 +6,29 @@
 
 library dev_compiler.test.expression_compiler;
 
+import 'package:dev_compiler/dev_compiler.dart' show ModuleFormat;
 import 'package:test/test.dart';
 import 'expression_compiler_e2e_shared.dart';
 import 'expression_compiler_e2e_suite.dart';
 
 void main() async {
   var driver = await TestDriver.init();
-  var setup = SetupCompilerOptions(soundNullSafety: false);
 
   group('(Unsound null safety)', () {
     tearDownAll(() {
       driver.finish();
     });
 
-    runSharedTests(setup, driver);
+    group('(AMD module system)', () {
+      var setup = SetupCompilerOptions(
+          soundNullSafety: false, moduleFormat: ModuleFormat.amd);
+      runSharedTests(setup, driver);
+    });
+
+    group('(DDC module system)', () {
+      var setup = SetupCompilerOptions(
+          soundNullSafety: false, moduleFormat: ModuleFormat.ddc);
+      runSharedTests(setup, driver);
+    });
   });
 }
diff --git a/pkg/dev_compiler/test/expression_compiler/expression_compiler_test.dart b/pkg/dev_compiler/test/expression_compiler/expression_compiler_test.dart
index 17e60eb..d5fbeea 100644
--- a/pkg/dev_compiler/test/expression_compiler/expression_compiler_test.dart
+++ b/pkg/dev_compiler/test/expression_compiler/expression_compiler_test.dart
@@ -405,149 +405,6 @@
           });
         });
 
-        group('Expression compiler extension symbols tests', () {
-          var source = '''
-          ${options.dartLangComment}
-
-          main() {
-            List<int> list = {};
-            list.add(0);
-            /* evaluation placeholder */
-          }
-          ''';
-
-          TestDriver driver;
-
-          setUp(() {
-            driver = TestDriver(options, source);
-          });
-
-          tearDown(() {
-            driver.delete();
-          });
-
-          test('extension symbol used in original compilation', () async {
-            await driver.check(
-                scope: <String, String>{'list': 'list'},
-                expression: 'list.add(1)',
-                expectedResult: '''
-            (function(list) {
-              const dart_sdk = ${options.loadModule}('dart_sdk');
-              const dartx = dart_sdk.dartx;
-              var \$add = dartx.add;
-              var S = {\$add: dartx.add};
-              return list[\$add](1);
-            }(
-              list
-            ))
-            ''');
-          });
-
-          test('extension symbol used only in expression compilation',
-              () async {
-            await driver.check(
-                scope: <String, String>{'list': 'list'},
-                expression: 'list.first',
-                expectedResult: '''
-            (function(list) {
-              const dart_sdk = ${options.loadModule}('dart_sdk');
-              const dartx = dart_sdk.dartx;
-              var S = {\$first: dartx.first};
-              return list[S.\$first];
-            }(
-              list
-            ))
-            ''');
-          });
-        });
-
-        group('Expression compiler tests in closures:', () {
-          var source = '''
-          ${options.dartLangComment}
-          int globalFunction() {
-            int x = 15;
-            var c = C(1, 2);
-
-            var outerClosure = (int y) {
-              var closureCaptureInner = (int z) {
-                /* evaluation placeholder */
-                print('\$y+\$z');
-              };
-              closureCaptureInner(0);
-            };
-
-            outerClosure(3);
-            return 0;
-          }
-
-          main() => 0;
-          ''';
-
-          TestDriver driver;
-          setUp(() {
-            driver = TestDriver(options, source);
-          });
-
-          tearDown(() {
-            driver.delete();
-          });
-
-          test('compilation error', () async {
-            await driver.check(scope: <String, String>{
-              'x': '1',
-              'c': 'null',
-              'y': '3',
-              'z': '0'
-            }, expression: 'typo', expectedError: "Getter not found: 'typo'.");
-          });
-
-          test('expression using uncaptured variables', () async {
-            await driver.check(
-                scope: <String, String>{
-                  'x': '1',
-                  'c': 'null',
-                  'y': '3',
-                  'z': '0'
-                },
-                expression: "'\$x+\$y+\$z'",
-                expectedResult: '''
-            (function(x, c, y, z) {
-              const dart_sdk = ${options.loadModule}('dart_sdk');
-              const dart = dart_sdk.dart;
-              return dart.str(x) + "+" + dart.str(y) + "+" + dart.str(z);
-            }(
-              1,
-              null,
-              3,
-              0
-            ))
-            ''');
-          });
-
-          test('expression using captured variables', () async {
-            await driver.check(
-                scope: <String, String>{
-                  'x': '1',
-                  'c': 'null',
-                  'y': '3',
-                  'z': '0'
-                },
-                expression: "'\$y+\$z'",
-                expectedResult: '''
-            (function(x, c, y, z) {
-              const dart_sdk = ${options.loadModule}('dart_sdk');
-              const dart = dart_sdk.dart;
-              return dart.str(y) + "+" + dart.str(z);
-            }(
-              1,
-              null,
-              3,
-              0
-            ))
-            ''');
-          });
-        });
-
         group(
             'Expression compiler tests for interactions with module containers:',
             () {
@@ -679,74 +536,6 @@
           });
         });
 
-        group('Expression compiler tests in generic method:', () {
-          var source = '''
-          ${options.dartLangComment}
-          class A {
-            void generic<TType, KType>(TType a, KType b) {
-              /* evaluation placeholder */
-              print(a);
-              print(b);
-            }
-          }
-
-          void main() => generic<int, String>(0, 'hi');
-          ''';
-
-          TestDriver driver;
-          setUp(() {
-            driver = TestDriver(options, source);
-          });
-
-          tearDown(() {
-            driver.delete();
-          });
-
-          test('evaluate formals', () async {
-            await driver.check(
-                scope: <String, String>{
-                  'TType': 'TType',
-                  'KType': 'KType',
-                  'a': 'a',
-                  'b': 'b'
-                },
-                expression: 'a',
-                expectedResult: '''
-            (function(TType, KType, a, b) {
-                return a;
-            }.bind(this)(
-              TType,
-              KType,
-              a,
-              b
-            ))
-            ''');
-          });
-
-          test('evaluate type parameters', () async {
-            await driver.check(
-                scope: <String, String>{
-                  'TType': 'TType',
-                  'KType': 'KType',
-                  'a': 'a',
-                  'b': 'b'
-                },
-                expression: 'TType',
-                expectedResult: '''
-            (function(TType, KType, a, b) {
-              const dart_sdk = ${options.loadModule}('dart_sdk');
-              const dart = dart_sdk.dart;
-              return dart.wrapType(dart.legacy(TType));
-            }.bind(this)(
-              TType,
-              KType,
-              a,
-              b
-            ))
-            ''');
-          });
-        });
-
         group('Expression compiler tests using extension symbols', () {
           var source = '''
           ${options.dartLangComment}
@@ -878,218 +667,8 @@
           });
         });
 
-        group('Expression compiler extension symbols tests', () {
-          var source = '''
-          ${options.dartLangComment}
-    
-          main() {
-            List<int> list = {};
-            list.add(0);
-            /* evaluation placeholder */
-          }
-          ''';
-
-          TestDriver driver;
-
-          setUp(() {
-            driver = TestDriver(options, source);
-          });
-
-          tearDown(() {
-            driver.delete();
-          });
-
-          test('extension symbol used in original compilation', () async {
-            await driver.check(
-                scope: <String, String>{'list': 'list'},
-                expression: 'list.add(1)',
-                expectedResult: '''
-            (function(list) {
-              const dart_sdk = ${options.loadModule}('dart_sdk');
-              const dartx = dart_sdk.dartx;
-              var \$add = dartx.add;
-              var S = {\$add: dartx.add};
-              return list[\$add](1);
-            }(
-              list
-            ))
-            ''');
-          });
-
-          test('extension symbol used only in expression compilation',
-              () async {
-            await driver.check(
-                scope: <String, String>{'list': 'list'},
-                expression: 'list.first',
-                expectedResult: '''
-            (function(list) {
-              const dart_sdk = ${options.loadModule}('dart_sdk');
-              const dartx = dart_sdk.dartx;
-              var S = {\$first: dartx.first};
-              return list[S.\$first];
-            }(
-              list
-            ))
-            ''');
-          });
-        });
-
-        group('Expression compiler tests in closures:', () {
-          var source = '''
-          ${options.dartLangComment}
-          int globalFunction() {
-            int x = 15;
-            var c = C(1, 2);
-
-            var outerClosure = (int y) {
-              var closureCaptureInner = (int z) {
-                /* evaluation placeholder */
-                print('\$y+\$z');
-              };
-              closureCaptureInner(0);
-            };
-
-            outerClosure(3);
-            return 0;
-          }
-
-          main() => 0;
-          ''';
-
-          TestDriver driver;
-          setUp(() {
-            driver = TestDriver(options, source);
-          });
-
-          tearDown(() {
-            driver.delete();
-          });
-
-          test('compilation error', () async {
-            await driver.check(scope: <String, String>{
-              'x': '1',
-              'c': 'null',
-              'y': '3',
-              'z': '0'
-            }, expression: 'typo', expectedError: "Getter not found: 'typo'.");
-          });
-
-          test('expression using uncaptured variables', () async {
-            await driver.check(
-                scope: <String, String>{
-                  'x': '1',
-                  'c': 'null',
-                  'y': '3',
-                  'z': '0'
-                },
-                expression: "'\$x+\$y+\$z'",
-                expectedResult: '''
-            (function(x, c, y, z) {
-              const dart_sdk = ${options.loadModule}('dart_sdk');
-              const dart = dart_sdk.dart;
-              return dart.str(x) + "+" + dart.str(y) + "+" + dart.str(z);
-            }(
-              1,
-              null,
-              3,
-              0
-            ))
-            ''');
-          });
-
-          test('expression using captured variables', () async {
-            await driver.check(
-                scope: <String, String>{
-                  'x': '1',
-                  'c': 'null',
-                  'y': '3',
-                  'z': '0'
-                },
-                expression: "'\$y+\$z'",
-                expectedResult: '''
-            (function(x, c, y, z) {
-              const dart_sdk = ${options.loadModule}('dart_sdk');
-              const dart = dart_sdk.dart;
-              return dart.str(y) + "+" + dart.str(z);
-            }(
-              1,
-              null,
-              3,
-              0
-            ))
-            ''');
-          });
-        });
-
-        group('Expression compiler tests in generic method:', () {
-          var source = '''
-          ${options.dartLangComment}
-          class A {
-            void generic<TType, KType>(TType a, KType b) {
-              /* evaluation placeholder */
-              print(a);
-              print(b);
-            }
-          }
-
-          void main() => generic<int, String>(0, 'hi');
-          ''';
-
-          TestDriver driver;
-          setUp(() {
-            driver = TestDriver(options, source);
-          });
-
-          tearDown(() {
-            driver.delete();
-          });
-
-          test('evaluate formals', () async {
-            await driver.check(
-                scope: <String, String>{
-                  'TType': 'TType',
-                  'KType': 'KType',
-                  'a': 'a',
-                  'b': 'b'
-                },
-                expression: 'a',
-                expectedResult: '''
-            (function(TType, KType, a, b) {
-                return a;
-            }.bind(this)(
-              TType,
-              KType,
-              a,
-              b
-            ))
-            ''');
-          });
-
-          test('evaluate type parameters', () async {
-            await driver.check(
-                scope: <String, String>{
-                  'TType': 'TType',
-                  'KType': 'KType',
-                  'a': 'a',
-                  'b': 'b'
-                },
-                expression: 'TType',
-                expectedResult: '''
-            (function(TType, KType, a, b) {
-              const dart_sdk = ${options.loadModule}('dart_sdk');
-              const dart = dart_sdk.dart;
-              return dart.wrapType(TType);
-            }.bind(this)(
-              TType,
-              KType,
-              a,
-              b
-            ))
-            ''');
-          });
-        });
-
-        group('Expression compiler tests using extension symbols', () {
+        group('Expression compiler expressions that import extension symbols',
+            () {
           var source = '''
           ${options.dartLangComment}
           void bar() {
diff --git a/pkg/vm_service/CHANGELOG.md b/pkg/vm_service/CHANGELOG.md
index 2492753..5f0da4d 100644
--- a/pkg/vm_service/CHANGELOG.md
+++ b/pkg/vm_service/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Changelog
 
+## 6.3.0-dev
+- Add support for `setBreakpointState` RPC and updated `Breakpoint` class to include
+  `enabled` property.
+
 ## 6.2.0
 - Added support for `getHttpProfile` and `clearHttpProfile` `dart:io` service extensions.
 
diff --git a/pkg/vm_service/example/vm_service_assert.dart b/pkg/vm_service/example/vm_service_assert.dart
index 7122a12..c861f82 100644
--- a/pkg/vm_service/example/vm_service_assert.dart
+++ b/pkg/vm_service/example/vm_service_assert.dart
@@ -136,6 +136,7 @@
   if (obj == "BreakpointAdded") return obj;
   if (obj == "BreakpointRemoved") return obj;
   if (obj == "BreakpointResolved") return obj;
+  if (obj == "BreakpointUpdated") return obj;
   if (obj == "Extension") return obj;
   if (obj == "GC") return obj;
   if (obj == "Inspect") return obj;
@@ -293,6 +294,7 @@
   assertNotNull(obj);
   assertString(obj.id!);
   assertInt(obj.breakpointNumber!);
+  assertBool(obj.enabled!);
   assertBool(obj.resolved!);
   if (obj.location is vms.SourceLocation) {
     assertSourceLocation(obj.location!);
diff --git a/pkg/vm_service/java/.gitignore b/pkg/vm_service/java/.gitignore
index 7e45717..cdc39af 100644
--- a/pkg/vm_service/java/.gitignore
+++ b/pkg/vm_service/java/.gitignore
@@ -4,6 +4,7 @@
 src/org/dartlang/vm/service/consumer/AddBreakpointAtEntryConsumer.java
 src/org/dartlang/vm/service/consumer/AddBreakpointConsumer.java
 src/org/dartlang/vm/service/consumer/AddBreakpointWithScriptUriConsumer.java
+src/org/dartlang/vm/service/consumer/BreakpointConsumer.java
 src/org/dartlang/vm/service/consumer/ClearCpuSamplesConsumer.java
 src/org/dartlang/vm/service/consumer/CpuSamplesConsumer.java
 src/org/dartlang/vm/service/consumer/EvaluateConsumer.java
diff --git a/pkg/vm_service/java/version.properties b/pkg/vm_service/java/version.properties
index 452573e..d934516 100644
--- a/pkg/vm_service/java/version.properties
+++ b/pkg/vm_service/java/version.properties
@@ -1 +1 @@
-version=3.44
+version=3.45
diff --git a/pkg/vm_service/lib/src/vm_service.dart b/pkg/vm_service/lib/src/vm_service.dart
index 8b869fb..50fe029 100644
--- a/pkg/vm_service/lib/src/vm_service.dart
+++ b/pkg/vm_service/lib/src/vm_service.dart
@@ -26,7 +26,7 @@
         HeapSnapshotObjectNoData,
         HeapSnapshotObjectNullData;
 
-const String vmServiceVersion = '3.44.0';
+const String vmServiceVersion = '3.45.0';
 
 /// @optional
 const String optional = 'optional';
@@ -229,6 +229,7 @@
   'removeBreakpoint': const ['Success'],
   'requestHeapSnapshot': const ['Success'],
   'resume': const ['Success'],
+  'setBreakpointState': const ['Breakpoint'],
   'setExceptionPauseMode': const ['Success'],
   'setFlag': const ['Success', 'Error'],
   'setLibraryDebuggable': const ['Success'],
@@ -1008,6 +1009,18 @@
   Future<Success> resume(String isolateId,
       {/*StepOption*/ String? step, int? frameIndex});
 
+  /// The `setBreakpointState` RPC allows for breakpoints to be enabled or
+  /// disabled, without requiring for the breakpoint to be completely removed.
+  ///
+  /// If `isolateId` refers to an isolate which has exited, then the `Collected`
+  /// [Sentinel] is returned.
+  ///
+  /// The returned [Breakpoint] is the updated breakpoint with its new values.
+  ///
+  /// See [Breakpoint].
+  Future<Breakpoint> setBreakpointState(
+      String isolateId, String breakpointId, bool enable);
+
   /// The `setExceptionPauseMode` RPC is used to control if an isolate pauses
   /// when an exception is thrown.
   ///
@@ -1136,7 +1149,7 @@
   /// IsolateReload, ServiceExtensionAdded
   /// Debug | PauseStart, PauseExit, PauseBreakpoint, PauseInterrupted,
   /// PauseException, PausePostRequest, Resume, BreakpointAdded,
-  /// BreakpointResolved, BreakpointRemoved, Inspect, None
+  /// BreakpointResolved, BreakpointRemoved, BreakpointUpdated, Inspect, None
   /// GC | GC
   /// Extension | Extension
   /// Timeline | TimelineEvents, TimelineStreamsSubscriptionUpdate
@@ -1471,6 +1484,13 @@
             frameIndex: params['frameIndex'],
           );
           break;
+        case 'setBreakpointState':
+          response = await _serviceImplementation.setBreakpointState(
+            params!['isolateId'],
+            params['breakpointId'],
+            params['enable'],
+          );
+          break;
         case 'setExceptionPauseMode':
           response = await _serviceImplementation.setExceptionPauseMode(
             params!['isolateId'],
@@ -1667,7 +1687,7 @@
   // IsolateStart, IsolateRunnable, IsolateExit, IsolateUpdate, IsolateReload, ServiceExtensionAdded
   Stream<Event> get onIsolateEvent => _getEventController('Isolate').stream;
 
-  // PauseStart, PauseExit, PauseBreakpoint, PauseInterrupted, PauseException, PausePostRequest, Resume, BreakpointAdded, BreakpointResolved, BreakpointRemoved, Inspect, None
+  // PauseStart, PauseExit, PauseBreakpoint, PauseInterrupted, PauseException, PausePostRequest, Resume, BreakpointAdded, BreakpointResolved, BreakpointRemoved, BreakpointUpdated, Inspect, None
   Stream<Event> get onDebugEvent => _getEventController('Debug').stream;
 
   // GC
@@ -1982,6 +2002,15 @@
       });
 
   @override
+  Future<Breakpoint> setBreakpointState(
+          String isolateId, String breakpointId, bool enable) =>
+      _call('setBreakpointState', {
+        'isolateId': isolateId,
+        'breakpointId': breakpointId,
+        'enable': enable
+      });
+
+  @override
   Future<Success> setExceptionPauseMode(
           String isolateId, /*ExceptionPauseMode*/ String mode) =>
       _call('setExceptionPauseMode', {'isolateId': isolateId, 'mode': mode});
@@ -2430,6 +2459,9 @@
   /// A breakpoint has been removed.
   static const String kBreakpointRemoved = 'BreakpointRemoved';
 
+  /// A breakpoint has been updated.
+  static const String kBreakpointUpdated = 'BreakpointUpdated';
+
   /// A garbage collection event.
   static const String kGC = 'GC';
 
@@ -2810,6 +2842,9 @@
   /// A number identifying this breakpoint to the user.
   int? breakpointNumber;
 
+  /// Is this breakpoint enabled?
+  bool? enabled;
+
   /// Has this breakpoint been assigned to a specific program location?
   bool? resolved;
 
@@ -2826,6 +2861,7 @@
 
   Breakpoint({
     required this.breakpointNumber,
+    required this.enabled,
     required this.resolved,
     required this.location,
     required String id,
@@ -2836,6 +2872,7 @@
 
   Breakpoint._fromJson(Map<String, dynamic> json) : super._fromJson(json) {
     breakpointNumber = json['breakpointNumber'] ?? -1;
+    enabled = json['enabled'] ?? false;
     resolved = json['resolved'] ?? false;
     isSyntheticAsyncContinuation = json['isSyntheticAsyncContinuation'];
     location = createServiceObject(json['location']!,
@@ -2851,6 +2888,7 @@
     json['type'] = type;
     json.addAll({
       'breakpointNumber': breakpointNumber,
+      'enabled': enabled,
       'resolved': resolved,
       'location': location?.toJson(),
     });
@@ -2864,8 +2902,8 @@
   operator ==(other) => other is Breakpoint && id == other.id;
 
   String toString() => '[Breakpoint ' //
-      'id: ${id}, breakpointNumber: ${breakpointNumber}, resolved: ${resolved}, ' //
-      'location: ${location}]';
+      'id: ${id}, breakpointNumber: ${breakpointNumber}, enabled: ${enabled}, ' //
+      'resolved: ${resolved}, location: ${location}]';
 }
 
 /// `ClassRef` is a reference to a `Class`.
@@ -3685,6 +3723,7 @@
   ///  - BreakpointAdded
   ///  - BreakpointRemoved
   ///  - BreakpointResolved
+  ///  - BreakpointUpdated
   @optional
   Breakpoint? breakpoint;
 
diff --git a/pkg/vm_service/pubspec.yaml b/pkg/vm_service/pubspec.yaml
index 5ba220b..dfe2e30 100644
--- a/pkg/vm_service/pubspec.yaml
+++ b/pkg/vm_service/pubspec.yaml
@@ -3,7 +3,7 @@
   A library to communicate with a service implementing the Dart VM
   service protocol.
 
-version: 6.2.0
+version: 6.3.0-dev
 
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/vm_service
 
diff --git a/pkg/vm_service/test/set_breakpoint_state_test.dart b/pkg/vm_service/test/set_breakpoint_state_test.dart
new file mode 100644
index 0000000..7bc96ab
--- /dev/null
+++ b/pkg/vm_service/test/set_breakpoint_state_test.dart
@@ -0,0 +1,71 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--verbose_debug
+
+import 'package:vm_service/vm_service.dart';
+import 'package:test/test.dart';
+
+import 'common/service_test_common.dart';
+import 'common/test_helper.dart';
+
+const int LINE_A = 17;
+const int LINE_B = LINE_A + 1;
+
+testMain() {
+  while (true) {
+    print('a'); // LINE_A
+    print('b'); // LINE_B
+  }
+}
+
+late Breakpoint bpt;
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  (VmService service, IsolateRef isolateRef) async {
+    bpt = await service.addBreakpointWithScriptUri(
+      isolateRef.id!,
+      'set_breakpoint_state_test.dart',
+      LINE_A,
+    );
+    expect(bpt.enabled, true);
+  },
+  setBreakpointAtLine(LINE_B),
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  (VmService service, IsolateRef isolateRef) async {
+    bpt = await service.setBreakpointState(
+      isolateRef.id!,
+      bpt.id!,
+      false,
+    );
+    expect(bpt.enabled, false);
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  (VmService service, IsolateRef isolateRef) async {
+    bpt = await service.setBreakpointState(
+      isolateRef.id!,
+      bpt.id!,
+      true,
+    );
+    expect(bpt.enabled, true);
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+];
+
+main([args = const <String>[]]) => runIsolateTests(
+      args,
+      tests,
+      'set_breakpoint_state_test.dart',
+      pause_on_start: true,
+      testeeConcurrent: testMain,
+    );
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index 1516d15..e32c00f 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -2407,6 +2407,9 @@
   // Either SourceLocation or UnresolvedSourceLocation.
   Location? location;
 
+  // Is the breakpoint enabled?
+  bool? enabled;
+
   // The breakpoint is in a file which is not yet loaded.
   bool? latent;
 
@@ -2425,6 +2428,7 @@
     // number never changes.
     assert((number == null) || (number == newNumber));
     number = newNumber;
+    enabled = map['enabled'];
     resolved = map['resolved'];
 
     var oldLocation = location;
@@ -2448,6 +2452,15 @@
     assert(resolved! || location is UnresolvedSourceLocation);
   }
 
+  Future<void> setState(bool enable) {
+    return location!.script.isolate!.invokeRpcNoUpgrade('setBreakpointState', {
+      'breakpointId': 'breakpoints/$number',
+      'enable': enable,
+    }).then((Map result) {
+      _update(result, false);
+    });
+  }
+
   void remove() {
     location!.script._removeBreakpoint(this);
   }
diff --git a/runtime/observatory/tests/service/get_version_rpc_test.dart b/runtime/observatory/tests/service/get_version_rpc_test.dart
index b63155d..1fe66c5 100644
--- a/runtime/observatory/tests/service/get_version_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_version_rpc_test.dart
@@ -12,7 +12,7 @@
     final result = await vm.invokeRpcNoUpgrade('getVersion', {});
     expect(result['type'], 'Version');
     expect(result['major'], 3);
-    expect(result['minor'], 44);
+    expect(result['minor'], 45);
     expect(result['_privateMajor'], 0);
     expect(result['_privateMinor'], 0);
   },
diff --git a/runtime/observatory/tests/service/service_kernel.status b/runtime/observatory/tests/service/service_kernel.status
index 3ddf48d..291688c 100644
--- a/runtime/observatory/tests/service/service_kernel.status
+++ b/runtime/observatory/tests/service/service_kernel.status
@@ -175,6 +175,7 @@
 reload_sources_test: SkipByDesign #  Hot reload is disabled in AOT mode.
 rewind_optimized_out_test: SkipByDesign # Debugger is disabled in AOT mode.
 rewind_test: SkipByDesign # Debugger is disabled in AOT mode.
+set_breakpoint_state_test: SkipByDesign # Debugger is disabled in AOT mode.
 set_library_debuggable_test: SkipByDesign # Debugger is disabled in AOT mode.
 sigquit_starts_service_test: SkipByDesign # Spawns a secondary process using Platform.executable.
 simple_reload_test: SkipByDesign # Hot reload is disabled in AOT mode.
diff --git a/runtime/observatory/tests/service/set_breakpoint_state_test.dart b/runtime/observatory/tests/service/set_breakpoint_state_test.dart
new file mode 100644
index 0000000..fdcee6a
--- /dev/null
+++ b/runtime/observatory/tests/service/set_breakpoint_state_test.dart
@@ -0,0 +1,65 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--verbose_debug
+
+import 'package:observatory/service_io.dart';
+import 'package:test/test.dart';
+
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const int LINE_A = 17;
+const int LINE_B = LINE_A + 1;
+
+testMain() {
+  while (true) {
+    print('a'); // LINE_A
+    print('b'); // LINE_B
+  }
+}
+
+late Breakpoint bpt;
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  (Isolate isolate) async {
+    bpt = await isolate.addBreakpointByScriptUri(
+      'set_breakpoint_state_test.dart',
+      LINE_A,
+    );
+    expect(bpt.enabled, true);
+  },
+  setBreakpointAtLine(LINE_B),
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  (Isolate isolate) async {
+    await bpt.setState(
+      false,
+    );
+    expect(bpt.enabled, false);
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  (Isolate isolate) async {
+    await bpt.setState(
+      true,
+    );
+    expect(bpt.enabled, true);
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+];
+
+main([args = const <String>[]]) => runIsolateTests(
+      args,
+      tests,
+      pause_on_start: true,
+      testeeConcurrent: testMain,
+    );
diff --git a/runtime/observatory_2/lib/src/service/object.dart b/runtime/observatory_2/lib/src/service/object.dart
index 1c5c9bc..743ab24 100644
--- a/runtime/observatory_2/lib/src/service/object.dart
+++ b/runtime/observatory_2/lib/src/service/object.dart
@@ -2418,6 +2418,9 @@
   // Either SourceLocation or UnresolvedSourceLocation.
   Location location;
 
+  // Is the breakpoint enabled?
+  bool enabled;
+
   // The breakpoint is in a file which is not yet loaded.
   bool latent;
 
@@ -2436,6 +2439,7 @@
     // number never changes.
     assert((number == null) || (number == newNumber));
     number = newNumber;
+    enabled = map['enabled'];
     resolved = map['resolved'];
 
     var oldLocation = location;
@@ -2459,6 +2463,15 @@
     assert(resolved || location is UnresolvedSourceLocation);
   }
 
+  Future<void> setState(bool enable) {
+    return location.script.isolate.invokeRpcNoUpgrade('setBreakpointState', {
+      'breakpointId': 'breakpoints/$number',
+      'enable': enable,
+    }).then((Map result) {
+      _update(result, false);
+    });
+  }
+
   void remove() {
     location.script._removeBreakpoint(this);
   }
diff --git a/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart
index e7a9528..bd9d9b1 100644
--- a/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart
+++ b/runtime/observatory_2/tests/service_2/get_version_rpc_test.dart
@@ -12,7 +12,7 @@
     var result = await vm.invokeRpcNoUpgrade('getVersion', {});
     expect(result['type'], equals('Version'));
     expect(result['major'], equals(3));
-    expect(result['minor'], equals(44));
+    expect(result['minor'], equals(45));
     expect(result['_privateMajor'], equals(0));
     expect(result['_privateMinor'], equals(0));
   },
diff --git a/runtime/observatory_2/tests/service_2/service_2_kernel.status b/runtime/observatory_2/tests/service_2/service_2_kernel.status
index 099e686..717b43e 100644
--- a/runtime/observatory_2/tests/service_2/service_2_kernel.status
+++ b/runtime/observatory_2/tests/service_2/service_2_kernel.status
@@ -174,6 +174,7 @@
 reload_sources_test: SkipByDesign # Hot reload is disabled in AOT mode.
 rewind_optimized_out_test: SkipByDesign # Debugger is disabled in AOT mode.
 rewind_test: SkipByDesign # Debugger is disabled in AOT mode.
+set_breakpoint_state_test: SkipByDesign # Debugger is disabled in AOT mode.
 set_library_debuggable_test: SkipByDesign # Debugger is disabled in AOT mode.
 sigquit_starts_service_test: SkipByDesign # Spawns a secondary process using Platform.executable.
 simple_reload_test: SkipByDesign # Hot reload is disabled in AOT mode.
diff --git a/runtime/observatory_2/tests/service_2/set_breakpoint_state_test.dart b/runtime/observatory_2/tests/service_2/set_breakpoint_state_test.dart
new file mode 100644
index 0000000..78e0fcb
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/set_breakpoint_state_test.dart
@@ -0,0 +1,65 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--verbose_debug
+
+import 'package:observatory_2/service_io.dart';
+import 'package:test/test.dart';
+
+import 'service_test_common.dart';
+import 'test_helper.dart';
+
+const int LINE_A = 17;
+const int LINE_B = LINE_A + 1;
+
+testMain() {
+  while (true) {
+    print('a'); // LINE_A
+    print('b'); // LINE_B
+  }
+}
+
+Breakpoint bpt;
+
+var tests = <IsolateTest>[
+  hasPausedAtStart,
+  (Isolate isolate) async {
+    bpt = await isolate.addBreakpointByScriptUri(
+      'set_breakpoint_state_test.dart',
+      LINE_A,
+    );
+    expect(bpt.enabled, true);
+  },
+  setBreakpointAtLine(LINE_B),
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  (Isolate isolate) async {
+    await bpt.setState(
+      false,
+    );
+    expect(bpt.enabled, false);
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_B),
+  (Isolate isolate) async {
+    await bpt.setState(
+      true,
+    );
+    expect(bpt.enabled, true);
+  },
+  resumeIsolate,
+  hasStoppedAtBreakpoint,
+  stoppedAtLine(LINE_A),
+];
+
+main([args = const <String>[]]) => runIsolateTests(
+      args,
+      tests,
+      pause_on_start: true,
+      testeeConcurrent: testMain,
+    );
diff --git a/runtime/tests/vm/dart/gen_snapshot_include_resolved_urls_script.dart b/runtime/tests/vm/dart/gen_snapshot_include_resolved_urls_script.dart
new file mode 100644
index 0000000..630dd02
--- /dev/null
+++ b/runtime/tests/vm/dart/gen_snapshot_include_resolved_urls_script.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:developer';
+import 'dart:isolate' as I;
+
+import 'package:vm_service/vm_service.dart';
+import 'package:vm_service/vm_service_io.dart';
+
+int fib(int n) {
+  if (n <= 1) return n;
+  return fib(n - 1) + fib(n - 2);
+}
+
+Future<void> main() async {
+  // Do some work.
+  fib(20);
+
+  ServiceProtocolInfo serviceInfo = await Service.getInfo();
+  while (serviceInfo.serverUri == null) {
+    await Future.delayed(const Duration(milliseconds: 200));
+    serviceInfo = await Service.getInfo();
+  }
+  final isolateId = Service.getIsolateID(I.Isolate.current)!;
+  final uri = serviceInfo.serverUri!.replace(scheme: 'ws', pathSegments: [
+    ...serviceInfo.serverUri!.pathSegments.where((e) => e != ''),
+    'ws'
+  ]);
+  final service = await vmServiceConnectUri(uri.toString());
+  final timeExtent = Duration(minutes: 5).inMicroseconds;
+  final samples = await service.getCpuSamples(isolateId, 0, timeExtent);
+
+  // Cleanup VM service connection as it's no longer needed.
+  await service.dispose();
+
+  final functions = samples.functions!.where((f) => f.kind! == 'Dart').toList();
+  if (functions.isEmpty) {
+    print('FAILED: could not find a profiled Dart function');
+    return;
+  }
+
+  functions.retainWhere((f) => f.resolvedUrl!.isNotEmpty);
+  if (functions.isNotEmpty) {
+    print('SUCCESS');
+  } else {
+    print('FAILED');
+  }
+}
diff --git a/runtime/tests/vm/dart/gen_snapshot_include_resolved_urls_test.dart b/runtime/tests/vm/dart/gen_snapshot_include_resolved_urls_test.dart
new file mode 100644
index 0000000..9b6d74d
--- /dev/null
+++ b/runtime/tests/vm/dart/gen_snapshot_include_resolved_urls_test.dart
@@ -0,0 +1,118 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:async";
+import "dart:io";
+import "dart:convert";
+
+import 'package:expect/expect.dart';
+import 'package:path/path.dart' as path;
+import 'package:test/test.dart';
+
+main(List<String> args) async {
+  if (!Platform.executable.endsWith("dart_precompiled_runtime")) {
+    return; // Running in JIT: AOT binaries not available.
+  }
+
+  if (Platform.isAndroid) {
+    return; // SDK tree and gen_snapshot not available on the test device.
+  }
+
+  final buildDir = path.dirname(Platform.executable);
+  final sdkDir = path.dirname(path.dirname(buildDir));
+  final scriptUrl = path.join(
+    sdkDir,
+    'runtime',
+    'tests',
+    'vm',
+    'dart',
+    'gen_snapshot_include_resolved_urls_script.dart',
+  );
+
+  final platformDill = path.join(buildDir, 'vm_platform_strong.dill');
+  final genSnapshot = path.join(buildDir, 'gen_snapshot');
+  final aotRuntime = path.join(buildDir, 'dart_precompiled_runtime');
+
+  late Directory tempDir;
+  setUpAll(() async {
+    tempDir = Directory.systemTemp.createTempSync('aot-script-urls-test');
+    final scriptDill = path.join(tempDir.path, 'test.dill');
+
+    // Compile script to Kernel IR.
+    await run('pkg/vm/tool/gen_kernel', <String>[
+      '--aot',
+      '--packages=$sdkDir/.packages',
+      '--platform=$platformDill',
+      '-o',
+      scriptDill,
+      scriptUrl,
+    ]);
+  });
+
+  tearDownAll(() {
+    tempDir.deleteSync(recursive: true);
+  });
+
+  // Let the test runner handle timeouts.
+  test(
+    'Include resolved urls',
+    () async {
+      final scriptDill = path.join(tempDir.path, 'test.dill');
+
+      // Compile script to Kernel IR.
+      await run('pkg/vm/tool/gen_kernel', <String>[
+        '--aot',
+        '--packages=$sdkDir/.packages',
+        '--platform=$platformDill',
+        '-o',
+        scriptDill,
+        scriptUrl,
+      ]);
+
+      final elfFile = path.join(tempDir.path, 'aot.snapshot');
+      await run(genSnapshot, <String>[
+        '--snapshot-kind=app-aot-elf',
+        '--elf=$elfFile',
+        scriptDill,
+      ]);
+
+      // Ensure we can actually run the code.
+      expect(
+        await run(aotRuntime, <String>[
+          '--enable-vm-service=0',
+          '--profiler',
+          elfFile,
+        ]),
+        true,
+      );
+    },
+    timeout: Timeout.none,
+  );
+}
+
+Future<String> readFile(String file) {
+  return File(file).readAsString();
+}
+
+Future<bool> run(String executable, List<String> args) async {
+  print('Running $executable ${args.join(' ')}');
+
+  final result = await Process.run(executable, args);
+  final String stdout = result.stdout;
+  final String stderr = result.stderr;
+  if (stdout.isNotEmpty) {
+    print('stdout:');
+    print(stdout);
+  }
+  if (stderr.isNotEmpty) {
+    print('stderr:');
+    print(stderr);
+  }
+
+  if (result.exitCode != 0) {
+    print('Command failed with non-zero exit code (was ${result.exitCode})');
+    return false;
+  }
+  return result.stdout.contains('SUCCESS') && stderr.isEmpty;
+}
diff --git a/runtime/tests/vm/dart_2/gen_snapshot_include_resolved_urls_script.dart b/runtime/tests/vm/dart_2/gen_snapshot_include_resolved_urls_script.dart
new file mode 100644
index 0000000..d36bd7f
--- /dev/null
+++ b/runtime/tests/vm/dart_2/gen_snapshot_include_resolved_urls_script.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:developer';
+import 'dart:isolate' as I;
+
+import 'package:vm_service/vm_service.dart';
+import 'package:vm_service/vm_service_io.dart';
+
+int fib(int n) {
+  if (n <= 1) return n;
+  return fib(n - 1) + fib(n - 2);
+}
+
+Future<void> main() async {
+  // Do some work.
+  fib(20);
+
+  ServiceProtocolInfo serviceInfo = await Service.getInfo();
+  while (serviceInfo.serverUri == null) {
+    await Future.delayed(const Duration(milliseconds: 200));
+    serviceInfo = await Service.getInfo();
+  }
+  final isolateId = Service.getIsolateID(I.Isolate.current);
+  final uri = serviceInfo.serverUri.replace(scheme: 'ws', pathSegments: [
+    ...serviceInfo.serverUri.pathSegments.where((e) => e != ''),
+    'ws'
+  ]);
+  final service = await vmServiceConnectUri(uri.toString());
+  final timeExtent = Duration(minutes: 5).inMicroseconds;
+  final samples = await service.getCpuSamples(isolateId, 0, timeExtent);
+
+  // Cleanup VM service connection as it's no longer needed.
+  await service.dispose();
+
+  final functions = samples.functions.where((f) => f.kind == 'Dart').toList();
+  if (functions.isEmpty) {
+    print('FAILED: could not find a profiled Dart function');
+    return;
+  }
+
+  functions.retainWhere((f) => f.resolvedUrl.isNotEmpty);
+  if (functions.isNotEmpty) {
+    print('SUCCESS');
+  } else {
+    print('FAILED');
+  }
+}
diff --git a/runtime/tests/vm/dart_2/gen_snapshot_include_resolved_urls_test.dart b/runtime/tests/vm/dart_2/gen_snapshot_include_resolved_urls_test.dart
new file mode 100644
index 0000000..bea28ff
--- /dev/null
+++ b/runtime/tests/vm/dart_2/gen_snapshot_include_resolved_urls_test.dart
@@ -0,0 +1,118 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:async";
+import "dart:io";
+import "dart:convert";
+
+import 'package:expect/expect.dart';
+import 'package:path/path.dart' as path;
+import 'package:test/test.dart';
+
+main(List<String> args) async {
+  if (!Platform.executable.endsWith("dart_precompiled_runtime")) {
+    return; // Running in JIT: AOT binaries not available.
+  }
+
+  if (Platform.isAndroid) {
+    return; // SDK tree and gen_snapshot not available on the test device.
+  }
+
+  final buildDir = path.dirname(Platform.executable);
+  final sdkDir = path.dirname(path.dirname(buildDir));
+  final scriptUrl = path.join(
+    sdkDir,
+    'runtime',
+    'tests',
+    'vm',
+    'dart_2',
+    'gen_snapshot_include_resolved_urls_script.dart',
+  );
+
+  final platformDill = path.join(buildDir, 'vm_platform_strong.dill');
+  final genSnapshot = path.join(buildDir, 'gen_snapshot');
+  final aotRuntime = path.join(buildDir, 'dart_precompiled_runtime');
+
+  Directory tempDir;
+  setUpAll(() async {
+    tempDir = Directory.systemTemp.createTempSync('aot-script-urls-test');
+    final scriptDill = path.join(tempDir.path, 'test.dill');
+
+    // Compile script to Kernel IR.
+    await run('pkg/vm/tool/gen_kernel', <String>[
+      '--aot',
+      '--packages=$sdkDir/.packages',
+      '--platform=$platformDill',
+      '-o',
+      scriptDill,
+      scriptUrl,
+    ]);
+  });
+
+  tearDownAll(() {
+    tempDir.deleteSync(recursive: true);
+  });
+
+  // Let the test runner handle timeouts.
+  test(
+    'Include resolved urls',
+    () async {
+      final scriptDill = path.join(tempDir.path, 'test.dill');
+
+      // Compile script to Kernel IR.
+      await run('pkg/vm/tool/gen_kernel', <String>[
+        '--aot',
+        '--packages=$sdkDir/.packages',
+        '--platform=$platformDill',
+        '-o',
+        scriptDill,
+        scriptUrl,
+      ]);
+
+      final elfFile = path.join(tempDir.path, 'aot.snapshot');
+      await run(genSnapshot, <String>[
+        '--snapshot-kind=app-aot-elf',
+        '--elf=$elfFile',
+        scriptDill,
+      ]);
+
+      // Ensure we can actually run the code.
+      expect(
+        await run(aotRuntime, <String>[
+          '--enable-vm-service=0',
+          '--profiler',
+          elfFile,
+        ]),
+        true,
+      );
+    },
+    timeout: Timeout.none,
+  );
+}
+
+Future<String> readFile(String file) {
+  return File(file).readAsString();
+}
+
+Future<bool> run(String executable, List<String> args) async {
+  print('Running $executable ${args.join(' ')}');
+
+  final result = await Process.run(executable, args);
+  final String stdout = result.stdout;
+  final String stderr = result.stderr;
+  if (stdout.isNotEmpty) {
+    print('stdout:');
+    print(stdout);
+  }
+  if (stderr.isNotEmpty) {
+    print('stderr:');
+    print(stderr);
+  }
+
+  if (result.exitCode != 0) {
+    print('Command failed with non-zero exit code (was ${result.exitCode})');
+    return false;
+  }
+  return result.stdout.contains('SUCCESS') && stderr.isEmpty;
+}
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index a95d016..d4bfbe0 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -128,7 +128,9 @@
 cc/CoreSnapshotSize: SkipByDesign # Imports dart:mirrors
 cc/CreateMirrorSystem: SkipByDesign # Imports dart:mirrors
 cc/StandaloneSnapshotSize: SkipByDesign # Imports dart:mirrors
+dart/gen_snapshot_include_resolved_urls_test: SkipByDesign # Script URLs not included in product gen_snapshot
 dart/redirection_type_shuffling_test: SkipByDesign # Imports dart:mirrors
+dart_2/gen_snapshot_include_resolved_urls_test: SkipByDesign # Script URLs not included in product gen_snapshot
 dart_2/redirection_type_shuffling_test: SkipByDesign # Imports dart:mirrors
 
 [ $nnbd == legacy ]
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index 4eddc2e..8946b68 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -2538,7 +2538,9 @@
           program_info.set_libraries_cache(Array::null_array());
           program_info.set_classes_cache(Array::null_array());
         }
+#if defined(PRODUCT)
         script.set_resolved_url(String::null_string());
+#endif  // defined(PRODUCT)
         script.set_compile_time_constants(Array::null_array());
         script.set_line_starts(null_typed_data);
         script.set_debug_positions(Array::null_array());
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index 592a7e5..cfa5e5e 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -109,7 +109,14 @@
 }
 
 bool BreakpointLocation::AnyEnabled() const {
-  return breakpoints() != NULL;
+  Breakpoint* bpt = breakpoints();
+  while (bpt != nullptr) {
+    if (bpt->is_enabled()) {
+      return true;
+    }
+    bpt = bpt->next();
+  }
+  return false;
 }
 
 void BreakpointLocation::SetResolved(const Function& func,
@@ -175,6 +182,7 @@
   jsobj.AddProperty("type", "Breakpoint");
 
   jsobj.AddFixedServiceId("breakpoints/%" Pd "", id());
+  jsobj.AddProperty("enabled", enabled_);
   jsobj.AddProperty("breakpointNumber", id());
   if (is_synthetic_async()) {
     jsobj.AddProperty("isSyntheticAsyncContinuation", is_synthetic_async());
@@ -358,7 +366,7 @@
 void BreakpointLocation::AddBreakpoint(Breakpoint* bpt, Debugger* dbg) {
   bpt->set_next(breakpoints());
   set_breakpoints(bpt);
-
+  bpt->Enable();
   dbg->group_debugger()->SyncBreakpointLocation(this);
   dbg->SendBreakpointEvent(ServiceEvent::kBreakpointAdded, bpt);
 }
@@ -2945,7 +2953,6 @@
 // associated with the breakpoint location loc.
 void GroupDebugger::SyncBreakpointLocation(BreakpointLocation* loc) {
   bool any_enabled = loc->AnyEnabled();
-
   SafepointWriteRwLocker sl(Thread::Current(), code_breakpoints_lock());
   CodeBreakpoint* cbpt = code_breakpoints_;
   while (cbpt != NULL) {
@@ -4283,6 +4290,21 @@
   return Code::null();
 }
 
+bool Debugger::SetBreakpointState(Breakpoint* bpt, bool enable) {
+  SafepointWriteRwLocker sl(Thread::Current(),
+                            group_debugger()->breakpoint_locations_lock());
+  if (bpt->is_enabled() != enable) {
+    if (FLAG_verbose_debug) {
+      OS::PrintErr("Setting breakpoint %" Pd " to state: %s\n", bpt->id(),
+                   enable ? "enabled" : "disabled");
+    }
+    enable ? bpt->Enable() : bpt->Disable();
+    group_debugger()->SyncBreakpointLocation(bpt->bpt_location());
+    return true;
+  }
+  return false;
+}
+
 // Remove and delete the source breakpoint bpt and its associated
 // code breakpoints.
 void Debugger::RemoveBreakpoint(intptr_t bp_id) {
diff --git a/runtime/vm/debugger.h b/runtime/vm/debugger.h
index bd2d0de..b9d99de 100644
--- a/runtime/vm/debugger.h
+++ b/runtime/vm/debugger.h
@@ -81,6 +81,18 @@
     closure_ = closure.ptr();
   }
 
+  void Enable() {
+    ASSERT(!enabled_);
+    enabled_ = true;
+  }
+
+  void Disable() {
+    ASSERT(enabled_);
+    enabled_ = false;
+  }
+
+  bool is_enabled() const { return enabled_; }
+
   // Mark that this breakpoint is a result of a step OverAwait request.
   void set_is_synthetic_async(bool is_synthetic_async) {
     is_synthetic_async_ = is_synthetic_async;
@@ -105,6 +117,7 @@
   InstancePtr closure_;
   BreakpointLocation* bpt_location_;
   bool is_synthetic_async_;
+  bool enabled_ = false;
 
   friend class BreakpointLocation;
   DISALLOW_COPY_AND_ASSIGN(Breakpoint);
@@ -713,6 +726,9 @@
                                                   intptr_t line_number,
                                                   intptr_t column_number);
 
+  // Returns true if the breakpoint's state changed.
+  bool SetBreakpointState(Breakpoint* bpt, bool enable);
+
   void RemoveBreakpoint(intptr_t bp_id);
   Breakpoint* GetBreakpointById(intptr_t id);
 
diff --git a/runtime/vm/debugger_api_impl_test.cc b/runtime/vm/debugger_api_impl_test.cc
index 965764b..51ba8bd 100644
--- a/runtime/vm/debugger_api_impl_test.cc
+++ b/runtime/vm/debugger_api_impl_test.cc
@@ -149,7 +149,7 @@
     UNWRAP_AND_CHECK_PARAM(String, script_url, script_url_in);
 
     Debugger* debugger = I->debugger();
-    bpt = debugger->SetBreakpointAtLine(script_url, line_number);
+    bpt = debugger->SetBreakpointAtLineCol(script_url, line_number, -1);
     if (bpt == NULL) {
       return Api::NewError("%s: could not set breakpoint at line %" Pd
                            " in '%s'",
diff --git a/runtime/vm/deferred_objects.cc b/runtime/vm/deferred_objects.cc
index 4b21ce5..27edd7a 100644
--- a/runtime/vm/deferred_objects.cc
+++ b/runtime/vm/deferred_objects.cc
@@ -398,12 +398,11 @@
               // it is already converted to 32-bit float via DoubleToFloat
               // instruction before it was stored.
               // Reinterpret double value as float to get the value back.
-              union {
-                double d;
-                float f;
-              } v;
-              v.d = Double::Cast(value).value();
-              typed_data.SetFloat32(element_offset, v.f);
+              typed_data.SetFloat32(
+                  element_offset,
+                  bit_cast<float, uint32_t>(
+                      static_cast<uint32_t>(bit_cast<uint64_t, double>(
+                          Double::Cast(value).value()))));
               break;
             case kTypedDataFloat64ArrayCid:
               typed_data.SetFloat64(element_offset,
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index b24f93e..bbec4f1 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -1439,7 +1439,11 @@
   CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) {
     switch (kind) {
       case Snapshot::kFullAOT:
+#if defined(PRODUCT)
         return reinterpret_cast<CompressedObjectPtr*>(&url_);
+#else
+        return reinterpret_cast<CompressedObjectPtr*>(&resolved_url_);
+#endif
       case Snapshot::kFull:
       case Snapshot::kFullCore:
       case Snapshot::kFullJIT:
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index ee7a7ec..4c5578f 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -4805,6 +4805,36 @@
   return true;
 }
 
+static const MethodParameter* set_breakpoint_state_params[] = {
+    ISOLATE_PARAMETER,
+    new IdParameter("breakpointId", true),
+    new BoolParameter("enable", true),
+    nullptr,
+};
+
+static bool SetBreakpointState(Thread* thread, JSONStream* js) {
+  Isolate* isolate = thread->isolate();
+  const char* bpt_id = js->LookupParam("breakpointId");
+  bool enable = BoolParameter::Parse(js->LookupParam("enable"), true);
+  ObjectIdRing::LookupResult lookup_result;
+  Breakpoint* bpt = LookupBreakpoint(isolate, bpt_id, &lookup_result);
+  // TODO(bkonyi): Should we return a different error for bpts which
+  // have been already removed?
+  if (bpt == nullptr) {
+    PrintInvalidParamError(js, "breakpointId");
+    return true;
+  }
+  if (isolate->debugger()->SetBreakpointState(bpt, enable)) {
+    if (Service::debug_stream.enabled()) {
+      ServiceEvent event(isolate, ServiceEvent::kBreakpointUpdated);
+      event.set_breakpoint(bpt);
+      Service::HandleEvent(&event);
+    }
+  }
+  bpt->PrintJSON(js);
+  return true;
+}
+
 static const MethodParameter* get_flag_list_params[] = {
     NO_ISOLATE_PARAMETER,
     NULL,
@@ -5188,6 +5218,8 @@
     request_heap_snapshot_params },
   { "_evaluateCompiledExpression", EvaluateCompiledExpression,
     evaluate_compiled_expression_params },
+  { "setBreakpointState", SetBreakpointState,
+    set_breakpoint_state_params },
   { "setExceptionPauseMode", SetExceptionPauseMode,
     set_exception_pause_mode_params },
   { "setFlag", SetFlag,
diff --git a/runtime/vm/service.h b/runtime/vm/service.h
index 032fafd..0b94d3d 100644
--- a/runtime/vm/service.h
+++ b/runtime/vm/service.h
@@ -15,7 +15,7 @@
 namespace dart {
 
 #define SERVICE_PROTOCOL_MAJOR_VERSION 3
-#define SERVICE_PROTOCOL_MINOR_VERSION 44
+#define SERVICE_PROTOCOL_MINOR_VERSION 45
 
 class Array;
 class EmbedderServiceHandler;
diff --git a/runtime/vm/service/service.md b/runtime/vm/service/service.md
index e78af3e..99bdab7 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -1,8 +1,8 @@
-# Dart VM Service Protocol 3.44
+# Dart VM Service Protocol 3.45
 
 > Please post feedback to the [observatory-discuss group][discuss-list]
 
-This document describes of _version 3.44_ of the Dart VM Service Protocol. This
+This document describes of _version 3.45_ of the Dart VM Service Protocol. This
 protocol is used to communicate with a running Dart Virtual Machine.
 
 To use the Service Protocol, start the VM with the *--observe* flag.
@@ -67,6 +67,7 @@
   - [reloadSources](#reloadsources)
   - [removeBreakpoint](#removebreakpoint)
   - [resume](#resume)
+  - [setBreakpointState](#setbreakpointstate)
   - [setExceptionPauseMode](#setexceptionpausemode)
   - [setFlag](#setflag)
   - [setLibraryDebuggable](#setlibrarydebuggable)
@@ -1305,6 +1306,24 @@
 
 See [Success](#success), [StepOption](#StepOption).
 
+### setBreakpointState
+
+```
+Breakpoint setBreakpointState(string isolateId,
+                              string breakpointId,
+                              bool enable)
+```
+
+The _setBreakpointState_ RPC allows for breakpoints to be enabled or disabled,
+without requiring for the breakpoint to be completely removed.
+
+If _isolateId_ refers to an isolate which has exited, then the
+_Collected_ [Sentinel](#sentinel) is returned.
+
+The returned [Breakpoint](#breakpoint) is the updated breakpoint with its new
+values.
+
+See [Breakpoint](#breakpoint).
 ### setExceptionPauseMode
 
 ```
@@ -1457,7 +1476,7 @@
 -------- | -----------
 VM | VMUpdate, VMFlagUpdate
 Isolate | IsolateStart, IsolateRunnable, IsolateExit, IsolateUpdate, IsolateReload, ServiceExtensionAdded
-Debug | PauseStart, PauseExit, PauseBreakpoint, PauseInterrupted, PauseException, PausePostRequest, Resume, BreakpointAdded, BreakpointResolved, BreakpointRemoved, Inspect, None
+Debug | PauseStart, PauseExit, PauseBreakpoint, PauseInterrupted, PauseException, PausePostRequest, Resume, BreakpointAdded, BreakpointResolved, BreakpointRemoved, BreakpointUpdated, Inspect, None
 GC | GC
 Extension | Extension
 Timeline | TimelineEvents, TimelineStreamsSubscriptionUpdate
@@ -1639,6 +1658,9 @@
   // A number identifying this breakpoint to the user.
   int breakpointNumber;
 
+  // Is this breakpoint enabled?
+  bool enabled;
+
   // Has this breakpoint been assigned to a specific program location?
   bool resolved;
 
@@ -2002,6 +2024,7 @@
   //   BreakpointAdded
   //   BreakpointRemoved
   //   BreakpointResolved
+  //   BreakpointUpdated
   Breakpoint breakpoint [optional];
 
   // The list of breakpoints at which we are currently paused
@@ -2199,6 +2222,9 @@
   // A breakpoint has been removed.
   BreakpointRemoved,
 
+  // A breakpoint has been updated.
+  BreakpointUpdated,
+
   // A garbage collection event.
   GC,
 
@@ -4011,5 +4037,6 @@
 3.42 | Added `limit` optional parameter to `getStack` RPC.
 3.43 | Updated heap snapshot format to include identity hash codes. Added `getAllocationTraces` and `setTraceClassAllocation` RPCs, updated `CpuSample` to include `identityHashCode` and `classId` properties, updated `Class` to include `traceAllocations` property.
 3.44 | Added `identityHashCode` property to `@Instance` and `Instance`.
+3.45 | Added `setBreakpointState` RPC and `BreakpointUpdated` event kind.
 
 [discuss-list]: https://groups.google.com/a/dartlang.org/forum/#!forum/observatory-discuss
diff --git a/runtime/vm/service_event.cc b/runtime/vm/service_event.cc
index aed7093..6b97b6d 100644
--- a/runtime/vm/service_event.cc
+++ b/runtime/vm/service_event.cc
@@ -117,6 +117,8 @@
       return "BreakpointResolved";
     case kBreakpointRemoved:
       return "BreakpointRemoved";
+    case kBreakpointUpdated:
+      return "BreakpointUpdated";
     case kGC:
       return "GC";  // TODO(koda): Change to GarbageCollected.
     case kInspect:
@@ -166,6 +168,7 @@
     case kBreakpointAdded:
     case kBreakpointResolved:
     case kBreakpointRemoved:
+    case kBreakpointUpdated:
     case kInspect:
     case kDebuggerSettingsUpdate:
       return &Service::debug_stream;
diff --git a/runtime/vm/service_event.h b/runtime/vm/service_event.h
index 08979ac..80aaa8a 100644
--- a/runtime/vm/service_event.h
+++ b/runtime/vm/service_event.h
@@ -44,6 +44,7 @@
     kBreakpointAdded,
     kBreakpointResolved,
     kBreakpointRemoved,
+    kBreakpointUpdated,
     kInspect,
     kDebuggerSettingsUpdate,
 
@@ -128,7 +129,8 @@
   Breakpoint* breakpoint() const { return breakpoint_; }
   void set_breakpoint(Breakpoint* bpt) {
     ASSERT(kind() == kPauseBreakpoint || kind() == kBreakpointAdded ||
-           kind() == kBreakpointResolved || kind() == kBreakpointRemoved);
+           kind() == kBreakpointResolved || kind() == kBreakpointRemoved ||
+           kind() == kBreakpointUpdated);
     breakpoint_ = bpt;
   }
 
diff --git a/tests/language/nonfunction_type_aliases/private_names/private_name_cast_test.dart b/tests/language/nonfunction_type_aliases/private_names/private_name_cast_test.dart
new file mode 100644
index 0000000..414c5af
--- /dev/null
+++ b/tests/language/nonfunction_type_aliases/private_names/private_name_cast_test.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=nonfunction-type-aliases
+
+// Test that private names exported via public typedefs can be used for casts
+
+import "package:expect/expect.dart";
+
+import "private_name_library.dart";
+
+class Derived1 extends PublicClass {}
+
+class Derived2 implements PublicClass {
+  noSuchMethod(_) {}
+}
+
+void test1() {
+  // Test casts from a derived subclass.
+  var d1 = Derived1();
+  Expect.equals(d1, d1 as Derived1);
+  Expect.equals(d1, d1 as PublicClass);
+  Expect.equals(d1, d1 as AlsoPublicClass);
+  Expect.throws(() => d1 as Derived2);
+
+  // Test casts from a derived implementation
+  var d2 = Derived2();
+  Expect.throws(() => d2 as Derived1);
+  Expect.equals(d2, d2 as PublicClass);
+  Expect.equals(d2, d2 as AlsoPublicClass);
+  Expect.equals(d2, d2 as Derived2);
+
+  // Test casts from the exported private subclass.
+  var p = PublicClass();
+  Expect.throws(() => p as Derived1);
+  Expect.equals(p, p as PublicClass);
+  Expect.equals(p, p as AlsoPublicClass);
+  Expect.throws(() => p as Derived2);
+}
+
+void main() {
+  test1();
+}
diff --git a/tests/language/nonfunction_type_aliases/private_names/private_name_creation_test.dart b/tests/language/nonfunction_type_aliases/private_names/private_name_creation_test.dart
new file mode 100644
index 0000000..b43d9b7
--- /dev/null
+++ b/tests/language/nonfunction_type_aliases/private_names/private_name_creation_test.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=nonfunction-type-aliases
+
+// Test that private names exported via public typedefs allow creation.
+
+import "package:expect/expect.dart";
+
+import "private_name_library.dart";
+
+void test1() {
+  // Test that a private class can be created via an exported public name using
+  // an unnamed constructor.
+  var p = PublicClass();
+  Expect.equals(privateLibrarySentinel, p.x);
+  Expect.equals(privateLibrarySentinel, p.instanceMethod());
+  Expect.equals(privateLibrarySentinel, callPrivateInstanceMethod(p));
+}
+
+void test2() {
+  // Test that a private class can be created via an exported public name using
+  // a named constructor.
+  var p = AlsoPublicClass.named(1);
+  Expect.equals(1, p.x);
+  Expect.equals(privateLibrarySentinel, p.instanceMethod());
+  Expect.equals(privateLibrarySentinel, callPrivateInstanceMethod(p));
+}
+
+void test3() {
+  // Test that a private class can be created as const via an exported public
+  // name.
+  const c1 = PublicClass();
+  const c2 = AlsoPublicClass();
+  Expect.identical(c1, c2);
+}
+
+void main() {
+  test1();
+  test2();
+  test3();
+}
diff --git a/tests/language/nonfunction_type_aliases/private_names/private_name_duplicate_interface_error_test.dart b/tests/language/nonfunction_type_aliases/private_names/private_name_duplicate_interface_error_test.dart
new file mode 100644
index 0000000..7d482d0
--- /dev/null
+++ b/tests/language/nonfunction_type_aliases/private_names/private_name_duplicate_interface_error_test.dart
@@ -0,0 +1,66 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=nonfunction-type-aliases
+
+// Test that private names exported via public typedefs may not appear multiple
+// times in a super-interface graph.
+
+import "private_name_library.dart";
+
+/// Test that having a private class in the implements and extends class via two
+/// different public names is an error.
+class A0 extends PublicClass implements AlsoPublicClass {
+//    ^
+// [cfe] '_PrivateClass' can't be used in both 'extends' and 'implements' clauses.
+//                                      ^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.IMPLEMENTS_SUPER_CLASS
+}
+
+/// Test that having a private class in the implements class twice via the same
+/// public name is an error.
+class A1 implements PublicClass, PublicClass {
+//                               ^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.IMPLEMENTS_REPEATED
+// [cfe] unspecified
+  noSuchMethod(_) => null;
+}
+
+/// Test that having a private class in the implements class twice via two
+/// different public names is an error.
+class A2 implements PublicClass, AlsoPublicClass {
+//                               ^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.IMPLEMENTS_REPEATED
+// [cfe] unspecified
+  noSuchMethod(_) => null;
+}
+
+/// Helper class for the following test
+class A3 extends PublicGenericClassOfInt {}
+
+/// Test that having a private generic class in the super-interface graph
+/// twice with two different generic instantiations is an error.
+class A4 extends A3 implements PublicGenericClass<String> {
+// [error line 42, column 1, length 411]
+// [analyzer] COMPILE_TIME_ERROR.CONFLICTING_GENERIC_INTERFACES
+//    ^
+// [cfe] 'A4' can't implement both '_PrivateGenericClass<int>' and '_PrivateGenericClass<String>'
+}
+
+/// Test that having a private generic class in the super-interface graph
+/// twice at the same instantiation is not an error.
+class A5 extends A3 implements PublicGenericClass<int> {}
+
+/// Test that having a private generic class in the implements clause twice with
+/// two different generic instantiations is an error.
+class A6 implements PublicGenericClass<int>, PublicGenericClass<String> {
+// [error line 55, column 1, length 546]
+// [analyzer] COMPILE_TIME_ERROR.CONFLICTING_GENERIC_INTERFACES
+//    ^
+// [cfe] 'A6' can't implement both '_PrivateGenericClass<int>' and '_PrivateGenericClass<String>'
+//                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.IMPLEMENTS_REPEATED
+}
+
+void main() {}
diff --git a/tests/language/nonfunction_type_aliases/private_names/private_name_extension_test.dart b/tests/language/nonfunction_type_aliases/private_names/private_name_extension_test.dart
index ece07c3..5c48f2a 100644
--- a/tests/language/nonfunction_type_aliases/private_names/private_name_extension_test.dart
+++ b/tests/language/nonfunction_type_aliases/private_names/private_name_extension_test.dart
@@ -10,36 +10,83 @@
 
 import "private_name_library.dart";
 
+/// Extend a private class via a public typedef without overriding any methods.
 class Derived extends PublicClass {
-  Derived() : super(0);
+  // Check that super constructor calls work.
+  Derived() : super();
 }
 
+/// Extend a private class via a public typedef overriding methods and
+/// properties.  The final field `x` is overriden with a getter which returns
+/// different values every time it is called.
 class AlsoDerived extends AlsoPublicClass {
-  AlsoDerived() : super.named(0);
-  int instanceMethod() => 0;
-  int _privateInstanceMethod() => 0;
+  int backingStore = publicLibrarySentinel;
+  int get x => backingStore++;
+  int get y => super.x;
+  // Check that named super constructors work.  Use the private sentinel value
+  // to allow us to distinguish reads of `x` from `super.x`.
+  AlsoDerived() : super.named(privateLibrarySentinel);
+  // Override the instanceMethod to return a distinguishing value.
+  int instanceMethod() => publicLibrarySentinel;
+  // Add a non-overriding private method with the same textual name as a private
+  // name in the super class which returns a distinguishing value.
+  int _privateInstanceMethod() => publicLibrarySentinel;
 }
 
 /// Test that inherited methods work correctly.
 void test1() {
-  {
-    PublicClass p = Derived();
-    Expect.equals(3, p.instanceMethod());
-    Expect.throwsNoSuchMethodError(() => (p as dynamic)._privateInstanceMethod());
-  }
+  PublicClass p = Derived();
+  Expect.equals(privateLibrarySentinel, p.instanceMethod());
+  // Calling the inherited private method from the private library should work.
+  Expect.equals(privateLibrarySentinel, callPrivateInstanceMethod(p));
+  Expect.equals(privateLibrarySentinel, callInstanceMethod(p));
+  // Calling the inherited private method from this library should throw.
+  Expect.throwsNoSuchMethodError(() => (p as dynamic)._privateInstanceMethod());
 }
 
-/// Test that inherited methods work correctly.
+/// Test that overriden methods work correctly.
 void test2() {
-  {
-    var p = AlsoDerived();
-    Expect.equals(0, p.instanceMethod());
-    Expect.equals(0, p._privateInstanceMethod());
-    Expect.equals(0, (p as dynamic)._privateInstanceMethod());
-  }
+  var p = AlsoDerived();
+  Expect.equals(publicLibrarySentinel, p.instanceMethod());
+  // Calling the overriden private method from this library should work.
+  Expect.equals(publicLibrarySentinel, p._privateInstanceMethod());
+  // Calling the inherited private method from the private library should work.
+  Expect.equals(privateLibrarySentinel, callPrivateInstanceMethod(p));
+  // Calling the overriden private method dynamically from this library should
+  // work.
+  Expect.equals(publicLibrarySentinel, (p as dynamic)._privateInstanceMethod());
+}
+
+/// Test that inherited properties work correctly
+void test3() {
+  var p = Derived();
+  // Reading the virtual field should give the private value
+  Expect.equals(privateLibrarySentinel, p.x);
+  // Reading the virtual field from the private library should give the private
+  // value
+  Expect.equals(privateLibrarySentinel, readInstanceField(p));
+}
+
+/// Test that overriden properties work correctly.
+void test4() {
+  var p = AlsoDerived();
+  // Reading the original virtual field should give the private value.
+  Expect.equals(privateLibrarySentinel, p.y);
+  // Reading the overriding getter from this library should give the public
+  // value and increment it each time it is called.
+  Expect.equals(publicLibrarySentinel, readInstanceField(p));
+  // Reading the overriding getter from the original library should give the
+  // public value and increment it each time it is called.
+  Expect.equals(publicLibrarySentinel + 1, p.x);
+
+  Expect.equals(privateLibrarySentinel, p.y);
+  Expect.equals(publicLibrarySentinel + 2, readInstanceField(p));
+  Expect.equals(publicLibrarySentinel + 3, p.x);
 }
 
 void main() {
   test1();
   test2();
+  test3();
+  test4();
 }
diff --git a/tests/language/nonfunction_type_aliases/private_names/private_name_implementation_test.dart b/tests/language/nonfunction_type_aliases/private_names/private_name_implementation_test.dart
new file mode 100644
index 0000000..eafc545
--- /dev/null
+++ b/tests/language/nonfunction_type_aliases/private_names/private_name_implementation_test.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=nonfunction-type-aliases
+
+// Test that private names exported via public typedefs allow implementation
+
+import "package:expect/expect.dart";
+
+import "private_name_library.dart";
+
+class Derived implements PublicClass {
+  int x;
+  Derived(this.x);
+  int instanceMethod() => publicLibrarySentinel;
+  int _privateInstanceMethod() => publicLibrarySentinel;
+}
+
+void test1() {
+  PublicClass _ = Derived(publicLibrarySentinel);
+  var p = Derived(publicLibrarySentinel);
+  Expect.equals(publicLibrarySentinel, p.instanceMethod());
+  // Calling the private instance method from this library should succeed.
+  Expect.equals(publicLibrarySentinel, p._privateInstanceMethod());
+  // Calling the private instance method from the other library should fail.
+  Expect.throwsNoSuchMethodError(() => callPrivateInstanceMethod(p));
+}
+
+void main() {
+  test1();
+}
diff --git a/tests/language/nonfunction_type_aliases/private_names/private_name_instance_checks_test.dart b/tests/language/nonfunction_type_aliases/private_names/private_name_instance_checks_test.dart
new file mode 100644
index 0000000..4496a7a
--- /dev/null
+++ b/tests/language/nonfunction_type_aliases/private_names/private_name_instance_checks_test.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=nonfunction-type-aliases
+
+// Test that private names exported via public typedefs can be used for instance
+// checks
+
+import "package:expect/expect.dart";
+
+import "private_name_library.dart";
+
+class Derived1 extends PublicClass {}
+
+class Derived2 implements PublicClass {
+  // Dummy implementation for the class using noSuchMethod.
+  noSuchMethod(_) {}
+}
+
+void test1() {
+  var d1 = Derived1();
+  Expect.isTrue(d1 is Derived1);
+  Expect.isTrue(d1 is PublicClass);
+  Expect.isTrue(d1 is AlsoPublicClass);
+  Expect.isFalse(d1 is Derived2);
+
+  var d2 = Derived2();
+  Expect.isFalse(d2 is Derived1);
+  Expect.isTrue(d2 is PublicClass);
+  Expect.isTrue(d2 is AlsoPublicClass);
+  Expect.isTrue(d2 is Derived2);
+
+  var p = PublicClass();
+  Expect.isFalse(p is Derived1);
+  Expect.isTrue(p is PublicClass);
+  Expect.isTrue(p is AlsoPublicClass);
+  Expect.isFalse(p is Derived2);
+}
+
+void main() {
+  test1();
+}
diff --git a/tests/language/nonfunction_type_aliases/private_names/private_name_library.dart b/tests/language/nonfunction_type_aliases/private_names/private_name_library.dart
index 07e441c..9f34b2f 100644
--- a/tests/language/nonfunction_type_aliases/private_names/private_name_library.dart
+++ b/tests/language/nonfunction_type_aliases/private_names/private_name_library.dart
@@ -7,26 +7,74 @@
 
 library private;
 
+// Sentinel values for checking that the correct methods are called.  Methods
+// defined in this library return the private sentinel, and (potentially
+// overriding) methods defined in other libraries return the public sentinel.
+// By checking the return value of methods against the respective sentinels,
+// test expectations can establish whether the correct method has been called.
+const int privateLibrarySentinel = -1;
+const int publicLibrarySentinel = privateLibrarySentinel + 1;
+
+// A private class that will be exported via a public typedef.
 class _PrivateClass {
-  int x;
-  _PrivateClass(this.x);
+  final int x;
+  const _PrivateClass() : x = privateLibrarySentinel;
   _PrivateClass.named(this.x);
-  static int staticMethod() => 3;
-  static int _privateStaticMethod() => 3;
-  int instanceMethod() => 3;
-  int _privateInstanceMethod() => 3;
+  static int staticMethod() => privateLibrarySentinel;
+  static int _privateStaticMethod() => privateLibrarySentinel;
+  int instanceMethod() => privateLibrarySentinel;
+  int _privateInstanceMethod() => privateLibrarySentinel;
 }
 
+// Export the private class publicly, along with a factory.
 typedef PublicClass = _PrivateClass;
-PublicClass mkPublicClass() => PublicClass(0);
+PublicClass mkPublicClass() => PublicClass();
 
+// Export the private class publicly via an indirection through another private
+// typedef, along with a factory.
 typedef _PrivateTypeDef = _PrivateClass;
 typedef AlsoPublicClass = _PrivateTypeDef;
-AlsoPublicClass mkAlsoPublicClass() => AlsoPublicClass(0);
+AlsoPublicClass mkAlsoPublicClass() => AlsoPublicClass();
 
+// A private generic class which will be exported through a public typedef.
 class _PrivateGenericClass<T> {
-  static int staticMethod() => 3;
+  static int staticMethod() => privateLibrarySentinel;
 }
+
+// Export the private generic class publicly, along with a factory and a
+// specific instantiation.
 typedef PublicGenericClass<T> = _PrivateGenericClass<T>;
 PublicGenericClass<T> mkPublicGenericClass<T>() => PublicGenericClass();
 typedef PublicGenericClassOfInt = _PrivateGenericClass<int>;
+
+// Helper methods to do virtual calls on instances of _PrivateClass in this
+// library context.
+int callPrivateInstanceMethod(_PrivateClass other) => other._privateInstanceMethod();
+int callInstanceMethod(_PrivateClass other) => other.instanceMethod();
+int readInstanceField(_PrivateClass other) => other.x;
+
+// A private mixin to be exported via a typedef.
+mixin _PrivateMixin {
+  int mixinMethod() => privateLibrarySentinel;
+  int _privateMixinMethod() => privateLibrarySentinel;
+}
+
+// Helper method to call a private method on the mixin in this library context.
+int callPrivateMixinMethod(_PrivateMixin other) => other._privateMixinMethod();
+
+// Export the private mixin
+typedef PublicMixin = _PrivateMixin;
+
+// A private super-mixin which is intended to be mixed onto PublicClass
+// and which makes super calls into it.
+mixin _PrivateSuperMixin on PublicClass {
+  int mixinMethod() => super.instanceMethod();
+  int _privateMixinMethod() => super._privateInstanceMethod();
+}
+
+// Call the private SuperMixinMethod
+int callPrivateSuperMixinMethod(_PrivateSuperMixin other) =>
+other._privateMixinMethod();
+
+// Export the private super-mixin.
+typedef PublicSuperMixin = _PrivateSuperMixin;
diff --git a/tests/language/nonfunction_type_aliases/private_names/private_name_mixin_error_test.dart b/tests/language/nonfunction_type_aliases/private_names/private_name_mixin_error_test.dart
new file mode 100644
index 0000000..87642bc
--- /dev/null
+++ b/tests/language/nonfunction_type_aliases/private_names/private_name_mixin_error_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=nonfunction-type-aliases
+
+// Test that a private mixin exported via a typedef cannot be used as a class.
+
+import "private_name_library.dart";
+
+/// Class that attempts to use a private mixin as a class via a public typedef
+/// name.
+class A0 extends PublicMixin {}
+//    ^
+// [cfe] The superclass, '_PrivateMixin', has no unnamed constructor that takes no arguments.
+//               ^^^^^^^^^^^
+// [analyzer] COMPILE_TIME_ERROR.EXTENDS_NON_CLASS
+
+void main() {}
diff --git a/tests/language/nonfunction_type_aliases/private_names/private_name_mixin_test.dart b/tests/language/nonfunction_type_aliases/private_names/private_name_mixin_test.dart
new file mode 100644
index 0000000..3ca5bc3
--- /dev/null
+++ b/tests/language/nonfunction_type_aliases/private_names/private_name_mixin_test.dart
@@ -0,0 +1,75 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=nonfunction-type-aliases
+
+// Test that private names exported via public typedefs can be used as mixins.
+
+import "package:expect/expect.dart";
+
+import "private_name_library.dart";
+
+// Class that mixes in a private mixin via a public name.
+class Derived0 with PublicMixin {}
+
+void test0() {
+  // Test that the Derived0 class receives the PublicMixin methods.
+  PublicMixin p = Derived0();
+  Expect.equals(privateLibrarySentinel, p.mixinMethod());
+  // The private mixin method is accessible in the original library.
+  Expect.equals(privateLibrarySentinel, callPrivateMixinMethod(p));
+  // The private mixin method is not accessible in this library.
+  Expect.throwsNoSuchMethodError(() => (p as dynamic)._privateMixinMethod());
+}
+
+// Class that mixes in a private mixin via a public name and overrides the
+// PublicMixin methods.
+class Derived1 with PublicMixin {
+  int mixinMethod() => publicLibrarySentinel;
+  int _privateMixinMethod() => publicLibrarySentinel;
+}
+
+void test1() {
+  // Test that the mixed in methods have been overriden correctly, and that the
+  // private methods from the two libraries resolve correctly.
+  var p = Derived1();
+  Expect.equals(publicLibrarySentinel, p.mixinMethod());
+  // The overriding private mixin method is accessible in this library.
+  Expect.equals(publicLibrarySentinel, p._privateMixinMethod());
+  // The original private mixin method is accessible in the other library.
+  Expect.equals(privateLibrarySentinel, callPrivateMixinMethod(p));
+}
+
+class _Derived2 extends PublicClass {}
+
+// This class mixes a private super-mixin onto a subclass of a private class,
+// and also defines new library private members with the same textual name as
+// private members defined in the other library.
+class Derived2 extends _Derived2 with PublicSuperMixin {
+  int _privateMixinMethod() => publicLibrarySentinel;
+  int _privateInstanceMethod() => publicLibrarySentinel;
+}
+
+void test2() {
+  // Test that the super-mixin methods resolve correctly.
+  var p = Derived2();
+  PublicSuperMixin _ = p; // Check assignability
+  PublicClass __ = p; // Check assignability
+  // The mixin and instance methods are accessible.
+  Expect.equals(privateLibrarySentinel, p.mixinMethod());
+  Expect.equals(privateLibrarySentinel, p.instanceMethod());
+  // The original private mixin and instance methods are accessible in the
+  // original library.
+  Expect.equals(privateLibrarySentinel, callPrivateSuperMixinMethod(p));
+  Expect.equals(privateLibrarySentinel, callPrivateInstanceMethod(p));
+  // The new private mixin and instance methods are acessible in this library.
+  Expect.equals(publicLibrarySentinel, p._privateMixinMethod());
+  Expect.equals(publicLibrarySentinel, p._privateInstanceMethod());
+}
+
+void main() {
+  test0();
+  test1();
+  test2();
+}
diff --git a/tests/language/nonfunction_type_aliases/private_names/private_name_static_methods_test.dart b/tests/language/nonfunction_type_aliases/private_names/private_name_static_methods_test.dart
index 8ea31a4..639e6c9 100644
--- a/tests/language/nonfunction_type_aliases/private_names/private_name_static_methods_test.dart
+++ b/tests/language/nonfunction_type_aliases/private_names/private_name_static_methods_test.dart
@@ -15,13 +15,14 @@
 /// Test that each public typedef can be used to access static methods.
 void test1() {
   {
-    Expect.equals(3, PublicClass.staticMethod());
+    Expect.equals(privateLibrarySentinel, PublicClass.staticMethod());
     PublicClass.staticMethod().expectStaticType<Exactly<int>>();
 
-    Expect.equals(3, AlsoPublicClass.staticMethod());
+    Expect.equals(privateLibrarySentinel, AlsoPublicClass.staticMethod());
     AlsoPublicClass.staticMethod().expectStaticType<Exactly<int>>();
 
-    Expect.equals(3, PublicGenericClassOfInt.staticMethod());
+    Expect.equals(
+        privateLibrarySentinel, PublicGenericClassOfInt.staticMethod());
     PublicGenericClassOfInt.staticMethod().expectStaticType<Exactly<int>>();
   }
 }
diff --git a/tests/language/nonfunction_type_aliases/private_names/private_name_try_catch_test.dart b/tests/language/nonfunction_type_aliases/private_names/private_name_try_catch_test.dart
new file mode 100644
index 0000000..e4b4947
--- /dev/null
+++ b/tests/language/nonfunction_type_aliases/private_names/private_name_try_catch_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=nonfunction-type-aliases
+
+// Test that private names exported via public typedefs can be used in a try
+// catch.
+
+import "package:expect/expect.dart";
+
+import "private_name_library.dart";
+
+class Derived extends PublicClass {}
+
+void test1() {
+  try {
+    throw Derived();
+  } on PublicClass catch (e) {}
+
+  try {
+    throw Derived();
+  } on Derived catch (e) {}
+
+  try {
+    throw PublicClass();
+  } on PublicClass catch (e) {}
+
+  try {
+    throw PublicClass();
+  } on AlsoPublicClass catch (e) {}
+
+  Expect.throws(() {
+    try {
+      throw PublicClass();
+    } on Derived catch (e) {}
+  });
+}
+
+void main() {
+  test1();
+}
diff --git a/tools/VERSION b/tools/VERSION
index f65d244..0c0a1fb 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 13
 PATCH 0
-PRERELEASE 211
+PRERELEASE 212
 PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index 9d6d61a..94d11a1 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -380,6 +380,7 @@
       "pkg/status_file/",
       "pkg/test_runner/",
       "pkg/vm/",
+      "pkg/vm_service/",
       "pkg/vm_snapshot_analysis/",
       "runtime/",
       "sdk/",