Version 2.17.0-171.0.dev

Merge commit '62628e4c0084ee4dbf4203e7317055e20bba3bf5' into 'dev'
diff --git a/DEPS b/DEPS
index f9788c5..90d3669 100644
--- a/DEPS
+++ b/DEPS
@@ -90,7 +90,7 @@
   "chrome_rev" : "19997",
   "cli_util_rev" : "b0adbba89442b2ea6fef39c7a82fe79cb31e1168",
   "clock_rev" : "5631a0612f4ac7e1b32f7c9a00fc7c00a41615e1",
-  "collection_rev": "a4c941ab94044d118b2086a3f261c30377604127",
+  "collection_rev": "e1407da23b9f17400b3a905aafe2b8fa10db3d86",
   "convert_rev": "e063fdca4bebffecbb5e6aa5525995120982d9ce",
   "crypto_rev": "b5024e4de2b1c474dd558bef593ddbf0bfade152",
   "csslib_rev": "518761b166974537f334dbf264e7f56cb157a96a",
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/remove_leading_underscore.dart b/pkg/analysis_server/lib/src/services/correction/dart/remove_leading_underscore.dart
index 838e6a2..918c2a7 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/remove_leading_underscore.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/remove_leading_underscore.dart
@@ -57,6 +57,11 @@
           references = findLocalElementReferences(root, element);
         }
       }
+    } else if (element is PrefixElement) {
+      var root = node.thisOrAncestorOfType<CompilationUnit>();
+      if (root != null) {
+        references = findPrefixElementReferences(root, element);
+      }
     }
     if (references == null) {
       return;
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/remove_unnecessary_late.dart b/pkg/analysis_server/lib/src/services/correction/dart/remove_unnecessary_late.dart
new file mode 100644
index 0000000..08c09db
--- /dev/null
+++ b/pkg/analysis_server/lib/src/services/correction/dart/remove_unnecessary_late.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2022, 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 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:analyzer_plugin/utilities/range_factory.dart';
+
+class RemoveUnnecessaryLate extends CorrectionProducer {
+  @override
+  bool get canBeAppliedInBulk => true;
+
+  @override
+  bool get canBeAppliedToFile => true;
+
+  @override
+  FixKind get fixKind => DartFixKind.REMOVE_UNNECESSARY_LATE;
+
+  @override
+  FixKind get multiFixKind => DartFixKind.REMOVE_UNNECESSARY_LATE_MULTI;
+
+  @override
+  Future<void> compute(ChangeBuilder builder) async {
+    final declaration = node;
+    if (declaration is! VariableDeclaration) {
+      return;
+    }
+    final declarationList = declaration.parent;
+    if (declarationList is! VariableDeclarationList) {
+      return;
+    }
+
+    if (declarationList.variables.any((v) => v.initializer == null)) {
+      // At least one variable declared in the same list does _not_ have an
+      // initializer; removing `late` may make such a variable declaration
+      // invalid.
+      return;
+    }
+
+    final lateToken = declarationList.lateKeyword;
+    if (lateToken == null) {
+      return;
+    }
+
+    await builder.addDartFileEdit(file, (builder) {
+      builder.addDeletion(range.startStart(lateToken, lateToken.next!));
+    });
+  }
+
+  /// Return an instance of this class. Used as a tear-off in `FixProcessor`.
+  static RemoveUnnecessaryLate newInstance() => RemoveUnnecessaryLate();
+}
diff --git a/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml b/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml
index 0f8b8ce..fa7be23 100644
--- a/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml
+++ b/pkg/analysis_server/lib/src/services/correction/error_fix_status.yaml
@@ -1606,7 +1606,7 @@
 LintCode.no_duplicate_case_values:
   status: hasFix
 LintCode.no_leading_underscores_for_library_prefixes:
-  status: needsFix
+  status: hasFix
 LintCode.no_leading_underscores_for_local_identifiers:
   status: hasFix
 LintCode.no_logic_in_create_state:
@@ -1779,7 +1779,7 @@
 LintCode.unnecessary_lambdas:
   status: hasFix
 LintCode.unnecessary_late:
-  status: needsFix
+  status: hasFix
 LintCode.unnecessary_new:
   status: hasFix
 LintCode.unnecessary_null_aware_assignments:
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index 724920c..d3411f7 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -1073,6 +1073,16 @@
     DartFixKindPriority.IN_FILE,
     'Remove unnecessary const keywords everywhere in file',
   );
+  static const REMOVE_UNNECESSARY_LATE = FixKind(
+    'dart.fix.remove.unnecessaryLate',
+    DartFixKindPriority.DEFAULT,
+    'Remove unnecessary late keyword',
+  );
+  static const REMOVE_UNNECESSARY_LATE_MULTI = FixKind(
+    'dart.fix.remove.unnecessaryLate.multi',
+    DartFixKindPriority.IN_FILE,
+    'Remove unnecessary late keywords everywhere in file',
+  );
   static const REMOVE_UNNECESSARY_NEW = FixKind(
     'dart.fix.remove.unnecessaryNew',
     DartFixKindPriority.DEFAULT,
diff --git a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
index bb89d71..11db925 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -131,6 +131,7 @@
 import 'package:analysis_server/src/services/correction/dart/remove_type_annotation.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_type_arguments.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_cast.dart';
+import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_late.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_new.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_parentheses.dart';
 import 'package:analysis_server/src/services/correction/dart/remove_unnecessary_raw_string.dart';
@@ -454,6 +455,9 @@
     LintNames.no_duplicate_case_values: [
       RemoveDuplicateCase.newInstance,
     ],
+    LintNames.no_leading_underscores_for_library_prefixes: [
+      RemoveLeadingUnderscore.newInstance,
+    ],
     LintNames.no_leading_underscores_for_local_identifiers: [
       RemoveLeadingUnderscore.newInstance,
     ],
@@ -617,6 +621,9 @@
     LintNames.unnecessary_lambdas: [
       ReplaceWithTearOff.newInstance,
     ],
+    LintNames.unnecessary_late: [
+      RemoveUnnecessaryLate.newInstance,
+    ],
     LintNames.unnecessary_new: [
       RemoveUnnecessaryNew.newInstance,
     ],
diff --git a/pkg/analysis_server/lib/src/services/correction/util.dart b/pkg/analysis_server/lib/src/services/correction/util.dart
index 0fac6a9..bdb7b99 100644
--- a/pkg/analysis_server/lib/src/services/correction/util.dart
+++ b/pkg/analysis_server/lib/src/services/correction/util.dart
@@ -161,6 +161,14 @@
   return collector.references;
 }
 
+/// Return references to the [element] inside the [root] node.
+List<SimpleIdentifier> findPrefixElementReferences(
+    AstNode root, PrefixElement element) {
+  var collector = _ElementReferenceCollector(element);
+  root.accept(collector);
+  return collector.references;
+}
+
 /// TODO(scheglov) replace with nodes once there will be
 /// [CompilationUnit.getComments].
 ///
diff --git a/pkg/analysis_server/lib/src/services/linter/lint_names.dart b/pkg/analysis_server/lib/src/services/linter/lint_names.dart
index d94fd94..472ddf8 100644
--- a/pkg/analysis_server/lib/src/services/linter/lint_names.dart
+++ b/pkg/analysis_server/lib/src/services/linter/lint_names.dart
@@ -59,6 +59,8 @@
   static const String leading_newlines_in_multiline_strings =
       'leading_newlines_in_multiline_strings';
   static const String no_duplicate_case_values = 'no_duplicate_case_values';
+  static const String no_leading_underscores_for_library_prefixes =
+      'no_leading_underscores_for_library_prefixes';
   static const String no_leading_underscores_for_local_identifiers =
       'no_leading_underscores_for_local_identifiers';
   static const String non_constant_identifier_names =
@@ -132,6 +134,7 @@
   static const String unnecessary_getters_setters =
       'unnecessary_getters_setters';
   static const String unnecessary_lambdas = 'unnecessary_lambdas';
+  static const String unnecessary_late = 'unnecessary_late';
   static const String unnecessary_new = 'unnecessary_new';
   static const String unnecessary_null_in_if_null_operators =
       'unnecessary_null_in_if_null_operators';
diff --git a/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart b/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
index 7de85d0..87e18e9 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
@@ -247,6 +247,7 @@
   /// Return the kind of fixes being tested by this test class.
   FixKind get kind;
 
+  /// Asserts that the resolved compilation unit has a fix which produces [expected] output.
   Future<void> assertHasFix(String expected,
       {bool Function(AnalysisError)? errorFilter,
       int? length,
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_leading_underscore_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_leading_underscore_test.dart
index adf0a5a..3f0a3cd 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/remove_leading_underscore_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_leading_underscore_test.dart
@@ -12,7 +12,8 @@
 void main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(RemoveLeadingUnderscoreBulkTest);
-    defineReflectiveTests(RemoveLeadingUnderscoreTest);
+    defineReflectiveTests(RemoveLeadingUnderscoreForLibraryPrefixesTest);
+    defineReflectiveTests(RemoveLeadingUnderscoreForLocalVariablesTest);
   });
 }
 
@@ -44,7 +45,29 @@
 }
 
 @reflectiveTest
-class RemoveLeadingUnderscoreTest extends FixProcessorLintTest {
+class RemoveLeadingUnderscoreForLibraryPrefixesTest
+    extends FixProcessorLintTest {
+  @override
+  FixKind get kind => DartFixKind.REMOVE_LEADING_UNDERSCORE;
+
+  @override
+  String get lintCode => LintNames.no_leading_underscores_for_library_prefixes;
+
+  Future<void> test_importPrefix() async {
+    await resolveTestCode('''
+import 'dart:core' as _core;
+_core.int i = 1;
+''');
+    await assertHasFix('''
+import 'dart:core' as core;
+core.int i = 1;
+''');
+  }
+}
+
+@reflectiveTest
+class RemoveLeadingUnderscoreForLocalVariablesTest
+    extends FixProcessorLintTest {
   @override
   FixKind get kind => DartFixKind.REMOVE_LEADING_UNDERSCORE;
 
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_unnecessary_late_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_unnecessary_late_test.dart
new file mode 100644
index 0000000..171d193
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_unnecessary_late_test.dart
@@ -0,0 +1,96 @@
+// Copyright (c) 2019, 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 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/linter/lint_names.dart';
+import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'fix_processor.dart';
+
+void main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(RemoveUnnecessaryLateBulkTest);
+    defineReflectiveTests(RemoveUnnecessaryLateTest);
+  });
+}
+
+@reflectiveTest
+class RemoveUnnecessaryLateBulkTest extends BulkFixProcessorTest {
+  @override
+  String get lintCode => LintNames.unnecessary_late;
+
+  Future<void> test_singleFile() async {
+    await resolveTestCode('''
+late String s1 = '';
+late final String s2 = '';
+''');
+    await assertHasFix('''
+String s1 = '';
+final String s2 = '';
+''');
+  }
+}
+
+@reflectiveTest
+class RemoveUnnecessaryLateTest extends FixProcessorLintTest {
+  @override
+  FixKind get kind => DartFixKind.REMOVE_UNNECESSARY_LATE;
+
+  @override
+  String get lintCode => LintNames.unnecessary_late;
+
+  Future<void> test_static() async {
+    await resolveTestCode('''
+class C {
+  static late String s1 = '';
+}
+''');
+    await assertHasFix('''
+class C {
+  static String s1 = '';
+}
+''');
+  }
+
+  Future<void> test_topLevel() async {
+    await resolveTestCode('''
+late String s1 = '';
+''');
+    await assertHasFix('''
+String s1 = '';
+''');
+  }
+
+  Future<void> test_topLevel_multipleVariables_fixFirst() async {
+    await resolveTestCode('''
+late String s1 = '', s2 = '';
+''');
+    await assertHasFix(
+      '''
+String s1 = '', s2 = '';
+''',
+      errorFilter: (error) => error.toString().contains('test.dart(21..27)'),
+    );
+  }
+
+  Future<void> test_topLevel_multipleVariables_fixSecond() async {
+    await resolveTestCode('''
+late String s1 = '', s2 = '';
+''');
+    await assertHasFix(
+      '''
+String s1 = '', s2 = '';
+''',
+      errorFilter: (error) => error.toString().contains('test.dart(12..18)'),
+    );
+  }
+
+  Future<void> test_topLevel_multipleVariables_notAllHaveInitializer() async {
+    await resolveTestCode('''
+late String s1, s2 = '';
+''');
+    await assertNoFix();
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
index fc4bb66..5997525 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
@@ -160,6 +160,7 @@
 import 'remove_type_arguments_test.dart' as remove_type_arguments;
 import 'remove_unnecessary_cast_test.dart' as remove_unnecessary_cast;
 import 'remove_unnecessary_const_test.dart' as remove_unnecessary_const;
+import 'remove_unnecessary_late_test.dart' as remove_unnecessary_late;
 import 'remove_unnecessary_new_test.dart' as remove_unnecessary_new;
 import 'remove_unnecessary_parentheses_test.dart'
     as remove_unnecessary_parentheses;
@@ -362,6 +363,7 @@
     remove_type_arguments.main();
     remove_unnecessary_cast.main();
     remove_unnecessary_const.main();
+    remove_unnecessary_late.main();
     remove_unnecessary_new.main();
     remove_unnecessary_parentheses.main();
     remove_unnecessary_raw_string.main();
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index f4e2995..2322191 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -980,6 +980,12 @@
       // The name of a NamedType does not provide any context.
       // So, we don't need to resolve anything.
       if (parent is NamedType) {
+        // `{foo^ print(0);}` looks as `foo print; (0);`.
+        var parent3 = parent.parent?.parent;
+        if (parent3 is VariableDeclarationStatement &&
+            parent3.semicolon.isSynthetic) {
+          return false;
+        }
         return true;
       }
 
diff --git a/pkg/analyzer/lib/src/dart/element/greatest_lower_bound.dart b/pkg/analyzer/lib/src/dart/element/greatest_lower_bound.dart
index 7e5b176..92fc5ba 100644
--- a/pkg/analyzer/lib/src/dart/element/greatest_lower_bound.dart
+++ b/pkg/analyzer/lib/src/dart/element/greatest_lower_bound.dart
@@ -273,18 +273,13 @@
 
     // The bounds of type parameters must be equal.
     // Otherwise the result is `Never`.
-    var freshTypeFormalTypes =
-        FunctionTypeImpl.relateTypeFormals(f, g, (t, s) => t == s);
-    if (freshTypeFormalTypes == null) {
+    var fresh = _typeSystem.relateTypeParameters(f.typeFormals, g.typeFormals);
+    if (fresh == null) {
       return NeverTypeImpl.instance;
     }
 
-    var typeFormals = freshTypeFormalTypes
-        .map<TypeParameterElement>((t) => t.element)
-        .toList();
-
-    f = f.instantiate(freshTypeFormalTypes);
-    g = g.instantiate(freshTypeFormalTypes);
+    f = f.instantiate(fresh.typeParameterTypes);
+    g = g.instantiate(fresh.typeParameterTypes);
 
     var fParameters = f.parameters;
     var gParameters = g.parameters;
@@ -379,7 +374,7 @@
     var returnType = getGreatestLowerBound(f.returnType, g.returnType);
 
     return FunctionTypeImpl(
-      typeFormals: typeFormals,
+      typeFormals: fresh.typeParameters,
       parameters: parameters,
       returnType: returnType,
       nullabilitySuffix: NullabilitySuffix.none,
diff --git a/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart b/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart
index 55f46ff..c675895 100644
--- a/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart
+++ b/pkg/analyzer/lib/src/dart/element/least_upper_bound.dart
@@ -723,18 +723,13 @@
 
     // The bounds of type parameters must be equal.
     // Otherwise the result is `Function`.
-    var freshTypeFormalTypes =
-        FunctionTypeImpl.relateTypeFormals(f, g, (t, s) => t == s);
-    if (freshTypeFormalTypes == null) {
+    var fresh = _typeSystem.relateTypeParameters(f.typeFormals, g.typeFormals);
+    if (fresh == null) {
       return _interfaceTypeFunctionNone;
     }
 
-    var typeFormals = freshTypeFormalTypes
-        .map<TypeParameterElement>((t) => t.element)
-        .toList();
-
-    f = f.instantiate(freshTypeFormalTypes);
-    g = g.instantiate(freshTypeFormalTypes);
+    f = f.instantiate(fresh.typeParameterTypes);
+    g = g.instantiate(fresh.typeParameterTypes);
 
     var fParameters = f.parameters;
     var gParameters = g.parameters;
@@ -822,7 +817,7 @@
     var returnType = getLeastUpperBound(f.returnType, g.returnType);
 
     return FunctionTypeImpl(
-      typeFormals: typeFormals,
+      typeFormals: fresh.typeParameters,
       parameters: parameters,
       returnType: returnType,
       nullabilitySuffix: NullabilitySuffix.none,
diff --git a/pkg/analyzer/lib/src/dart/element/subtype.dart b/pkg/analyzer/lib/src/dart/element/subtype.dart
index 50ec06d..9ff6e69 100644
--- a/pkg/analyzer/lib/src/dart/element/subtype.dart
+++ b/pkg/analyzer/lib/src/dart/element/subtype.dart
@@ -20,16 +20,17 @@
 /// https://github.com/dart-lang/language
 /// See `resources/type-system/subtyping.md`
 class SubtypeHelper {
+  final TypeSystemImpl _typeSystem;
   final TypeProviderImpl _typeProvider;
   final InterfaceTypeImpl _nullNone;
   final InterfaceTypeImpl _objectNone;
   final InterfaceTypeImpl _objectQuestion;
 
-  SubtypeHelper(TypeSystemImpl typeSystem)
-      : _typeProvider = typeSystem.typeProvider,
-        _nullNone = typeSystem.nullNone,
-        _objectNone = typeSystem.objectNone,
-        _objectQuestion = typeSystem.objectQuestion;
+  SubtypeHelper(this._typeSystem)
+      : _typeProvider = _typeSystem.typeProvider,
+        _nullNone = _typeSystem.nullNone,
+        _objectNone = _typeSystem.objectNone,
+        _objectQuestion = _typeSystem.objectQuestion;
 
   /// Return `true` if [T0_] is a subtype of [T1_].
   bool isSubtypeOf(DartType T0_, DartType T1_) {
@@ -342,24 +343,13 @@
 
   /// Check that [f] is a subtype of [g].
   bool _isFunctionSubtypeOf(FunctionType f, FunctionType g) {
-    var fTypeFormals = f.typeFormals;
-    var gTypeFormals = g.typeFormals;
-
-    // The number of type parameters must be the same.
-    if (fTypeFormals.length != gTypeFormals.length) {
+    var fresh = _typeSystem.relateTypeParameters(f.typeFormals, g.typeFormals);
+    if (fresh == null) {
       return false;
     }
 
-    // The bounds of type parameters must be equal.
-    var freshTypeFormalTypes = FunctionTypeImpl.relateTypeFormals(f, g, (t, s) {
-      return isSubtypeOf(t, s) && isSubtypeOf(s, t);
-    });
-    if (freshTypeFormalTypes == null) {
-      return false;
-    }
-
-    f = f.instantiate(freshTypeFormalTypes);
-    g = g.instantiate(freshTypeFormalTypes);
+    f = f.instantiate(fresh.typeParameterTypes);
+    g = g.instantiate(fresh.typeParameterTypes);
 
     if (!isSubtypeOf(f.returnType, g.returnType)) {
       return false;
diff --git a/pkg/analyzer/lib/src/dart/element/type_system.dart b/pkg/analyzer/lib/src/dart/element/type_system.dart
index 1b41aeb5..9097f205 100644
--- a/pkg/analyzer/lib/src/dart/element/type_system.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_system.dart
@@ -32,6 +32,19 @@
 import 'package:analyzer/src/dart/element/type_schema_elimination.dart';
 import 'package:analyzer/src/dart/element/well_bounded.dart';
 
+/// Fresh type parameters created to unify two lists of type parameters.
+class RelatedTypeParameters {
+  static final _empty = RelatedTypeParameters._([], []);
+
+  final List<TypeParameterElement> typeParameters;
+  final List<TypeParameterType> typeParameterTypes;
+
+  RelatedTypeParameters._(
+    this.typeParameters,
+    this.typeParameterTypes,
+  );
+}
+
 /// The [TypeSystem] implementation.
 class TypeSystemImpl implements TypeSystem {
   /// If `true`, then NNBD type rules should be used.
@@ -803,6 +816,15 @@
     return false;
   }
 
+  /// Check if [left] is equal to [right].
+  ///
+  /// Implements:
+  /// https://github.com/dart-lang/language
+  /// See `resources/type-system/subtyping.md#type-equality`
+  bool isEqualTo(DartType left, DartType right) {
+    return isSubtypeOf(left, right) && isSubtypeOf(right, left);
+  }
+
   /// A function bounded type is either `Function` itself, or a type variable
   /// whose bound is function bounded, or an intersection (promoted type
   /// parameter type) whose second operand is function bounded.
@@ -1423,6 +1445,72 @@
     }
   }
 
+  /// Given two lists of type parameters, check that that they have the same
+  /// number of elements, and their bounds are equal.
+  ///
+  /// The return value will be a new list of fresh type parameters, that can
+  /// be used to instantiate both function types, allowing further comparison.
+  RelatedTypeParameters? relateTypeParameters(
+    List<TypeParameterElement> typeParameters1,
+    List<TypeParameterElement> typeParameters2,
+  ) {
+    if (typeParameters1.length != typeParameters2.length) {
+      return null;
+    }
+    if (typeParameters1.isEmpty) {
+      return RelatedTypeParameters._empty;
+    }
+
+    var freshTypeParameters = <TypeParameterElementImpl>[];
+    var freshTypeParameterTypes = <TypeParameterType>[];
+    for (var i = 0; i < typeParameters1.length; i++) {
+      var freshTypeParameter = TypeParameterElementImpl(
+        typeParameters1[i].name,
+        -1,
+      );
+      freshTypeParameters.add(freshTypeParameter);
+      freshTypeParameterTypes.add(
+        TypeParameterTypeImpl(
+          element: freshTypeParameter,
+          nullabilitySuffix: NullabilitySuffix.none,
+        ),
+      );
+    }
+
+    var substitution1 = Substitution.fromPairs(
+      typeParameters1,
+      freshTypeParameterTypes,
+    );
+    var substitution2 = Substitution.fromPairs(
+      typeParameters2,
+      freshTypeParameterTypes,
+    );
+
+    for (var i = 0; i < typeParameters1.length; i++) {
+      var bound1 = typeParameters1[i].bound;
+      var bound2 = typeParameters2[i].bound;
+      if (bound1 == null && bound2 == null) {
+        continue;
+      }
+      bound1 ??= DynamicTypeImpl.instance;
+      bound2 ??= DynamicTypeImpl.instance;
+      bound1 = substitution1.substituteType(bound1);
+      bound2 = substitution2.substituteType(bound2);
+      if (!isEqualTo(bound1, bound2)) {
+        return null;
+      }
+
+      if (!bound1.isDynamic) {
+        freshTypeParameters[i].bound = bound1;
+      }
+    }
+
+    return RelatedTypeParameters._(
+      freshTypeParameters,
+      freshTypeParameterTypes,
+    );
+  }
+
   /// Replaces all covariant occurrences of `dynamic`, `void`, and `Object` or
   /// `Object?` with `Null` or `Never` and all contravariant occurrences of
   /// `Null` or `Never` with `Object` or `Object?`.
diff --git a/pkg/analyzer/lib/src/error/inheritance_override.dart b/pkg/analyzer/lib/src/error/inheritance_override.dart
index d82f871..0e38986 100644
--- a/pkg/analyzer/lib/src/error/inheritance_override.dart
+++ b/pkg/analyzer/lib/src/error/inheritance_override.dart
@@ -387,7 +387,7 @@
 
     if (interfaceElement.isDartCoreEnum &&
         library.featureSet.isEnabled(Feature.enhanced_enums)) {
-      if (classElement.isAbstract) {
+      if (classElement.isAbstract || classElement.isEnum) {
         return false;
       }
       reporter.reportErrorForNode(
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index c923c69..01ff198 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -74,6 +74,9 @@
   /// for the kind of the function body, e.g. not `Future` for `async`.
   bool hasLegalReturnType = true;
 
+  /// The number of enclosing [CatchClause] in this executable.
+  int catchClauseLevel = 0;
+
   EnclosingExecutableContext(this.element,
       {bool? isAsynchronous, this.catchErrorOnErrorReturnType})
       : isAsynchronous =
@@ -164,11 +167,6 @@
   /// The manager for the inheritance mappings.
   final InheritanceManager3 _inheritanceManager;
 
-  /// A flag indicating whether the visitor is currently within a catch clause.
-  ///
-  /// See [visitCatchClause].
-  bool _isInCatchClause = false;
-
   /// A flag indicating whether the visitor is currently within a comment.
   bool _isInComment = false;
 
@@ -250,7 +248,6 @@
         _duplicateDefinitionVerifier = DuplicateDefinitionVerifier(
             _inheritanceManager, _currentLibrary, errorReporter) {
     _isInSystemLibrary = _currentLibrary.source.uri.isScheme('dart');
-    _isInCatchClause = false;
     _isInStaticVariableDeclaration = false;
     _isInConstructorInitializer = false;
     _intType = _typeProvider.intType;
@@ -409,13 +406,12 @@
   @override
   void visitCatchClause(CatchClause node) {
     _duplicateDefinitionVerifier.checkCatchClause(node);
-    bool previousIsInCatchClause = _isInCatchClause;
     try {
-      _isInCatchClause = true;
+      _enclosingExecutable.catchClauseLevel++;
       _checkForTypeAnnotationDeferredClass(node.exceptionType);
       super.visitCatchClause(node);
     } finally {
-      _isInCatchClause = previousIsInCatchClause;
+      _enclosingExecutable.catchClauseLevel--;
     }
   }
 
@@ -4112,7 +4108,7 @@
   ///
   /// See [CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH].
   void _checkForRethrowOutsideCatch(RethrowExpression expression) {
-    if (!_isInCatchClause) {
+    if (_enclosingExecutable.catchClauseLevel == 0) {
       errorReporter.reportErrorForNode(
           CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH, expression);
     }
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
deleted file mode 100644
index c457420..0000000
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright (c) 2015, 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.
-
-@Deprecated("Use package:analyzer/src/dart/element/type_system.dart instead")
-library type_system_generated;
-
-export 'package:analyzer/src/dart/element/type_system.dart';
diff --git a/pkg/analyzer/test/src/dart/analysis/resolve_for_completion_test.dart b/pkg/analyzer/test/src/dart/analysis/resolve_for_completion_test.dart
index c8395fc..d570325 100644
--- a/pkg/analyzer/test/src/dart/analysis/resolve_for_completion_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/resolve_for_completion_test.dart
@@ -87,7 +87,7 @@
 
   void foo2() {
     print(0);
-    bar^;
+    bar^
     print(1);
   }
 
@@ -96,7 +96,7 @@
 ''');
 
     result.assertResolvedNodes([
-      'void foo2() {print(0); bar; print(1);}',
+      'void foo2() {print(0); bar print; (1);}',
     ]);
   }
 
@@ -139,7 +139,7 @@
 
   B() {
     print(0);
-    bar^;
+    bar^
     print(1);
   }
 
@@ -148,7 +148,7 @@
 ''');
 
     result.assertResolvedNodes([
-      'B() {print(0); bar; print(1);}',
+      'B() {print(0); bar print; (1);}',
     ]);
   }
 
@@ -246,7 +246,7 @@
 
   void foo2() {
     print(0);
-    bar^;
+    bar^
     print(1);
   }
 
@@ -255,7 +255,7 @@
 ''');
 
     result.assertResolvedNodes([
-      'void foo2() {print(0); bar; print(1);}',
+      'void foo2() {print(0); bar print; (1);}',
     ]);
   }
 
@@ -297,6 +297,24 @@
 
 void foo2() {
   print(0);
+  bar^
+  print(1);
+}
+
+void foo3() {}
+''');
+
+    result.assertResolvedNodes([
+      'void foo2() {print(0); bar print; (1);}',
+    ]);
+  }
+
+  test_functionDeclaration_body_withSemicolon() async {
+    var result = _resolveTestCode(r'''
+void foo1() {}
+
+void foo2() {
+  print(0);
   bar^;
   print(1);
 }
@@ -396,7 +414,7 @@
 
   void foo2() {
     print(0);
-    bar^;
+    bar^
     print(1);
   }
 
@@ -405,7 +423,7 @@
 ''');
 
     result.assertResolvedNodes([
-      'void foo2() {print(0); bar; print(1);}',
+      'void foo2() {print(0); bar print; (1);}',
     ]);
   }
 
diff --git a/pkg/analyzer/test/src/dart/element/subtype_test.dart b/pkg/analyzer/test/src/dart/element/subtype_test.dart
index 481f288..884d010 100644
--- a/pkg/analyzer/test/src/dart/element/subtype_test.dart
+++ b/pkg/analyzer/test/src/dart/element/subtype_test.dart
@@ -1479,6 +1479,41 @@
     );
   }
 
+  test_functionType_74() {
+    var T1 = typeParameter('T');
+    var R1 = typeParameter(
+      'R',
+      bound: typeParameterType(
+        T1,
+        nullabilitySuffix: NullabilitySuffix.none,
+      ),
+    );
+
+    var T2 = typeParameter('T');
+    var R2 = typeParameter(
+      'R',
+      bound: typeParameterType(
+        T2,
+        nullabilitySuffix: NullabilitySuffix.none,
+      ),
+    );
+
+    // Note, the order `R extends T`, then `T` is important.
+    // We test that all type parameters replaced at once, not as we go.
+    isSubtype(
+      functionTypeNone(
+        typeFormals: [R1, T1],
+        returnType: voidNone,
+      ),
+      functionTypeNone(
+        typeFormals: [R2, T2],
+        returnType: voidNone,
+      ),
+      strT0: 'void Function<R extends T, T>()',
+      strT1: 'void Function<R extends T, T>()',
+    );
+  }
+
   test_functionType_generic_nested() {
     var E0 = typeParameter('E0');
     var F0 = typeParameter('F0');
diff --git a/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
index d5d78f2..1846448 100644
--- a/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/postfix_expression_test.dart
@@ -30,15 +30,27 @@
 }
 ''');
 
-    assertPostfixExpression(
-      findNode.postfix('foo++'),
-      readElement: findElement.getter('foo'),
-      readType: 'int',
-      writeElement: findElement.setter('foo'),
-      writeType: 'int',
-      element: numElement.getMethod('+'),
-      type: 'int?',
-    );
+    assertResolvedNodeText(findNode.postfix('foo++'), r'''
+PostfixExpression
+  operand: PropertyAccess
+    target: SimpleIdentifier
+      token: a
+      staticElement: a@38
+      staticType: A?
+    operator: ?.
+    propertyName: SimpleIdentifier
+      token: foo
+      staticElement: <null>
+      staticType: null
+    staticType: null
+  operator: ++
+  readElement: self::@class::A::@getter::foo
+  readType: int
+  writeElement: self::@class::A::@setter::foo
+  writeType: int
+  staticElement: dart:core::@class::num::@method::+
+  staticType: int?
+''');
   }
 
   test_inc_simpleIdentifier_parameter_depromote() async {
@@ -55,15 +67,20 @@
 }
 ''');
 
-    assertPostfixExpression(
-      findNode.postfix('x++'),
-      readElement: findElement.parameter('x'),
-      readType: 'A',
-      writeElement: findElement.parameter('x'),
-      writeType: 'Object',
-      element: findElement.method('+'),
-      type: 'A',
-    );
+    assertResolvedNodeText(findNode.postfix('x++'), r'''
+PostfixExpression
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@63
+    staticType: null
+  operator: ++
+  readElement: x@63
+  readType: A
+  writeElement: x@63
+  writeType: Object
+  staticElement: self::@class::A::@method::+
+  staticType: A
+''');
 
     assertType(findNode.simple('x; // ref'), 'Object');
   }
@@ -75,15 +92,16 @@
 }
 ''');
 
-    assertPostfixExpression(
-      findNode.postfix('x!'),
-      readElement: null,
-      readType: null,
-      writeElement: null,
-      writeType: null,
-      element: null,
-      type: 'int',
-    );
+    assertResolvedNodeText(findNode.postfix('x!'), r'''
+PostfixExpression
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@12
+    staticType: int?
+  operator: !
+  staticElement: <null>
+  staticType: int
+''');
   }
 
   test_nullCheck_functionExpressionInvocation_rewrite() async {
@@ -118,15 +136,25 @@
   staticType: int?
 ''');
 
-    assertPostfixExpression(
-      findNode.postfix(']!'),
-      readElement: null,
-      readType: null,
-      writeElement: null,
-      writeType: null,
-      element: null,
-      type: 'int',
-    );
+    assertResolvedNodeText(findNode.postfix(']!'), r'''
+PostfixExpression
+  operand: IndexExpression
+    target: SimpleIdentifier
+      token: a
+      staticElement: a@24
+      staticType: Map<String, int>
+    leftBracket: [
+    index: SimpleStringLiteral
+      literal: 'foo'
+    rightBracket: ]
+    staticElement: MethodMember
+      base: dart:core::@class::Map::@method::[]
+      substitution: {K: String, V: int}
+    staticType: int?
+  operator: !
+  staticElement: <null>
+  staticType: int
+''');
   }
 
   test_nullCheck_null() async {
@@ -156,15 +184,28 @@
       type: 'int?',
     );
 
-    assertPostfixExpression(
-      findNode.postfix('f(null)!'),
-      readElement: null,
-      readType: null,
-      writeElement: null,
-      writeType: null,
-      element: null,
-      type: 'int',
-    );
+    assertResolvedNodeText(findNode.postfix('f(null)!'), r'''
+PostfixExpression
+  operand: MethodInvocation
+    methodName: SimpleIdentifier
+      token: f
+      staticElement: self::@function::f
+      staticType: T Function<T>(T)
+    argumentList: ArgumentList
+      leftParenthesis: (
+      arguments
+        NullLiteral
+          literal: null
+          staticType: Null
+      rightParenthesis: )
+    staticInvokeType: int? Function(int?)
+    staticType: int?
+    typeArgumentTypes
+      int?
+  operator: !
+  staticElement: <null>
+  staticType: int
+''');
   }
 
   /// See https://github.com/dart-lang/language/issues/1163
@@ -245,15 +286,15 @@
 
     assertTypeDynamic(findNode.super_('super!'));
 
-    assertPostfixExpression(
-      findNode.postfix('super!'),
-      readElement: null,
-      readType: null,
-      writeElement: null,
-      writeType: null,
-      element: null,
-      type: 'dynamic',
-    );
+    assertResolvedNodeText(findNode.postfix('super!'), r'''
+PostfixExpression
+  operand: SuperExpression
+    superKeyword: super
+    staticType: dynamic
+  operator: !
+  staticElement: <null>
+  staticType: dynamic
+''');
 
     assertMethodInvocation2(
       findNode.methodInvocation('foo();'),
@@ -272,15 +313,16 @@
 ''');
 
     var postfixExpression = findNode.postfix('x!');
-    assertPostfixExpression(
-      postfixExpression,
-      readElement: null,
-      readType: null,
-      writeElement: null,
-      writeType: null,
-      element: null,
-      type: 'T & Object',
-    );
+    assertResolvedNodeText(postfixExpression, r'''
+PostfixExpression
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@13
+    staticType: T?
+  operator: !
+  staticElement: <null>
+  staticType: T & Object
+''');
   }
 
   test_nullCheck_typeParameter_already_promoted() async {
@@ -293,15 +335,16 @@
 ''');
 
     var postfixExpression = findNode.postfix('x!');
-    assertPostfixExpression(
-      postfixExpression,
-      readElement: null,
-      readType: null,
-      writeElement: null,
-      writeType: null,
-      element: null,
-      type: 'T & num',
-    );
+    assertResolvedNodeText(postfixExpression, r'''
+PostfixExpression
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@13
+    staticType: T? & num?
+  operator: !
+  staticElement: <null>
+  staticType: T & num
+''');
   }
 }
 
@@ -313,18 +356,40 @@
 }
 ''');
 
-    assertPostfixExpression(
-      findNode.postfix('x--'),
-      readElement: findElement.parameter('x'),
-      readType: 'int',
-      writeElement: findElement.parameter('x'),
-      writeType: 'int',
-      element: elementMatcher(
-        numElement.getMethod('-'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'int',
-    );
+    var node = findNode.postfix('x--');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@11
+    staticType: null
+  operator: --
+  readElement: x@11
+  readType: int
+  writeElement: x@11
+  writeType: int
+  staticElement: dart:core::@class::num::@method::-
+  staticType: int
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@11
+    staticType: null
+  operator: --
+  readElement: x@11
+  readType: int*
+  writeElement: x@11
+  writeType: int*
+  staticElement: MethodMember
+    base: dart:core::@class::num::@method::-
+    isLegacy: true
+  staticType: int*
+''');
+    }
   }
 
   test_inc_indexExpression_instance() async {
@@ -339,18 +404,56 @@
 }
 ''');
 
-    assertPostfixExpression(
-      findNode.postfix('a[0]++'),
-      readElement: findElement.method('[]'),
-      readType: 'int',
-      writeElement: findElement.method('[]='),
-      writeType: 'num',
-      element: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'int',
-    );
+    var node = findNode.postfix('a[0]++');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: IndexExpression
+    target: SimpleIdentifier
+      token: a
+      staticElement: a@91
+      staticType: A
+    leftBracket: [
+    index: IntegerLiteral
+      literal: 0
+      staticType: int
+    rightBracket: ]
+    staticElement: <null>
+    staticType: null
+  operator: ++
+  readElement: self::@class::A::@method::[]
+  readType: int
+  writeElement: self::@class::A::@method::[]=
+  writeType: num
+  staticElement: dart:core::@class::num::@method::+
+  staticType: int
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: IndexExpression
+    target: SimpleIdentifier
+      token: a
+      staticElement: a@91
+      staticType: A*
+    leftBracket: [
+    index: IntegerLiteral
+      literal: 0
+      staticType: int*
+    rightBracket: ]
+    staticElement: <null>
+    staticType: null
+  operator: ++
+  readElement: self::@class::A::@method::[]
+  readType: int*
+  writeElement: self::@class::A::@method::[]=
+  writeType: num*
+  staticElement: MethodMember
+    base: dart:core::@class::num::@method::+
+    isLegacy: true
+  staticType: int*
+''');
+    }
   }
 
   test_inc_indexExpression_super() async {
@@ -367,18 +470,54 @@
 }
 ''');
 
-    assertPostfixExpression(
-      findNode.postfix('[0]++'),
-      readElement: findElement.method('[]'),
-      readType: 'int',
-      writeElement: findElement.method('[]='),
-      writeType: 'num',
-      element: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'int',
-    );
+    var node = findNode.postfix('[0]++');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: IndexExpression
+    target: SuperExpression
+      superKeyword: super
+      staticType: B
+    leftBracket: [
+    index: IntegerLiteral
+      literal: 0
+      staticType: int
+    rightBracket: ]
+    staticElement: <null>
+    staticType: null
+  operator: ++
+  readElement: self::@class::A::@method::[]
+  readType: int
+  writeElement: self::@class::A::@method::[]=
+  writeType: num
+  staticElement: dart:core::@class::num::@method::+
+  staticType: int
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: IndexExpression
+    target: SuperExpression
+      superKeyword: super
+      staticType: B*
+    leftBracket: [
+    index: IntegerLiteral
+      literal: 0
+      staticType: int*
+    rightBracket: ]
+    staticElement: <null>
+    staticType: null
+  operator: ++
+  readElement: self::@class::A::@method::[]
+  readType: int*
+  writeElement: self::@class::A::@method::[]=
+  writeType: num*
+  staticElement: MethodMember
+    base: dart:core::@class::num::@method::+
+    isLegacy: true
+  staticType: int*
+''');
+    }
   }
 
   test_inc_indexExpression_this() async {
@@ -393,18 +532,54 @@
 }
 ''');
 
-    assertPostfixExpression(
-      findNode.postfix('[0]++'),
-      readElement: findElement.method('[]'),
-      readType: 'int',
-      writeElement: findElement.method('[]='),
-      writeType: 'num',
-      element: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'int',
-    );
+    var node = findNode.postfix('[0]++');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: IndexExpression
+    target: ThisExpression
+      thisKeyword: this
+      staticType: A
+    leftBracket: [
+    index: IntegerLiteral
+      literal: 0
+      staticType: int
+    rightBracket: ]
+    staticElement: <null>
+    staticType: null
+  operator: ++
+  readElement: self::@class::A::@method::[]
+  readType: int
+  writeElement: self::@class::A::@method::[]=
+  writeType: num
+  staticElement: dart:core::@class::num::@method::+
+  staticType: int
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: IndexExpression
+    target: ThisExpression
+      thisKeyword: this
+      staticType: A*
+    leftBracket: [
+    index: IntegerLiteral
+      literal: 0
+      staticType: int*
+    rightBracket: ]
+    staticElement: <null>
+    staticType: null
+  operator: ++
+  readElement: self::@class::A::@method::[]
+  readType: int*
+  writeElement: self::@class::A::@method::[]=
+  writeType: num*
+  staticElement: MethodMember
+    base: dart:core::@class::num::@method::+
+    isLegacy: true
+  staticType: int*
+''');
+    }
   }
 
   test_inc_notLValue_parenthesized() async {
@@ -416,15 +591,44 @@
       error(ParserErrorCode.ILLEGAL_ASSIGNMENT_TO_NON_ASSIGNABLE, 16, 2),
     ]);
 
-    assertPostfixExpression(
-      findNode.postfix('(0)++'),
-      readElement: null,
-      readType: 'dynamic',
-      writeElement: null,
-      writeType: 'dynamic',
-      element: null,
-      type: 'dynamic',
-    );
+    var node = findNode.postfix('(0)++');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: ParenthesizedExpression
+    leftParenthesis: (
+    expression: IntegerLiteral
+      literal: 0
+      staticType: int
+    rightParenthesis: )
+    staticType: int
+  operator: ++
+  readElement: <null>
+  readType: dynamic
+  writeElement: <null>
+  writeType: dynamic
+  staticElement: <null>
+  staticType: dynamic
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: ParenthesizedExpression
+    leftParenthesis: (
+    expression: IntegerLiteral
+      literal: 0
+      staticType: int*
+    rightParenthesis: )
+    staticType: int*
+  operator: ++
+  readElement: <null>
+  readType: dynamic
+  writeElement: <null>
+  writeType: dynamic
+  staticElement: <null>
+  staticType: dynamic
+''');
+    }
   }
 
   test_inc_notLValue_simpleIdentifier_typeLiteral() async {
@@ -436,15 +640,38 @@
       error(CompileTimeErrorCode.ASSIGNMENT_TO_TYPE, 13, 3),
     ]);
 
-    assertPostfixExpression(
-      findNode.postfix('int++'),
-      readElement: intElement,
-      readType: 'dynamic',
-      writeElement: intElement,
-      writeType: 'dynamic',
-      element: null,
-      type: 'dynamic',
-    );
+    var node = findNode.postfix('int++');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: SimpleIdentifier
+    token: int
+    staticElement: <null>
+    staticType: null
+  operator: ++
+  readElement: dart:core::@class::int
+  readType: dynamic
+  writeElement: dart:core::@class::int
+  writeType: dynamic
+  staticElement: <null>
+  staticType: dynamic
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: SimpleIdentifier
+    token: int
+    staticElement: <null>
+    staticType: null
+  operator: ++
+  readElement: dart:core::@class::int
+  readType: dynamic
+  writeElement: dart:core::@class::int
+  writeType: dynamic
+  staticElement: <null>
+  staticType: dynamic
+''');
+    }
   }
 
   test_inc_notLValue_simpleIdentifier_typeLiteral_typeParameter() async {
@@ -456,19 +683,41 @@
       error(CompileTimeErrorCode.ASSIGNMENT_TO_TYPE, 16, 1),
     ]);
 
-    var postfix = findNode.postfix('T++');
-    assertPostfixExpression(
-      postfix,
-      readElement: findElement.typeParameter('T'),
-      readType: 'dynamic',
-      writeElement: findElement.typeParameter('T'),
-      writeType: 'dynamic',
-      element: null,
-      type: 'dynamic',
-    );
+    var node = findNode.postfix('T++');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: SimpleIdentifier
+    token: T
+    staticElement: <null>
+    staticType: null
+  operator: ++
+  readElement: T@7
+  readType: dynamic
+  writeElement: T@7
+  writeType: dynamic
+  staticElement: <null>
+  staticType: dynamic
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: SimpleIdentifier
+    token: T
+    staticElement: <null>
+    staticType: null
+  operator: ++
+  readElement: T@7
+  readType: dynamic
+  writeElement: T@7
+  writeType: dynamic
+  staticElement: <null>
+  staticType: dynamic
+''');
+    }
 
     assertSimpleIdentifierAssignmentTarget(
-      postfix.operand,
+      node.operand,
     );
   }
 
@@ -483,18 +732,56 @@
 }
 ''');
 
-    assertPostfixExpression(
-      findNode.postfix('x++'),
-      readElement: findElement.getter('x'),
-      readType: 'int',
-      writeElement: findElement.setter('x'),
-      writeType: 'int',
-      element: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'int',
-    );
+    var node = findNode.postfix('x++');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: PrefixedIdentifier
+    prefix: SimpleIdentifier
+      token: a
+      staticElement: a@35
+      staticType: A
+    period: .
+    identifier: SimpleIdentifier
+      token: x
+      staticElement: <null>
+      staticType: null
+    staticElement: <null>
+    staticType: null
+  operator: ++
+  readElement: self::@class::A::@getter::x
+  readType: int
+  writeElement: self::@class::A::@setter::x
+  writeType: int
+  staticElement: dart:core::@class::num::@method::+
+  staticType: int
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: PrefixedIdentifier
+    prefix: SimpleIdentifier
+      token: a
+      staticElement: a@35
+      staticType: A*
+    period: .
+    identifier: SimpleIdentifier
+      token: x
+      staticElement: <null>
+      staticType: null
+    staticElement: <null>
+    staticType: null
+  operator: ++
+  readElement: self::@class::A::@getter::x
+  readType: int*
+  writeElement: self::@class::A::@setter::x
+  writeType: int*
+  staticElement: MethodMember
+    base: dart:core::@class::num::@method::+
+    isLegacy: true
+  staticType: int*
+''');
+    }
   }
 
   test_inc_prefixedIdentifier_topLevel() async {
@@ -511,21 +798,58 @@
 
     var importFind = findElement.importFind('package:test/a.dart');
 
-    var postfix = findNode.postfix('x++');
-    assertPostfixExpression(
-      postfix,
-      readElement: importFind.topGet('x'),
-      readType: 'int',
-      writeElement: importFind.topSet('x'),
-      writeType: 'int',
-      element: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'int',
-    );
+    var node = findNode.postfix('x++');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: PrefixedIdentifier
+    prefix: SimpleIdentifier
+      token: p
+      staticElement: self::@prefix::p
+      staticType: null
+    period: .
+    identifier: SimpleIdentifier
+      token: x
+      staticElement: <null>
+      staticType: null
+    staticElement: <null>
+    staticType: null
+  operator: ++
+  readElement: package:test/a.dart::@getter::x
+  readType: int
+  writeElement: package:test/a.dart::@setter::x
+  writeType: int
+  staticElement: dart:core::@class::num::@method::+
+  staticType: int
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: PrefixedIdentifier
+    prefix: SimpleIdentifier
+      token: p
+      staticElement: self::@prefix::p
+      staticType: null
+    period: .
+    identifier: SimpleIdentifier
+      token: x
+      staticElement: <null>
+      staticType: null
+    staticElement: <null>
+    staticType: null
+  operator: ++
+  readElement: package:test/a.dart::@getter::x
+  readType: int*
+  writeElement: package:test/a.dart::@setter::x
+  writeType: int*
+  staticElement: MethodMember
+    base: dart:core::@class::num::@method::+
+    isLegacy: true
+  staticType: int*
+''');
+    }
 
-    var prefixed = postfix.operand as PrefixedIdentifier;
+    var prefixed = node.operand as PrefixedIdentifier;
     assertImportPrefix(prefixed.prefix, importFind.prefix);
   }
 
@@ -540,18 +864,72 @@
 }
 ''');
 
-    assertPostfixExpression(
-      findNode.postfix('x++'),
-      readElement: findElement.getter('x'),
-      readType: 'int',
-      writeElement: findElement.setter('x'),
-      writeType: 'int',
-      element: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'int',
-    );
+    var node = findNode.postfix('x++');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: PropertyAccess
+    target: InstanceCreationExpression
+      constructorName: ConstructorName
+        type: NamedType
+          name: SimpleIdentifier
+            token: A
+            staticElement: self::@class::A
+            staticType: null
+          type: A
+        staticElement: self::@class::A::@constructor::•
+      argumentList: ArgumentList
+        leftParenthesis: (
+        rightParenthesis: )
+      staticType: A
+    operator: .
+    propertyName: SimpleIdentifier
+      token: x
+      staticElement: <null>
+      staticType: null
+    staticType: null
+  operator: ++
+  readElement: self::@class::A::@getter::x
+  readType: int
+  writeElement: self::@class::A::@setter::x
+  writeType: int
+  staticElement: dart:core::@class::num::@method::+
+  staticType: int
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: PropertyAccess
+    target: InstanceCreationExpression
+      constructorName: ConstructorName
+        type: NamedType
+          name: SimpleIdentifier
+            token: A
+            staticElement: self::@class::A
+            staticType: null
+          type: A*
+        staticElement: self::@class::A::@constructor::•
+      argumentList: ArgumentList
+        leftParenthesis: (
+        rightParenthesis: )
+      staticType: A*
+    operator: .
+    propertyName: SimpleIdentifier
+      token: x
+      staticElement: <null>
+      staticType: null
+    staticType: null
+  operator: ++
+  readElement: self::@class::A::@getter::x
+  readType: int*
+  writeElement: self::@class::A::@setter::x
+  writeType: int*
+  staticElement: MethodMember
+    base: dart:core::@class::num::@method::+
+    isLegacy: true
+  staticType: int*
+''');
+    }
   }
 
   test_inc_propertyAccess_super() async {
@@ -571,18 +949,52 @@
 }
 ''');
 
-    assertPostfixExpression(
-      findNode.postfix('x++'),
-      readElement: findElement.getter('x', of: 'A'),
-      readType: 'int',
-      writeElement: findElement.setter('x', of: 'A'),
-      writeType: 'num',
-      element: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'int',
-    );
+    var node = findNode.postfix('x++');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: PropertyAccess
+    target: SuperExpression
+      superKeyword: super
+      staticType: B
+    operator: .
+    propertyName: SimpleIdentifier
+      token: x
+      staticElement: <null>
+      staticType: null
+    staticType: null
+  operator: ++
+  readElement: self::@class::A::@getter::x
+  readType: int
+  writeElement: self::@class::A::@setter::x
+  writeType: num
+  staticElement: dart:core::@class::num::@method::+
+  staticType: int
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: PropertyAccess
+    target: SuperExpression
+      superKeyword: super
+      staticType: B*
+    operator: .
+    propertyName: SimpleIdentifier
+      token: x
+      staticElement: <null>
+      staticType: null
+    staticType: null
+  operator: ++
+  readElement: self::@class::A::@getter::x
+  readType: int*
+  writeElement: self::@class::A::@setter::x
+  writeType: num*
+  staticElement: MethodMember
+    base: dart:core::@class::num::@method::+
+    isLegacy: true
+  staticType: int*
+''');
+    }
   }
 
   test_inc_propertyAccess_this() async {
@@ -597,18 +1009,52 @@
 }
 ''');
 
-    assertPostfixExpression(
-      findNode.postfix('x++'),
-      readElement: findElement.getter('x'),
-      readType: 'int',
-      writeElement: findElement.setter('x'),
-      writeType: 'num',
-      element: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'int',
-    );
+    var node = findNode.postfix('x++');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: PropertyAccess
+    target: ThisExpression
+      thisKeyword: this
+      staticType: A
+    operator: .
+    propertyName: SimpleIdentifier
+      token: x
+      staticElement: <null>
+      staticType: null
+    staticType: null
+  operator: ++
+  readElement: self::@class::A::@getter::x
+  readType: int
+  writeElement: self::@class::A::@setter::x
+  writeType: num
+  staticElement: dart:core::@class::num::@method::+
+  staticType: int
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: PropertyAccess
+    target: ThisExpression
+      thisKeyword: this
+      staticType: A*
+    operator: .
+    propertyName: SimpleIdentifier
+      token: x
+      staticElement: <null>
+      staticType: null
+    staticType: null
+  operator: ++
+  readElement: self::@class::A::@getter::x
+  readType: int*
+  writeElement: self::@class::A::@setter::x
+  writeType: num*
+  staticElement: MethodMember
+    base: dart:core::@class::num::@method::+
+    isLegacy: true
+  staticType: int*
+''');
+    }
   }
 
   test_inc_simpleIdentifier_parameter_double() async {
@@ -618,18 +1064,40 @@
 }
 ''');
 
-    assertPostfixExpression(
-      findNode.postfix('x++'),
-      readElement: findElement.parameter('x'),
-      readType: 'double',
-      writeElement: findElement.parameter('x'),
-      writeType: 'double',
-      element: elementMatcher(
-        doubleElement.getMethod('+'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'double',
-    );
+    var node = findNode.postfix('x++');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@14
+    staticType: null
+  operator: ++
+  readElement: x@14
+  readType: double
+  writeElement: x@14
+  writeType: double
+  staticElement: dart:core::@class::double::@method::+
+  staticType: double
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@14
+    staticType: null
+  operator: ++
+  readElement: x@14
+  readType: double*
+  writeElement: x@14
+  writeType: double*
+  staticElement: MethodMember
+    base: dart:core::@class::double::@method::+
+    isLegacy: true
+  staticType: double*
+''');
+    }
   }
 
   test_inc_simpleIdentifier_parameter_int() async {
@@ -639,18 +1107,40 @@
 }
 ''');
 
-    assertPostfixExpression(
-      findNode.postfix('x++'),
-      readElement: findElement.parameter('x'),
-      readType: 'int',
-      writeElement: findElement.parameter('x'),
-      writeType: 'int',
-      element: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'int',
-    );
+    var node = findNode.postfix('x++');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@11
+    staticType: null
+  operator: ++
+  readElement: x@11
+  readType: int
+  writeElement: x@11
+  writeType: int
+  staticElement: dart:core::@class::num::@method::+
+  staticType: int
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@11
+    staticType: null
+  operator: ++
+  readElement: x@11
+  readType: int*
+  writeElement: x@11
+  writeType: int*
+  staticElement: MethodMember
+    base: dart:core::@class::num::@method::+
+    isLegacy: true
+  staticType: int*
+''');
+    }
   }
 
   test_inc_simpleIdentifier_parameter_num() async {
@@ -660,18 +1150,40 @@
 }
 ''');
 
-    assertPostfixExpression(
-      findNode.postfix('x++'),
-      readElement: findElement.parameter('x'),
-      readType: 'num',
-      writeElement: findElement.parameter('x'),
-      writeType: 'num',
-      element: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'num',
-    );
+    var node = findNode.postfix('x++');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@11
+    staticType: null
+  operator: ++
+  readElement: x@11
+  readType: num
+  writeElement: x@11
+  writeType: num
+  staticElement: dart:core::@class::num::@method::+
+  staticType: num
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@11
+    staticType: null
+  operator: ++
+  readElement: x@11
+  readType: num*
+  writeElement: x@11
+  writeType: num*
+  staticElement: MethodMember
+    base: dart:core::@class::num::@method::+
+    isLegacy: true
+  staticType: num*
+''');
+    }
   }
 
   test_inc_simpleIdentifier_thisGetter_superSetter() async {
@@ -688,22 +1200,43 @@
 }
 ''');
 
-    var postfix = findNode.postfix('x++');
-    assertPostfixExpression(
-      postfix,
-      readElement: findElement.getter('x'),
-      readType: 'int',
-      writeElement: findElement.setter('x'),
-      writeType: 'num',
-      element: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'int',
-    );
+    var node = findNode.postfix('x++');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: SimpleIdentifier
+    token: x
+    staticElement: <null>
+    staticType: null
+  operator: ++
+  readElement: self::@class::B::@getter::x
+  readType: int
+  writeElement: self::@class::A::@setter::x
+  writeType: num
+  staticElement: dart:core::@class::num::@method::+
+  staticType: int
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: SimpleIdentifier
+    token: x
+    staticElement: <null>
+    staticType: null
+  operator: ++
+  readElement: self::@class::B::@getter::x
+  readType: int*
+  writeElement: self::@class::A::@setter::x
+  writeType: num*
+  staticElement: MethodMember
+    base: dart:core::@class::num::@method::+
+    isLegacy: true
+  staticType: int*
+''');
+    }
 
     assertSimpleIdentifierAssignmentTarget(
-      postfix.operand,
+      node.operand,
     );
   }
 
@@ -718,22 +1251,43 @@
 }
 ''');
 
-    var postfix = findNode.postfix('x++');
-    assertPostfixExpression(
-      postfix,
-      readElement: findElement.topGet('x'),
-      readType: 'int',
-      writeElement: findElement.topSet('x'),
-      writeType: 'num',
-      element: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'int',
-    );
+    var node = findNode.postfix('x++');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: SimpleIdentifier
+    token: x
+    staticElement: <null>
+    staticType: null
+  operator: ++
+  readElement: self::@getter::x
+  readType: int
+  writeElement: self::@setter::x
+  writeType: num
+  staticElement: dart:core::@class::num::@method::+
+  staticType: int
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: SimpleIdentifier
+    token: x
+    staticElement: <null>
+    staticType: null
+  operator: ++
+  readElement: self::@getter::x
+  readType: int*
+  writeElement: self::@setter::x
+  writeType: num*
+  staticElement: MethodMember
+    base: dart:core::@class::num::@method::+
+    isLegacy: true
+  staticType: int*
+''');
+    }
 
     assertSimpleIdentifierAssignmentTarget(
-      postfix.operand,
+      node.operand,
     );
   }
 
@@ -750,22 +1304,43 @@
 }
 ''');
 
-    var postfix = findNode.postfix('x++');
-    assertPostfixExpression(
-      postfix,
-      readElement: findElement.topGet('x'),
-      readType: 'int',
-      writeElement: findElement.topSet('x'),
-      writeType: 'num',
-      element: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'int',
-    );
+    var node = findNode.postfix('x++');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: SimpleIdentifier
+    token: x
+    staticElement: <null>
+    staticType: null
+  operator: ++
+  readElement: self::@getter::x
+  readType: int
+  writeElement: self::@setter::x
+  writeType: num
+  staticElement: dart:core::@class::num::@method::+
+  staticType: int
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PostfixExpression
+  operand: SimpleIdentifier
+    token: x
+    staticElement: <null>
+    staticType: null
+  operator: ++
+  readElement: self::@getter::x
+  readType: int*
+  writeElement: self::@setter::x
+  writeType: num*
+  staticElement: MethodMember
+    base: dart:core::@class::num::@method::+
+    isLegacy: true
+  staticType: int*
+''');
+    }
 
     assertSimpleIdentifierAssignmentTarget(
-      postfix.operand,
+      node.operand,
     );
   }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart
index 24948fe..59238ca 100644
--- a/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/prefix_expression_test.dart
@@ -2,7 +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.
 
-import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/error/syntactic_errors.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -33,15 +32,23 @@
           55, 6),
     ]);
 
-    assertPrefixExpression(
-      findNode.prefix('!a'),
-      readElement: null,
-      readType: null,
-      writeElement: null,
-      writeType: null,
-      element: boolElement.getMethod('!'),
-      type: 'bool',
-    );
+    assertResolvedNodeText(findNode.prefix('!a'), r'''
+PrefixExpression
+  operator: !
+  operand: PropertyAccess
+    target: SimpleIdentifier
+      token: a
+      staticElement: a@47
+      staticType: A?
+    operator: ?.
+    propertyName: SimpleIdentifier
+      token: foo
+      staticElement: self::@class::A::@getter::foo
+      staticType: bool
+    staticType: bool?
+  staticElement: <null>
+  staticType: bool
+''');
   }
 
   test_minus_no_nullShorting() async {
@@ -58,15 +65,23 @@
           50, 1),
     ]);
 
-    assertPrefixExpression(
-      findNode.prefix('-a'),
-      readElement: null,
-      readType: null,
-      writeElement: null,
-      writeType: null,
-      element: intElement.getMethod('unary-'),
-      type: 'int',
-    );
+    assertResolvedNodeText(findNode.prefix('-a'), r'''
+PrefixExpression
+  operator: -
+  operand: PropertyAccess
+    target: SimpleIdentifier
+      token: a
+      staticElement: a@43
+      staticType: A?
+    operator: ?.
+    propertyName: SimpleIdentifier
+      token: foo
+      staticElement: self::@class::A::@getter::foo
+      staticType: int
+    staticType: int?
+  staticElement: dart:core::@class::int::@method::unary-
+  staticType: int
+''');
   }
 
   test_plusPlus_depromote() async {
@@ -82,15 +97,20 @@
 }
 ''');
 
-    assertPrefixExpression(
-      findNode.prefix('++x'),
-      readElement: findElement.parameter('x'),
-      readType: 'A',
-      writeElement: findElement.parameter('x'),
-      writeType: 'Object',
-      element: findElement.method('+'),
-      type: 'Object',
-    );
+    assertResolvedNodeText(findNode.prefix('++x'), r'''
+PrefixExpression
+  operator: ++
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@63
+    staticType: null
+  readElement: x@63
+  readType: A
+  writeElement: x@63
+  writeType: Object
+  staticElement: self::@class::A::@method::+
+  staticType: Object
+''');
   }
 
   test_plusPlus_nullShorting() async {
@@ -104,15 +124,27 @@
 }
 ''');
 
-    assertPrefixExpression(
-      findNode.prefix('++a'),
-      readElement: findElement.getter('foo'),
-      readType: 'int',
-      writeElement: findElement.setter('foo'),
-      writeType: 'int',
-      element: numElement.getMethod('+'),
-      type: 'int?',
-    );
+    assertResolvedNodeText(findNode.prefix('++a'), r'''
+PrefixExpression
+  operator: ++
+  operand: PropertyAccess
+    target: SimpleIdentifier
+      token: a
+      staticElement: a@38
+      staticType: A?
+    operator: ?.
+    propertyName: SimpleIdentifier
+      token: foo
+      staticElement: <null>
+      staticType: null
+    staticType: null
+  readElement: self::@class::A::@getter::foo
+  readType: int
+  writeElement: self::@class::A::@setter::foo
+  writeType: int
+  staticElement: dart:core::@class::num::@method::+
+  staticType: int?
+''');
   }
 
   test_tilde_no_nullShorting() async {
@@ -129,15 +161,23 @@
           50, 1),
     ]);
 
-    assertPrefixExpression(
-      findNode.prefix('~a'),
-      readElement: null,
-      readType: null,
-      writeElement: null,
-      writeType: null,
-      element: intElement.getMethod('~'),
-      type: 'int',
-    );
+    assertResolvedNodeText(findNode.prefix('~a'), r'''
+PrefixExpression
+  operator: ~
+  operand: PropertyAccess
+    target: SimpleIdentifier
+      token: a
+      staticElement: a@43
+      staticType: A?
+    operator: ?.
+    propertyName: SimpleIdentifier
+      token: foo
+      staticElement: self::@class::A::@getter::foo
+      staticType: int
+    staticType: int?
+  staticElement: dart:core::@class::int::@method::~
+  staticType: int
+''');
   }
 }
 
@@ -161,15 +201,46 @@
       type: 'bool',
     );
 
-    assertPrefixExpression(
-      findNode.prefix('!f()'),
-      readElement: null,
-      readType: null,
-      writeElement: null,
-      writeType: null,
-      element: boolElement.getMethod('!'),
-      type: 'bool',
-    );
+    var node = findNode.prefix('!f()');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: !
+  operand: MethodInvocation
+    methodName: SimpleIdentifier
+      token: f
+      staticElement: self::@function::f
+      staticType: T Function<T>()
+    argumentList: ArgumentList
+      leftParenthesis: (
+      rightParenthesis: )
+    staticInvokeType: bool Function()
+    staticType: bool
+    typeArgumentTypes
+      bool
+  staticElement: <null>
+  staticType: bool
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: !
+  operand: MethodInvocation
+    methodName: SimpleIdentifier
+      token: f
+      staticElement: self::@function::f
+      staticType: T* Function<T>()*
+    argumentList: ArgumentList
+      leftParenthesis: (
+      rightParenthesis: )
+    staticInvokeType: bool* Function()*
+    staticType: bool*
+    typeArgumentTypes
+      bool*
+  staticElement: <null>
+  staticType: bool*
+''');
+    }
   }
 
   test_bang_bool_localVariable() async {
@@ -179,15 +250,30 @@
 }
 ''');
 
-    assertPrefixExpression(
-      findNode.prefix('!x'),
-      readElement: null,
-      readType: null,
-      writeElement: null,
-      writeType: null,
-      element: boolElement.getMethod('!'),
-      type: 'bool',
-    );
+    var node = findNode.prefix('!x');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: !
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@12
+    staticType: bool
+  staticElement: <null>
+  staticType: bool
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: !
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@12
+    staticType: bool*
+  staticElement: <null>
+  staticType: bool*
+''');
+    }
   }
 
   test_bang_int_localVariable() async {
@@ -199,15 +285,30 @@
       error(CompileTimeErrorCode.NON_BOOL_NEGATION_EXPRESSION, 19, 1),
     ]);
 
-    assertPrefixExpression(
-      findNode.prefix('!x'),
-      readElement: null,
-      readType: null,
-      writeElement: null,
-      writeType: null,
-      element: null,
-      type: 'bool',
-    );
+    var node = findNode.prefix('!x');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: !
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@11
+    staticType: int
+  staticElement: <null>
+  staticType: bool
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: !
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@11
+    staticType: int*
+  staticElement: <null>
+  staticType: bool*
+''');
+    }
   }
 
   test_inc_indexExpression_instance() async {
@@ -222,18 +323,56 @@
 }
 ''');
 
-    assertPrefixExpression(
-      findNode.prefix('++'),
-      readElement: findElement.method('[]'),
-      readType: 'int',
-      writeElement: findElement.method('[]='),
-      writeType: 'num',
-      element: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'int',
-    );
+    var node = findNode.prefix('++');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: IndexExpression
+    target: SimpleIdentifier
+      token: a
+      staticElement: a@91
+      staticType: A
+    leftBracket: [
+    index: IntegerLiteral
+      literal: 0
+      staticType: int
+    rightBracket: ]
+    staticElement: <null>
+    staticType: null
+  readElement: self::@class::A::@method::[]
+  readType: int
+  writeElement: self::@class::A::@method::[]=
+  writeType: num
+  staticElement: dart:core::@class::num::@method::+
+  staticType: int
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: IndexExpression
+    target: SimpleIdentifier
+      token: a
+      staticElement: a@91
+      staticType: A*
+    leftBracket: [
+    index: IntegerLiteral
+      literal: 0
+      staticType: int*
+    rightBracket: ]
+    staticElement: <null>
+    staticType: null
+  readElement: self::@class::A::@method::[]
+  readType: int*
+  writeElement: self::@class::A::@method::[]=
+  writeType: num*
+  staticElement: MethodMember
+    base: dart:core::@class::num::@method::+
+    isLegacy: true
+  staticType: int*
+''');
+    }
   }
 
   test_inc_indexExpression_super() async {
@@ -250,18 +389,54 @@
 }
 ''');
 
-    assertPrefixExpression(
-      findNode.prefix('++'),
-      readElement: findElement.method('[]'),
-      readType: 'int',
-      writeElement: findElement.method('[]='),
-      writeType: 'num',
-      element: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'int',
-    );
+    var node = findNode.prefix('++');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: IndexExpression
+    target: SuperExpression
+      superKeyword: super
+      staticType: B
+    leftBracket: [
+    index: IntegerLiteral
+      literal: 0
+      staticType: int
+    rightBracket: ]
+    staticElement: <null>
+    staticType: null
+  readElement: self::@class::A::@method::[]
+  readType: int
+  writeElement: self::@class::A::@method::[]=
+  writeType: num
+  staticElement: dart:core::@class::num::@method::+
+  staticType: int
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: IndexExpression
+    target: SuperExpression
+      superKeyword: super
+      staticType: B*
+    leftBracket: [
+    index: IntegerLiteral
+      literal: 0
+      staticType: int*
+    rightBracket: ]
+    staticElement: <null>
+    staticType: null
+  readElement: self::@class::A::@method::[]
+  readType: int*
+  writeElement: self::@class::A::@method::[]=
+  writeType: num*
+  staticElement: MethodMember
+    base: dart:core::@class::num::@method::+
+    isLegacy: true
+  staticType: int*
+''');
+    }
   }
 
   test_inc_indexExpression_this() async {
@@ -276,18 +451,54 @@
 }
 ''');
 
-    assertPrefixExpression(
-      findNode.prefix('++'),
-      readElement: findElement.method('[]'),
-      readType: 'int',
-      writeElement: findElement.method('[]='),
-      writeType: 'num',
-      element: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'int',
-    );
+    var node = findNode.prefix('++');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: IndexExpression
+    target: ThisExpression
+      thisKeyword: this
+      staticType: A
+    leftBracket: [
+    index: IntegerLiteral
+      literal: 0
+      staticType: int
+    rightBracket: ]
+    staticElement: <null>
+    staticType: null
+  readElement: self::@class::A::@method::[]
+  readType: int
+  writeElement: self::@class::A::@method::[]=
+  writeType: num
+  staticElement: dart:core::@class::num::@method::+
+  staticType: int
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: IndexExpression
+    target: ThisExpression
+      thisKeyword: this
+      staticType: A*
+    leftBracket: [
+    index: IntegerLiteral
+      literal: 0
+      staticType: int*
+    rightBracket: ]
+    staticElement: <null>
+    staticType: null
+  readElement: self::@class::A::@method::[]
+  readType: int*
+  writeElement: self::@class::A::@method::[]=
+  writeType: num*
+  staticElement: MethodMember
+    base: dart:core::@class::num::@method::+
+    isLegacy: true
+  staticType: int*
+''');
+    }
   }
 
   test_minus_simpleIdentifier_parameter_int() async {
@@ -297,18 +508,32 @@
 }
 ''');
 
-    assertPrefixExpression(
-      findNode.prefix('-x'),
-      readElement: null,
-      readType: null,
-      writeElement: null,
-      writeType: null,
-      element: elementMatcher(
-        intElement.getMethod('unary-'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'int',
-    );
+    var node = findNode.prefix('-x');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: -
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@11
+    staticType: int
+  staticElement: dart:core::@class::int::@method::unary-
+  staticType: int
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: -
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@11
+    staticType: int*
+  staticElement: MethodMember
+    base: dart:core::@class::int::@method::unary-
+    isLegacy: true
+  staticType: int*
+''');
+    }
   }
 
   test_plusPlus_notLValue_extensionOverride() async {
@@ -328,15 +553,60 @@
       error(ParserErrorCode.MISSING_ASSIGNABLE_SELECTOR, 103, 1),
     ]);
 
-    assertPrefixExpression(
-      findNode.prefix('++Ext'),
-      readElement: null,
-      readType: 'dynamic',
-      writeElement: null,
-      writeType: 'dynamic',
-      element: findElement.method('+'),
-      type: 'int',
-    );
+    var node = findNode.prefix('++Ext');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: ExtensionOverride
+    extensionName: SimpleIdentifier
+      token: Ext
+      staticElement: self::@extension::Ext
+      staticType: null
+    argumentList: ArgumentList
+      leftParenthesis: (
+      arguments
+        SimpleIdentifier
+          token: c
+          staticElement: c@89
+          staticType: C
+      rightParenthesis: )
+    extendedType: C
+    staticType: null
+  readElement: <null>
+  readType: dynamic
+  writeElement: <null>
+  writeType: dynamic
+  staticElement: self::@extension::Ext::@method::+
+  staticType: int
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: ExtensionOverride
+    extensionName: SimpleIdentifier
+      token: Ext
+      staticElement: self::@extension::Ext
+      staticType: null
+    argumentList: ArgumentList
+      leftParenthesis: (
+      arguments
+        SimpleIdentifier
+          token: c
+          staticElement: c@89
+          staticType: C*
+      rightParenthesis: )
+    extendedType: C*
+    staticType: null
+  readElement: <null>
+  readType: dynamic
+  writeElement: <null>
+  writeType: dynamic
+  staticElement: self::@extension::Ext::@method::+
+  staticType: int*
+''');
+    }
   }
 
   test_plusPlus_notLValue_simpleIdentifier_typeLiteral() async {
@@ -348,15 +618,38 @@
       error(CompileTimeErrorCode.ASSIGNMENT_TO_TYPE, 15, 3),
     ]);
 
-    assertPrefixExpression(
-      findNode.prefix('++int'),
-      readElement: intElement,
-      readType: 'dynamic',
-      writeElement: intElement,
-      writeType: 'dynamic',
-      element: null,
-      type: 'dynamic',
-    );
+    var node = findNode.prefix('++int');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: SimpleIdentifier
+    token: int
+    staticElement: <null>
+    staticType: null
+  readElement: dart:core::@class::int
+  readType: dynamic
+  writeElement: dart:core::@class::int
+  writeType: dynamic
+  staticElement: <null>
+  staticType: dynamic
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: SimpleIdentifier
+    token: int
+    staticElement: <null>
+    staticType: null
+  readElement: dart:core::@class::int
+  readType: dynamic
+  writeElement: dart:core::@class::int
+  writeType: dynamic
+  staticElement: <null>
+  staticType: dynamic
+''');
+    }
   }
 
   test_plusPlus_prefixedIdentifier_instance() async {
@@ -370,18 +663,56 @@
 }
 ''');
 
-    assertPrefixExpression(
-      findNode.prefix('++'),
-      readElement: findElement.getter('x'),
-      readType: 'int',
-      writeElement: findElement.setter('x'),
-      writeType: 'int',
-      element: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'int',
-    );
+    var node = findNode.prefix('++');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: PrefixedIdentifier
+    prefix: SimpleIdentifier
+      token: a
+      staticElement: a@35
+      staticType: A
+    period: .
+    identifier: SimpleIdentifier
+      token: x
+      staticElement: <null>
+      staticType: null
+    staticElement: <null>
+    staticType: null
+  readElement: self::@class::A::@getter::x
+  readType: int
+  writeElement: self::@class::A::@setter::x
+  writeType: int
+  staticElement: dart:core::@class::num::@method::+
+  staticType: int
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: PrefixedIdentifier
+    prefix: SimpleIdentifier
+      token: a
+      staticElement: a@35
+      staticType: A*
+    period: .
+    identifier: SimpleIdentifier
+      token: x
+      staticElement: <null>
+      staticType: null
+    staticElement: <null>
+    staticType: null
+  readElement: self::@class::A::@getter::x
+  readType: int*
+  writeElement: self::@class::A::@setter::x
+  writeType: int*
+  staticElement: MethodMember
+    base: dart:core::@class::num::@method::+
+    isLegacy: true
+  staticType: int*
+''');
+    }
   }
 
   test_plusPlus_prefixedIdentifier_topLevel() async {
@@ -396,24 +727,56 @@
 }
 ''');
 
-    var importFind = findElement.importFind('package:test/a.dart');
-
-    var prefix = findNode.prefix('++');
-    assertPrefixExpression(
-      prefix,
-      readElement: importFind.topGet('x'),
-      readType: 'int',
-      writeElement: importFind.topSet('x'),
-      writeType: 'int',
-      element: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'int',
-    );
-
-    var prefixed = prefix.operand as PrefixedIdentifier;
-    assertImportPrefix(prefixed.prefix, importFind.prefix);
+    var node = findNode.prefix('++');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: PrefixedIdentifier
+    prefix: SimpleIdentifier
+      token: p
+      staticElement: self::@prefix::p
+      staticType: null
+    period: .
+    identifier: SimpleIdentifier
+      token: x
+      staticElement: <null>
+      staticType: null
+    staticElement: <null>
+    staticType: null
+  readElement: package:test/a.dart::@getter::x
+  readType: int
+  writeElement: package:test/a.dart::@setter::x
+  writeType: int
+  staticElement: dart:core::@class::num::@method::+
+  staticType: int
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: PrefixedIdentifier
+    prefix: SimpleIdentifier
+      token: p
+      staticElement: self::@prefix::p
+      staticType: null
+    period: .
+    identifier: SimpleIdentifier
+      token: x
+      staticElement: <null>
+      staticType: null
+    staticElement: <null>
+    staticType: null
+  readElement: package:test/a.dart::@getter::x
+  readType: int*
+  writeElement: package:test/a.dart::@setter::x
+  writeType: int*
+  staticElement: MethodMember
+    base: dart:core::@class::num::@method::+
+    isLegacy: true
+  staticType: int*
+''');
+    }
   }
 
   test_plusPlus_propertyAccess_instance() async {
@@ -427,18 +790,72 @@
 }
 ''');
 
-    assertPrefixExpression(
-      findNode.prefix('++'),
-      readElement: findElement.getter('x'),
-      readType: 'int',
-      writeElement: findElement.setter('x'),
-      writeType: 'int',
-      element: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'int',
-    );
+    var node = findNode.prefix('++');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: PropertyAccess
+    target: InstanceCreationExpression
+      constructorName: ConstructorName
+        type: NamedType
+          name: SimpleIdentifier
+            token: A
+            staticElement: self::@class::A
+            staticType: null
+          type: A
+        staticElement: self::@class::A::@constructor::•
+      argumentList: ArgumentList
+        leftParenthesis: (
+        rightParenthesis: )
+      staticType: A
+    operator: .
+    propertyName: SimpleIdentifier
+      token: x
+      staticElement: <null>
+      staticType: null
+    staticType: null
+  readElement: self::@class::A::@getter::x
+  readType: int
+  writeElement: self::@class::A::@setter::x
+  writeType: int
+  staticElement: dart:core::@class::num::@method::+
+  staticType: int
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: PropertyAccess
+    target: InstanceCreationExpression
+      constructorName: ConstructorName
+        type: NamedType
+          name: SimpleIdentifier
+            token: A
+            staticElement: self::@class::A
+            staticType: null
+          type: A*
+        staticElement: self::@class::A::@constructor::•
+      argumentList: ArgumentList
+        leftParenthesis: (
+        rightParenthesis: )
+      staticType: A*
+    operator: .
+    propertyName: SimpleIdentifier
+      token: x
+      staticElement: <null>
+      staticType: null
+    staticType: null
+  readElement: self::@class::A::@getter::x
+  readType: int*
+  writeElement: self::@class::A::@setter::x
+  writeType: int*
+  staticElement: MethodMember
+    base: dart:core::@class::num::@method::+
+    isLegacy: true
+  staticType: int*
+''');
+    }
   }
 
   test_plusPlus_propertyAccess_super() async {
@@ -458,18 +875,52 @@
 }
 ''');
 
-    assertPrefixExpression(
-      findNode.prefix('++'),
-      readElement: findElement.getter('x', of: 'A'),
-      readType: 'int',
-      writeElement: findElement.setter('x', of: 'A'),
-      writeType: 'num',
-      element: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'int',
-    );
+    var node = findNode.prefix('++');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: PropertyAccess
+    target: SuperExpression
+      superKeyword: super
+      staticType: B
+    operator: .
+    propertyName: SimpleIdentifier
+      token: x
+      staticElement: <null>
+      staticType: null
+    staticType: null
+  readElement: self::@class::A::@getter::x
+  readType: int
+  writeElement: self::@class::A::@setter::x
+  writeType: num
+  staticElement: dart:core::@class::num::@method::+
+  staticType: int
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: PropertyAccess
+    target: SuperExpression
+      superKeyword: super
+      staticType: B*
+    operator: .
+    propertyName: SimpleIdentifier
+      token: x
+      staticElement: <null>
+      staticType: null
+    staticType: null
+  readElement: self::@class::A::@getter::x
+  readType: int*
+  writeElement: self::@class::A::@setter::x
+  writeType: num*
+  staticElement: MethodMember
+    base: dart:core::@class::num::@method::+
+    isLegacy: true
+  staticType: int*
+''');
+    }
   }
 
   test_plusPlus_propertyAccess_this() async {
@@ -484,18 +935,52 @@
 }
 ''');
 
-    assertPrefixExpression(
-      findNode.prefix('++'),
-      readElement: findElement.getter('x'),
-      readType: 'int',
-      writeElement: findElement.setter('x'),
-      writeType: 'num',
-      element: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'int',
-    );
+    var node = findNode.prefix('++');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: PropertyAccess
+    target: ThisExpression
+      thisKeyword: this
+      staticType: A
+    operator: .
+    propertyName: SimpleIdentifier
+      token: x
+      staticElement: <null>
+      staticType: null
+    staticType: null
+  readElement: self::@class::A::@getter::x
+  readType: int
+  writeElement: self::@class::A::@setter::x
+  writeType: num
+  staticElement: dart:core::@class::num::@method::+
+  staticType: int
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: PropertyAccess
+    target: ThisExpression
+      thisKeyword: this
+      staticType: A*
+    operator: .
+    propertyName: SimpleIdentifier
+      token: x
+      staticElement: <null>
+      staticType: null
+    staticType: null
+  readElement: self::@class::A::@getter::x
+  readType: int*
+  writeElement: self::@class::A::@setter::x
+  writeType: num*
+  staticElement: MethodMember
+    base: dart:core::@class::num::@method::+
+    isLegacy: true
+  staticType: int*
+''');
+    }
   }
 
   test_plusPlus_simpleIdentifier_parameter_double() async {
@@ -505,18 +990,40 @@
 }
 ''');
 
-    assertPrefixExpression(
-      findNode.prefix('++x'),
-      readElement: findElement.parameter('x'),
-      readType: 'double',
-      writeElement: findElement.parameter('x'),
-      writeType: 'double',
-      element: elementMatcher(
-        doubleElement.getMethod('+'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'double',
-    );
+    var node = findNode.prefix('++x');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@14
+    staticType: null
+  readElement: x@14
+  readType: double
+  writeElement: x@14
+  writeType: double
+  staticElement: dart:core::@class::double::@method::+
+  staticType: double
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@14
+    staticType: null
+  readElement: x@14
+  readType: double*
+  writeElement: x@14
+  writeType: double*
+  staticElement: MethodMember
+    base: dart:core::@class::double::@method::+
+    isLegacy: true
+  staticType: double*
+''');
+    }
   }
 
   test_plusPlus_simpleIdentifier_parameter_int() async {
@@ -526,18 +1033,40 @@
 }
 ''');
 
-    assertPrefixExpression(
-      findNode.prefix('++x'),
-      readElement: findElement.parameter('x'),
-      readType: 'int',
-      writeElement: findElement.parameter('x'),
-      writeType: 'int',
-      element: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'int',
-    );
+    var node = findNode.prefix('++x');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@11
+    staticType: null
+  readElement: x@11
+  readType: int
+  writeElement: x@11
+  writeType: int
+  staticElement: dart:core::@class::num::@method::+
+  staticType: int
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@11
+    staticType: null
+  readElement: x@11
+  readType: int*
+  writeElement: x@11
+  writeType: int*
+  staticElement: MethodMember
+    base: dart:core::@class::num::@method::+
+    isLegacy: true
+  staticType: int*
+''');
+    }
   }
 
   test_plusPlus_simpleIdentifier_parameter_num() async {
@@ -547,18 +1076,40 @@
 }
 ''');
 
-    assertPrefixExpression(
-      findNode.prefix('++x'),
-      readElement: findElement.parameter('x'),
-      readType: 'num',
-      writeElement: findElement.parameter('x'),
-      writeType: 'num',
-      element: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'num',
-    );
+    var node = findNode.prefix('++x');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@11
+    staticType: null
+  readElement: x@11
+  readType: num
+  writeElement: x@11
+  writeType: num
+  staticElement: dart:core::@class::num::@method::+
+  staticType: num
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@11
+    staticType: null
+  readElement: x@11
+  readType: num*
+  writeElement: x@11
+  writeType: num*
+  staticElement: MethodMember
+    base: dart:core::@class::num::@method::+
+    isLegacy: true
+  staticType: num*
+''');
+    }
   }
 
   test_plusPlus_simpleIdentifier_parameter_typeParameter() async {
@@ -573,18 +1124,40 @@
       ], legacy: []),
     );
 
-    assertPrefixExpression(
-      findNode.prefix('++x'),
-      readElement: findElement.parameter('x'),
-      readType: 'T',
-      writeElement: findElement.parameter('x'),
-      writeType: 'T',
-      element: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'num',
-    );
+    var node = findNode.prefix('++x');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@24
+    staticType: null
+  readElement: x@24
+  readType: T
+  writeElement: x@24
+  writeType: T
+  staticElement: dart:core::@class::num::@method::+
+  staticType: num
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@24
+    staticType: null
+  readElement: x@24
+  readType: T*
+  writeElement: x@24
+  writeType: T*
+  staticElement: MethodMember
+    base: dart:core::@class::num::@method::+
+    isLegacy: true
+  staticType: num*
+''');
+    }
   }
 
   test_plusPlus_simpleIdentifier_thisGetter_superSetter() async {
@@ -601,22 +1174,43 @@
 }
 ''');
 
-    var prefix = findNode.prefix('++x');
-    assertPrefixExpression(
-      prefix,
-      readElement: findElement.getter('x'),
-      readType: 'int',
-      writeElement: findElement.setter('x'),
-      writeType: 'num',
-      element: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'int',
-    );
+    var node = findNode.prefix('++x');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: SimpleIdentifier
+    token: x
+    staticElement: <null>
+    staticType: null
+  readElement: self::@class::B::@getter::x
+  readType: int
+  writeElement: self::@class::A::@setter::x
+  writeType: num
+  staticElement: dart:core::@class::num::@method::+
+  staticType: int
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: SimpleIdentifier
+    token: x
+    staticElement: <null>
+    staticType: null
+  readElement: self::@class::B::@getter::x
+  readType: int*
+  writeElement: self::@class::A::@setter::x
+  writeType: num*
+  staticElement: MethodMember
+    base: dart:core::@class::num::@method::+
+    isLegacy: true
+  staticType: int*
+''');
+    }
 
     assertSimpleIdentifierAssignmentTarget(
-      prefix.operand,
+      node.operand,
     );
   }
 
@@ -631,22 +1225,43 @@
 }
 ''');
 
-    var prefix = findNode.prefix('++x');
-    assertPrefixExpression(
-      prefix,
-      readElement: findElement.getter('x'),
-      readType: 'int',
-      writeElement: findElement.setter('x'),
-      writeType: 'num',
-      element: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'int',
-    );
+    var node = findNode.prefix('++x');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: SimpleIdentifier
+    token: x
+    staticElement: <null>
+    staticType: null
+  readElement: self::@class::A::@getter::x
+  readType: int
+  writeElement: self::@class::A::@setter::x
+  writeType: num
+  staticElement: dart:core::@class::num::@method::+
+  staticType: int
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: SimpleIdentifier
+    token: x
+    staticElement: <null>
+    staticType: null
+  readElement: self::@class::A::@getter::x
+  readType: int*
+  writeElement: self::@class::A::@setter::x
+  writeType: num*
+  staticElement: MethodMember
+    base: dart:core::@class::num::@method::+
+    isLegacy: true
+  staticType: int*
+''');
+    }
 
     assertSimpleIdentifierAssignmentTarget(
-      prefix.operand,
+      node.operand,
     );
   }
 
@@ -661,22 +1276,43 @@
 }
 ''');
 
-    var prefix = findNode.prefix('++x');
-    assertPrefixExpression(
-      prefix,
-      readElement: findElement.topGet('x'),
-      readType: 'int',
-      writeElement: findElement.topSet('x'),
-      writeType: 'num',
-      element: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'int',
-    );
+    var node = findNode.prefix('++x');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: SimpleIdentifier
+    token: x
+    staticElement: <null>
+    staticType: null
+  readElement: self::@getter::x
+  readType: int
+  writeElement: self::@setter::x
+  writeType: num
+  staticElement: dart:core::@class::num::@method::+
+  staticType: int
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: SimpleIdentifier
+    token: x
+    staticElement: <null>
+    staticType: null
+  readElement: self::@getter::x
+  readType: int*
+  writeElement: self::@setter::x
+  writeType: num*
+  staticElement: MethodMember
+    base: dart:core::@class::num::@method::+
+    isLegacy: true
+  staticType: int*
+''');
+    }
 
     assertSimpleIdentifierAssignmentTarget(
-      prefix.operand,
+      node.operand,
     );
   }
 
@@ -693,22 +1329,43 @@
 }
 ''');
 
-    var prefix = findNode.prefix('++x');
-    assertPrefixExpression(
-      prefix,
-      readElement: findElement.topGet('x'),
-      readType: 'int',
-      writeElement: findElement.topSet('x'),
-      writeType: 'num',
-      element: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'int',
-    );
+    var node = findNode.prefix('++x');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: SimpleIdentifier
+    token: x
+    staticElement: <null>
+    staticType: null
+  readElement: self::@getter::x
+  readType: int
+  writeElement: self::@setter::x
+  writeType: num
+  staticElement: dart:core::@class::num::@method::+
+  staticType: int
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: SimpleIdentifier
+    token: x
+    staticElement: <null>
+    staticType: null
+  readElement: self::@getter::x
+  readType: int*
+  writeElement: self::@setter::x
+  writeType: num*
+  staticElement: MethodMember
+    base: dart:core::@class::num::@method::+
+    isLegacy: true
+  staticType: int*
+''');
+    }
 
     assertSimpleIdentifierAssignmentTarget(
-      prefix.operand,
+      node.operand,
     );
   }
 
@@ -723,18 +1380,40 @@
 }
 ''');
 
-    assertPrefixExpression(
-      findNode.prefix('++x'),
-      readElement: findElement.topGet('x'),
-      readType: 'int',
-      writeElement: findElement.topSet('x'),
-      writeType: 'int',
-      element: elementMatcher(
-        numElement.getMethod('+'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'int',
-    );
+    var node = findNode.prefix('++x');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: SimpleIdentifier
+    token: x
+    staticElement: <null>
+    staticType: null
+  readElement: self::@getter::x
+  readType: int
+  writeElement: self::@setter::x
+  writeType: int
+  staticElement: dart:core::@class::num::@method::+
+  staticType: int
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ++
+  operand: SimpleIdentifier
+    token: x
+    staticElement: <null>
+    staticType: null
+  readElement: self::@getter::x
+  readType: int*
+  writeElement: self::@setter::x
+  writeType: int*
+  staticElement: MethodMember
+    base: dart:core::@class::num::@method::+
+    isLegacy: true
+  staticType: int*
+''');
+    }
   }
 
   test_tilde_simpleIdentifier_parameter_int() async {
@@ -744,18 +1423,32 @@
 }
 ''');
 
-    assertPrefixExpression(
-      findNode.prefix('~x'),
-      readElement: null,
-      readType: null,
-      writeElement: null,
-      writeType: null,
-      element: elementMatcher(
-        intElement.getMethod('~'),
-        isLegacy: isLegacyLibrary,
-      ),
-      type: 'int',
-    );
+    var node = findNode.prefix('~x');
+    if (isNullSafetyEnabled) {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ~
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@11
+    staticType: int
+  staticElement: dart:core::@class::int::@method::~
+  staticType: int
+''');
+    } else {
+      assertResolvedNodeText(node, r'''
+PrefixExpression
+  operator: ~
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@11
+    staticType: int*
+  staticElement: MethodMember
+    base: dart:core::@class::int::@method::~
+    isLegacy: true
+  staticType: int*
+''');
+    }
   }
 }
 
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart
index 9dac30e..0495690 100644
--- a/pkg/analyzer/test/src/dart/resolution/resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -593,30 +593,6 @@
     assertType(parameterElement.type, expected);
   }
 
-  void assertPostfixExpression(
-    PostfixExpression node, {
-    required Object? readElement,
-    required String? readType,
-    required Object? writeElement,
-    required String? writeType,
-    required Object? element,
-    required String type,
-  }) {
-    assertCompoundAssignment(
-      node,
-      readElement: readElement,
-      readType: readType,
-      writeElement: writeElement,
-      writeType: writeType,
-    );
-    assertElement(node.staticElement, element);
-    assertType(node, type);
-
-    if (writeElement != null) {
-      _assertUnresolvedAssignmentTarget(node.operand);
-    }
-  }
-
   void assertPrefixedIdentifier(
     PrefixedIdentifier node, {
     required Object? element,
@@ -626,30 +602,6 @@
     assertType(node, type);
   }
 
-  void assertPrefixExpression(
-    PrefixExpression node, {
-    required Object? readElement,
-    required String? readType,
-    required Object? writeElement,
-    required String? writeType,
-    required Object? element,
-    required String type,
-  }) {
-    assertCompoundAssignment(
-      node,
-      readElement: readElement,
-      readType: readType,
-      writeElement: writeElement,
-      writeType: writeType,
-    );
-    assertElement(node.staticElement, element);
-    assertType(node, type);
-
-    if (writeElement != null) {
-      _assertUnresolvedAssignmentTarget(node.operand);
-    }
-  }
-
   void assertPropertyAccess(
     PropertyAccess access,
     Element expectedElement,
diff --git a/pkg/analyzer/test/src/diagnostics/concrete_class_has_enum_superinterface_test.dart b/pkg/analyzer/test/src/diagnostics/concrete_class_has_enum_superinterface_test.dart
index 4b963e3..2a8c23e 100644
--- a/pkg/analyzer/test/src/diagnostics/concrete_class_has_enum_superinterface_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/concrete_class_has_enum_superinterface_test.dart
@@ -59,12 +59,10 @@
   }
 
   test_enum() async {
-    await assertErrorsInCode('''
+    await assertNoErrorsInCode('''
 enum E implements Enum {
   v
 }
-''', [
-      error(CompileTimeErrorCode.CONCRETE_CLASS_HAS_ENUM_SUPERINTERFACE, 18, 4),
-    ]);
+''');
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart
index 96157cc..cc85b0c 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_override_test.dart
@@ -202,6 +202,18 @@
 ''');
   }
 
+  test_issue48468() async {
+    await assertNoErrorsInCode(r'''
+abstract class A {
+  void foo<T extends R, R>();
+}
+
+class B implements A {
+  void foo<T extends R, R>() {}
+}
+''');
+  }
+
   test_method_parameter_functionTyped_optOut_extends_optIn() async {
     newFile('$testPackageLibPath/a.dart', content: r'''
 abstract class A {
diff --git a/pkg/analyzer/test/src/diagnostics/receiver_of_type_never_test.dart b/pkg/analyzer/test/src/diagnostics/receiver_of_type_never_test.dart
index 5707c74..ae6f8b6 100644
--- a/pkg/analyzer/test/src/diagnostics/receiver_of_type_never_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/receiver_of_type_never_test.dart
@@ -463,15 +463,20 @@
       error(HintCode.RECEIVER_OF_TYPE_NEVER, 20, 1),
     ]);
 
-    assertPostfixExpression(
-      findNode.postfix('x++'),
-      readElement: findElement.parameter('x'),
-      readType: 'Never',
-      writeElement: findElement.parameter('x'),
-      writeType: 'Never',
-      element: null,
-      type: 'Never',
-    );
+    assertResolvedNodeText(findNode.postfix('x++'), r'''
+PostfixExpression
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@13
+    staticType: null
+  operator: ++
+  readElement: x@13
+  readType: Never
+  writeElement: x@13
+  writeType: Never
+  staticElement: <null>
+  staticType: Never
+''');
   }
 
   test_postfixExpression_neverQ_plusPlus() async {
@@ -484,15 +489,20 @@
           22, 2),
     ]);
 
-    assertPostfixExpression(
-      findNode.postfix('x++'),
-      readElement: findElement.parameter('x'),
-      readType: 'Never?',
-      writeElement: findElement.parameter('x'),
-      writeType: 'Never?',
-      element: null,
-      type: 'Never?',
-    );
+    assertResolvedNodeText(findNode.postfix('x++'), r'''
+PostfixExpression
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@14
+    staticType: null
+  operator: ++
+  readElement: x@14
+  readType: Never?
+  writeElement: x@14
+  writeType: Never?
+  staticElement: <null>
+  staticType: Never?
+''');
   }
 
   test_prefixExpression_never_plusPlus() async {
@@ -505,15 +515,20 @@
       error(HintCode.RECEIVER_OF_TYPE_NEVER, 22, 1),
     ]);
 
-    assertPrefixExpression(
-      findNode.prefix('++x'),
-      readElement: findElement.parameter('x'),
-      readType: 'Never',
-      writeElement: findElement.parameter('x'),
-      writeType: 'Never',
-      element: null,
-      type: 'Never',
-    );
+    assertResolvedNodeText(findNode.prefix('++x'), r'''
+PrefixExpression
+  operator: ++
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@13
+    staticType: null
+  readElement: x@13
+  readType: Never
+  writeElement: x@13
+  writeType: Never
+  staticElement: <null>
+  staticType: Never
+''');
   }
 
   test_prefixExpression_neverQ_plusPlus() async {
@@ -526,15 +541,20 @@
           21, 2),
     ]);
 
-    assertPrefixExpression(
-      findNode.prefix('++x'),
-      readElement: findElement.parameter('x'),
-      readType: 'Never?',
-      writeElement: findElement.parameter('x'),
-      writeType: 'Never?',
-      element: null,
-      type: 'dynamic',
-    );
+    assertResolvedNodeText(findNode.prefix('++x'), r'''
+PrefixExpression
+  operator: ++
+  operand: SimpleIdentifier
+    token: x
+    staticElement: x@14
+    staticType: null
+  readElement: x@14
+  readType: Never?
+  writeElement: x@14
+  writeType: Never?
+  staticElement: <null>
+  staticType: dynamic
+''');
   }
 
   test_propertyAccess_never_read() async {
diff --git a/pkg/analyzer/test/src/diagnostics/rethrow_outside_catch_test.dart b/pkg/analyzer/test/src/diagnostics/rethrow_outside_catch_test.dart
index ee8c262..717c3a4 100644
--- a/pkg/analyzer/test/src/diagnostics/rethrow_outside_catch_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/rethrow_outside_catch_test.dart
@@ -17,9 +17,37 @@
 class RethrowOutsideCatchTest extends PubPackageResolutionTest {
   test_insideCatch() async {
     await assertNoErrorsInCode(r'''
-class A {
-  void m() {
-    try {} catch (e) {rethrow;}
+void f() {
+  try {} catch (e) {
+    rethrow;
+  }
+}
+''');
+  }
+
+  test_insideCatch_insideClosure() async {
+    await assertErrorsInCode(r'''
+void f() {
+  try {} catch (e) {
+    () {
+      rethrow;
+    };
+  }
+}
+''', [
+      error(CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH, 47, 7),
+    ]);
+  }
+
+  test_insideCatch_insideClosure_insideCatch() async {
+    await assertNoErrorsInCode(r'''
+void f() {
+  try {} catch (e1) {
+    () {
+      try {} catch (e2) {
+        rethrow;
+      }
+    };
   }
 }
 ''');
@@ -27,11 +55,11 @@
 
   test_withoutCatch() async {
     await assertErrorsInCode(r'''
-f() {
+void f() {
   rethrow;
 }
 ''', [
-      error(CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH, 8, 7),
+      error(CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH, 13, 7),
     ]);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart b/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart
index 3540ebc..9671ee1 100644
--- a/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/type_argument_not_matching_bounds_test.dart
@@ -80,6 +80,22 @@
 ''');
   }
 
+  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/48509')
+  test_extensionOverride_optIn_fromOptOut_Null() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+extension E<X extends int> on List<X> {
+  void m() {}
+}
+''');
+
+    await assertNoErrorsInCode(r'''
+// @dart=2.6
+import 'a.dart';
+
+f() => E<Null>([]).m();
+''');
+  }
+
   test_functionReference() async {
     await assertErrorsInCode('''
 void foo<T extends num>(T a) {}
@@ -130,6 +146,19 @@
 ''');
   }
 
+  test_instanceCreation_optIn_fromOptOut_Null() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+class A<X extends int> {}
+''');
+
+    await assertNoErrorsInCode(r'''
+// @dart=2.6
+import 'a.dart';
+
+f() => A<Null>();
+''');
+  }
+
   test_metadata_matching() async {
     await assertNoErrorsInCode(r'''
 class A<T extends num> {
@@ -193,6 +222,20 @@
     ]);
   }
 
+  test_methodInvocation_optIn_fromOptOut_Null() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+class A {
+  void m<X extends int>() {}
+''');
+
+    await assertNoErrorsInCode(r'''
+// @dart=2.6
+import 'a.dart';
+
+f() => A().m<Null>();
+''');
+  }
+
   test_nonFunctionTypeAlias_body_typeArgument_mismatch() async {
     await assertErrorsInCode(r'''
 class A {}
@@ -282,6 +325,23 @@
     ]);
   }
 
+  test_redirectingConstructor_optIn_fromOptOut_Null() async {
+    newFile('$testPackageLibPath/a.dart', content: r'''
+import 'test.dart';
+
+class A<X extends int> implements B {}
+''');
+
+    await assertNoErrorsInCode(r'''
+// @dart=2.6
+import 'a.dart';
+
+class B {
+  factory B() = A<Null>;
+}
+''');
+  }
+
   test_regression_42196() async {
     await assertNoErrorsInCode(r'''
 typedef G<X> = Function(X);
diff --git a/pkg/dartdev/lib/src/analysis_server.dart b/pkg/dartdev/lib/src/analysis_server.dart
index c9fe68b0..d135042 100644
--- a/pkg/dartdev/lib/src/analysis_server.dart
+++ b/pkg/dartdev/lib/src/analysis_server.dart
@@ -44,10 +44,14 @@
 
   Process? _process;
 
-  Completer<bool> _analysisFinished = Completer();
+  /// When not null, this is a [Completer] which completes when analysis has
+  /// finished, otherwise `null`.
+  Completer<bool>? _analysisFinished;
 
   int _id = 0;
 
+  bool _shutdownResponseReceived = false;
+
   Stream<bool> get onAnalyzing {
     // {"event":"server.status","params":{"analysis":{"isAnalyzing":true}}}
     return _streamController('server.status')
@@ -59,7 +63,7 @@
   /// This future completes when we next receive an analysis finished event
   /// (unless there's no current analysis and we've already received a complete
   /// event, in which case this future completes immediately).
-  Future<bool> get analysisFinished => _analysisFinished.future;
+  Future<bool>? get analysisFinished => _analysisFinished?.future;
 
   Stream<FileAnalysisErrors> get onErrors {
     // {"event":"analysis.errors","params":{"file":"/Users/.../lib/main.dart","errors":[]}}
@@ -80,6 +84,11 @@
   final Map<String, StreamController<Map<String, dynamic>>> _streamControllers =
       {};
 
+  /// Completes when an analysis server crash has been detected.
+  Future<void> get onCrash => _onCrash.future;
+
+  final _onCrash = Completer<void>();
+
   final Map<String, Completer<Map<String, dynamic>>> _requestCompleters = {};
 
   Future<void> start({bool setAnalysisRoots = true}) async {
@@ -96,17 +105,41 @@
       if (packagesFile != null) '--packages=${packagesFile!.path}',
     ];
 
-    _process = await startDartProcess(sdk, command);
-    final proc = _process!;
+    final process = await startDartProcess(sdk, command);
+    _process = process;
+    _shutdownResponseReceived = false;
     // This callback hookup can't throw.
-    proc.exitCode.whenComplete(() => _process = null);
+    process.exitCode.whenComplete(() {
+      _process = null;
 
-    final Stream<String> errorStream = proc.stderr
+      if (!_shutdownResponseReceived) {
+        // The process exited unexpectedly. Report the crash.
+        // If `server.error` reported an error, that has been logged by
+        // `_handleServerError`.
+
+        final error = StateError('The analysis server crashed unexpectedly');
+
+        final analysisFinished = _analysisFinished;
+        if (analysisFinished != null && !analysisFinished.isCompleted) {
+          // Complete this completer in order to unstick the process.
+          analysisFinished.completeError(error);
+        }
+
+        // Complete these completers in order to unstick the process.
+        for (final completer in _requestCompleters.values) {
+          completer.completeError(error);
+        }
+
+        _onCrash.complete();
+      }
+    });
+
+    final errorStream = process.stderr
         .transform<String>(utf8.decoder)
         .transform<String>(const LineSplitter());
     errorStream.listen(log.stderr);
 
-    final Stream<String> inStream = proc.stdout
+    final inStream = process.stdout
         .transform<String>(utf8.decoder)
         .transform<String>(const LineSplitter());
     inStream.listen(_handleServerResponse);
@@ -130,12 +163,15 @@
     ];
 
     onAnalyzing.listen((isAnalyzing) {
-      if (isAnalyzing && _analysisFinished.isCompleted) {
+      final analysisFinished = _analysisFinished;
+      if (isAnalyzing && (analysisFinished?.isCompleted ?? true)) {
         // Start a new completer, to be completed when we receive the
         // corresponding analysis complete event.
         _analysisFinished = Completer();
-      } else if (!isAnalyzing && !_analysisFinished.isCompleted) {
-        _analysisFinished.complete(true);
+      } else if (!isAnalyzing &&
+          analysisFinished != null &&
+          !analysisFinished.isCompleted) {
+        analysisFinished.complete(true);
       }
     });
 
@@ -166,6 +202,7 @@
   Future<void> shutdown({Duration timeout = const Duration(seconds: 5)}) async {
     // Request shutdown.
     await _sendCommand('server.shutdown').then((value) {
+      _shutdownResponseReceived = true;
       return null;
     }).timeout(timeout, onTimeout: () async {
       await dispose();
diff --git a/pkg/dartdev/lib/src/commands/analyze.dart b/pkg/dartdev/lib/src/commands/analyze.dart
index 1112fe8..7bcc9c5 100644
--- a/pkg/dartdev/lib/src/commands/analyze.dart
+++ b/pkg/dartdev/lib/src/commands/analyze.dart
@@ -81,7 +81,7 @@
   String get invocation => '${super.invocation} [<directory>]';
 
   @override
-  FutureOr<int> run() async {
+  Future<int> run() async {
     final args = argResults!;
     // Find targets from the 'rest' params.
     final List<io.FileSystemEntity> targets = [];
@@ -135,6 +135,12 @@
       }
     });
 
+    server.onCrash.then((_) {
+      log.stderr('The analysis server shut down unexpectedly.');
+      log.stdout('Please report this at dartbug.com.');
+      io.exit(1);
+    });
+
     await server.analysisFinished;
     analysisFinished = true;
 
diff --git a/pkg/dartdev/lib/src/commands/compile.dart b/pkg/dartdev/lib/src/commands/compile.dart
index 6e3d600..295bc86 100644
--- a/pkg/dartdev/lib/src/commands/compile.dart
+++ b/pkg/dartdev/lib/src/commands/compile.dart
@@ -23,38 +23,21 @@
   final String help;
   final String? abbr;
   final String? defaultsTo;
+  final String? valueHelp;
   final List<String>? allowed;
   final Map<String, String>? allowedHelp;
 
-  Option(
-      {required this.flag,
-      required this.help,
-      this.abbr,
-      this.defaultsTo,
-      this.allowed,
-      this.allowedHelp});
+  const Option({
+    required this.flag,
+    required this.help,
+    this.abbr,
+    this.defaultsTo,
+    this.valueHelp,
+    this.allowed,
+    this.allowedHelp,
+  });
 }
 
-final Map<String, Option> commonOptions = {
-  'outputFile': Option(
-    flag: 'output',
-    abbr: 'o',
-    help: '''
-Write the output to <file name>.
-This can be an absolute or relative path.
-''',
-  ),
-  'verbosity': Option(
-    flag: 'verbosity',
-    help: '''
-Sets the verbosity level of the compilation.
-''',
-    defaultsTo: Verbosity.defaultValue,
-    allowed: Verbosity.allowedValues,
-    allowedHelp: Verbosity.allowedValuesHelp,
-  ),
-};
-
 bool checkFile(String sourcePath) {
   if (!FileSystemEntity.isFileSync(sourcePath)) {
     stderr.writeln('"$sourcePath" file not found.');
@@ -117,19 +100,24 @@
   }) : super(commandName, 'Compile Dart $help', verbose) {
     argParser
       ..addOption(
-        commonOptions['outputFile']!.flag,
-        help: commonOptions['outputFile']!.help,
-        abbr: commonOptions['outputFile']!.abbr,
+        outputFileOption.flag,
+        help: outputFileOption.help,
+        abbr: outputFileOption.abbr,
       )
       ..addOption(
-        commonOptions['verbosity']!.flag,
-        help: commonOptions['verbosity']!.help,
-        abbr: commonOptions['verbosity']!.abbr,
-        defaultsTo: commonOptions['verbosity']!.defaultsTo,
-        allowed: commonOptions['verbosity']!.allowed,
-        allowedHelp: commonOptions['verbosity']!.allowedHelp,
+        verbosityOption.flag,
+        help: verbosityOption.help,
+        abbr: verbosityOption.abbr,
+        defaultsTo: verbosityOption.defaultsTo,
+        allowed: verbosityOption.allowed,
+        allowedHelp: verbosityOption.allowedHelp,
+      )
+      ..addMultiOption(
+        defineOption.flag,
+        help: defineOption.help,
+        abbr: defineOption.abbr,
+        valueHelp: defineOption.valueHelp,
       );
-
     addExperimentalFlags(argParser, verbose);
   }
 
@@ -160,7 +148,7 @@
     }
 
     // Determine output file name.
-    String? outputFile = args[commonOptions['outputFile']!.flag];
+    String? outputFile = args[outputFileOption.flag];
     if (outputFile == null) {
       final inputWithoutDart = sourcePath.endsWith('.dart')
           ? sourcePath.substring(0, sourcePath.length - 5)
@@ -169,12 +157,13 @@
     }
 
     final enabledExperiments = args.enabledExperiments;
+    final environmentVars = args['define'] ?? <String, String>{};
     // Build arguments.
     List<String> buildArgs = [];
     buildArgs.add('--snapshot-kind=$formatName');
     buildArgs.add('--snapshot=${path.canonicalize(outputFile)}');
 
-    String? verbosity = args[commonOptions['verbosity']!.flag];
+    String? verbosity = args[verbosityOption.flag];
     buildArgs.add('--verbosity=$verbosity');
 
     if (enabledExperiments.isNotEmpty) {
@@ -183,6 +172,9 @@
     if (verbose) {
       buildArgs.add('-v');
     }
+    if (environmentVars.isNotEmpty) {
+      buildArgs.addAll(environmentVars.map<String>((e) => '--define=$e'));
+    }
     buildArgs.add(path.canonicalize(sourcePath));
 
     // Add the training arguments.
@@ -214,21 +206,24 @@
   }) : super(commandName, 'Compile Dart $help', verbose) {
     argParser
       ..addOption(
-        commonOptions['outputFile']!.flag,
-        help: commonOptions['outputFile']!.help,
-        abbr: commonOptions['outputFile']!.abbr,
+        outputFileOption.flag,
+        help: outputFileOption.help,
+        abbr: outputFileOption.abbr,
       )
       ..addOption(
-        commonOptions['verbosity']!.flag,
-        help: commonOptions['verbosity']!.help,
-        abbr: commonOptions['verbosity']!.abbr,
-        defaultsTo: commonOptions['verbosity']!.defaultsTo,
-        allowed: commonOptions['verbosity']!.allowed,
-        allowedHelp: commonOptions['verbosity']!.allowedHelp,
+        verbosityOption.flag,
+        help: verbosityOption.help,
+        abbr: verbosityOption.abbr,
+        defaultsTo: verbosityOption.defaultsTo,
+        allowed: verbosityOption.allowed,
+        allowedHelp: verbosityOption.allowedHelp,
       )
-      ..addMultiOption('define', abbr: 'D', valueHelp: 'key=value', help: '''
-Define an environment declaration. To specify multiple declarations, use multiple options or use commas to separate key-value pairs.
-For example: dart compile $commandName -Da=1,b=2 main.dart''')
+      ..addMultiOption(
+        defineOption.flag,
+        help: defineOption.help,
+        abbr: defineOption.abbr,
+        valueHelp: defineOption.valueHelp,
+      )
       ..addFlag('enable-asserts',
           negatable: false, help: 'Enable assert statements.')
       ..addOption('packages',
@@ -307,9 +302,36 @@
 }
 
 abstract class CompileSubcommandCommand extends DartdevCommand {
+  final outputFileOption = Option(
+    flag: 'output',
+    abbr: 'o',
+    help: '''
+Write the output to <file name>.
+This can be an absolute or relative path.
+''',
+  );
+  final verbosityOption = Option(
+    flag: 'verbosity',
+    help: '''
+Sets the verbosity level of the compilation.
+''',
+    defaultsTo: Verbosity.defaultValue,
+    allowed: Verbosity.allowedValues,
+    allowedHelp: Verbosity.allowedValuesHelp,
+  );
+  late final Option defineOption;
+
   CompileSubcommandCommand(String name, String description, bool verbose,
       {bool hidden = false})
-      : super(name, description, verbose, hidden: hidden);
+      : defineOption = Option(
+          flag: 'define',
+          abbr: 'D',
+          valueHelp: 'key=value',
+          help: '''
+Define an environment declaration. To specify multiple declarations, use multiple options or use commas to separate key-value pairs.
+For example: dart compile $name -Da=1,b=2 main.dart''',
+        ),
+        super(name, description, verbose, hidden: hidden);
 }
 
 class CompileCommand extends DartdevCommand {
diff --git a/pkg/dartdev/lib/src/commands/fix.dart b/pkg/dartdev/lib/src/commands/fix.dart
index aea2ecb..dffebaa 100644
--- a/pkg/dartdev/lib/src/commands/fix.dart
+++ b/pkg/dartdev/lib/src/commands/fix.dart
@@ -64,7 +64,7 @@
   }
 
   @override
-  FutureOr<int> run() async {
+  Future<int> run() async {
     final args = argResults!;
     var dryRun = args['dry-run'];
     var inTestMode = args['compare-to-golden'];
@@ -112,6 +112,12 @@
       }
     });
 
+    server.onCrash.then((_) {
+      log.stderr('The analysis server shut down unexpectedly.');
+      log.stdout('Please report this at dartbug.com.');
+      io.exit(1);
+    });
+
     Future<Map<String, BulkFix>> _applyAllEdits() async {
       var detailsMap = <String, BulkFix>{};
       List<SourceFileEdit> edits;
diff --git a/pkg/dartdev/test/commands/compile_test.dart b/pkg/dartdev/test/commands/compile_test.dart
index 82478e9..bac5e34 100644
--- a/pkg/dartdev/test/commands/compile_test.dart
+++ b/pkg/dartdev/test/commands/compile_test.dart
@@ -12,7 +12,7 @@
 const int compileErrorExitCode = 64;
 
 void main() {
-  group('compile', defineCompileTests, timeout: longTimeout);
+  group('compile -', defineCompileTests, timeout: longTimeout);
 }
 
 const String soundNullSafetyMessage = 'Info: Compiling with sound null safety';
@@ -99,6 +99,37 @@
     expect(result.exitCode, 0);
   });
 
+  test('Compile and run jit snapshot with environment variables', () async {
+    final p = project(mainSrc: '''
+        void main() {
+          print('1: ' + const String.fromEnvironment('foo'));
+          print('2: ' + const String.fromEnvironment('bar'));
+        }''');
+    final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
+    final outFile = path.canonicalize(path.join(p.dirPath, 'main.jit'));
+
+    var result = await p.run([
+      'compile',
+      'jit-snapshot',
+      '-Dfoo=bar',
+      '--define=bar=foo',
+      '-o',
+      outFile,
+      '-v',
+      inFile,
+    ]);
+    expect(result.stderr, isEmpty);
+    expect(result.exitCode, 0);
+    final file = File(outFile);
+    expect(file.existsSync(), true, reason: 'File not found: $outFile');
+
+    result = await p.run(['run', 'main.jit']);
+
+    // Ensure the -D and --define arguments were processed correctly.
+    expect(result.stdout, contains('1: bar'));
+    expect(result.stdout, contains('2: foo'));
+  });
+
   test('Compile and run executable', () async {
     final p = project(mainSrc: 'void main() { print("I love executables"); }');
     final inFile = path.canonicalize(path.join(p.dirPath, p.relativeFilePath));
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index d7d2208..9fbb7d0 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -4167,8 +4167,6 @@
       !IsTypedDataViewClassId(class_id) && !IsTypedDataClassId(class_id)) {
     RETURN_TYPE_ERROR(Z, object, 'TypedData');
   }
-  T->DecrementNoSafepointScopeDepth();
-  END_NO_CALLBACK_SCOPE(T);
   if (FLAG_verify_acquired_data) {
     const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
     WeakTable* table = I->group()->api_state()->acquired_table();
@@ -4180,6 +4178,8 @@
     table->SetValue(obj.ptr(), 0);  // Delete entry from table.
     delete ad;
   }
+  T->DecrementNoSafepointScopeDepth();
+  END_NO_CALLBACK_SCOPE(T);
   return Api::Success();
 }
 
diff --git a/tools/VERSION b/tools/VERSION
index f2a49b1..46a6247 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 17
 PATCH 0
-PRERELEASE 170
+PRERELEASE 171
 PRERELEASE_PATCH 0
\ No newline at end of file