Version 2.17.0-201.0.dev

Merge commit '4b0706aec7b69a18f4c30d69d30e461a0c778923' into 'dev'
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
index 01bfc12..5292a02 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart
@@ -7048,11 +7048,17 @@
         // to determine if this is part of a conditional expression
         //
         Listener originalListener = listener;
-        listener = new ForwardingListener();
-        // TODO(danrubel): consider using TokenStreamGhostWriter here
+        TokenStreamRewriter? originalRewriter = cachedRewriter;
+        listener = new NullListener();
+        UndoableTokenStreamRewriter undoableTokenStreamRewriter =
+            new UndoableTokenStreamRewriter();
+        cachedRewriter = undoableTokenStreamRewriter;
         Token afterExpression =
             parseExpressionWithoutCascade(afterIdentifier).next!;
+        // Undo all changes and reset.
+        undoableTokenStreamRewriter.undo();
         listener = originalListener;
+        cachedRewriter = originalRewriter;
 
         if (optional(':', afterExpression)) {
           // Looks like part of a conditional expression.
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
index a1e8437..6ae02e1 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_code_actions.dart
@@ -169,12 +169,13 @@
   /// version of each document being modified so it's important to call this
   /// immediately after computing edits to ensure the document is not modified
   /// before the version number is read.
-  CodeAction _createAssistAction(SourceChange change) {
+  CodeAction _createAssistAction(SourceChange change, ResolvedUnitResult unit) {
     return CodeAction(
       title: change.message,
       kind: toCodeActionKind(change.id, CodeActionKind.Refactor),
       diagnostics: const [],
-      edit: createWorkspaceEdit(server, change),
+      edit: createWorkspaceEdit(server, change,
+          allowSnippets: true, filePath: unit.path, lineInfo: unit.lineInfo),
     );
   }
 
@@ -182,12 +183,14 @@
   /// version of each document being modified so it's important to call this
   /// immediately after computing edits to ensure the document is not modified
   /// before the version number is read.
-  CodeAction _createFixAction(SourceChange change, Diagnostic diagnostic) {
+  CodeAction _createFixAction(
+      SourceChange change, Diagnostic diagnostic, ResolvedUnitResult unit) {
     return CodeAction(
       title: change.message,
       kind: toCodeActionKind(change.id, CodeActionKind.QuickFix),
       diagnostics: [diagnostic],
-      edit: createWorkspaceEdit(server, change),
+      edit: createWorkspaceEdit(server, change,
+          allowSnippets: true, filePath: unit.path, lineInfo: unit.lineInfo),
     );
   }
 
@@ -269,12 +272,12 @@
 
       final codeActions = <CodeAction>[];
       codeActions.addAll(assists.map((assist) {
-        final action = _createAssistAction(assist.change);
+        final action = _createAssistAction(assist.change, unit);
         codeActionPriorities[action] = assist.kind.priority;
         return action;
       }));
       codeActions.addAll(pluginChanges.map((change) {
-        final action = _createAssistAction(change.change);
+        final action = _createAssistAction(change.change, unit);
         codeActionPriorities[action] = change.priority;
         return action;
       }));
@@ -361,7 +364,7 @@
           );
           codeActions.addAll(
             fixes.map((fix) {
-              final action = _createFixAction(fix.change, diagnostic);
+              final action = _createFixAction(fix.change, diagnostic, unit);
               codeActionPriorities[action] = fix.kind.priority;
               return action;
             }),
@@ -382,7 +385,7 @@
       final pluginFixActions = pluginFixes.expand(
         (fix) => fix.fixes.map((fixChange) {
           final action = _createFixAction(
-              fixChange.change, pluginErrorToDiagnostic(fix.error));
+              fixChange.change, pluginErrorToDiagnostic(fix.error), unit);
           codeActionPriorities[action] = fixChange.priority;
           return action;
         }),
diff --git a/pkg/analysis_server/lib/src/lsp/mapping.dart b/pkg/analysis_server/lib/src/lsp/mapping.dart
index 9026e05..8125d9a 100644
--- a/pkg/analysis_server/lib/src/lsp/mapping.dart
+++ b/pkg/analysis_server/lib/src/lsp/mapping.dart
@@ -119,51 +119,74 @@
   return edit;
 }
 
-/// Creates a [lsp.WorkspaceEdit] from a [server.SourceChange] that can include
-/// experimental [server.SnippetTextEdit]s if the client has indicated support
-/// for these in the experimental section of their client capabilities.
+/// Creates a [lsp.WorkspaceEdit] from a [server.SourceChange].
+///
+/// Can return experimental [server.SnippetTextEdit]s if the following are true:
+/// - the client has indicated support for in the experimental section of their
+///   client capabilities, and
+/// - [allowSnippets] is true, and
+/// - [change] contains only a single edit to the single file [filePath]
+/// - [lineInfo] is provided (which should be for the single edited file)
 ///
 /// Note: This code will fetch the version of each document being modified so
 /// it's important to call this immediately after computing edits to ensure
 /// the document is not modified before the version number is read.
 lsp.WorkspaceEdit createWorkspaceEdit(
-    lsp.LspAnalysisServer server, server.SourceChange change) {
+  lsp.LspAnalysisServer server,
+  server.SourceChange change, {
+  // The caller must specify whether snippets are valid here for where they're
+  // sending this edit. Right now, support is limited to CodeActions.
+  bool allowSnippets = false,
+  String? filePath,
+  LineInfo? lineInfo,
+}) {
   // In order to return snippets, we must ensure we are only modifying a single
-  // existing file with a single edit and that there is a linked edit group with
-  // only one position and no suggestions.
-  if (!server.clientCapabilities!.experimentalSnippetTextEdit ||
+  // existing file with a single edit and that there is either a selection or a
+  // linked edit group (otherwise there's no value in snippets).
+  if (!allowSnippets ||
+      !server.clientCapabilities!.experimentalSnippetTextEdit ||
+      !server.clientCapabilities!.documentChanges ||
+      filePath == null ||
+      lineInfo == null ||
       change.edits.length != 1 ||
-      change.edits.first.fileStamp == -1 || // new file
-      change.edits.first.edits.length != 1 ||
-      change.linkedEditGroups.isEmpty ||
-      change.linkedEditGroups.first.positions.length != 1 ||
-      change.linkedEditGroups.first.suggestions.isNotEmpty) {
+      change.edits.single.fileStamp == -1 || // new file
+      change.edits.single.file != filePath ||
+      change.edits.single.edits.length != 1 ||
+      (change.selection == null && change.linkedEditGroups.isEmpty)) {
     return createPlainWorkspaceEdit(server, change.edits);
   }
 
-  // Additionally, the selection must fall within the edit offset.
-  final edit = change.edits.first.edits.first;
-  final selectionOffset = change.linkedEditGroups.first.positions.first.offset;
-  final selectionLength = change.linkedEditGroups.first.length;
+  final fileEdit = change.edits.single;
+  final snippetEdits = toSnippetTextEdits(
+    fileEdit.file,
+    fileEdit,
+    change.linkedEditGroups,
+    lineInfo,
+    selectionOffset: change.selection?.offset,
+  );
 
-  if (selectionOffset < edit.offset ||
-      selectionOffset + selectionLength > edit.offset + edit.length) {
-    return createPlainWorkspaceEdit(server, change.edits);
-  }
+  // Compile the edits into a TextDocumentEdit for this file.
+  final textDocumentEdit = lsp.TextDocumentEdit(
+    textDocument: server.getVersionedDocumentIdentifier(fileEdit.file),
+    edits: snippetEdits
+        .map((e) => Either3<lsp.SnippetTextEdit, lsp.AnnotatedTextEdit,
+            lsp.TextEdit>.t1(e))
+        .toList(),
+  );
 
-  return toWorkspaceEdit(
-      server.clientCapabilities!,
-      change.edits
-          .map((e) => FileEditInformation(
-                server.getVersionedDocumentIdentifier(e.file),
-                // We should never produce edits for a file with no LineInfo.
-                server.getLineInfo(e.file)!,
-                e.edits,
-                selectionOffsetRelative: selectionOffset - edit.offset,
-                selectionLength: selectionLength,
-                newFile: e.fileStamp == -1,
-              ))
-          .toList());
+  // Convert to the union that documentChanges require.
+  final textDocumentEditsAsUnion = Either4<lsp.TextDocumentEdit, lsp.CreateFile,
+      lsp.RenameFile, lsp.DeleteFile>.t1(textDocumentEdit);
+
+  // Convert to the union that documentChanges is.
+  final documentChanges = Either2<
+      List<lsp.TextDocumentEdit>,
+      List<
+          Either4<lsp.TextDocumentEdit, lsp.CreateFile, lsp.RenameFile,
+              lsp.DeleteFile>>>.t2([textDocumentEditsAsUnion]);
+
+  /// Add the textDocumentEdit to a WorkspaceEdit.
+  return lsp.WorkspaceEdit(documentChanges: documentChanges);
 }
 
 lsp.CompletionItemKind? declarationKindToCompletionItemKind(
diff --git a/pkg/analysis_server/lib/src/lsp/snippets.dart b/pkg/analysis_server/lib/src/lsp/snippets.dart
index e88dcaa..0c9d5c6 100644
--- a/pkg/analysis_server/lib/src/lsp/snippets.dart
+++ b/pkg/analysis_server/lib/src/lsp/snippets.dart
@@ -85,6 +85,11 @@
         // Use the index as an ID to keep all related positions together (so
         // the remain "linked").
         linkedGroupId: index,
+        // If there is no selection, no tabstops, and only a single edit group
+        // allow it to be the final tabstop.
+        isFinal: selectionOffset == null &&
+            (tabStopOffsetLengthPairs?.isEmpty ?? false) &&
+            editGroups?.length == 1,
       ),
     );
   }
diff --git a/pkg/analysis_server/lib/src/plugin/plugin_locator.dart b/pkg/analysis_server/lib/src/plugin/plugin_locator.dart
index 4453aea..f5e1247 100644
--- a/pkg/analysis_server/lib/src/plugin/plugin_locator.dart
+++ b/pkg/analysis_server/lib/src/plugin/plugin_locator.dart
@@ -14,9 +14,6 @@
   /// directory.
   static const String defaultPluginFolderName = 'analyzer_plugin';
 
-  /// The name of the `pubspec.yaml` file.
-  static const String pubspecFileName = 'pubspec.yaml';
-
   /// The name of the `tools` directory, in which the default plugin directory
   /// is located.
   static const String toolsFolderName = 'tools';
diff --git a/pkg/analysis_server/lib/src/plugin/plugin_manager.dart b/pkg/analysis_server/lib/src/plugin/plugin_manager.dart
index fa6eee9..7e1578b 100644
--- a/pkg/analysis_server/lib/src/plugin/plugin_manager.dart
+++ b/pkg/analysis_server/lib/src/plugin/plugin_manager.dart
@@ -14,6 +14,7 @@
 import 'package:analyzer/instrumentation/instrumentation.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/util/file_paths.dart' as file_paths;
 import 'package:analyzer/src/util/glob.dart';
 import 'package:analyzer/src/workspace/bazel.dart';
 import 'package:analyzer/src/workspace/gn.dart';
@@ -418,7 +419,7 @@
   @visibleForTesting
   List<String> pathsFor(String pluginPath) {
     var pluginFolder = resourceProvider.getFolder(pluginPath);
-    var pubspecFile = pluginFolder.getChildAssumingFile('pubspec.yaml');
+    var pubspecFile = pluginFolder.getChildAssumingFile(file_paths.pubspecYaml);
     if (!pubspecFile.exists) {
       // If there's no pubspec file, then we don't need to copy the package
       // because we won't be running pub.
@@ -689,7 +690,8 @@
     var stateName = _uniqueDirectoryName(pluginPath) + '.packages';
     var packagesFile = stateFolder.getChildAssumingFile(stateName);
     if (!packagesFile.exists) {
-      var pluginPubspec = pluginFolder.getChildAssumingFile('pubspec.yaml');
+      var pluginPubspec =
+          pluginFolder.getChildAssumingFile(file_paths.pubspecYaml);
       if (!pluginPubspec.exists) {
         return null;
       }
@@ -710,8 +712,8 @@
               if (packageSource != null) {
                 var libDirPath = context.dirname(packageSource.fullName);
                 visitedPackages[packageName] = libDirPath;
-                var pubspecPath =
-                    context.join(context.dirname(libDirPath), 'pubspec.yaml');
+                var pubspecPath = context.join(
+                    context.dirname(libDirPath), file_paths.pubspecYaml);
                 pubspecFiles.add(resourceProvider.getFile(pubspecPath));
               }
             }
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/update_sdk_constraints.dart b/pkg/analysis_server/lib/src/services/correction/dart/update_sdk_constraints.dart
index 16a3c80..68e682f 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/update_sdk_constraints.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/update_sdk_constraints.dart
@@ -7,6 +7,7 @@
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/source/source_range.dart';
 import 'package:analyzer/src/hint/sdk_constraint_extractor.dart';
+import 'package:analyzer/src/util/file_paths.dart' as file_paths;
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
 import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
 
@@ -72,7 +73,7 @@
   File? _findPubspecFile() {
     var file = resourceProvider.getFile(this.file);
     for (var folder in file.parent.withAncestors) {
-      var pubspecFile = folder.getChildAssumingFile('pubspec.yaml');
+      var pubspecFile = folder.getChildAssumingFile(file_paths.pubspecYaml);
       if (pubspecFile.exists) {
         return pubspecFile;
       }
diff --git a/pkg/analysis_server/lib/src/status/diagnostics.dart b/pkg/analysis_server/lib/src/status/diagnostics.dart
index b7f2f61..68863ac 100644
--- a/pkg/analysis_server/lib/src/status/diagnostics.dart
+++ b/pkg/analysis_server/lib/src/status/diagnostics.dart
@@ -30,6 +30,7 @@
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/source/package_map_resolver.dart';
+import 'package:analyzer/src/util/file_paths.dart' as file_paths;
 import 'package:collection/collection.dart';
 import 'package:path/path.dart' as path;
 
@@ -501,8 +502,8 @@
     buf.writeln('<p>');
     buf.writeln(
         writeOption('Has .packages file', folder.getChild('.packages').exists));
-    buf.writeln(writeOption(
-        'Has pubspec.yaml file', folder.getChild('pubspec.yaml').exists));
+    buf.writeln(writeOption('Has pubspec.yaml file',
+        folder.getChild(file_paths.pubspecYaml).exists));
     buf.writeln('</p>');
 
     buf.writeln('</div>');
diff --git a/pkg/analysis_server/test/abstract_context.dart b/pkg/analysis_server/test/abstract_context.dart
index 58804ac..2d8b06f 100644
--- a/pkg/analysis_server/test/abstract_context.dart
+++ b/pkg/analysis_server/test/abstract_context.dart
@@ -50,6 +50,7 @@
   /// class, an empty list if there are no experiments that should be enabled.
   List<String> get experiments => [
         EnableString.enhanced_enums,
+        EnableString.macros,
         EnableString.named_arguments_anywhere,
         EnableString.super_parameters,
       ];
diff --git a/pkg/analysis_server/test/analysis/notification_errors_test.dart b/pkg/analysis_server/test/analysis/notification_errors_test.dart
index 491d5b9..a85cfaefb 100644
--- a/pkg/analysis_server/test/analysis/notification_errors_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_errors_test.dart
@@ -474,8 +474,7 @@
   }
 
   Future<void> test_pubspecFile() async {
-    var filePath = join(projectPath, 'pubspec.yaml');
-    var pubspecFile = newFile(filePath, content: '''
+    var pubspecFile = newPubspecYamlFile(projectPath, '''
 version: 1.3.2
 ''').path;
 
@@ -488,7 +487,7 @@
     var errors = filesErrors[pubspecFile]!;
     expect(errors, hasLength(1));
     var error = errors[0];
-    expect(error.location.file, filePath);
+    expect(error.location.file, pubspecFile);
     expect(error.severity, AnalysisErrorSeverity.WARNING);
     expect(error.type, AnalysisErrorType.STATIC_WARNING);
     //
@@ -512,8 +511,7 @@
     - sort_pub_dependencies
 ''');
 
-    var filePath = join(projectPath, 'pubspec.yaml');
-    var pubspecFile = newFile(filePath, content: '''
+    var pubspecFile = newPubspecYamlFile(projectPath, '''
 name: sample
 
 dependencies:
@@ -530,7 +528,7 @@
     var errors = filesErrors[pubspecFile]!;
     expect(errors, hasLength(1));
     var error = errors[0];
-    expect(error.location.file, filePath);
+    expect(error.location.file, pubspecFile);
     expect(error.severity, AnalysisErrorSeverity.INFO);
     expect(error.type, AnalysisErrorType.LINT);
     //
diff --git a/pkg/analysis_server/test/client/completion_driver_test.dart b/pkg/analysis_server/test/client/completion_driver_test.dart
index 47c6443..6316a24 100644
--- a/pkg/analysis_server/test/client/completion_driver_test.dart
+++ b/pkg/analysis_server/test/client/completion_driver_test.dart
@@ -27,6 +27,10 @@
   late CompletionDriver driver;
   late List<CompletionSuggestion> suggestions;
 
+  bool get isProtocolVersion1 {
+    return protocol == TestingCompletionProtocol.version1;
+  }
+
   bool get isProtocolVersion2 {
     return protocol == TestingCompletionProtocol.version2;
   }
@@ -35,22 +39,6 @@
 
   AnalysisServerOptions get serverOptions => AnalysisServerOptions();
 
-  bool get _isProtocolVersion1 {
-    return protocol == TestingCompletionProtocol.version1;
-  }
-
-  Future<void> addProjectFile(String relativePath, String content) async {
-    newFile('$testPackageRootPath/$relativePath', content: content);
-    // todo (pq): handle more than lib
-    expect(relativePath, startsWith('lib/'));
-    var packageRelativePath = relativePath.substring(4);
-    var uriStr = 'package:test/$packageRelativePath';
-
-    if (_isProtocolVersion1) {
-      await driver.waitForSetWithUri(uriStr);
-    }
-  }
-
   Future<List<CompletionSuggestion>> addTestFile(String content,
       {int? offset}) async {
     driver.addTestFile(content, offset: offset);
@@ -110,9 +98,9 @@
   }
 
   Future<List<CompletionSuggestion>> getSuggestions() async {
-    if (_isProtocolVersion1) {
-      await driver.waitForSetWithUri('dart:core');
-      await driver.waitForSetWithUri('dart:async');
+    if (isProtocolVersion1) {
+      await waitForSetWithUri('dart:core');
+      await waitForSetWithUri('dart:async');
     }
 
     switch (protocol) {
@@ -159,7 +147,7 @@
 ''');
 
     driver = CompletionDriver(
-      supportsAvailableSuggestions: _isProtocolVersion1,
+      supportsAvailableSuggestions: isProtocolVersion1,
       server: this,
     );
     await driver.createProject();
@@ -211,6 +199,10 @@
     return matches.first;
   }
 
+  Future<void> waitForSetWithUri(String uri) {
+    return driver.waitForSetWithUri(uri);
+  }
+
   void _assertNoErrorsInProjectFiles() {
     var errors = <AnalysisError>[];
     driver.filesErrors.forEach((file, fileErrors) {
@@ -304,14 +296,19 @@
 
 mixin CompletionWithSuggestionsTestCases on AbstractCompletionDriverTest {
   Future<void> test_project_filterImports_defaultConstructor() async {
-    await addProjectFile('lib/a.dart', r'''
+    newFile('$testPackageLibPath/a.dart', content: r'''
 class A {}
 ''');
 
-    await addProjectFile('lib/b.dart', r'''
+    newFile('$testPackageLibPath/b.dart', content: r'''
 export 'a.dart';
 ''');
 
+    if (isProtocolVersion1) {
+      await waitForSetWithUri('package:test/a.dart');
+      await waitForSetWithUri('package:test/b.dart');
+    }
+
     await addTestFile('''
 import 'a.dart';
 void f() {
@@ -327,16 +324,21 @@
 
   /// See: https://github.com/dart-lang/sdk/issues/40620
   Future<void> test_project_filterImports_enumValues() async {
-    await addProjectFile('lib/a.dart', r'''
+    newFile('$testPackageLibPath/a.dart', content: r'''
 enum E {
   e,
 }
 ''');
 
-    await addProjectFile('lib/b.dart', r'''
+    newFile('$testPackageLibPath/b.dart', content: r'''
 export 'a.dart';
 ''');
 
+    if (isProtocolVersion1) {
+      await waitForSetWithUri('package:test/a.dart');
+      await waitForSetWithUri('package:test/b.dart');
+    }
+
     await addTestFile('''
 import 'a.dart';
 void f() {
@@ -351,16 +353,21 @@
 
   /// See: https://github.com/dart-lang/sdk/issues/40620
   Future<void> test_project_filterImports_namedConstructors() async {
-    await addProjectFile('lib/a.dart', r'''
+    newFile('$testPackageLibPath/a.dart', content: r'''
 class A {
   A.a();
 }
 ''');
 
-    await addProjectFile('lib/b.dart', r'''
+    newFile('$testPackageLibPath/b.dart', content: r'''
 export 'a.dart';
 ''');
 
+    if (isProtocolVersion1) {
+      await waitForSetWithUri('package:test/a.dart');
+      await waitForSetWithUri('package:test/b.dart');
+    }
+
     await addTestFile('''
 import 'a.dart';
 void f() {
@@ -375,14 +382,19 @@
   }
 
   Future<void> test_project_filterMultipleImports() async {
-    await addProjectFile('lib/a.dart', r'''
+    newFile('$testPackageLibPath/a.dart', content: r'''
 class A {}
 ''');
 
-    await addProjectFile('lib/b.dart', r'''
+    newFile('$testPackageLibPath/b.dart', content: r'''
 export 'a.dart';
 ''');
 
+    if (isProtocolVersion1) {
+      await waitForSetWithUri('package:test/a.dart');
+      await waitForSetWithUri('package:test/b.dart');
+    }
+
     await addTestFile('''
 import 'a.dart';
 import 'b.dart';
@@ -398,7 +410,7 @@
   }
 
   Future<void> test_project_lib() async {
-    await addProjectFile('lib/a.dart', r'''
+    newFile('$testPackageLibPath/a.dart', content: r'''
 class A {}
 enum E {
   e,
@@ -410,6 +422,10 @@
 var v = 0;
 ''');
 
+    if (isProtocolVersion1) {
+      await waitForSetWithUri('package:test/a.dart');
+    }
+
     await addTestFile('''
 void f() {
   ^
@@ -451,12 +467,16 @@
   }
 
   Future<void> test_project_lib_fields_class() async {
-    await addProjectFile('lib/a.dart', r'''
+    newFile('$testPackageLibPath/a.dart', content: r'''
 class A {
   int f = 0;
 }
 ''');
 
+    if (isProtocolVersion1) {
+      await waitForSetWithUri('package:test/a.dart');
+    }
+
     await addTestFile('''
 void m() {
   ^
@@ -467,12 +487,16 @@
   }
 
   Future<void> test_project_lib_fields_static() async {
-    await addProjectFile('lib/a.dart', r'''
+    newFile('$testPackageLibPath/a.dart', content: r'''
 class A {
   static int f = 0;
 }
 ''');
 
+    if (isProtocolVersion1) {
+      await waitForSetWithUri('package:test/a.dart');
+    }
+
     await addTestFile('''
 void f() {
   ^
@@ -486,12 +510,16 @@
   }
 
   Future<void> test_project_lib_getters_class() async {
-    await addProjectFile('lib/a.dart', r'''
+    newFile('$testPackageLibPath/a.dart', content: r'''
 class A {
   int get g => 0;
 }
 ''');
 
+    if (isProtocolVersion1) {
+      await waitForSetWithUri('package:test/a.dart');
+    }
+
     await addTestFile('''
 void f() {
   ^
@@ -502,12 +530,16 @@
   }
 
   Future<void> test_project_lib_getters_static() async {
-    await addProjectFile('lib/a.dart', r'''
+    newFile('$testPackageLibPath/a.dart', content: r'''
 class A {
   static int get g => 0;
 }
 ''');
 
+    if (isProtocolVersion1) {
+      await waitForSetWithUri('package:test/a.dart');
+    }
+
     await addTestFile('''
 void f() {
   ^
@@ -522,10 +554,14 @@
 
   /// See: https://github.com/dart-lang/sdk/issues/40626
   Future<void> test_project_lib_getters_topLevel() async {
-    await addProjectFile('lib/a.dart', r'''
+    newFile('$testPackageLibPath/a.dart', content: r'''
 int get g => 0;
 ''');
 
+    if (isProtocolVersion1) {
+      await waitForSetWithUri('package:test/a.dart');
+    }
+
     await addTestFile('''
 void f() {
   ^
@@ -539,12 +575,16 @@
   }
 
   Future<void> test_project_lib_methods_class() async {
-    await addProjectFile('lib/a.dart', r'''
+    newFile('$testPackageLibPath/a.dart', content: r'''
 class A {
   void foo() => 0;
 }
 ''');
 
+    if (isProtocolVersion1) {
+      await waitForSetWithUri('package:test/a.dart');
+    }
+
     await addTestFile('''
 void f() {
   ^
@@ -555,12 +595,16 @@
   }
 
   Future<void> test_project_lib_methods_static() async {
-    await addProjectFile('lib/a.dart', r'''
+    newFile('$testPackageLibPath/a.dart', content: r'''
 class A {
   static void foo() => 0;
 }
 ''');
 
+    if (isProtocolVersion1) {
+      await waitForSetWithUri('package:test/a.dart');
+    }
+
     await addTestFile('''
 void f() {
   ^
@@ -571,14 +615,19 @@
   }
 
   Future<void> test_project_lib_multipleExports() async {
-    await addProjectFile('lib/a.dart', r'''
+    newFile('$testPackageLibPath/a.dart', content: r'''
 class A {}
 ''');
 
-    await addProjectFile('lib/b.dart', r'''
+    newFile('$testPackageLibPath/b.dart', content: r'''
 export 'a.dart';
 ''');
 
+    if (isProtocolVersion1) {
+      await waitForSetWithUri('package:test/a.dart');
+      await waitForSetWithUri('package:test/b.dart');
+    }
+
     await addTestFile('''
 void f() {
   ^
@@ -593,12 +642,16 @@
   }
 
   Future<void> test_project_lib_setters_class() async {
-    await addProjectFile('lib/a.dart', r'''
+    newFile('$testPackageLibPath/a.dart', content: r'''
 class A {
   set s(int s) {}
 }
 ''');
 
+    if (isProtocolVersion1) {
+      await waitForSetWithUri('package:test/a.dart');
+    }
+
     await addTestFile('''
 void f() {
   ^
@@ -609,12 +662,16 @@
   }
 
   Future<void> test_project_lib_setters_static() async {
-    await addProjectFile('lib/a.dart', r'''
+    newFile('$testPackageLibPath/a.dart', content: r'''
 class A {
   static set g(int g) {}
 }
 ''');
 
+    if (isProtocolVersion1) {
+      await waitForSetWithUri('package:test/a.dart');
+    }
+
     await addTestFile('''
 void f() {
   ^
@@ -626,10 +683,14 @@
 
   /// See: https://github.com/dart-lang/sdk/issues/40626
   Future<void> test_project_lib_setters_topLevel() async {
-    await addProjectFile('lib/a.dart', r'''
+    newFile('$testPackageLibPath/a.dart', content: r'''
 set s(int s) {}
 ''');
 
+    if (isProtocolVersion1) {
+      await waitForSetWithUri('package:test/a.dart');
+    }
+
     await addTestFile('''
 void f() {
   ^
@@ -645,7 +706,7 @@
   @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/38739')
   Future<void>
       test_project_suggestionRelevance_constructorParameterType() async {
-    await addProjectFile('lib/a.dart', r'''
+    newFile('$testPackageLibPath/a.dart', content: r'''
 import 'b.dart';
 
 class A {
@@ -653,10 +714,15 @@
 }
 ''');
 
-    await addProjectFile('lib/b.dart', r'''
+    newFile('$testPackageLibPath/b.dart', content: r'''
 class O { }
 ''');
 
+    if (isProtocolVersion1) {
+      await waitForSetWithUri('package:test/a.dart');
+      await waitForSetWithUri('package:test/b.dart');
+    }
+
     await addTestFile('''
 import 'a.dart';
 
@@ -679,10 +745,14 @@
   }
 
   Future<void> test_project_suggestionRelevance_constructorsAndTypes() async {
-    await addProjectFile('lib/a.dart', r'''
+    newFile('$testPackageLibPath/a.dart', content: r'''
 class A { }
 ''');
 
+    if (isProtocolVersion1) {
+      await waitForSetWithUri('package:test/a.dart');
+    }
+
     await addTestFile('''
 import 'a.dart';
 
@@ -707,11 +777,15 @@
 
   /// See: https://github.com/dart-lang/sdk/issues/35529
   Future<void> test_project_suggestMixins() async {
-    await addProjectFile('lib/a.dart', r'''
+    newFile('$testPackageLibPath/a.dart', content: r'''
 mixin M { }
 class A { }
 ''');
 
+    if (isProtocolVersion1) {
+      await waitForSetWithUri('package:test/a.dart');
+    }
+
     await addTestFile('''
 class C extends Object with ^
 ''');
diff --git a/pkg/analysis_server/test/client/impl/completion_driver.dart b/pkg/analysis_server/test/client/impl/completion_driver.dart
index 095db29..c57c328 100644
--- a/pkg/analysis_server/test/client/impl/completion_driver.dart
+++ b/pkg/analysis_server/test/client/impl/completion_driver.dart
@@ -279,16 +279,12 @@
     } else if (notification.event == SERVER_NOTIFICATION_CONNECTED) {
       // Ignored.
     } else {
-      print('Unhandled notififcation: ${notification.event}');
+      print('Unhandled notification: ${notification.event}');
     }
   }
 
-  Future<AvailableSuggestionSet> waitForSetWithUri(String uri) async {
-    while (true) {
-      var result = uriToSetMap[uri];
-      if (result != null) {
-        return result;
-      }
+  Future<void> waitForSetWithUri(String uri) async {
+    while (uriToSetMap[uri] == null) {
       await Future.delayed(const Duration(milliseconds: 1));
     }
   }
diff --git a/pkg/analysis_server/test/integration/analysis/hint_sdk_version_async_exported_from_core_test.dart b/pkg/analysis_server/test/integration/analysis/hint_sdk_version_async_exported_from_core_test.dart
index 38428ff..f07d1ac 100644
--- a/pkg/analysis_server/test/integration/analysis/hint_sdk_version_async_exported_from_core_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/hint_sdk_version_async_exported_from_core_test.dart
@@ -2,6 +2,7 @@
 // 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/src/util/file_paths.dart' as file_paths;
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -17,7 +18,7 @@
 class SdkVersionAsyncExportedFromCoreIntegrationTest
     extends AbstractAnalysisServerIntegrationTest {
   Future<void> test_update_pubspec() async {
-    var pubspecPath = sourcePath('pubspec.yaml');
+    var pubspecPath = sourcePath(file_paths.pubspecYaml);
     writeFile(pubspecPath, r'''
 name: test
 environment:
diff --git a/pkg/analysis_server/test/lsp/change_workspace_folders_test.dart b/pkg/analysis_server/test/lsp/change_workspace_folders_test.dart
index 98ad357..14ae4a4 100644
--- a/pkg/analysis_server/test/lsp/change_workspace_folders_test.dart
+++ b/pkg/analysis_server/test/lsp/change_workspace_folders_test.dart
@@ -2,6 +2,7 @@
 // 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/src/util/file_paths.dart' as file_paths;
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -32,9 +33,9 @@
     workspaceFolder2Uri = Uri.file(workspaceFolder2Path);
     workspaceFolder3Uri = Uri.file(workspaceFolder3Path);
 
-    newFile(join(workspaceFolder1Path, 'pubspec.yaml'));
-    newFile(join(workspaceFolder2Path, 'pubspec.yaml'));
-    newFile(join(workspaceFolder3Path, 'pubspec.yaml'));
+    newPubspecYamlFile(workspaceFolder1Path, '');
+    newPubspecYamlFile(workspaceFolder2Path, '');
+    newPubspecYamlFile(workspaceFolder3Path, '');
   }
 
   Future<void> test_changeWorkspaceFolders_add() async {
@@ -220,8 +221,14 @@
     final nestedFilePath = join(nestedFolderPath, 'test.dart');
     final nestedFileUri = Uri.file(nestedFilePath);
     newFile(nestedFilePath);
-    deleteFile(join(
-        workspaceFolder1Path, 'pubspec.yaml')); // Ensure no pubspecs in tree.
+
+    // Ensure no pubspecs in tree.
+    deleteFile(
+      join(
+        workspaceFolder1Path,
+        file_paths.pubspecYaml,
+      ),
+    );
 
     await initialize(allowEmptyRootUri: true);
     await openFile(nestedFileUri, '');
diff --git a/pkg/analysis_server/test/lsp/code_actions_assists_test.dart b/pkg/analysis_server/test/lsp/code_actions_assists_test.dart
index cf67637f..68652df 100644
--- a/pkg/analysis_server/test/lsp/code_actions_assists_test.dart
+++ b/pkg/analysis_server/test/lsp/code_actions_assists_test.dart
@@ -249,7 +249,70 @@
     );
   }
 
-  Future<void> test_snippetTextEdits_supported() async {
+  Future<void> test_snippetTextEdits_multiEditGroup() async {
+    // As test_snippetTextEdits_singleEditGroup, but uses an assist that
+    // produces multiple linked edit groups.
+
+    const content = '''
+    import 'package:flutter/widgets.dart';
+    build() {
+      return Container(
+        child: Ro^w(
+          children: [
+            Text('111'),
+            Text('222'),
+            Container(),
+          ],
+        ),
+      );
+    }
+    ''';
+
+    const expectedContent = r'''
+    import 'package:flutter/widgets.dart';
+    build() {
+      return Container(
+        child: ${1:widget}(
+          ${2:child}: Row(
+            children: [
+              Text('111'),
+              Text('222'),
+              Container(),
+            ],
+          ),
+        ),
+      );
+    }
+    ''';
+
+    newFile(mainFilePath, content: withoutMarkers(content));
+    await initialize(
+      textDocumentCapabilities: withCodeActionKinds(
+          emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
+      workspaceCapabilities:
+          withDocumentChangesSupport(emptyWorkspaceClientCapabilities),
+      experimentalCapabilities: {
+        'snippetTextEdit': true,
+      },
+    );
+
+    final codeActions = await getCodeActions(mainFileUri.toString(),
+        position: positionFromMarker(content));
+    final assist = findEditAction(
+        codeActions,
+        CodeActionKind('refactor.flutter.wrap.generic'),
+        'Wrap with widget...')!;
+
+    // Ensure applying the changes will give us the expected content.
+    final edit = assist.edit!;
+    final contents = {
+      mainFilePath: withoutMarkers(content),
+    };
+    applyDocumentChanges(contents, edit.documentChanges!);
+    expect(contents[mainFilePath], equals(expectedContent));
+  }
+
+  Future<void> test_snippetTextEdits_singleEditGroup() async {
     // This tests experimental support for including Snippets in TextEdits.
     // https://github.com/rust-analyzer/rust-analyzer/blob/b35559a2460e7f0b2b79a7029db0c5d4e0acdb44/docs/dev/lsp-extensions.md#snippet-textedit
     //
@@ -273,8 +336,8 @@
     ''';
 
     // For testing, the snippet will be inserted literally into the text, as
-    // this requires some magic on the client. The expected text should therefore
-    // contain the snippets in the standard format.
+    // this requires some magic on the client. The expected text should
+    // therefore contain the snippets in the standard format.
     const expectedContent = r'''
     import 'package:flutter/widgets.dart';
     build() {
@@ -426,6 +489,63 @@
     );
   }
 
+  Future<void> test_surround_editGroupsAndSelection() async {
+    const content = '''
+void f() {
+  [[print(0);]]
+}
+''';
+
+    const expectedContent = r'''
+void f() {
+  if (${1:condition}) {
+    print(0);
+  }$0
+}
+''';
+
+    newFile(mainFilePath, content: withoutMarkers(content));
+    await initialize(
+      textDocumentCapabilities: withCodeActionKinds(
+          emptyTextDocumentClientCapabilities, [CodeActionKind.Refactor]),
+      workspaceCapabilities:
+          withDocumentChangesSupport(emptyWorkspaceClientCapabilities),
+      experimentalCapabilities: {
+        'snippetTextEdit': true,
+      },
+    );
+
+    final codeActions = await getCodeActions(mainFileUri.toString(),
+        range: rangeFromMarkers(content));
+    final assist = findEditAction(codeActions,
+        CodeActionKind('refactor.surround.if'), "Surround with 'if'")!;
+
+    // Ensure the edit came back, and using documentChanges.
+    final edit = assist.edit!;
+    expect(edit.documentChanges, isNotNull);
+    expect(edit.changes, isNull);
+
+    // Ensure applying the changes will give us the expected content.
+    final contents = {
+      mainFilePath: withoutMarkers(content),
+    };
+    applyDocumentChanges(contents, edit.documentChanges!);
+    expect(contents[mainFilePath], equals(expectedContent));
+
+    // Also ensure there was a single edit that was correctly marked
+    // as a SnippetTextEdit.
+    final textEdits = _extractTextDocumentEdits(edit.documentChanges!)
+        .expand((tde) => tde.edits)
+        .map((edit) => edit.map(
+              (e) => e,
+              (e) => throw 'Expected SnippetTextEdit, got AnnotatedTextEdit',
+              (e) => throw 'Expected SnippetTextEdit, got TextEdit',
+            ))
+        .toList();
+    expect(textEdits, hasLength(1));
+    expect(textEdits.first.insertTextFormat, equals(InsertTextFormat.Snippet));
+  }
+
   List<TextDocumentEdit> _extractTextDocumentEdits(
           Either2<
                   List<TextDocumentEdit>,
diff --git a/pkg/analysis_server/test/lsp/initialization_test.dart b/pkg/analysis_server/test/lsp/initialization_test.dart
index 5cf681a..6b43de8 100644
--- a/pkg/analysis_server/test/lsp/initialization_test.dart
+++ b/pkg/analysis_server/test/lsp/initialization_test.dart
@@ -502,8 +502,7 @@
     final file2 = join(projectFolderPath, 'file2.dart');
     final file2Uri = Uri.file(file2);
     newFile(file2);
-    final pubspecPath = join(projectFolderPath, 'pubspec.yaml');
-    newFile(pubspecPath);
+    newPubspecYamlFile(projectFolderPath, '');
 
     await initialize(allowEmptyRootUri: true);
 
@@ -549,8 +548,7 @@
         projectFolderPath, 'nested', 'deeply', 'in', 'folders', 'test.dart');
     final nestedFileUri = Uri.file(nestedFilePath);
     newFile(nestedFilePath);
-    final pubspecPath = join(projectFolderPath, 'pubspec.yaml');
-    newFile(pubspecPath);
+    newPubspecYamlFile(projectFolderPath, '');
 
     // The project folder shouldn't be added to start with.
     await initialize(allowEmptyRootUri: true);
@@ -716,8 +714,7 @@
   }
 
   Future<void> test_nonFileScheme_workspaceFolders() async {
-    final pubspecPath = join(projectFolderPath, 'pubspec.yaml');
-    newFile(pubspecPath);
+    newPubspecYamlFile(projectFolderPath, '');
 
     final rootUri = Uri.parse('vsls://');
     final fileUri = rootUri.replace(path: '/file1.dart');
@@ -788,8 +785,7 @@
     final file2 = join(projectFolderPath, 'file2.dart');
     final file2Uri = Uri.file(file2);
     newFile(file2);
-    final pubspecPath = join(projectFolderPath, 'pubspec.yaml');
-    newFile(pubspecPath);
+    newPubspecYamlFile(projectFolderPath, '');
 
     await initialize(
       rootUri: projectFolderUri,
@@ -842,8 +838,7 @@
         projectFolderPath, 'nested', 'deeply', 'in', 'folders', 'test.dart');
     final nestedFileUri = Uri.file(nestedFilePath);
     newFile(nestedFilePath);
-    final pubspecPath = join(projectFolderPath, 'pubspec.yaml');
-    newFile(pubspecPath);
+    newPubspecYamlFile(projectFolderPath, '');
 
     // The project folder shouldn't be added to start with.
     await initialize(
diff --git a/pkg/analysis_server/test/lsp/server_abstract.dart b/pkg/analysis_server/test/lsp/server_abstract.dart
index f9f3c7d..4d5a6c4 100644
--- a/pkg/analysis_server/test/lsp/server_abstract.dart
+++ b/pkg/analysis_server/test/lsp/server_abstract.dart
@@ -22,6 +22,7 @@
 import 'package:analyzer/src/test_utilities/mock_sdk.dart';
 import 'package:analyzer/src/test_utilities/package_config_file_builder.dart';
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
+import 'package:analyzer/src/util/file_paths.dart' as file_paths;
 import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
 import 'package:analyzer_plugin/src/protocol/protocol_internal.dart' as plugin;
 import 'package:collection/collection.dart';
@@ -212,7 +213,7 @@
     newFile(join(projectFolderPath, 'lib', 'file.dart'));
     mainFilePath = join(projectFolderPath, 'lib', 'main.dart');
     mainFileUri = Uri.file(mainFilePath);
-    pubspecFilePath = join(projectFolderPath, 'pubspec.yaml');
+    pubspecFilePath = join(projectFolderPath, file_paths.pubspecYaml);
     pubspecFileUri = Uri.file(pubspecFilePath);
     analysisOptionsPath = join(projectFolderPath, 'analysis_options.yaml');
     analysisOptionsUri = Uri.file(analysisOptionsPath);
diff --git a/pkg/analysis_server/test/lsp/snippets_test.dart b/pkg/analysis_server/test/lsp/snippets_test.dart
index a126c9b..48cefb0 100644
--- a/pkg/analysis_server/test/lsp/snippets_test.dart
+++ b/pkg/analysis_server/test/lsp/snippets_test.dart
@@ -155,7 +155,7 @@
       ],
     );
     expect(result, equals(r'''
-var ${1|a,aaa,bbb\${\}\,\|,ccc|} = 1;
+var ${0|a,aaa,bbb\${\}\,\|,ccc|} = 1;
 '''));
   }
 
@@ -180,8 +180,8 @@
       ],
     );
     expect(result, equals(r'''
-class $1 {
-  $1();
+class $0 {
+  $0();
 }
 '''));
   }
@@ -208,8 +208,8 @@
       ],
     );
     expect(result, equals(r'''
-class ${1:A} {
-  ${1:A}();
+class ${0:A} {
+  ${0:A}();
 }
 '''));
   }
@@ -235,8 +235,8 @@
       ],
     );
     expect(result, equals(r'''
-class ${1:A} {
-  ${1:A}();
+class ${0:A} {
+  ${0:A}();
 }
 '''));
   }
@@ -264,8 +264,8 @@
       ],
     );
     expect(result, equals(r'''
-class ${1:A} {
-  ${1:A}();
+class ${0:A} {
+  ${0:A}();
 }
 '''));
   }
diff --git a/pkg/analysis_server/test/services/completion/dart/declaration/enum_test.dart b/pkg/analysis_server/test/services/completion/dart/declaration/enum_test.dart
index d154a6e..66a1a19 100644
--- a/pkg/analysis_server/test/services/completion/dart/declaration/enum_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/declaration/enum_test.dart
@@ -59,10 +59,14 @@
   }
 
   Future<void> test_enumConstantName_imported_withPrefix() async {
-    await addProjectFile('lib/a.dart', r'''
+    newFile('$testPackageLibPath/a.dart', content: r'''
 enum MyEnum { foo01 }
 ''');
 
+    if (isProtocolVersion1) {
+      await waitForSetWithUri('package:test/a.dart');
+    }
+
     var response = await getTestCodeSuggestions('''
 import 'a.dart' as prefix;
 
@@ -115,10 +119,14 @@
   }
 
   Future<void> test_enumName_imported_withPrefix() async {
-    await addProjectFile('lib/a.dart', r'''
+    newFile('$testPackageLibPath/a.dart', content: r'''
 enum MyEnum { foo01 }
 ''');
 
+    if (isProtocolVersion1) {
+      await waitForSetWithUri('package:test/a.dart');
+    }
+
     var response = await getTestCodeSuggestions('''
 import 'a.dart' as prefix;
 
@@ -147,10 +155,14 @@
 
   @FailingTest(reason: 'element.kind is LIBRARY')
   Future<void> test_importPrefix() async {
-    await addProjectFile('lib/a.dart', r'''
+    newFile('$testPackageLibPath/a.dart', content: r'''
 enum MyEnum { v }
 ''');
 
+    if (isProtocolVersion1) {
+      await waitForSetWithUri('package:test/a.dart');
+    }
+
     var response = await getTestCodeSuggestions('''
 import 'a.dart' as prefix01;
 
@@ -177,10 +189,14 @@
   }
 
   Future<void> test_importPrefix_dot() async {
-    await addProjectFile('lib/a.dart', r'''
+    newFile('$testPackageLibPath/a.dart', content: r'''
 enum MyEnum { v }
 ''');
 
+    if (isProtocolVersion1) {
+      await waitForSetWithUri('package:test/a.dart');
+    }
+
     var response = await getTestCodeSuggestions('''
 import 'a.dart' as prefix;
 
@@ -230,10 +246,14 @@
   }
 
   Future<void> test_nothing_imported_withPrefix() async {
-    await addProjectFile('lib/a.dart', r'''
+    newFile('$testPackageLibPath/a.dart', content: r'''
 enum MyEnum { v }
 ''');
 
+    if (isProtocolVersion1) {
+      await waitForSetWithUri('package:test/a.dart');
+    }
+
     var response = await getTestCodeSuggestions('''
 import 'a.dart' as prefix;
 
@@ -284,9 +304,12 @@
 
     // imported
     {
-      await addProjectFile('lib/a.dart', '''
+      newFile('$testPackageLibPath/a.dart', content: '''
 $declaration
 ''');
+      if (isProtocolVersion1) {
+        await waitForSetWithUri('package:test/a.dart');
+      }
       var response = await getTestCodeSuggestions('''
 import 'a.dart';
 void f() {
@@ -298,9 +321,12 @@
 
     // not imported
     {
-      await addProjectFile('lib/a.dart', '''
+      newFile('$testPackageLibPath/a.dart', content: '''
 $declaration
 ''');
+      if (isProtocolVersion1) {
+        await waitForSetWithUri('package:test/a.dart');
+      }
       var response = await getTestCodeSuggestions('''
 void f() {
   $codeAtCompletion
diff --git a/pkg/analysis_server/test/src/plugin/plugin_locator_test.dart b/pkg/analysis_server/test/src/plugin/plugin_locator_test.dart
index cf45244..4156e12 100644
--- a/pkg/analysis_server/test/src/plugin/plugin_locator_test.dart
+++ b/pkg/analysis_server/test/src/plugin/plugin_locator_test.dart
@@ -69,9 +69,7 @@
   }
 
   void _createPubspec(String content) {
-    pubspecPath =
-        newFile('/package/${PluginLocator.pubspecFileName}', content: content)
-            .path;
+    pubspecPath = newPubspecYamlFile('/package', content).path;
   }
 
   String _createPubspecWithKey() {
diff --git a/pkg/analysis_server/test/src/plugin/plugin_manager_test.dart b/pkg/analysis_server/test/src/plugin/plugin_manager_test.dart
index ffb6492..d2644f7 100644
--- a/pkg/analysis_server/test/src/plugin/plugin_manager_test.dart
+++ b/pkg/analysis_server/test/src/plugin/plugin_manager_test.dart
@@ -10,6 +10,7 @@
 import 'package:analyzer/instrumentation/instrumentation.dart';
 import 'package:analyzer/src/dart/analysis/context_root.dart';
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
+import 'package:analyzer/src/util/file_paths.dart' as file_paths;
 import 'package:analyzer/src/workspace/basic.dart';
 import 'package:analyzer_plugin/channel/channel.dart';
 import 'package:analyzer_plugin/protocol/protocol.dart';
@@ -760,7 +761,7 @@
       //
       // Create a pubspec.yaml file.
       //
-      var pubspecFile = io.File(path.join(pluginPath, 'pubspec.yaml'));
+      var pubspecFile = io.File(path.join(pluginPath, file_paths.pubspecYaml));
       pubspecFile.writeAsStringSync(_getPubspecFileContent());
       //
       // Create the 'bin' directory.
diff --git a/pkg/analysis_server/test/src/services/completion/yaml/pubspec_generator_test.dart b/pkg/analysis_server/test/src/services/completion/yaml/pubspec_generator_test.dart
index 051c4eb..1104ef2 100644
--- a/pkg/analysis_server/test/src/services/completion/yaml/pubspec_generator_test.dart
+++ b/pkg/analysis_server/test/src/services/completion/yaml/pubspec_generator_test.dart
@@ -7,6 +7,7 @@
 import 'package:analysis_server/src/services/pub/pub_command.dart';
 import 'package:analysis_server/src/services/pub/pub_package_service.dart';
 import 'package:analyzer/instrumentation/service.dart';
+import 'package:analyzer/src/util/file_paths.dart' as file_paths;
 import 'package:http/http.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -28,7 +29,7 @@
   late PubPackageService pubPackageService;
 
   @override
-  String get fileName => 'pubspec.yaml';
+  String get fileName => file_paths.pubspecYaml;
 
   @override
   PubspecGenerator get generator =>
diff --git a/pkg/analysis_server/test/stress/replay/replay.dart b/pkg/analysis_server/test/stress/replay/replay.dart
index 7de5c96..2cbad2f 100644
--- a/pkg/analysis_server/test/stress/replay/replay.dart
+++ b/pkg/analysis_server/test/stress/replay/replay.dart
@@ -13,6 +13,7 @@
 import 'package:analyzer/src/dart/scanner/reader.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
 import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/util/file_paths.dart' as file_paths;
 import 'package:analyzer/src/util/glob.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:args/args.dart';
@@ -48,9 +49,6 @@
   /// interaction to use when making `analysis.updateContent` requests.
   static String OVERLAY_STYLE_OPTION_NAME = 'overlay-style';
 
-  /// The name of the pubspec file.
-  static const String PUBSPEC_FILE_NAME = 'pubspec.yaml';
-
   /// The name of the branch used to clean-up after making temporary changes.
   static const String TEMP_BRANCH_NAME = 'temp';
 
@@ -203,7 +201,7 @@
       var children = directory.listSync(recursive: true, followLinks: false);
       for (var child in children) {
         var filePath = child.path;
-        if (path.basename(filePath) == PUBSPEC_FILE_NAME) {
+        if (path.basename(filePath) == file_paths.pubspecYaml) {
           pubspecFiles.add(filePath);
         }
       }
@@ -353,7 +351,7 @@
           statistics.commitsWithChangeInRootCount++;
           await _replayDiff(commitDelta);
         }
-        changedPubspecs = commitDelta.filesMatching(PUBSPEC_FILE_NAME);
+        changedPubspecs = commitDelta.filesMatching(file_paths.pubspecYaml);
       }
     } finally {
       // Ensure that the repository is left at the most recent commit.
diff --git a/pkg/analysis_server/tool/code_completion/corpus.dart b/pkg/analysis_server/tool/code_completion/corpus.dart
index d7f02f2..26cae4f 100644
--- a/pkg/analysis_server/tool/code_completion/corpus.dart
+++ b/pkg/analysis_server/tool/code_completion/corpus.dart
@@ -5,6 +5,7 @@
 import 'dart:convert';
 import 'dart:io';
 
+import 'package:analyzer/src/util/file_paths.dart' as file_paths;
 import 'package:html/parser.dart' show parse;
 import 'package:http/http.dart' as http;
 import 'package:path/path.dart' as path;
@@ -96,7 +97,8 @@
         headers: const {'User-Agent': 'dart.pkg.completion_metrics'});
 
 bool _hasPubspec(FileSystemEntity f) =>
-    f is Directory && File(path.join(f.path, 'pubspec.yaml')).existsSync();
+    f is Directory &&
+    File(path.join(f.path, file_paths.pubspecYaml)).existsSync();
 
 Future<ProcessResult> _runPub(String dir) async =>
     await Process.run('flutter', ['pub', 'get'], workingDirectory: dir);
diff --git a/pkg/analyzer/lib/src/dart/analysis/context_builder.dart b/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
index d3a04fe..0aa945a 100644
--- a/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
@@ -27,6 +27,7 @@
 import 'package:analyzer/src/summary/summary_sdk.dart';
 import 'package:analyzer/src/summary2/package_bundle_format.dart';
 import 'package:analyzer/src/task/options.dart';
+import 'package:analyzer/src/util/file_paths.dart' as file_paths;
 import 'package:analyzer/src/util/sdk.dart';
 import 'package:analyzer/src/workspace/workspace.dart';
 
@@ -198,7 +199,7 @@
   /// TODO(scheglov) Get it from [Workspace]?
   File? _findPubspecFile(ContextRoot contextRoot) {
     for (var current in contextRoot.root.withAncestors) {
-      var file = current.getChildAssumingFile('pubspec.yaml');
+      var file = current.getChildAssumingFile(file_paths.pubspecYaml);
       if (file.exists) {
         return file;
       }
diff --git a/pkg/analyzer/lib/src/workspace/package_build.dart b/pkg/analyzer/lib/src/workspace/package_build.dart
index c30333e..5a10e9a 100644
--- a/pkg/analyzer/lib/src/workspace/package_build.dart
+++ b/pkg/analyzer/lib/src/workspace/package_build.dart
@@ -10,6 +10,7 @@
 import 'package:analyzer/src/source/package_map_resolver.dart';
 import 'package:analyzer/src/summary/api_signature.dart';
 import 'package:analyzer/src/summary/package_bundle_reader.dart';
+import 'package:analyzer/src/util/file_paths.dart' as file_paths;
 import 'package:analyzer/src/util/uri.dart';
 import 'package:analyzer/src/workspace/pub.dart';
 import 'package:analyzer/src/workspace/workspace.dart';
@@ -136,10 +137,6 @@
     'generated'
   ];
 
-  /// We use pubspec.yaml to get the package name to be consistent with how
-  /// package:build does it.
-  static const String _pubspecName = 'pubspec.yaml';
-
   /// The associated pubspec file.
   final File _pubspecFile;
 
@@ -298,7 +295,7 @@
       Map<String, List<Folder>> packageMap, String filePath) {
     var startFolder = provider.getFolder(filePath);
     for (var folder in startFolder.withAncestors) {
-      final File pubspec = folder.getChildAssumingFile(_pubspecName);
+      final File pubspec = folder.getChildAssumingFile(file_paths.pubspecYaml);
       final Folder dartToolDir =
           folder.getChildAssumingFolder(_dartToolRootName);
       final Folder dartToolBuildDir =
diff --git a/pkg/analyzer/lib/src/workspace/pub.dart b/pkg/analyzer/lib/src/workspace/pub.dart
index 1d83253..a6e66ce 100644
--- a/pkg/analyzer/lib/src/workspace/pub.dart
+++ b/pkg/analyzer/lib/src/workspace/pub.dart
@@ -7,15 +7,13 @@
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/lint/pub.dart';
 import 'package:analyzer/src/summary/api_signature.dart';
+import 'package:analyzer/src/util/file_paths.dart' as file_paths;
 import 'package:analyzer/src/workspace/simple.dart';
 import 'package:analyzer/src/workspace/workspace.dart';
 import 'package:meta/meta.dart';
 
 /// Information about a Pub workspace.
 class PubWorkspace extends SimpleWorkspace {
-  /// The name of the file that identifies the root of the workspace.
-  static const String _pubspecName = 'pubspec.yaml';
-
   /// The singular package in this workspace.
   ///
   /// Each Pub workspace is itself one package.
@@ -68,7 +66,7 @@
   ) {
     var start = provider.getFolder(filePath);
     for (var current in start.withAncestors) {
-      var pubspec = current.getChildAssumingFile(_pubspecName);
+      var pubspec = current.getChildAssumingFile(file_paths.pubspecYaml);
       if (pubspec.exists) {
         var root = current.path;
         return PubWorkspace._(provider, packageMap, root, pubspec);
diff --git a/pkg/analyzer/test/src/dart/resolution/ast_rewrite_test.dart b/pkg/analyzer/test/src/dart/resolution/ast_rewrite_test.dart
index 77954c0..26937b0 100644
--- a/pkg/analyzer/test/src/dart/resolution/ast_rewrite_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/ast_rewrite_test.dart
@@ -4,7 +4,6 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -366,15 +365,44 @@
 }
 ''');
 
-    var creation = findNode.instanceCreation('A<int, String>(0);');
-    assertInstanceCreation(
-      creation,
-      findElement.class_('A'),
-      'A<int, String>',
-      expectedConstructorMember: true,
-      expectedSubstitution: {'T': 'int', 'U': 'String'},
-    );
-    _assertArgumentList(creation.argumentList, ['0']);
+    var node = findNode.instanceCreation('A<int, String>(0);');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: SimpleIdentifier
+        token: A
+        staticElement: self::@class::A
+        staticType: null
+      typeArguments: TypeArgumentList
+        leftBracket: <
+        arguments
+          NamedType
+            name: SimpleIdentifier
+              token: int
+              staticElement: dart:core::@class::int
+              staticType: null
+            type: int
+          NamedType
+            name: SimpleIdentifier
+              token: String
+              staticElement: dart:core::@class::String
+              staticType: null
+            type: String
+        rightBracket: >
+      type: A<int, String>
+    staticElement: ConstructorMember
+      base: self::@class::A::@constructor::•
+      substitution: {T: int, U: String}
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      IntegerLiteral
+        literal: 0
+        staticType: int
+    rightParenthesis: )
+  staticType: A<int, String>
+''');
   }
 
   test_targetNull_extension() async {
@@ -408,10 +436,42 @@
 }
 ''');
 
-    var invocation = findNode.methodInvocation('A<int, String>(0);');
-    assertElement(invocation, findElement.topFunction('A'));
-    assertInvokeType(invocation, 'void Function(int)');
-    _assertArgumentList(invocation.argumentList, ['0']);
+    var node = findNode.methodInvocation('A<int, String>(0);');
+    assertResolvedNodeText(node, r'''
+MethodInvocation
+  methodName: SimpleIdentifier
+    token: A
+    staticElement: self::@function::A
+    staticType: void Function<T, U>(int)
+  typeArguments: TypeArgumentList
+    leftBracket: <
+    arguments
+      NamedType
+        name: SimpleIdentifier
+          token: int
+          staticElement: dart:core::@class::int
+          staticType: null
+        type: int
+      NamedType
+        name: SimpleIdentifier
+          token: String
+          staticElement: dart:core::@class::String
+          staticType: null
+        type: String
+    rightBracket: >
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      IntegerLiteral
+        literal: 0
+        staticType: int
+    rightParenthesis: )
+  staticInvokeType: void Function(int)
+  staticType: void
+  typeArgumentTypes
+    int
+    String
+''');
   }
 
   test_targetNull_typeAlias_interfaceType() async {
@@ -427,16 +487,44 @@
 }
 ''');
 
-    var creation = findNode.instanceCreation('X<int, String>(0);');
-    assertInstanceCreation(
-      creation,
-      findElement.class_('A'),
-      'A<int, String>',
-      expectedConstructorMember: true,
-      expectedSubstitution: {'T': 'int', 'U': 'String'},
-      expectedTypeNameElement: findElement.typeAlias('X'),
-    );
-    _assertArgumentList(creation.argumentList, ['0']);
+    var node = findNode.instanceCreation('X<int, String>(0);');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: SimpleIdentifier
+        token: X
+        staticElement: self::@typeAlias::X
+        staticType: null
+      typeArguments: TypeArgumentList
+        leftBracket: <
+        arguments
+          NamedType
+            name: SimpleIdentifier
+              token: int
+              staticElement: dart:core::@class::int
+              staticType: null
+            type: int
+          NamedType
+            name: SimpleIdentifier
+              token: String
+              staticElement: dart:core::@class::String
+              staticType: null
+            type: String
+        rightBracket: >
+      type: A<int, String>
+    staticElement: ConstructorMember
+      base: self::@class::A::@constructor::•
+      substitution: {T: int, U: String}
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      IntegerLiteral
+        literal: 0
+        staticType: int
+    rightParenthesis: )
+  staticType: A<int, String>
+''');
   }
 
   test_targetNull_typeAlias_Never() async {
@@ -469,19 +557,43 @@
 }
 ''');
 
-    var importFind = findElement.importFind('package:test/a.dart');
-
-    var creation = findNode.instanceCreation('A.named(0);');
-    assertInstanceCreation(
-      creation,
-      importFind.class_('A'),
-      'A<int>',
-      constructorName: 'named',
-      expectedPrefix: importFind.prefix,
-      expectedConstructorMember: true,
-      expectedSubstitution: {'T': 'int'},
-    );
-    _assertArgumentList(creation.argumentList, ['0']);
+    var node = findNode.instanceCreation('A.named(0);');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: PrefixedIdentifier
+        prefix: SimpleIdentifier
+          token: prefix
+          staticElement: self::@prefix::prefix
+          staticType: null
+        period: .
+        identifier: SimpleIdentifier
+          token: A
+          staticElement: package:test/a.dart::@class::A
+          staticType: null
+        staticElement: package:test/a.dart::@class::A
+        staticType: null
+      type: A<int>
+    period: .
+    name: SimpleIdentifier
+      token: named
+      staticElement: ConstructorMember
+        base: package:test/a.dart::@class::A::@constructor::named
+        substitution: {T: dynamic}
+      staticType: null
+    staticElement: ConstructorMember
+      base: package:test/a.dart::@class::A::@constructor::named
+      substitution: {T: int}
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      IntegerLiteral
+        literal: 0
+        staticType: int
+    rightParenthesis: )
+  staticType: A<int>
+''');
   }
 
   test_targetPrefixedIdentifier_prefix_class_constructor_typeArguments() async {
@@ -503,24 +615,53 @@
           messageContains: ["The constructor 'prefix.A.named'"]),
     ]);
 
-    var importFind = findElement.importFind('package:test/a.dart');
-
-    var creation = findNode.instanceCreation('named<int>(0);');
-    assertInstanceCreation(
-      creation,
-      importFind.class_('A'),
-      'A<int>',
-      constructorName: 'named',
-      expectedPrefix: importFind.prefix,
-      expectedConstructorMember: true,
-      expectedSubstitution: {'T': 'int'},
-    );
-    _assertTypeArgumentList(
-      creation.constructorName.type.typeArguments,
-      ['int'],
-    );
-    expect((creation as InstanceCreationExpressionImpl).typeArguments, isNull);
-    _assertArgumentList(creation.argumentList, ['0']);
+    var node = findNode.instanceCreation('named<int>(0);');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: PrefixedIdentifier
+        prefix: SimpleIdentifier
+          token: prefix
+          staticElement: self::@prefix::prefix
+          staticType: null
+        period: .
+        identifier: SimpleIdentifier
+          token: A
+          staticElement: package:test/a.dart::@class::A
+          staticType: null
+        staticElement: package:test/a.dart::@class::A
+        staticType: null
+      typeArguments: TypeArgumentList
+        leftBracket: <
+        arguments
+          NamedType
+            name: SimpleIdentifier
+              token: int
+              staticElement: dart:core::@class::int
+              staticType: null
+            type: int
+        rightBracket: >
+      type: A<int>
+    period: .
+    name: SimpleIdentifier
+      token: named
+      staticElement: ConstructorMember
+        base: package:test/a.dart::@class::A::@constructor::named
+        substitution: {T: int}
+      staticType: null
+    staticElement: ConstructorMember
+      base: package:test/a.dart::@class::A::@constructor::named
+      substitution: {T: int}
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      IntegerLiteral
+        literal: 0
+        staticType: int
+    rightParenthesis: )
+  staticType: A<int>
+''');
   }
 
   test_targetPrefixedIdentifier_prefix_class_constructor_typeArguments_new() async {
@@ -542,23 +683,53 @@
           messageContains: ["The constructor 'prefix.A.new'"]),
     ]);
 
-    var importFind = findElement.importFind('package:test/a.dart');
-
-    var creation = findNode.instanceCreation('new<int>(0);');
-    assertInstanceCreation(
-      creation,
-      importFind.class_('A'),
-      'A<int>',
-      expectedPrefix: importFind.prefix,
-      expectedConstructorMember: true,
-      expectedSubstitution: {'T': 'int'},
-    );
-    _assertTypeArgumentList(
-      creation.constructorName.type.typeArguments,
-      ['int'],
-    );
-    expect((creation as InstanceCreationExpressionImpl).typeArguments, isNull);
-    _assertArgumentList(creation.argumentList, ['0']);
+    var node = findNode.instanceCreation('new<int>(0);');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: PrefixedIdentifier
+        prefix: SimpleIdentifier
+          token: prefix
+          staticElement: self::@prefix::prefix
+          staticType: null
+        period: .
+        identifier: SimpleIdentifier
+          token: A
+          staticElement: package:test/a.dart::@class::A
+          staticType: null
+        staticElement: package:test/a.dart::@class::A
+        staticType: null
+      typeArguments: TypeArgumentList
+        leftBracket: <
+        arguments
+          NamedType
+            name: SimpleIdentifier
+              token: int
+              staticElement: dart:core::@class::int
+              staticType: null
+            type: int
+        rightBracket: >
+      type: A<int>
+    period: .
+    name: SimpleIdentifier
+      token: new
+      staticElement: ConstructorMember
+        base: package:test/a.dart::@class::A::@constructor::•
+        substitution: {T: int}
+      staticType: null
+    staticElement: ConstructorMember
+      base: package:test/a.dart::@class::A::@constructor::•
+      substitution: {T: int}
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      IntegerLiteral
+        literal: 0
+        staticType: int
+    rightParenthesis: )
+  staticType: A<int>
+''');
   }
 
   test_targetPrefixedIdentifier_prefix_getter_method() async {
@@ -578,12 +749,36 @@
 }
 ''');
 
-    var importFind = findElement.importFind('package:test/a.dart');
-
-    var invocation = findNode.methodInvocation('bar(0);');
-    assertElement(invocation, importFind.class_('A').getMethod('bar'));
-    assertInvokeType(invocation, 'void Function(int)');
-    _assertArgumentList(invocation.argumentList, ['0']);
+    var node = findNode.methodInvocation('bar(0);');
+    assertResolvedNodeText(node, r'''
+MethodInvocation
+  target: PrefixedIdentifier
+    prefix: SimpleIdentifier
+      token: prefix
+      staticElement: self::@prefix::prefix
+      staticType: null
+    period: .
+    identifier: SimpleIdentifier
+      token: foo
+      staticElement: package:test/a.dart::@getter::foo
+      staticType: A
+    staticElement: package:test/a.dart::@getter::foo
+    staticType: A
+  operator: .
+  methodName: SimpleIdentifier
+    token: bar
+    staticElement: package:test/a.dart::@class::A::@method::bar
+    staticType: void Function(int)
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      IntegerLiteral
+        literal: 0
+        staticType: int
+    rightParenthesis: )
+  staticInvokeType: void Function(int)
+  staticType: void
+''');
   }
 
   test_targetPrefixedIdentifier_typeAlias_interfaceType_constructor() async {
@@ -603,20 +798,43 @@
 }
 ''');
 
-    var importFind = findElement.importFind('package:test/a.dart');
-
-    var creation = findNode.instanceCreation('X.named(0);');
-    assertInstanceCreation(
-      creation,
-      importFind.class_('A'),
-      'A<int>',
-      constructorName: 'named',
-      expectedConstructorMember: true,
-      expectedSubstitution: {'T': 'int'},
-      expectedPrefix: findElement.prefix('prefix'),
-      expectedTypeNameElement: importFind.typeAlias('X'),
-    );
-    _assertArgumentList(creation.argumentList, ['0']);
+    var node = findNode.instanceCreation('X.named(0);');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: PrefixedIdentifier
+        prefix: SimpleIdentifier
+          token: prefix
+          staticElement: self::@prefix::prefix
+          staticType: null
+        period: .
+        identifier: SimpleIdentifier
+          token: X
+          staticElement: package:test/a.dart::@typeAlias::X
+          staticType: null
+        staticElement: package:test/a.dart::@typeAlias::X
+        staticType: null
+      type: A<int>
+    period: .
+    name: SimpleIdentifier
+      token: named
+      staticElement: ConstructorMember
+        base: package:test/a.dart::@class::A::@constructor::named
+        substitution: {T: dynamic}
+      staticType: null
+    staticElement: ConstructorMember
+      base: package:test/a.dart::@class::A::@constructor::named
+      substitution: {T: int}
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      IntegerLiteral
+        literal: 0
+        staticType: int
+    rightParenthesis: )
+  staticType: A<int>
+''');
   }
 
   test_targetSimpleIdentifier_class_constructor() async {
@@ -630,16 +848,35 @@
 }
 ''');
 
-    var creation = findNode.instanceCreation('A.named(0);');
-    assertInstanceCreation(
-      creation,
-      findElement.class_('A'),
-      'A<int>',
-      constructorName: 'named',
-      expectedConstructorMember: true,
-      expectedSubstitution: {'T': 'int'},
-    );
-    _assertArgumentList(creation.argumentList, ['0']);
+    var node = findNode.instanceCreation('A.named(0);');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: SimpleIdentifier
+        token: A
+        staticElement: self::@class::A
+        staticType: null
+      type: A<int>
+    period: .
+    name: SimpleIdentifier
+      token: named
+      staticElement: ConstructorMember
+        base: self::@class::A::@constructor::named
+        substitution: {T: dynamic}
+      staticType: null
+    staticElement: ConstructorMember
+      base: self::@class::A::@constructor::named
+      substitution: {T: int}
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      IntegerLiteral
+        literal: 0
+        staticType: int
+    rightParenthesis: )
+  staticType: A<int>
+''');
   }
 
   test_targetSimpleIdentifier_class_constructor_typeArguments() async {
@@ -657,27 +894,52 @@
           messageContains: ["The constructor 'A.named'"]),
     ]);
 
-    var creation = findNode.instanceCreation('named<int, String>(0);');
-    assertInstanceCreation(
-      creation,
-      findElement.class_('A'),
-      // TODO(scheglov) Move type arguments
-      'A<dynamic, dynamic>',
-//      'A<int, String>',
-      constructorName: 'named',
-      expectedConstructorMember: true,
-      // TODO(scheglov) Move type arguments
-      expectedSubstitution: {'T': 'dynamic', 'U': 'dynamic'},
-//      expectedSubstitution: {'T': 'int', 'U': 'String'},
-    );
     // TODO(scheglov) Move type arguments
-//    _assertTypeArgumentList(
-//      creation.constructorName.type.typeArguments,
-//      ['int', 'String'],
-//    );
-    // TODO(scheglov) Fix and uncomment.
-//    expect((creation as InstanceCreationExpressionImpl).typeArguments, isNull);
-    _assertArgumentList(creation.argumentList, ['0']);
+    var node = findNode.instanceCreation('named<int, String>(0);');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: SimpleIdentifier
+        token: A
+        staticElement: self::@class::A
+        staticType: null
+      type: A<dynamic, dynamic>
+    period: .
+    name: SimpleIdentifier
+      token: named
+      staticElement: ConstructorMember
+        base: self::@class::A::@constructor::named
+        substitution: {T: dynamic, U: dynamic}
+      staticType: null
+    staticElement: ConstructorMember
+      base: self::@class::A::@constructor::named
+      substitution: {T: dynamic, U: dynamic}
+  typeArguments: TypeArgumentList
+    leftBracket: <
+    arguments
+      NamedType
+        name: SimpleIdentifier
+          token: int
+          staticElement: dart:core::@class::int
+          staticType: null
+        type: int
+      NamedType
+        name: SimpleIdentifier
+          token: String
+          staticElement: dart:core::@class::String
+          staticType: null
+        type: String
+    rightBracket: >
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      IntegerLiteral
+        literal: 0
+        staticType: int
+    rightParenthesis: )
+  staticType: A<dynamic, dynamic>
+''');
   }
 
   test_targetSimpleIdentifier_class_constructor_typeArguments_new() async {
@@ -695,26 +957,52 @@
           messageContains: ["The constructor 'A.new'"]),
     ]);
 
-    var creation = findNode.instanceCreation('new<int, String>(0);');
-    assertInstanceCreation(
-      creation,
-      findElement.class_('A'),
-      // TODO(scheglov) Move type arguments
-      'A<dynamic, dynamic>',
-//      'A<int, String>',
-      expectedConstructorMember: true,
-      // TODO(scheglov) Move type arguments
-      expectedSubstitution: {'T': 'dynamic', 'U': 'dynamic'},
-//      expectedSubstitution: {'T': 'int', 'U': 'String'},
-    );
     // TODO(scheglov) Move type arguments
-//    _assertTypeArgumentList(
-//      creation.constructorName.type.typeArguments,
-//      ['int', 'String'],
-//    );
-    // TODO(scheglov) Fix and uncomment.
-//    expect((creation as InstanceCreationExpressionImpl).typeArguments, isNull);
-    _assertArgumentList(creation.argumentList, ['0']);
+    var node = findNode.instanceCreation('new<int, String>(0);');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: SimpleIdentifier
+        token: A
+        staticElement: self::@class::A
+        staticType: null
+      type: A<dynamic, dynamic>
+    period: .
+    name: SimpleIdentifier
+      token: new
+      staticElement: ConstructorMember
+        base: self::@class::A::@constructor::•
+        substitution: {T: dynamic, U: dynamic}
+      staticType: null
+    staticElement: ConstructorMember
+      base: self::@class::A::@constructor::•
+      substitution: {T: dynamic, U: dynamic}
+  typeArguments: TypeArgumentList
+    leftBracket: <
+    arguments
+      NamedType
+        name: SimpleIdentifier
+          token: int
+          staticElement: dart:core::@class::int
+          staticType: null
+        type: int
+      NamedType
+        name: SimpleIdentifier
+          token: String
+          staticElement: dart:core::@class::String
+          staticType: null
+        type: String
+    rightBracket: >
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      IntegerLiteral
+        literal: 0
+        staticType: int
+    rightParenthesis: )
+  staticType: A<dynamic, dynamic>
+''');
   }
 
   test_targetSimpleIdentifier_class_staticMethod() async {
@@ -747,18 +1035,52 @@
 }
 ''');
 
-    var importFind = findElement.importFind('package:test/a.dart');
-
-    var creation = findNode.instanceCreation('A<int, String>(0);');
-    assertInstanceCreation(
-      creation,
-      importFind.class_('A'),
-      'A<int, String>',
-      expectedPrefix: importFind.prefix,
-      expectedConstructorMember: true,
-      expectedSubstitution: {'T': 'int', 'U': 'String'},
-    );
-    _assertArgumentList(creation.argumentList, ['0']);
+    var node = findNode.instanceCreation('A<int, String>(0);');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: PrefixedIdentifier
+        prefix: SimpleIdentifier
+          token: prefix
+          staticElement: self::@prefix::prefix
+          staticType: null
+        period: .
+        identifier: SimpleIdentifier
+          token: A
+          staticElement: package:test/a.dart::@class::A
+          staticType: null
+        staticElement: package:test/a.dart::@class::A
+        staticType: null
+      typeArguments: TypeArgumentList
+        leftBracket: <
+        arguments
+          NamedType
+            name: SimpleIdentifier
+              token: int
+              staticElement: dart:core::@class::int
+              staticType: null
+            type: int
+          NamedType
+            name: SimpleIdentifier
+              token: String
+              staticElement: dart:core::@class::String
+              staticType: null
+            type: String
+        rightBracket: >
+      type: A<int, String>
+    staticElement: ConstructorMember
+      base: package:test/a.dart::@class::A::@constructor::•
+      substitution: {T: int, U: String}
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      IntegerLiteral
+        literal: 0
+        staticType: int
+    rightParenthesis: )
+  staticType: A<int, String>
+''');
   }
 
   test_targetSimpleIdentifier_prefix_extension() async {
@@ -803,12 +1125,47 @@
 }
 ''');
 
-    var importFind = findElement.importFind('package:test/a.dart');
-
-    var invocation = findNode.methodInvocation('A<int, String>(0);');
-    assertElement(invocation, importFind.topFunction('A'));
-    assertInvokeType(invocation, 'void Function(int)');
-    _assertArgumentList(invocation.argumentList, ['0']);
+    var node = findNode.methodInvocation('A<int, String>(0);');
+    assertResolvedNodeText(node, r'''
+MethodInvocation
+  target: SimpleIdentifier
+    token: prefix
+    staticElement: self::@prefix::prefix
+    staticType: null
+  operator: .
+  methodName: SimpleIdentifier
+    token: A
+    staticElement: package:test/a.dart::@function::A
+    staticType: void Function<T, U>(int)
+  typeArguments: TypeArgumentList
+    leftBracket: <
+    arguments
+      NamedType
+        name: SimpleIdentifier
+          token: int
+          staticElement: dart:core::@class::int
+          staticType: null
+        type: int
+      NamedType
+        name: SimpleIdentifier
+          token: String
+          staticElement: dart:core::@class::String
+          staticType: null
+        type: String
+    rightBracket: >
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      IntegerLiteral
+        literal: 0
+        staticType: int
+    rightParenthesis: )
+  staticInvokeType: void Function(int)
+  staticType: void
+  typeArgumentTypes
+    int
+    String
+''');
   }
 
   test_targetSimpleIdentifier_typeAlias_interfaceType_constructor() async {
@@ -824,27 +1181,35 @@
 }
 ''');
 
-    var creation = findNode.instanceCreation('X.named(0);');
-    assertInstanceCreation(
-      creation,
-      findElement.class_('A'),
-      'A<int>',
-      constructorName: 'named',
-      expectedConstructorMember: true,
-      expectedSubstitution: {'T': 'int'},
-      expectedTypeNameElement: findElement.typeAlias('X'),
-    );
-    _assertArgumentList(creation.argumentList, ['0']);
-  }
-
-  void _assertArgumentList(
-    ArgumentList argumentList,
-    List<String> expectedArguments,
-  ) {
-    var argumentStrings = argumentList.arguments
-        .map((e) => result.content.substring(e.offset, e.end))
-        .toList();
-    expect(argumentStrings, expectedArguments);
+    var node = findNode.instanceCreation('X.named(0);');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: SimpleIdentifier
+        token: X
+        staticElement: self::@typeAlias::X
+        staticType: null
+      type: A<int>
+    period: .
+    name: SimpleIdentifier
+      token: named
+      staticElement: ConstructorMember
+        base: self::@class::A::@constructor::named
+        substitution: {T: dynamic}
+      staticType: null
+    staticElement: ConstructorMember
+      base: self::@class::A::@constructor::named
+      substitution: {T: int}
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      IntegerLiteral
+        literal: 0
+        staticType: int
+    rightParenthesis: )
+  staticType: A<int>
+''');
   }
 
   void _assertExtensionOverride(
@@ -864,20 +1229,6 @@
     );
     assertType(override.extendedType, expectedExtendedType);
   }
-
-  void _assertTypeArgumentList(
-    TypeArgumentList? argumentList,
-    List<String> expectedArguments,
-  ) {
-    if (argumentList == null) {
-      fail('Expected TypeArgumentList, actually null.');
-    }
-
-    var argumentStrings = argumentList.arguments
-        .map((e) => result.content.substring(e.offset, e.end))
-        .toList();
-    expect(argumentStrings, expectedArguments);
-  }
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
index 7d4c7a1..bd15dd4 100644
--- a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
@@ -262,8 +262,8 @@
   List<String> get collectionIncludedPaths => [workspaceRootPath];
 
   List<String> get experiments => [
-        EnableString.constructor_tearoffs,
         EnableString.enhanced_enums,
+        EnableString.macros,
         EnableString.named_arguments_anywhere,
         EnableString.super_parameters,
       ];
diff --git a/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart b/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart
index 5175800..1508e0f 100644
--- a/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/instance_creation_test.dart
@@ -32,15 +32,35 @@
 
 ''');
 
-    var creation = findNode.instanceCreation('A.named(0)');
-    assertInstanceCreation(
-      creation,
-      findElement.class_('A'),
-      'A<int>',
-      constructorName: 'named',
-      expectedConstructorMember: true,
-      expectedSubstitution: {'T': 'int'},
-    );
+    var node = findNode.instanceCreation('A.named(0)');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: SimpleIdentifier
+        token: A
+        staticElement: self::@class::A
+        staticType: null
+      type: A<int>
+    period: .
+    name: SimpleIdentifier
+      token: named
+      staticElement: ConstructorMember
+        base: self::@class::A::@constructor::named
+        substitution: {T: dynamic}
+      staticType: null
+    staticElement: ConstructorMember
+      base: self::@class::A::@constructor::named
+      substitution: {T: int}
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      IntegerLiteral
+        literal: 0
+        staticType: int
+    rightParenthesis: )
+  staticType: A<int>
+''');
   }
 
   test_class_generic_named_withTypeArguments() async {
@@ -55,15 +75,41 @@
 
 ''');
 
-    var creation = findNode.instanceCreation('A<int>');
-    assertInstanceCreation(
-      creation,
-      findElement.class_('A'),
-      'A<int>',
-      constructorName: 'named',
-      expectedConstructorMember: true,
-      expectedSubstitution: {'T': 'int'},
-    );
+    var node = findNode.instanceCreation('A<int>');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: SimpleIdentifier
+        token: A
+        staticElement: self::@class::A
+        staticType: null
+      typeArguments: TypeArgumentList
+        leftBracket: <
+        arguments
+          NamedType
+            name: SimpleIdentifier
+              token: int
+              staticElement: dart:core::@class::int
+              staticType: null
+            type: int
+        rightBracket: >
+      type: A<int>
+    period: .
+    name: SimpleIdentifier
+      token: named
+      staticElement: ConstructorMember
+        base: self::@class::A::@constructor::named
+        substitution: {T: int}
+      staticType: null
+    staticElement: ConstructorMember
+      base: self::@class::A::@constructor::named
+      substitution: {T: int}
+  argumentList: ArgumentList
+    leftParenthesis: (
+    rightParenthesis: )
+  staticType: A<int>
+''');
     assertNamedType(findNode.namedType('int>'), intElement, 'int');
   }
 
@@ -79,14 +125,28 @@
 
 ''');
 
-    var creation = findNode.instanceCreation('A(0)');
-    assertInstanceCreation(
-      creation,
-      findElement.class_('A'),
-      'A<int>',
-      expectedConstructorMember: true,
-      expectedSubstitution: {'T': 'int'},
-    );
+    var node = findNode.instanceCreation('A(0)');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: SimpleIdentifier
+        token: A
+        staticElement: self::@class::A
+        staticType: null
+      type: A<int>
+    staticElement: ConstructorMember
+      base: self::@class::A::@constructor::•
+      substitution: {T: int}
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      IntegerLiteral
+        literal: 0
+        staticType: int
+    rightParenthesis: )
+  staticType: A<int>
+''');
   }
 
   test_class_generic_unnamed_withTypeArguments() async {
@@ -99,14 +159,34 @@
 
 ''');
 
-    var creation = findNode.instanceCreation('A<int>');
-    assertInstanceCreation(
-      creation,
-      findElement.class_('A'),
-      'A<int>',
-      expectedConstructorMember: true,
-      expectedSubstitution: {'T': 'int'},
-    );
+    var node = findNode.instanceCreation('A<int>');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: SimpleIdentifier
+        token: A
+        staticElement: self::@class::A
+        staticType: null
+      typeArguments: TypeArgumentList
+        leftBracket: <
+        arguments
+          NamedType
+            name: SimpleIdentifier
+              token: int
+              staticElement: dart:core::@class::int
+              staticType: null
+            type: int
+        rightBracket: >
+      type: A<int>
+    staticElement: ConstructorMember
+      base: self::@class::A::@constructor::•
+      substitution: {T: int}
+  argumentList: ArgumentList
+    leftParenthesis: (
+    rightParenthesis: )
+  staticType: A<int>
+''');
     assertNamedType(findNode.namedType('int>'), intElement, 'int');
   }
 
@@ -122,8 +202,26 @@
 
 ''');
 
-    var creation = findNode.instanceCreation('A(0)');
-    assertInstanceCreation(creation, findElement.class_('A'), 'A');
+    var node = findNode.instanceCreation('A(0)');
+    assertResolvedNodeText(node, r'''
+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: (
+    arguments
+      IntegerLiteral
+        literal: 0
+        staticType: int
+    rightParenthesis: )
+  staticType: A
+''');
   }
 
   test_demoteType() async {
@@ -140,10 +238,29 @@
 
 ''');
 
-    assertType(
-      findNode.instanceCreation('A(s)'),
-      'A<S>',
-    );
+    var node = findNode.instanceCreation('A(s)');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: SimpleIdentifier
+        token: A
+        staticElement: self::@class::A
+        staticType: null
+      type: A<S>
+    staticElement: ConstructorMember
+      base: self::@class::A::@constructor::•
+      substitution: {T: S}
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      SimpleIdentifier
+        token: s
+        staticElement: s@38
+        staticType: S & int
+    rightParenthesis: )
+  staticType: A<S>
+''');
   }
 
   test_error_newWithInvalidTypeParameters_implicitNew_inference_top() async {
@@ -153,14 +270,34 @@
       error(CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS, 12, 8),
     ]);
 
-    var creation = findNode.instanceCreation('Map<int>');
-    assertInstanceCreation(
-      creation,
-      mapElement,
-      'Map<dynamic, dynamic>',
-      expectedConstructorMember: true,
-      expectedSubstitution: {'K': 'dynamic', 'V': 'dynamic'},
-    );
+    var node = findNode.instanceCreation('Map<int>');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: SimpleIdentifier
+        token: Map
+        staticElement: dart:core::@class::Map
+        staticType: null
+      typeArguments: TypeArgumentList
+        leftBracket: <
+        arguments
+          NamedType
+            name: SimpleIdentifier
+              token: int
+              staticElement: dart:core::@class::int
+              staticType: null
+            type: int
+        rightBracket: >
+      type: Map<dynamic, dynamic>
+    staticElement: ConstructorMember
+      base: dart:core::@class::Map::@constructor::•
+      substitution: {K: dynamic, V: dynamic}
+  argumentList: ArgumentList
+    leftParenthesis: (
+    rightParenthesis: )
+  staticType: Map<dynamic, dynamic>
+''');
   }
 
   test_error_wrongNumberOfTypeArgumentsConstructor_explicitNew() async {
@@ -178,15 +315,42 @@
           messageContains: ["The constructor 'Foo.bar'"]),
     ]);
 
-    var creation = findNode.instanceCreation('Foo.bar<int>');
-    assertInstanceCreation(
-      creation,
-      findElement.class_('Foo'),
-      'Foo<dynamic>',
-      constructorName: 'bar',
-      expectedConstructorMember: true,
-      expectedSubstitution: {'X': 'dynamic'},
-    );
+    var node = findNode.instanceCreation('Foo.bar<int>');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  keyword: new
+  constructorName: ConstructorName
+    type: NamedType
+      name: SimpleIdentifier
+        token: Foo
+        staticElement: self::@class::Foo
+        staticType: null
+      type: Foo<dynamic>
+    period: .
+    name: SimpleIdentifier
+      token: bar
+      staticElement: ConstructorMember
+        base: self::@class::Foo::@constructor::bar
+        substitution: {X: dynamic}
+      staticType: null
+    staticElement: ConstructorMember
+      base: self::@class::Foo::@constructor::bar
+      substitution: {X: dynamic}
+  typeArguments: TypeArgumentList
+    leftBracket: <
+    arguments
+      NamedType
+        name: SimpleIdentifier
+          token: int
+          staticElement: dart:core::@class::int
+          staticType: null
+        type: int
+    rightBracket: >
+  argumentList: ArgumentList
+    leftParenthesis: (
+    rightParenthesis: )
+  staticType: Foo<dynamic>
+''');
   }
 
   test_error_wrongNumberOfTypeArgumentsConstructor_explicitNew_new() async {
@@ -204,14 +368,42 @@
           messageContains: ["The constructor 'Foo.new'"]),
     ]);
 
-    var creation = findNode.instanceCreation('Foo.new<int>');
-    assertInstanceCreation(
-      creation,
-      findElement.class_('Foo'),
-      'Foo<dynamic>',
-      expectedConstructorMember: true,
-      expectedSubstitution: {'X': 'dynamic'},
-    );
+    var node = findNode.instanceCreation('Foo.new<int>');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  keyword: new
+  constructorName: ConstructorName
+    type: NamedType
+      name: SimpleIdentifier
+        token: Foo
+        staticElement: self::@class::Foo
+        staticType: null
+      type: Foo<dynamic>
+    period: .
+    name: SimpleIdentifier
+      token: new
+      staticElement: ConstructorMember
+        base: self::@class::Foo::@constructor::•
+        substitution: {X: dynamic}
+      staticType: null
+    staticElement: ConstructorMember
+      base: self::@class::Foo::@constructor::•
+      substitution: {X: dynamic}
+  typeArguments: TypeArgumentList
+    leftBracket: <
+    arguments
+      NamedType
+        name: SimpleIdentifier
+          token: int
+          staticElement: dart:core::@class::int
+          staticType: null
+        type: int
+    rightBracket: >
+  argumentList: ArgumentList
+    leftParenthesis: (
+    rightParenthesis: )
+  staticType: Foo<dynamic>
+''');
   }
 
   test_error_wrongNumberOfTypeArgumentsConstructor_explicitNew_prefix() async {
@@ -232,15 +424,50 @@
 
     // TODO(brianwilkerson) Test this more carefully after we can re-write the
     // AST to reflect the expected structure.
-//    var creation = findNode.instanceCreation('Foo.bar<int>');
-//    var import = findElement.import('package:test/a.dart');
-//    assertInstanceCreation(
-//      creation,
-//      import.importedLibrary.getType('Foo'),
-//      'Foo',
-//      constructorName: 'bar',
-//      expectedPrefix: import.prefix,
-//    );
+    var node = findNode.instanceCreation('Foo.bar<int>');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  keyword: new
+  constructorName: ConstructorName
+    type: NamedType
+      name: PrefixedIdentifier
+        prefix: SimpleIdentifier
+          token: p
+          staticElement: self::@prefix::p
+          staticType: null
+        period: .
+        identifier: SimpleIdentifier
+          token: Foo
+          staticElement: package:test/a.dart::@class::Foo
+          staticType: null
+        staticElement: package:test/a.dart::@class::Foo
+        staticType: null
+      type: Foo<dynamic>
+    period: .
+    name: SimpleIdentifier
+      token: bar
+      staticElement: ConstructorMember
+        base: package:test/a.dart::@class::Foo::@constructor::bar
+        substitution: {X: dynamic}
+      staticType: null
+    staticElement: ConstructorMember
+      base: package:test/a.dart::@class::Foo::@constructor::bar
+      substitution: {X: dynamic}
+  typeArguments: TypeArgumentList
+    leftBracket: <
+    arguments
+      NamedType
+        name: SimpleIdentifier
+          token: int
+          staticElement: dart:core::@class::int
+          staticType: null
+        type: int
+    rightBracket: >
+  argumentList: ArgumentList
+    leftParenthesis: (
+    rightParenthesis: )
+  staticType: Foo<dynamic>
+''');
   }
 
   test_error_wrongNumberOfTypeArgumentsConstructor_implicitNew() async {
@@ -257,19 +484,41 @@
           5),
     ]);
 
-    var creation = findNode.instanceCreation('Foo.bar<int>');
-    assertInstanceCreation(
-      creation,
-      findElement.class_('Foo'),
-      // TODO(scheglov) Move type arguments
-      'Foo<dynamic>',
-//      'Foo<int>',
-      constructorName: 'bar',
-      expectedConstructorMember: true,
-      // TODO(scheglov) Move type arguments
-      expectedSubstitution: {'X': 'dynamic'},
-//      expectedSubstitution: {'X': 'int'},
-    );
+    var node = findNode.instanceCreation('Foo.bar<int>');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: SimpleIdentifier
+        token: Foo
+        staticElement: self::@class::Foo
+        staticType: null
+      type: Foo<dynamic>
+    period: .
+    name: SimpleIdentifier
+      token: bar
+      staticElement: ConstructorMember
+        base: self::@class::Foo::@constructor::bar
+        substitution: {X: dynamic}
+      staticType: null
+    staticElement: ConstructorMember
+      base: self::@class::Foo::@constructor::bar
+      substitution: {X: dynamic}
+  typeArguments: TypeArgumentList
+    leftBracket: <
+    arguments
+      NamedType
+        name: SimpleIdentifier
+          token: int
+          staticElement: dart:core::@class::int
+          staticType: null
+        type: int
+    rightBracket: >
+  argumentList: ArgumentList
+    leftParenthesis: (
+    rightParenthesis: )
+  staticType: Foo<dynamic>
+''');
   }
 
   test_error_wrongNumberOfTypeArgumentsConstructor_implicitNew_prefix() async {
@@ -289,18 +538,49 @@
           5),
     ]);
 
-    var import = findElement.import('package:test/a.dart');
-
-    var creation = findNode.instanceCreation('Foo.bar<int>');
-    assertInstanceCreation(
-      creation,
-      import.importedLibrary!.getType('Foo')!,
-      'Foo<int>',
-      constructorName: 'bar',
-      expectedConstructorMember: true,
-      expectedPrefix: import.prefix,
-      expectedSubstitution: {'X': 'int'},
-    );
+    var node = findNode.instanceCreation('Foo.bar<int>');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: PrefixedIdentifier
+        prefix: SimpleIdentifier
+          token: p
+          staticElement: self::@prefix::p
+          staticType: null
+        period: .
+        identifier: SimpleIdentifier
+          token: Foo
+          staticElement: package:test/a.dart::@class::Foo
+          staticType: null
+        staticElement: package:test/a.dart::@class::Foo
+        staticType: null
+      typeArguments: TypeArgumentList
+        leftBracket: <
+        arguments
+          NamedType
+            name: SimpleIdentifier
+              token: int
+              staticElement: dart:core::@class::int
+              staticType: null
+            type: int
+        rightBracket: >
+      type: Foo<int>
+    period: .
+    name: SimpleIdentifier
+      token: bar
+      staticElement: ConstructorMember
+        base: package:test/a.dart::@class::Foo::@constructor::bar
+        substitution: {X: int}
+      staticType: null
+    staticElement: ConstructorMember
+      base: package:test/a.dart::@class::Foo::@constructor::bar
+      substitution: {X: int}
+  argumentList: ArgumentList
+    leftParenthesis: (
+    rightParenthesis: )
+  staticType: Foo<int>
+''');
   }
 
   test_namedArgument_anywhere() async {
@@ -324,11 +604,85 @@
 }
 ''');
 
-    assertInstanceCreation(
-      findNode.instanceCreation('X(g'),
-      findElement.class_('X'),
-      'X',
-    );
+    var node = findNode.instanceCreation('X(g');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: SimpleIdentifier
+        token: X
+        staticElement: self::@class::X
+        staticType: null
+      type: X
+    staticElement: self::@class::X::@constructor::•
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      MethodInvocation
+        methodName: SimpleIdentifier
+          token: g1
+          staticElement: self::@function::g1
+          staticType: T Function<T>()
+        argumentList: ArgumentList
+          leftParenthesis: (
+          rightParenthesis: )
+        staticInvokeType: A Function()
+        staticType: A
+        typeArgumentTypes
+          A
+      NamedExpression
+        name: Label
+          label: SimpleIdentifier
+            token: c
+            staticElement: self::@class::X::@constructor::•::@parameter::c
+            staticType: null
+          colon: :
+        expression: MethodInvocation
+          methodName: SimpleIdentifier
+            token: g3
+            staticElement: self::@function::g3
+            staticType: T Function<T>()
+          argumentList: ArgumentList
+            leftParenthesis: (
+            rightParenthesis: )
+          staticInvokeType: C? Function()
+          staticType: C?
+          typeArgumentTypes
+            C?
+      MethodInvocation
+        methodName: SimpleIdentifier
+          token: g2
+          staticElement: self::@function::g2
+          staticType: T Function<T>()
+        argumentList: ArgumentList
+          leftParenthesis: (
+          rightParenthesis: )
+        staticInvokeType: B Function()
+        staticType: B
+        typeArgumentTypes
+          B
+      NamedExpression
+        name: Label
+          label: SimpleIdentifier
+            token: d
+            staticElement: self::@class::X::@constructor::•::@parameter::d
+            staticType: null
+          colon: :
+        expression: MethodInvocation
+          methodName: SimpleIdentifier
+            token: g4
+            staticElement: self::@function::g4
+            staticType: T Function<T>()
+          argumentList: ArgumentList
+            leftParenthesis: (
+            rightParenthesis: )
+          staticInvokeType: D? Function()
+          staticType: D?
+          typeArgumentTypes
+            D?
+    rightParenthesis: )
+  staticType: X
+''');
 
     var g1 = findNode.methodInvocation('g1()');
     assertType(g1, 'A');
@@ -362,16 +716,35 @@
 }
 ''');
 
-    var creation = findNode.instanceCreation('B.named(0)');
-    assertInstanceCreation(
-      creation,
-      findElement.class_('A'),
-      'A<int>',
-      constructorName: 'named',
-      expectedTypeNameElement: findElement.typeAlias('B'),
-      expectedConstructorMember: true,
-      expectedSubstitution: {'T': 'int'},
-    );
+    var node = findNode.instanceCreation('B.named(0)');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: SimpleIdentifier
+        token: B
+        staticElement: self::@typeAlias::B
+        staticType: null
+      type: A<int>
+    period: .
+    name: SimpleIdentifier
+      token: named
+      staticElement: ConstructorMember
+        base: self::@class::A::@constructor::named
+        substitution: {T: dynamic}
+      staticType: null
+    staticElement: ConstructorMember
+      base: self::@class::A::@constructor::named
+      substitution: {T: int}
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      IntegerLiteral
+        literal: 0
+        staticType: int
+    rightParenthesis: )
+  staticType: A<int>
+''');
   }
 
   test_typeAlias_generic_class_generic_named_infer_partial() async {
@@ -387,16 +760,37 @@
 }
 ''');
 
-    var creation = findNode.instanceCreation('B.named(0, ');
-    assertInstanceCreation(
-      creation,
-      findElement.class_('A'),
-      'A<int, String>',
-      constructorName: 'named',
-      expectedTypeNameElement: findElement.typeAlias('B'),
-      expectedConstructorMember: true,
-      expectedSubstitution: {'T': 'int', 'U': 'String'},
-    );
+    var node = findNode.instanceCreation('B.named(0, ');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: SimpleIdentifier
+        token: B
+        staticElement: self::@typeAlias::B
+        staticType: null
+      type: A<int, String>
+    period: .
+    name: SimpleIdentifier
+      token: named
+      staticElement: ConstructorMember
+        base: self::@class::A::@constructor::named
+        substitution: {T: dynamic, U: String}
+      staticType: null
+    staticElement: ConstructorMember
+      base: self::@class::A::@constructor::named
+      substitution: {T: int, U: String}
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      IntegerLiteral
+        literal: 0
+        staticType: int
+      SimpleStringLiteral
+        literal: ''
+    rightParenthesis: )
+  staticType: A<int, String>
+''');
   }
 
   test_typeAlias_generic_class_generic_unnamed_infer_all() async {
@@ -412,15 +806,28 @@
 }
 ''');
 
-    var creation = findNode.instanceCreation('B(0)');
-    assertInstanceCreation(
-      creation,
-      findElement.class_('A'),
-      'A<int>',
-      expectedTypeNameElement: findElement.typeAlias('B'),
-      expectedConstructorMember: true,
-      expectedSubstitution: {'T': 'int'},
-    );
+    var node = findNode.instanceCreation('B(0)');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: SimpleIdentifier
+        token: B
+        staticElement: self::@typeAlias::B
+        staticType: null
+      type: A<int>
+    staticElement: ConstructorMember
+      base: self::@class::A::@constructor::•
+      substitution: {T: int}
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      IntegerLiteral
+        literal: 0
+        staticType: int
+    rightParenthesis: )
+  staticType: A<int>
+''');
   }
 
   test_typeAlias_generic_class_generic_unnamed_infer_partial() async {
@@ -436,15 +843,30 @@
 }
 ''');
 
-    var creation = findNode.instanceCreation('B(0, ');
-    assertInstanceCreation(
-      creation,
-      findElement.class_('A'),
-      'A<int, String>',
-      expectedTypeNameElement: findElement.typeAlias('B'),
-      expectedConstructorMember: true,
-      expectedSubstitution: {'T': 'int', 'U': 'String'},
-    );
+    var node = findNode.instanceCreation('B(0, ');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: SimpleIdentifier
+        token: B
+        staticElement: self::@typeAlias::B
+        staticType: null
+      type: A<int, String>
+    staticElement: ConstructorMember
+      base: self::@class::A::@constructor::•
+      substitution: {T: int, U: String}
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      IntegerLiteral
+        literal: 0
+        staticType: int
+      SimpleStringLiteral
+        literal: ''
+    rightParenthesis: )
+  staticType: A<int, String>
+''');
   }
 
   test_typeAlias_notGeneric_class_generic_named_argumentTypeMismatch() async {
@@ -462,16 +884,35 @@
       error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 77, 1),
     ]);
 
-    var creation = findNode.instanceCreation('B.named(0)');
-    assertInstanceCreation(
-      creation,
-      findElement.class_('A'),
-      'A<String>',
-      constructorName: 'named',
-      expectedTypeNameElement: findElement.typeAlias('B'),
-      expectedConstructorMember: true,
-      expectedSubstitution: {'T': 'String'},
-    );
+    var node = findNode.instanceCreation('B.named(0)');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: SimpleIdentifier
+        token: B
+        staticElement: self::@typeAlias::B
+        staticType: null
+      type: A<String>
+    period: .
+    name: SimpleIdentifier
+      token: named
+      staticElement: ConstructorMember
+        base: self::@class::A::@constructor::named
+        substitution: {T: String}
+      staticType: null
+    staticElement: ConstructorMember
+      base: self::@class::A::@constructor::named
+      substitution: {T: String}
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      IntegerLiteral
+        literal: 0
+        staticType: int
+    rightParenthesis: )
+  staticType: A<String>
+''');
   }
 
   test_typeAlias_notGeneric_class_generic_unnamed_argumentTypeMismatch() async {
@@ -489,15 +930,28 @@
       error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 65, 1),
     ]);
 
-    var creation = findNode.instanceCreation('B(0)');
-    assertInstanceCreation(
-      creation,
-      findElement.class_('A'),
-      'A<String>',
-      expectedTypeNameElement: findElement.typeAlias('B'),
-      expectedConstructorMember: true,
-      expectedSubstitution: {'T': 'String'},
-    );
+    var node = findNode.instanceCreation('B(0)');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: SimpleIdentifier
+        token: B
+        staticElement: self::@typeAlias::B
+        staticType: null
+      type: A<String>
+    staticElement: ConstructorMember
+      base: self::@class::A::@constructor::•
+      substitution: {T: String}
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      IntegerLiteral
+        literal: 0
+        staticType: int
+    rightParenthesis: )
+  staticType: A<String>
+''');
   }
 
   test_unnamed_declaredNew() async {
@@ -512,8 +966,26 @@
 
 ''');
 
-    var creation = findNode.instanceCreation('A(0)');
-    assertInstanceCreation(creation, findElement.class_('A'), 'A');
+    var node = findNode.instanceCreation('A(0)');
+    assertResolvedNodeText(node, r'''
+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: (
+    arguments
+      IntegerLiteral
+        literal: 0
+        staticType: int
+    rightParenthesis: )
+  staticType: A
+''');
   }
 
   test_unnamedViaNew_declaredNew() async {
@@ -528,8 +1000,31 @@
 
 ''');
 
-    var creation = findNode.instanceCreation('A.new(0)');
-    assertInstanceCreation(creation, findElement.class_('A'), 'A');
+    var node = findNode.instanceCreation('A.new(0)');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: SimpleIdentifier
+        token: A
+        staticElement: self::@class::A
+        staticType: null
+      type: A
+    period: .
+    name: SimpleIdentifier
+      token: new
+      staticElement: self::@class::A::@constructor::•
+      staticType: null
+    staticElement: self::@class::A::@constructor::•
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      IntegerLiteral
+        literal: 0
+        staticType: int
+    rightParenthesis: )
+  staticType: A
+''');
   }
 
   test_unnamedViaNew_declaredUnnamed() async {
@@ -544,8 +1039,31 @@
 
 ''');
 
-    var creation = findNode.instanceCreation('A.new(0)');
-    assertInstanceCreation(creation, findElement.class_('A'), 'A');
+    var node = findNode.instanceCreation('A.new(0)');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: SimpleIdentifier
+        token: A
+        staticElement: self::@class::A
+        staticType: null
+      type: A
+    period: .
+    name: SimpleIdentifier
+      token: new
+      staticElement: self::@class::A::@constructor::•
+      staticType: null
+    staticElement: self::@class::A::@constructor::•
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      IntegerLiteral
+        literal: 0
+        staticType: int
+    rightParenthesis: )
+  staticType: A
+''');
   }
 }
 
@@ -567,7 +1085,30 @@
     ]);
 
     // Resolution should continue even though the experiment is not enabled.
-    var creation = findNode.instanceCreation('A.new(0)');
-    assertInstanceCreation(creation, findElement.class_('A'), 'A');
+    var node = findNode.instanceCreation('A.new(0)');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: SimpleIdentifier
+        token: A
+        staticElement: self::@class::A
+        staticType: null
+      type: A
+    period: .
+    name: SimpleIdentifier
+      token: new
+      staticElement: self::@class::A::@constructor::•
+      staticType: null
+    staticElement: self::@class::A::@constructor::•
+  argumentList: ArgumentList
+    leftParenthesis: (
+    arguments
+      IntegerLiteral
+        literal: 0
+        staticType: int
+    rightParenthesis: )
+  staticType: A
+''');
   }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart b/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart
index daa949c..a425545 100644
--- a/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/optional_const_test.dart
@@ -17,98 +17,220 @@
 
 @reflectiveTest
 class OptionalConstDriverResolutionTest extends PubPackageResolutionTest {
-  Map<String, LibraryElement> libraries = {};
-
-  LibraryElement get libraryA => libraries['package:test/a.dart']!;
-
   test_instantiateToBounds_notPrefixed_named() async {
-    var creation = await _resolveImplicitConst('B.named()');
-    assertInstanceCreation(
-      creation,
-      libraryA.getType('B')!,
-      'B<num>',
-      constructorName: 'named',
-      expectedConstructorMember: true,
-      expectedSubstitution: {'T': 'num'},
-    );
+    var node = await _resolveImplicitConst('B.named()');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: SimpleIdentifier
+        token: B
+        staticElement: package:test/a.dart::@class::B
+        staticType: null
+      type: B<num>
+    period: .
+    name: SimpleIdentifier
+      token: named
+      staticElement: ConstructorMember
+        base: package:test/a.dart::@class::B::@constructor::named
+        substitution: {T: num}
+      staticType: null
+    staticElement: ConstructorMember
+      base: package:test/a.dart::@class::B::@constructor::named
+      substitution: {T: num}
+  argumentList: ArgumentList
+    leftParenthesis: (
+    rightParenthesis: )
+  staticType: B<num>
+''');
   }
 
   test_instantiateToBounds_notPrefixed_unnamed() async {
-    var creation = await _resolveImplicitConst('B()');
-    assertInstanceCreation(
-      creation,
-      libraryA.getType('B')!,
-      'B<num>',
-      expectedConstructorMember: true,
-      expectedSubstitution: {'T': 'num'},
-    );
+    var node = await _resolveImplicitConst('B()');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: SimpleIdentifier
+        token: B
+        staticElement: package:test/a.dart::@class::B
+        staticType: null
+      type: B<num>
+    staticElement: ConstructorMember
+      base: package:test/a.dart::@class::B::@constructor::•
+      substitution: {T: num}
+  argumentList: ArgumentList
+    leftParenthesis: (
+    rightParenthesis: )
+  staticType: B<num>
+''');
   }
 
   test_instantiateToBounds_prefixed_named() async {
-    var creation = await _resolveImplicitConst('p.B.named()', prefix: 'p');
-    assertInstanceCreation(
-      creation,
-      libraryA.getType('B')!,
-      'B<num>',
-      constructorName: 'named',
-      expectedConstructorMember: true,
-      expectedSubstitution: {'T': 'num'},
-      expectedPrefix: _importOfA().prefix,
-    );
+    var node = await _resolveImplicitConst('p.B.named()', prefix: 'p');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: PrefixedIdentifier
+        prefix: SimpleIdentifier
+          token: p
+          staticElement: package:test/b.dart::@prefix::p
+          staticType: null
+        period: .
+        identifier: SimpleIdentifier
+          token: B
+          staticElement: package:test/a.dart::@class::B
+          staticType: null
+        staticElement: package:test/a.dart::@class::B
+        staticType: null
+      type: B<num>
+    period: .
+    name: SimpleIdentifier
+      token: named
+      staticElement: ConstructorMember
+        base: package:test/a.dart::@class::B::@constructor::named
+        substitution: {T: num}
+      staticType: null
+    staticElement: ConstructorMember
+      base: package:test/a.dart::@class::B::@constructor::named
+      substitution: {T: num}
+  argumentList: ArgumentList
+    leftParenthesis: (
+    rightParenthesis: )
+  staticType: B<num>
+''');
   }
 
   test_instantiateToBounds_prefixed_unnamed() async {
-    var creation = await _resolveImplicitConst('p.B()', prefix: 'p');
-    assertInstanceCreation(
-      creation,
-      libraryA.getType('B')!,
-      'B<num>',
-      expectedConstructorMember: true,
-      expectedSubstitution: {'T': 'num'},
-      expectedPrefix: _importOfA().prefix,
-    );
+    var node = await _resolveImplicitConst('p.B()', prefix: 'p');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: PrefixedIdentifier
+        prefix: SimpleIdentifier
+          token: p
+          staticElement: package:test/b.dart::@prefix::p
+          staticType: null
+        period: .
+        identifier: SimpleIdentifier
+          token: B
+          staticElement: package:test/a.dart::@class::B
+          staticType: null
+        staticElement: package:test/a.dart::@class::B
+        staticType: null
+      type: B<num>
+    staticElement: ConstructorMember
+      base: package:test/a.dart::@class::B::@constructor::•
+      substitution: {T: num}
+  argumentList: ArgumentList
+    leftParenthesis: (
+    rightParenthesis: )
+  staticType: B<num>
+''');
   }
 
   test_notPrefixed_named() async {
-    var creation = await _resolveImplicitConst('A.named()');
-    assertInstanceCreation(
-      creation,
-      libraryA.getType('A')!,
-      'A',
-      constructorName: 'named',
-    );
+    var node = await _resolveImplicitConst('A.named()');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: SimpleIdentifier
+        token: A
+        staticElement: package:test/a.dart::@class::A
+        staticType: null
+      type: A
+    period: .
+    name: SimpleIdentifier
+      token: named
+      staticElement: package:test/a.dart::@class::A::@constructor::named
+      staticType: null
+    staticElement: package:test/a.dart::@class::A::@constructor::named
+  argumentList: ArgumentList
+    leftParenthesis: (
+    rightParenthesis: )
+  staticType: A
+''');
   }
 
   test_notPrefixed_unnamed() async {
-    var creation = await _resolveImplicitConst('A()');
-    assertInstanceCreation(
-      creation,
-      libraryA.getType('A')!,
-      'A',
-    );
+    var node = await _resolveImplicitConst('A()');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: SimpleIdentifier
+        token: A
+        staticElement: package:test/a.dart::@class::A
+        staticType: null
+      type: A
+    staticElement: package:test/a.dart::@class::A::@constructor::•
+  argumentList: ArgumentList
+    leftParenthesis: (
+    rightParenthesis: )
+  staticType: A
+''');
   }
 
   test_prefixed_named() async {
-    var creation = await _resolveImplicitConst('p.A.named()', prefix: 'p');
-    // Note, that we don't resynthesize the import prefix.
-    assertInstanceCreation(
-      creation,
-      libraryA.getType('A')!,
-      'A',
-      constructorName: 'named',
-      expectedPrefix: _importOfA().prefix,
-    );
+    var node = await _resolveImplicitConst('p.A.named()', prefix: 'p');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: PrefixedIdentifier
+        prefix: SimpleIdentifier
+          token: p
+          staticElement: package:test/b.dart::@prefix::p
+          staticType: null
+        period: .
+        identifier: SimpleIdentifier
+          token: A
+          staticElement: package:test/a.dart::@class::A
+          staticType: null
+        staticElement: package:test/a.dart::@class::A
+        staticType: null
+      type: A
+    period: .
+    name: SimpleIdentifier
+      token: named
+      staticElement: package:test/a.dart::@class::A::@constructor::named
+      staticType: null
+    staticElement: package:test/a.dart::@class::A::@constructor::named
+  argumentList: ArgumentList
+    leftParenthesis: (
+    rightParenthesis: )
+  staticType: A
+''');
   }
 
   test_prefixed_unnamed() async {
-    var creation = await _resolveImplicitConst('p.A()', prefix: 'p');
-    // Note, that we don't resynthesize the import prefix.
-    assertInstanceCreation(
-      creation,
-      libraryA.getType('A')!,
-      'A',
-      expectedPrefix: _importOfA().prefix,
-    );
+    var node = await _resolveImplicitConst('p.A()', prefix: 'p');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: PrefixedIdentifier
+        prefix: SimpleIdentifier
+          token: p
+          staticElement: package:test/b.dart::@prefix::p
+          staticType: null
+        period: .
+        identifier: SimpleIdentifier
+          token: A
+          staticElement: package:test/a.dart::@class::A
+          staticType: null
+        staticElement: package:test/a.dart::@class::A
+        staticType: null
+      type: A
+    staticElement: package:test/a.dart::@class::A::@constructor::•
+  argumentList: ArgumentList
+    leftParenthesis: (
+    rightParenthesis: )
+  staticType: A
+''');
   }
 
   test_prefixed_unnamed_generic() async {
@@ -117,52 +239,49 @@
   const C();
 }
 ''');
+
     await assertNoErrorsInCode(r'''
 import 'a.dart' as p;
 
 const x = p.C<int>();
 ''');
-    _fillLibraries();
 
-    var element_C = libraryA.getType('C');
-    var element_p = findElement.prefix('p');
-
-    var creation = findNode.instanceCreation('p.C<int>()');
-    assertType(creation, 'C<int>');
-
-    var constructorName = creation.constructorName;
-
-    var typeName = constructorName.type;
-    assertType(typeName, 'C<int>');
-
-    var pC = typeName.name as PrefixedIdentifier;
-    assertElement(pC, element_C);
-    // TODO(scheglov) enforce
-//    assertTypeNull(pC);
-
-    var ref_p = pC.prefix;
-    assertElement(ref_p, element_p);
-    assertTypeNull(ref_p);
-
-    var ref_C = pC.identifier;
-    assertElement(ref_C, element_C);
-    assertTypeNull(ref_C);
-
-    assertType(typeName.typeArguments!.arguments[0], 'int');
-  }
-
-  void _fillLibraries([LibraryElement? library]) {
-    library ??= result.unit.declaredElement!.library;
-    var uriStr = library.source.uri.toString();
-    if (!libraries.containsKey(uriStr)) {
-      libraries[uriStr] = library;
-      library.importedLibraries.forEach(_fillLibraries);
-    }
-  }
-
-  ImportElement _importOfA() {
-    var importOfB = findElement.import('package:test/b.dart');
-    return importOfB.importedLibrary!.imports[0];
+    var node = findNode.instanceCreation('p.C<int>()');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: PrefixedIdentifier
+        prefix: SimpleIdentifier
+          token: p
+          staticElement: self::@prefix::p
+          staticType: null
+        period: .
+        identifier: SimpleIdentifier
+          token: C
+          staticElement: package:test/a.dart::@class::C
+          staticType: null
+        staticElement: package:test/a.dart::@class::C
+        staticType: null
+      typeArguments: TypeArgumentList
+        leftBracket: <
+        arguments
+          NamedType
+            name: SimpleIdentifier
+              token: int
+              staticElement: dart:core::@class::int
+              staticType: null
+            type: int
+        rightBracket: >
+      type: C<int>
+    staticElement: ConstructorMember
+      base: package:test/a.dart::@class::C::@constructor::•
+      substitution: {T: int}
+  argumentList: ArgumentList
+    leftParenthesis: (
+    rightParenthesis: )
+  staticType: C<int>
+''');
   }
 
   Future<InstanceCreationExpression> _resolveImplicitConst(String expr,
@@ -194,7 +313,6 @@
 import 'b.dart';
 var v = a;
 ''');
-    _fillLibraries();
 
     var vg = findNode.simple('a;').staticElement as PropertyAccessorElement;
     var v = vg.variable as ConstVariableElement;
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart
index 8744443..002686b 100644
--- a/pkg/analyzer/test/src/dart/resolution/resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -384,54 +384,6 @@
     assertTypeNull(identifier);
   }
 
-  /// TODO(srawlins): Refactor to accept an `Object? expectedConstructor` which
-  /// can accept `elementMatcher` for generics, and simplify, similar to
-  /// `assertConstructorReference`.
-  void assertInstanceCreation(
-    InstanceCreationExpression creation,
-    ClassElement expectedClassElement,
-    String expectedType, {
-    String? constructorName,
-    bool expectedConstructorMember = false,
-    Map<String, String>? expectedSubstitution,
-    PrefixElement? expectedPrefix,
-    Element? expectedTypeNameElement,
-  }) {
-    var expectedConstructorElement =
-        _getConstructorElement(expectedClassElement, constructorName);
-
-    var actualConstructorElement =
-        getNodeElement(creation) as ConstructorElement?;
-    var constructorName2 = creation.constructorName.name;
-    if (constructorName2 != null) {
-      // TODO(brianwilkerson) This used to enforce that the two elements were
-      // the same object, but the changes to the AstRewriteVisitor broke that.
-      // We should explore re-establishing this restriction for performance.
-      assertConstructorElement(
-        constructorName2.staticElement as ConstructorElement?,
-        actualConstructorElement,
-      );
-    }
-
-    if (expectedConstructorMember) {
-      expect(actualConstructorElement, const TypeMatcher<Member>());
-      assertMember(
-        creation,
-        expectedConstructorElement,
-        expectedSubstitution!,
-      );
-    } else {
-      assertElement(creation, expectedConstructorElement);
-    }
-
-    assertType(creation, expectedType);
-
-    var namedType = creation.constructorName.type;
-    expectedTypeNameElement ??= expectedClassElement;
-    assertNamedType(namedType, expectedTypeNameElement, expectedType,
-        expectedPrefix: expectedPrefix);
-  }
-
   /// Resolve the [code], and ensure that it can be resolved without a crash,
   /// and is invalid, i.e. produces a diagnostic.
   Future<void> assertInvalidTestCode(String code) async {
@@ -566,8 +518,15 @@
     assertType(node.staticType, type);
   }
 
-  void assertResolvedNodeText(AstNode node, String expected) {
-    var actual = _resolvedNodeText(node);
+  void assertResolvedNodeText(
+    AstNode node,
+    String expected, {
+    bool skipArgumentList = false,
+  }) {
+    var actual = _resolvedNodeText(
+      node,
+      skipArgumentList: skipArgumentList,
+    );
     if (actual != expected) {
       print(actual);
       NodeTextExpectationsCollector.add(actual);
@@ -935,23 +894,17 @@
     fail('Expected SimpleIdentifier: (${node.runtimeType}) $node');
   }
 
-  ConstructorElement _getConstructorElement(
-      ClassElement classElement, String? constructorName) {
-    var constructorElement = constructorName == null
-        ? classElement.unnamedConstructor
-        : classElement.getNamedConstructor(constructorName);
-    return constructorElement ??
-        fail("No constructor '${constructorName ?? '<unnamed>'}' in class "
-            "'${classElement.name}'.");
-  }
-
-  String _resolvedNodeText(AstNode node) {
+  String _resolvedNodeText(
+    AstNode node, {
+    bool skipArgumentList = false,
+  }) {
     var buffer = StringBuffer();
     node.accept(
       ResolvedAstPrinter(
         selfUriStr: result.uri.toString(),
         sink: buffer,
         indent: '',
+        skipArgumentList: skipArgumentList,
       ),
     );
     return buffer.toString();
diff --git a/pkg/analyzer/test/src/dart/resolution/variance_test.dart b/pkg/analyzer/test/src/dart/resolution/variance_test.dart
index 34067a8..96e40ac 100644
--- a/pkg/analyzer/test/src/dart/resolution/variance_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/variance_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/element/type.dart';
 import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -39,9 +38,22 @@
   inferContraContra(Contravariant<Upper>(), Contravariant<Middle>());
 }
     ''');
-    assertType(
-        findNode.methodInvocation('inferContraContra(').typeArgumentTypes![0],
-        'Middle');
+
+    var node = findNode.methodInvocation('inferContraContra(');
+    assertResolvedNodeText(
+        node,
+        r'''
+MethodInvocation
+  methodName: SimpleIdentifier
+    token: inferContraContra
+    staticElement: self::@function::inferContraContra
+    staticType: Exactly<T> Function<T>(Contravariant<T>, Contravariant<T>)
+  staticInvokeType: Exactly<Middle> Function(Contravariant<Middle>, Contravariant<Middle>)
+  staticType: Exactly<Middle>
+  typeArgumentTypes
+    Middle
+''',
+        skipArgumentList: true);
   }
 
   test_inference_in_parameter_downwards() async {
@@ -52,15 +64,30 @@
 }
 
 main() {
-  B<int> b = new B(<num>[])..x=2.2;
+  B<int> b = B(<num>[])..x=2.2;
 }
 ''', [
       error(HintCode.UNUSED_LOCAL_VARIABLE, 76, 1),
     ]);
-    assertType(
-        (findNode.instanceCreation('new B').staticType as InterfaceType)
-            .typeArguments[0],
-        'num');
+
+    var node = findNode.instanceCreation('B(<num>');
+    assertResolvedNodeText(
+        node,
+        r'''
+InstanceCreationExpression
+  constructorName: ConstructorName
+    type: NamedType
+      name: SimpleIdentifier
+        token: B
+        staticElement: self::@class::B
+        staticType: null
+      type: B<num>
+    staticElement: ConstructorMember
+      base: self::@class::B::@constructor::•
+      substitution: {T: num}
+  staticType: B<num>
+''',
+        skipArgumentList: true);
   }
 
   test_inference_inout_parameter() async {
@@ -79,6 +106,22 @@
       error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 159, 19),
       error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 180, 16),
     ]);
+
+    var node = findNode.methodInvocation('inferInvInv(');
+    assertResolvedNodeText(
+        node,
+        r'''
+MethodInvocation
+  methodName: SimpleIdentifier
+    token: inferInvInv
+    staticElement: self::@function::inferInvInv
+    staticType: Exactly<T> Function<T>(Invariant<T>, Invariant<T>)
+  staticInvokeType: Exactly<Object> Function(Invariant<Object>, Invariant<Object>)
+  staticType: Exactly<Object>
+  typeArgumentTypes
+    Object
+''',
+        skipArgumentList: true);
   }
 
   test_inference_out_parameter() async {
@@ -96,7 +139,21 @@
   inferCovCov(Covariant<Upper>(), Covariant<Middle>());
 }
 ''');
-    assertType(findNode.methodInvocation('inferCovCov(').typeArgumentTypes![0],
-        'Upper');
+
+    var node = findNode.methodInvocation('inferCovCov(');
+    assertResolvedNodeText(
+        node,
+        r'''
+MethodInvocation
+  methodName: SimpleIdentifier
+    token: inferCovCov
+    staticElement: self::@function::inferCovCov
+    staticType: Exactly<T> Function<T>(Covariant<T>, Covariant<T>)
+  staticInvokeType: Exactly<Upper> Function(Covariant<Upper>, Covariant<Upper>)
+  staticType: Exactly<Upper>
+  typeArgumentTypes
+    Upper
+''',
+        skipArgumentList: true);
   }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/mixin_instantiate_test.dart b/pkg/analyzer/test/src/diagnostics/mixin_instantiate_test.dart
index 8dd5c55..7bcc0e2 100644
--- a/pkg/analyzer/test/src/diagnostics/mixin_instantiate_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/mixin_instantiate_test.dart
@@ -30,9 +30,28 @@
       error(CompileTimeErrorCode.MIXIN_INSTANTIATE, 43, 1),
     ]);
 
-    var creation = findNode.instanceCreation('M.named();');
-    var m = findElement.mixin('M');
-    assertInstanceCreation(creation, m, 'M', constructorName: 'named');
+    var node = findNode.instanceCreation('M.named();');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  keyword: new
+  constructorName: ConstructorName
+    type: NamedType
+      name: SimpleIdentifier
+        token: M
+        staticElement: self::@mixin::M
+        staticType: null
+      type: M
+    period: .
+    name: SimpleIdentifier
+      token: named
+      staticElement: self::@mixin::M::@constructor::named
+      staticType: null
+    staticElement: self::@mixin::M::@constructor::named
+  argumentList: ArgumentList
+    leftParenthesis: (
+    rightParenthesis: )
+  staticType: M
+''');
   }
 
   test_namedConstructor_undefined() async {
@@ -62,8 +81,22 @@
       error(CompileTimeErrorCode.MIXIN_INSTANTIATE, 27, 1),
     ]);
 
-    var creation = findNode.instanceCreation('M();');
-    var m = findElement.mixin('M');
-    assertInstanceCreation(creation, m, 'M');
+    var node = findNode.instanceCreation('M();');
+    assertResolvedNodeText(node, r'''
+InstanceCreationExpression
+  keyword: new
+  constructorName: ConstructorName
+    type: NamedType
+      name: SimpleIdentifier
+        token: M
+        staticElement: self::@mixin::M
+        staticType: null
+      type: M
+    staticElement: self::@mixin::M::@constructor::•
+  argumentList: ArgumentList
+    leftParenthesis: (
+    rightParenthesis: )
+  staticType: M
+''');
   }
 }
diff --git a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
index e0617b5..f8a4382c 100644
--- a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
+++ b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
@@ -15,15 +15,6 @@
 import 'package:analyzer/src/summary2/reference.dart';
 import 'package:test/test.dart';
 
-/// Used in [ResolvedAstPrinter] to print lines of code that corresponding
-/// to a subtree of AST. This help to make the bulky presentation of AST a
-/// bit more understandable.
-abstract class CodeLinesProvider {
-  /// If the [offset] corresponds to a new, never requested before line,
-  /// return this line, otherwise return `null`.
-  String nextLine(int offset);
-}
-
 /// Prints AST as a tree, with properties and children.
 class ResolvedAstPrinter extends ThrowingAstVisitor<void> {
   /// The URI of the library that contains the AST being printed.
@@ -32,8 +23,7 @@
   /// The target sink to print AST.
   final StringSink _sink;
 
-  /// The optional provider for code lines, might be `null`.
-  final CodeLinesProvider? _codeLinesProvider;
+  final bool skipArgumentList;
 
   /// If `true`, linking of [EnumConstantDeclaration] will be checked
   /// TODO(scheglov) Remove after https://github.com/dart-lang/sdk/issues/48380
@@ -51,20 +41,18 @@
     required String? selfUriStr,
     required StringSink sink,
     required String indent,
-    CodeLinesProvider? codeLinesProvider,
+    this.skipArgumentList = false,
     this.withCheckingLinking = false,
     bool withOffsets = false,
     bool withResolution = true,
   })  : _selfUriStr = selfUriStr,
         _sink = sink,
-        _codeLinesProvider = codeLinesProvider,
         _withOffsets = withOffsets,
         _withResolution = withResolution,
         _indent = indent;
 
   @override
   void visitAdjacentStrings(AdjacentStrings node) {
-    _writeNextCodeLine(node);
     _writeln('AdjacentStrings');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -75,7 +63,6 @@
 
   @override
   void visitAnnotation(Annotation node) {
-    _writeNextCodeLine(node);
     _writeln('Annotation');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -85,7 +72,6 @@
 
   @override
   void visitArgumentList(ArgumentList node) {
-    _writeNextCodeLine(node);
     _writeln('ArgumentList');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -94,7 +80,6 @@
 
   @override
   void visitAsExpression(AsExpression node) {
-    _writeNextCodeLine(node);
     _writeln('AsExpression');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -104,7 +89,6 @@
 
   @override
   void visitAssertInitializer(AssertInitializer node) {
-    _writeNextCodeLine(node);
     _writeln('AssertInitializer');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -113,7 +97,6 @@
 
   @override
   void visitAssertStatement(AssertStatement node) {
-    _writeNextCodeLine(node);
     _writeln('AssertStatement');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -122,7 +105,6 @@
 
   @override
   void visitAssignmentExpression(AssignmentExpression node) {
-    _writeNextCodeLine(node);
     _writeln('AssignmentExpression');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -137,7 +119,6 @@
 
   @override
   void visitAwaitExpression(AwaitExpression node) {
-    _writeNextCodeLine(node);
     _writeln('AwaitExpression');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -147,7 +128,6 @@
 
   @override
   void visitBinaryExpression(BinaryExpression node) {
-    _writeNextCodeLine(node);
     _writeln('BinaryExpression');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -159,7 +139,6 @@
 
   @override
   void visitBlock(Block node) {
-    _writeNextCodeLine(node);
     _writeln('Block');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -168,7 +147,6 @@
 
   @override
   void visitBlockFunctionBody(BlockFunctionBody node) {
-    _writeNextCodeLine(node);
     _writeln('BlockFunctionBody');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -177,7 +155,6 @@
 
   @override
   void visitBooleanLiteral(BooleanLiteral node) {
-    _writeNextCodeLine(node);
     _writeln('BooleanLiteral');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -187,7 +164,6 @@
 
   @override
   void visitBreakStatement(BreakStatement node) {
-    _writeNextCodeLine(node);
     _writeln('BreakStatement');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -196,7 +172,6 @@
 
   @override
   void visitCascadeExpression(CascadeExpression node) {
-    _writeNextCodeLine(node);
     _writeln('CascadeExpression');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -206,7 +181,6 @@
 
   @override
   void visitCatchClause(CatchClause node) {
-    _writeNextCodeLine(node);
     _writeln('CatchClause');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -215,7 +189,6 @@
 
   @override
   void visitClassDeclaration(ClassDeclaration node) {
-    _writeNextCodeLine(node);
     _writeln('ClassDeclaration');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -227,7 +200,6 @@
 
   @override
   void visitComment(Comment node) {
-    _writeNextCodeLine(node);
     _writeln('Comment');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -236,7 +208,6 @@
 
   @override
   void visitCompilationUnit(CompilationUnit node) {
-    _writeNextCodeLine(node);
     _writeln('CompilationUnit');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -245,7 +216,6 @@
 
   @override
   void visitConditionalExpression(ConditionalExpression node) {
-    _writeNextCodeLine(node);
     _writeln('ConditionalExpression');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -255,7 +225,6 @@
 
   @override
   void visitConstructorDeclaration(ConstructorDeclaration node) {
-    _writeNextCodeLine(node);
     _writeln('ConstructorDeclaration');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -267,7 +236,6 @@
 
   @override
   void visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
-    _writeNextCodeLine(node);
     _writeln('ConstructorFieldInitializer');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -276,7 +244,6 @@
 
   @override
   void visitConstructorName(ConstructorName node) {
-    _writeNextCodeLine(node);
     _writeln('ConstructorName');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -304,7 +271,6 @@
 
   @override
   void visitContinueStatement(ContinueStatement node) {
-    _writeNextCodeLine(node);
     _writeln('ContinueStatement');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -313,7 +279,6 @@
 
   @override
   void visitDeclaredIdentifier(DeclaredIdentifier node) {
-    _writeNextCodeLine(node);
     _writeln('DeclaredIdentifier');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -325,7 +290,6 @@
 
   @override
   void visitDefaultFormalParameter(DefaultFormalParameter node) {
-    _writeNextCodeLine(node);
     _writeln('DefaultFormalParameter');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -338,7 +302,6 @@
 
   @override
   void visitDoStatement(DoStatement node) {
-    _writeNextCodeLine(node);
     _writeln('DoStatement');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -347,7 +310,6 @@
 
   @override
   void visitDoubleLiteral(DoubleLiteral node) {
-    _writeNextCodeLine(node);
     _writeln('DoubleLiteral');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -357,7 +319,6 @@
 
   @override
   void visitEmptyFunctionBody(EmptyFunctionBody node) {
-    _writeNextCodeLine(node);
     _writeln('EmptyFunctionBody');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -378,7 +339,6 @@
   @override
   void visitEnumConstantDeclaration(EnumConstantDeclaration node) {
     _checkChildrenEntitiesLinking(node);
-    _writeNextCodeLine(node);
     _writeln('EnumConstantDeclaration');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -390,7 +350,6 @@
 
   @override
   void visitEnumDeclaration(EnumDeclaration node) {
-    _writeNextCodeLine(node);
     _writeln('EnumDeclaration');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -402,7 +361,6 @@
 
   @override
   void visitExportDirective(ExportDirective node) {
-    _writeNextCodeLine(node);
     _writeln('ExportDirective');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -417,7 +375,6 @@
 
   @override
   void visitExpressionFunctionBody(ExpressionFunctionBody node) {
-    _writeNextCodeLine(node);
     _writeln('ExpressionFunctionBody');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -426,7 +383,6 @@
 
   @override
   void visitExpressionStatement(ExpressionStatement node) {
-    _writeNextCodeLine(node);
     _writeln('ExpressionStatement');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -435,7 +391,6 @@
 
   @override
   void visitExtendsClause(ExtendsClause node) {
-    _writeNextCodeLine(node);
     _writeln('ExtendsClause');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -444,7 +399,6 @@
 
   @override
   void visitExtensionOverride(ExtensionOverride node) {
-    _writeNextCodeLine(node);
     _writeln('ExtensionOverride');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -456,7 +410,6 @@
 
   @override
   void visitFieldDeclaration(FieldDeclaration node) {
-    _writeNextCodeLine(node);
     _writeln('FieldDeclaration');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -468,7 +421,6 @@
 
   @override
   void visitFieldFormalParameter(FieldFormalParameter node) {
-    _writeNextCodeLine(node);
     _writeln('FieldFormalParameter');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -481,7 +433,6 @@
 
   @override
   void visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) {
-    _writeNextCodeLine(node);
     _writeln('ForEachPartsWithDeclaration');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -490,7 +441,6 @@
 
   @override
   void visitForEachPartsWithIdentifier(ForEachPartsWithIdentifier node) {
-    _writeNextCodeLine(node);
     _writeln('ForEachPartsWithIdentifier');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -499,7 +449,6 @@
 
   @override
   void visitFormalParameterList(FormalParameterList node) {
-    _writeNextCodeLine(node);
     _writeln('FormalParameterList');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -508,7 +457,6 @@
 
   @override
   void visitForPartsWithDeclarations(ForPartsWithDeclarations node) {
-    _writeNextCodeLine(node);
     _writeln('ForPartsWithDeclarations');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -517,7 +465,6 @@
 
   @override
   void visitForPartsWithExpression(ForPartsWithExpression node) {
-    _writeNextCodeLine(node);
     _writeln('ForPartsWithExpression');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -526,7 +473,6 @@
 
   @override
   void visitForStatement(ForStatement node) {
-    _writeNextCodeLine(node);
     _writeln('ForStatement');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -535,7 +481,6 @@
 
   @override
   void visitFunctionDeclaration(FunctionDeclaration node) {
-    _writeNextCodeLine(node);
     _writeln('FunctionDeclaration');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -548,7 +493,6 @@
 
   @override
   void visitFunctionDeclarationStatement(FunctionDeclarationStatement node) {
-    _writeNextCodeLine(node);
     _writeln('FunctionDeclarationStatement');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -557,7 +501,6 @@
 
   @override
   void visitFunctionExpression(FunctionExpression node) {
-    _writeNextCodeLine(node);
     _writeln('FunctionExpression');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -570,7 +513,6 @@
 
   @override
   void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
-    _writeNextCodeLine(node);
     _writeln('FunctionExpressionInvocation');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -593,7 +535,6 @@
 
   @override
   void visitFunctionTypeAlias(FunctionTypeAlias node) {
-    _writeNextCodeLine(node);
     _writeln('FunctionTypeAlias');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -605,7 +546,6 @@
 
   @override
   void visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) {
-    _writeNextCodeLine(node);
     _writeln('FunctionTypedFormalParameter');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -618,7 +558,6 @@
 
   @override
   void visitGenericFunctionType(covariant GenericFunctionTypeImpl node) {
-    _writeNextCodeLine(node);
     _writeln('GenericFunctionType');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -634,7 +573,6 @@
 
   @override
   void visitGenericTypeAlias(GenericTypeAlias node) {
-    _writeNextCodeLine(node);
     _writeln('GenericTypeAlias');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -646,7 +584,6 @@
 
   @override
   void visitHideCombinator(HideCombinator node) {
-    _writeNextCodeLine(node);
     _writeln('HideCombinator');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -663,7 +600,6 @@
 
   @override
   void visitIfStatement(IfStatement node) {
-    _writeNextCodeLine(node);
     _writeln('IfStatement');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -672,7 +608,6 @@
 
   @override
   void visitImplementsClause(ImplementsClause node) {
-    _writeNextCodeLine(node);
     _writeln('ImplementsClause');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -692,7 +627,6 @@
 
   @override
   void visitImportDirective(ImportDirective node) {
-    _writeNextCodeLine(node);
     _writeln('ImportDirective');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -707,7 +641,6 @@
 
   @override
   void visitIndexExpression(IndexExpression node) {
-    _writeNextCodeLine(node);
     _writeln('IndexExpression');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -718,7 +651,6 @@
 
   @override
   void visitInstanceCreationExpression(InstanceCreationExpression node) {
-    _writeNextCodeLine(node);
     _writeln('InstanceCreationExpression');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -728,7 +660,6 @@
 
   @override
   void visitIntegerLiteral(IntegerLiteral node) {
-    _writeNextCodeLine(node);
     _writeln('IntegerLiteral');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -738,7 +669,6 @@
 
   @override
   void visitInterpolationExpression(InterpolationExpression node) {
-    _writeNextCodeLine(node);
     _writeln('InterpolationExpression');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -747,7 +677,6 @@
 
   @override
   void visitInterpolationString(InterpolationString node) {
-    _writeNextCodeLine(node);
     _writeln('InterpolationString');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -756,7 +685,6 @@
 
   @override
   void visitIsExpression(IsExpression node) {
-    _writeNextCodeLine(node);
     _writeln('IsExpression');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -766,7 +694,6 @@
 
   @override
   void visitLabel(Label node) {
-    _writeNextCodeLine(node);
     _writeln('Label');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -775,7 +702,6 @@
 
   @override
   void visitLibraryDirective(LibraryDirective node) {
-    _writeNextCodeLine(node);
     _writeln('LibraryDirective');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -785,7 +711,6 @@
 
   @override
   void visitLibraryIdentifier(LibraryIdentifier node) {
-    _writeNextCodeLine(node);
     _writeln('LibraryIdentifier');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -796,7 +721,6 @@
 
   @override
   void visitListLiteral(ListLiteral node) {
-    _writeNextCodeLine(node);
     _writeln('ListLiteral');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -806,7 +730,6 @@
 
   @override
   void visitMapLiteralEntry(MapLiteralEntry node) {
-    _writeNextCodeLine(node);
     _writeln('SetOrMapLiteral');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -815,7 +738,6 @@
 
   @override
   void visitMethodDeclaration(MethodDeclaration node) {
-    _writeNextCodeLine(node);
     _writeln('MethodDeclaration');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -828,7 +750,6 @@
 
   @override
   void visitMethodInvocation(MethodInvocation node) {
-    _writeNextCodeLine(node);
     _writeln('MethodInvocation');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -840,7 +761,6 @@
 
   @override
   void visitMixinDeclaration(MixinDeclaration node) {
-    _writeNextCodeLine(node);
     _writeln('MixinDeclaration');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -852,7 +772,6 @@
 
   @override
   void visitNamedExpression(NamedExpression node) {
-    _writeNextCodeLine(node);
     _writeln('NamedExpression');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -861,7 +780,6 @@
 
   @override
   void visitNamedType(NamedType node) {
-    _writeNextCodeLine(node);
     _writeln('NamedType');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -871,7 +789,6 @@
 
   @override
   void visitNullLiteral(NullLiteral node) {
-    _writeNextCodeLine(node);
     _writeln('NullLiteral');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -881,7 +798,6 @@
 
   @override
   void visitOnClause(OnClause node) {
-    _writeNextCodeLine(node);
     _writeln('OnClause');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -890,7 +806,6 @@
 
   @override
   void visitParenthesizedExpression(ParenthesizedExpression node) {
-    _writeNextCodeLine(node);
     _writeln('ParenthesizedExpression');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -900,7 +815,6 @@
 
   @override
   void visitPartDirective(PartDirective node) {
-    _writeNextCodeLine(node);
     _writeln('PartDirective');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -913,7 +827,6 @@
 
   @override
   void visitPartOfDirective(PartOfDirective node) {
-    _writeNextCodeLine(node);
     _writeln('PartOfDirective');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -923,7 +836,6 @@
 
   @override
   void visitPostfixExpression(PostfixExpression node) {
-    _writeNextCodeLine(node);
     _writeln('PostfixExpression');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -940,7 +852,6 @@
 
   @override
   void visitPrefixedIdentifier(PrefixedIdentifier node) {
-    _writeNextCodeLine(node);
     _writeln('PrefixedIdentifier');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -951,7 +862,6 @@
 
   @override
   void visitPrefixExpression(PrefixExpression node) {
-    _writeNextCodeLine(node);
     _writeln('PrefixExpression');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -968,7 +878,6 @@
 
   @override
   void visitPropertyAccess(PropertyAccess node) {
-    _writeNextCodeLine(node);
     _writeln('PropertyAccess');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -980,7 +889,6 @@
   void visitRedirectingConstructorInvocation(
     RedirectingConstructorInvocation node,
   ) {
-    _writeNextCodeLine(node);
     _writeln('RedirectingConstructorInvocation');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -990,7 +898,6 @@
 
   @override
   void visitReturnStatement(ReturnStatement node) {
-    _writeNextCodeLine(node);
     _writeln('ReturnStatement');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -999,7 +906,6 @@
 
   @override
   void visitSetOrMapLiteral(SetOrMapLiteral node) {
-    _writeNextCodeLine(node);
     _writeln('SetOrMapLiteral');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -1010,7 +916,6 @@
 
   @override
   void visitShowCombinator(ShowCombinator node) {
-    _writeNextCodeLine(node);
     _writeln('ShowCombinator');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -1019,7 +924,6 @@
 
   @override
   void visitSimpleFormalParameter(SimpleFormalParameter node) {
-    _writeNextCodeLine(node);
     _writeln('SimpleFormalParameter');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -1032,7 +936,6 @@
 
   @override
   void visitSimpleIdentifier(SimpleIdentifier node) {
-    _writeNextCodeLine(node);
     _writeln('SimpleIdentifier');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -1047,7 +950,6 @@
 
   @override
   void visitSimpleStringLiteral(SimpleStringLiteral node) {
-    _writeNextCodeLine(node);
     _writeln('SimpleStringLiteral');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -1064,7 +966,6 @@
 
   @override
   void visitStringInterpolation(StringInterpolation node) {
-    _writeNextCodeLine(node);
     _writeln('StringInterpolation');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -1075,7 +976,6 @@
 
   @override
   void visitSuperConstructorInvocation(SuperConstructorInvocation node) {
-    _writeNextCodeLine(node);
     _writeln('SuperConstructorInvocation');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -1085,7 +985,6 @@
 
   @override
   void visitSuperExpression(SuperExpression node) {
-    _writeNextCodeLine(node);
     _writeln('SuperExpression');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -1098,7 +997,6 @@
     if (withCheckingLinking) {
       _checkChildrenEntitiesLinking(node);
     }
-    _writeNextCodeLine(node);
     _writeln('SuperFormalParameter');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -1111,7 +1009,6 @@
 
   @override
   void visitSwitchCase(SwitchCase node) {
-    _writeNextCodeLine(node);
     _writeln('SwitchCase');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -1120,7 +1017,6 @@
 
   @override
   void visitSwitchDefault(SwitchDefault node) {
-    _writeNextCodeLine(node);
     _writeln('SwitchDefault');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -1129,7 +1025,6 @@
 
   @override
   void visitSwitchStatement(SwitchStatement node) {
-    _writeNextCodeLine(node);
     _writeln('SwitchStatement');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -1146,7 +1041,6 @@
 
   @override
   void visitThisExpression(ThisExpression node) {
-    _writeNextCodeLine(node);
     _writeln('ThisExpression');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -1156,7 +1050,6 @@
 
   @override
   void visitThrowExpression(ThrowExpression node) {
-    _writeNextCodeLine(node);
     _writeln('ThrowExpression');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -1166,7 +1059,6 @@
 
   @override
   void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
-    _writeNextCodeLine(node);
     _writeln('TopLevelVariableDeclaration');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -1178,7 +1070,6 @@
 
   @override
   void visitTryStatement(TryStatement node) {
-    _writeNextCodeLine(node);
     _writeln('TryStatement');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -1187,7 +1078,6 @@
 
   @override
   void visitTypeArgumentList(TypeArgumentList node) {
-    _writeNextCodeLine(node);
     _writeln('TypeArgumentList');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -1205,7 +1095,6 @@
 
   @override
   void visitTypeParameter(TypeParameter node) {
-    _writeNextCodeLine(node);
     _writeln('TypeParameter');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -1217,7 +1106,6 @@
 
   @override
   void visitTypeParameterList(TypeParameterList node) {
-    _writeNextCodeLine(node);
     _writeln('TypeParameterList');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -1226,7 +1114,6 @@
 
   @override
   void visitVariableDeclaration(VariableDeclaration node) {
-    _writeNextCodeLine(node);
     _writeln('VariableDeclaration');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -1238,7 +1125,6 @@
 
   @override
   void visitVariableDeclarationList(VariableDeclarationList node) {
-    _writeNextCodeLine(node);
     _writeln('VariableDeclarationList');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -1247,7 +1133,6 @@
 
   @override
   void visitVariableDeclarationStatement(VariableDeclarationStatement node) {
-    _writeNextCodeLine(node);
     _writeln('VariableDeclarationStatement');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -1256,7 +1141,6 @@
 
   @override
   void visitWhileStatement(WhileStatement node) {
-    _writeNextCodeLine(node);
     _writeln('WhileStatement');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -1265,7 +1149,6 @@
 
   @override
   void visitWithClause(WithClause node) {
-    _writeNextCodeLine(node);
     _writeln('WithClause');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -1274,7 +1157,6 @@
 
   @override
   void visitYieldStatement(YieldStatement node) {
-    _writeNextCodeLine(node);
     _writeln('YieldStatement');
     _withIndent(() {
       _writeNamedChildEntities(node);
@@ -1452,7 +1334,10 @@
       if (value is Token) {
         _writeToken(entity.name, value);
       } else if (value is AstNode) {
-        _writeNode(entity.name, value);
+        if (value is ArgumentList && skipArgumentList) {
+        } else {
+          _writeNode(entity.name, value);
+        }
       } else if (value is List<Token>) {
         _writeTokenList(entity.name, value);
       } else if (value is List<AstNode>) {
@@ -1463,15 +1348,6 @@
     }
   }
 
-  void _writeNextCodeLine(AstNode node) {
-    var nextCodeLine = _codeLinesProvider?.nextLine(node.offset);
-    if (nextCodeLine != null) {
-      nextCodeLine = nextCodeLine.trim();
-      _sink.writeln('// $nextCodeLine');
-      _sink.write(_indent);
-    }
-  }
-
   void _writeNode(String name, AstNode? node) {
     if (node != null) {
       _sink.write(_indent);
diff --git a/pkg/analyzer/test/util/feature_sets.dart b/pkg/analyzer/test/util/feature_sets.dart
index 85a4cd9..53627ba 100644
--- a/pkg/analyzer/test/util/feature_sets.dart
+++ b/pkg/analyzer/test/util/feature_sets.dart
@@ -37,8 +37,9 @@
   static final FeatureSet latestWithExperiments = FeatureSet.fromEnableFlags2(
     sdkLanguageVersion: ExperimentStatus.currentVersion,
     flags: [
-      EnableString.constructor_tearoffs,
       EnableString.enhanced_enums,
+      EnableString.macros,
+      EnableString.named_arguments_anywhere,
       EnableString.super_parameters,
     ],
   );
diff --git a/pkg/dartdev/lib/src/commands/compile.dart b/pkg/dartdev/lib/src/commands/compile.dart
index 295bc86..9b497f6 100644
--- a/pkg/dartdev/lib/src/commands/compile.dart
+++ b/pkg/dartdev/lib/src/commands/compile.dart
@@ -112,6 +112,12 @@
         allowed: verbosityOption.allowed,
         allowedHelp: verbosityOption.allowedHelp,
       )
+      ..addOption(
+        packagesOption.flag,
+        abbr: packagesOption.abbr,
+        valueHelp: packagesOption.valueHelp,
+        help: packagesOption.help,
+      )
       ..addMultiOption(
         defineOption.flag,
         help: defineOption.help,
@@ -158,12 +164,18 @@
 
     final enabledExperiments = args.enabledExperiments;
     final environmentVars = args['define'] ?? <String, String>{};
+
     // Build arguments.
-    List<String> buildArgs = [];
+    final buildArgs = <String>[];
     buildArgs.add('--snapshot-kind=$formatName');
     buildArgs.add('--snapshot=${path.canonicalize(outputFile)}');
 
-    String? verbosity = args[verbosityOption.flag];
+    final String? packages = args[packagesOption.flag];
+    if (packages != null) {
+      buildArgs.add('--packages=$packages');
+    }
+
+    final String? verbosity = args[verbosityOption.flag];
     buildArgs.add('--verbosity=$verbosity');
 
     if (enabledExperiments.isNotEmpty) {
@@ -226,13 +238,12 @@
       )
       ..addFlag('enable-asserts',
           negatable: false, help: 'Enable assert statements.')
-      ..addOption('packages',
-          abbr: 'p',
-          valueHelp: 'path',
-          help:
-              '''Get package locations from the specified file instead of .packages.
-<path> can be relative or absolute.
-For example: dart compile $commandName --packages=/tmp/pkgs main.dart''')
+      ..addOption(
+        packagesOption.flag,
+        abbr: packagesOption.abbr,
+        valueHelp: packagesOption.valueHelp,
+        help: packagesOption.help,
+      )
       ..addFlag('sound-null-safety',
           help: 'Respect the nullability of types at runtime.',
           defaultsTo: null)
@@ -319,7 +330,9 @@
     allowed: Verbosity.allowedValues,
     allowedHelp: Verbosity.allowedValuesHelp,
   );
+
   late final Option defineOption;
+  late final Option packagesOption;
 
   CompileSubcommandCommand(String name, String description, bool verbose,
       {bool hidden = false})
@@ -331,6 +344,14 @@
 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''',
         ),
+        packagesOption = Option(
+            flag: 'packages',
+            abbr: 'p',
+            valueHelp: 'path',
+            help:
+                '''Get package locations from the specified file instead of .packages.
+<path> can be relative or absolute.
+For example: dart compile $name --packages=/tmp/pkgs main.dart'''),
         super(name, description, verbose, hidden: hidden);
 }
 
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_47020.dart b/pkg/front_end/parser_testcases/nnbd/issue_47020.dart
new file mode 100644
index 0000000..2a6f3cb
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_47020.dart
@@ -0,0 +1,6 @@
+void main() {
+  Function? f = () {
+    print(1)
+  };
+  f();
+}
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_47020.dart.expect b/pkg/front_end/parser_testcases/nnbd/issue_47020.dart.expect
new file mode 100644
index 0000000..3bc47da
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_47020.dart.expect
@@ -0,0 +1,56 @@
+Problems reported:
+
+parser/nnbd/issue_47020:3:12: Expected ';' after this.
+    print(1)
+           ^
+
+beginCompilationUnit(void)
+  beginMetadataStar(void)
+  endMetadataStar(0)
+  beginTopLevelMember(void)
+    beginTopLevelMethod(, null, null)
+      handleVoidKeyword(void)
+      handleIdentifier(main, topLevelFunctionDeclaration)
+      handleNoTypeVariables(()
+      beginFormalParameters((, MemberKind.TopLevelMethod)
+      endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+      handleAsyncModifier(null, null)
+      beginBlockFunctionBody({)
+        beginMetadataStar(Function)
+        endMetadataStar(0)
+        handleIdentifier(Function, typeReference)
+        handleNoTypeArguments(?)
+        handleType(Function, ?)
+        beginVariablesDeclaration(f, null, null)
+          handleIdentifier(f, localVariableDeclaration)
+          beginInitializedIdentifier(f)
+            beginVariableInitializer(=)
+              handleNoTypeVariables(()
+              beginFunctionExpression(()
+                beginFormalParameters((, MemberKind.Local)
+                endFormalParameters(0, (, ), MemberKind.Local)
+                handleAsyncModifier(null, null)
+                beginBlockFunctionBody({)
+                  handleIdentifier(print, expression)
+                  handleNoTypeArguments(()
+                  beginArguments(()
+                    handleLiteralInt(1)
+                  endArguments(1, (, ))
+                  handleSend(print, })
+                  handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], ), ))
+                  handleExpressionStatement(;)
+                endBlockFunctionBody(1, {, })
+              endFunctionExpression((, ;)
+            endVariableInitializer(=)
+          endInitializedIdentifier(f)
+        endVariablesDeclaration(1, ;)
+        handleIdentifier(f, expression)
+        handleNoTypeArguments(()
+        beginArguments(()
+        endArguments(0, (, ))
+        handleSend(f, ;)
+        handleExpressionStatement(;)
+      endBlockFunctionBody(2, {, })
+    endTopLevelMethod(void, null, })
+  endTopLevelDeclaration()
+endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_47020.dart.intertwined.expect b/pkg/front_end/parser_testcases/nnbd/issue_47020.dart.intertwined.expect
new file mode 100644
index 0000000..06f70a8
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_47020.dart.intertwined.expect
@@ -0,0 +1,175 @@
+parseUnit(void)
+  skipErrorTokens(void)
+  listener: beginCompilationUnit(void)
+  syntheticPreviousToken(void)
+  parseTopLevelDeclarationImpl(, Instance of 'DirectiveContext')
+    parseMetadataStar()
+      listener: beginMetadataStar(void)
+      listener: endMetadataStar(0)
+    parseTopLevelMemberImpl()
+      listener: beginTopLevelMember(void)
+      parseTopLevelMethod(, null, null, , Instance of 'VoidType', null, main, false)
+        listener: beginTopLevelMethod(, null, null)
+        listener: handleVoidKeyword(void)
+        ensureIdentifierPotentiallyRecovered(void, topLevelFunctionDeclaration, false)
+          listener: handleIdentifier(main, topLevelFunctionDeclaration)
+        parseMethodTypeVar(main)
+          listener: handleNoTypeVariables(()
+        parseGetterOrFormalParameters(main, main, false, MemberKind.TopLevelMethod)
+          parseFormalParameters(main, MemberKind.TopLevelMethod)
+            parseFormalParametersRest((, MemberKind.TopLevelMethod)
+              listener: beginFormalParameters((, MemberKind.TopLevelMethod)
+              listener: endFormalParameters(0, (, ), MemberKind.TopLevelMethod)
+        parseAsyncModifierOpt())
+          listener: handleAsyncModifier(null, null)
+          inPlainSync()
+        parseFunctionBody(), false, false)
+          listener: beginBlockFunctionBody({)
+          notEofOrValue(}, Function)
+          parseStatement({)
+            parseStatementX({)
+              parseExpressionStatementOrDeclaration({, false)
+                parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                  looksLikeLocalFunction(f)
+                  parseExpressionWithoutCascade(=)
+                    parsePrecedenceExpression(=, 1, false)
+                      parseUnaryExpression(=, false)
+                        parsePrimary(=, expression)
+                          parseParenthesizedExpressionOrFunctionLiteral(=)
+                            parseFunctionExpression(=)
+                              parseFormalParametersRequiredOpt(=, MemberKind.Local)
+                                parseFormalParametersRest((, MemberKind.Local)
+                              parseAsyncOptBody(), true, false)
+                                parseAsyncModifierOpt())
+                                  inPlainSync()
+                                parseFunctionBody(), true, false)
+                                  notEofOrValue(}, print)
+                                  parseStatement({)
+                                    parseStatementX({)
+                                      parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                                        looksLikeLocalFunction(print)
+                                        parseExpressionStatement({)
+                                          parseExpression({)
+                                            parsePrecedenceExpression({, 1, true)
+                                              parseUnaryExpression({, true)
+                                                parsePrimary({, expression)
+                                                  parseSendOrFunctionLiteral({, expression)
+                                                    looksLikeFunctionBody(})
+                                                    parseSend({, expression)
+                                                      isNextIdentifier({)
+                                                      ensureIdentifier({, expression)
+                                                      parseArgumentsOpt(print)
+                                                        parseArguments(print)
+                                                          parseArgumentsRest(()
+                                                            parseExpression(()
+                                                              parsePrecedenceExpression((, 1, true)
+                                                                parseUnaryExpression((, true)
+                                                                  parsePrimary((, expression)
+                                                                    parseLiteralInt(()
+                                          ensureSemicolon())
+                                            reportRecoverableError(), Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+                                            rewriter()
+                                  notEofOrValue(}, })
+                  listener: beginMetadataStar(Function)
+                  listener: endMetadataStar(0)
+                  listener: handleIdentifier(Function, typeReference)
+                  listener: handleNoTypeArguments(?)
+                  listener: handleType(Function, ?)
+                  listener: beginVariablesDeclaration(f, null, null)
+                  parseVariablesDeclarationRest(?, true)
+                    parseOptionallyInitializedIdentifier(?)
+                      ensureIdentifier(?, localVariableDeclaration)
+                        listener: handleIdentifier(f, localVariableDeclaration)
+                      listener: beginInitializedIdentifier(f)
+                      parseVariableInitializerOpt(f)
+                        listener: beginVariableInitializer(=)
+                        parseExpression(=)
+                          parsePrecedenceExpression(=, 1, true)
+                            parseUnaryExpression(=, true)
+                              parsePrimary(=, expression)
+                                parseParenthesizedExpressionOrFunctionLiteral(=)
+                                  listener: handleNoTypeVariables(()
+                                  parseFunctionExpression(=)
+                                    listener: beginFunctionExpression(()
+                                    parseFormalParametersRequiredOpt(=, MemberKind.Local)
+                                      parseFormalParametersRest((, MemberKind.Local)
+                                        listener: beginFormalParameters((, MemberKind.Local)
+                                        listener: endFormalParameters(0, (, ), MemberKind.Local)
+                                    parseAsyncOptBody(), true, false)
+                                      parseAsyncModifierOpt())
+                                        listener: handleAsyncModifier(null, null)
+                                        inPlainSync()
+                                      parseFunctionBody(), true, false)
+                                        listener: beginBlockFunctionBody({)
+                                        notEofOrValue(}, print)
+                                        parseStatement({)
+                                          parseStatementX({)
+                                            parseExpressionStatementOrDeclarationAfterModifiers({, {, null, null, null, false)
+                                              looksLikeLocalFunction(print)
+                                              parseExpressionStatement({)
+                                                parseExpression({)
+                                                  parsePrecedenceExpression({, 1, true)
+                                                    parseUnaryExpression({, true)
+                                                      parsePrimary({, expression)
+                                                        parseSendOrFunctionLiteral({, expression)
+                                                          looksLikeFunctionBody(})
+                                                          parseSend({, expression)
+                                                            isNextIdentifier({)
+                                                            ensureIdentifier({, expression)
+                                                              listener: handleIdentifier(print, expression)
+                                                            listener: handleNoTypeArguments(()
+                                                            parseArgumentsOpt(print)
+                                                              parseArguments(print)
+                                                                parseArgumentsRest(()
+                                                                  listener: beginArguments(()
+                                                                  parseExpression(()
+                                                                    parsePrecedenceExpression((, 1, true)
+                                                                      parseUnaryExpression((, true)
+                                                                        parsePrimary((, expression)
+                                                                          parseLiteralInt(()
+                                                                            listener: handleLiteralInt(1)
+                                                                  listener: endArguments(1, (, ))
+                                                            listener: handleSend(print, })
+                                                ensureSemicolon())
+                                                  reportRecoverableError(), Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}])
+                                                    listener: handleRecoverableError(Message[ExpectedAfterButGot, Expected ';' after this., null, {string: ;}], ), ))
+                                                  rewriter()
+                                                listener: handleExpressionStatement(;)
+                                        notEofOrValue(}, })
+                                        listener: endBlockFunctionBody(1, {, })
+                                    listener: endFunctionExpression((, ;)
+                        listener: endVariableInitializer(=)
+                      listener: endInitializedIdentifier(f)
+                    ensureSemicolon(})
+                    listener: endVariablesDeclaration(1, ;)
+          notEofOrValue(}, f)
+          parseStatement(;)
+            parseStatementX(;)
+              parseExpressionStatementOrDeclarationAfterModifiers(;, ;, null, null, null, false)
+                looksLikeLocalFunction(f)
+                parseExpressionStatement(;)
+                  parseExpression(;)
+                    parsePrecedenceExpression(;, 1, true)
+                      parseUnaryExpression(;, true)
+                        parsePrimary(;, expression)
+                          parseSendOrFunctionLiteral(;, expression)
+                            looksLikeFunctionBody(;)
+                            parseSend(;, expression)
+                              isNextIdentifier(;)
+                              ensureIdentifier(;, expression)
+                                listener: handleIdentifier(f, expression)
+                              listener: handleNoTypeArguments(()
+                              parseArgumentsOpt(f)
+                                parseArguments(f)
+                                  parseArgumentsRest(()
+                                    listener: beginArguments(()
+                                    listener: endArguments(0, (, ))
+                              listener: handleSend(f, ;)
+                  ensureSemicolon())
+                  listener: handleExpressionStatement(;)
+          notEofOrValue(}, })
+          listener: endBlockFunctionBody(2, {, })
+        listener: endTopLevelMethod(void, null, })
+  listener: endTopLevelDeclaration()
+  reportAllErrorTokens(void)
+  listener: endCompilationUnit(1, )
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_47020.dart.parser.expect b/pkg/front_end/parser_testcases/nnbd/issue_47020.dart.parser.expect
new file mode 100644
index 0000000..f31ed62
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_47020.dart.parser.expect
@@ -0,0 +1,17 @@
+NOTICE: Stream was rewritten by parser!
+
+void main() {
+Function? f = () {
+print(1)
+;};
+f();
+}
+
+
+void[KeywordToken] main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+Function[KeywordToken]?[SimpleToken] f[StringToken] =[SimpleToken] ([BeginToken])[SimpleToken] {[BeginToken]
+print[StringToken]([BeginToken]1[StringToken])[SimpleToken]
+;[SyntheticToken]}[SimpleToken];[SimpleToken]
+f[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/pkg/front_end/parser_testcases/nnbd/issue_47020.dart.scanner.expect b/pkg/front_end/parser_testcases/nnbd/issue_47020.dart.scanner.expect
new file mode 100644
index 0000000..0bec4b0
--- /dev/null
+++ b/pkg/front_end/parser_testcases/nnbd/issue_47020.dart.scanner.expect
@@ -0,0 +1,15 @@
+void main() {
+Function? f = () {
+print(1)
+};
+f();
+}
+
+
+void[KeywordToken] main[StringToken]([BeginToken])[SimpleToken] {[BeginToken]
+Function[KeywordToken]?[SimpleToken] f[StringToken] =[SimpleToken] ([BeginToken])[SimpleToken] {[BeginToken]
+print[StringToken]([BeginToken]1[StringToken])[SimpleToken]
+}[SimpleToken];[SimpleToken]
+f[StringToken]([BeginToken])[SimpleToken];[SimpleToken]
+}[SimpleToken]
+[SimpleToken]
diff --git a/runtime/vm/heap/weak_code.cc b/runtime/vm/heap/weak_code.cc
index 44730a3..5e59703 100644
--- a/runtime/vm/heap/weak_code.cc
+++ b/runtime/vm/heap/weak_code.cc
@@ -58,7 +58,7 @@
   return false;
 }
 
-void WeakCodeReferences::DisableCode() {
+void WeakCodeReferences::DisableCode(bool are_mutators_stopped) {
   Thread* thread = Thread::Current();
   const Array& code_objects = Array::Handle(thread->zone(), array_.ptr());
 #if defined(DART_PRECOMPILED_RUNTIME)
@@ -74,8 +74,7 @@
   }
 
   auto isolate_group = IsolateGroup::Current();
-  // Deoptimize stacks and disable code with mutators stopped.
-  isolate_group->RunWithStoppedMutators([&]() {
+  auto disable_code_fun = [&]() {
     Code& code = Code::Handle();
     isolate_group->ForEachIsolate(
         [&](Isolate* isolate) {
@@ -140,7 +139,15 @@
     }
 
     UpdateArrayTo(Object::null_array());
-  });
+  };
+
+  // Deoptimize stacks and disable code (with mutators stopped if they are not
+  // stopped yet).
+  if (are_mutators_stopped) {
+    disable_code_fun();
+  } else {
+    isolate_group->RunWithStoppedMutators(disable_code_fun);
+  }
 
 #endif  // defined(DART_PRECOMPILED_RUNTIME)
 }
diff --git a/runtime/vm/heap/weak_code.h b/runtime/vm/heap/weak_code.h
index 74b4389..e87ac5c 100644
--- a/runtime/vm/heap/weak_code.h
+++ b/runtime/vm/heap/weak_code.h
@@ -28,7 +28,7 @@
 
   static bool IsOptimizedCode(const Array& dependent_code, const Code& code);
 
-  void DisableCode();
+  void DisableCode(bool are_mutators_stopped);
 
   bool HasCodes() const;
 
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 00807b5..241097c 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -4083,7 +4083,7 @@
       THR_Print("Deopt for CHA (new subclass %s)\n", subclass.ToCString());
     }
   }
-  a.DisableCode();
+  a.DisableCode(/*are_mutators_stopped=*/false);
 }
 
 void Class::DisableAllCHAOptimizedCode() {
@@ -10949,7 +10949,7 @@
   a.Register(code);
 }
 
-void Field::DeoptimizeDependentCode() const {
+void Field::DeoptimizeDependentCode(bool are_mutators_stopped) const {
   DEBUG_ASSERT(
       IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
   ASSERT(IsOriginal());
@@ -10957,7 +10957,7 @@
   if (FLAG_trace_deoptimization && a.HasCodes()) {
     THR_Print("Deopt for field guard (field %s)\n", ToCString());
   }
-  a.DisableCode();
+  a.DisableCode(are_mutators_stopped);
 }
 
 bool Field::IsConsistentWith(const Field& other) const {
@@ -11231,45 +11231,102 @@
   }
 }
 
-bool Field::UpdateGuardedCidAndLength(const Object& value) const {
-  ASSERT(IsOriginal());
-  const intptr_t cid = value.GetClassId();
+class FieldGuardUpdater {
+ public:
+  FieldGuardUpdater(const Field* field, const Object& value);
+
+  bool IsUpdateNeeded() {
+    return does_guarded_cid_need_update_ ||
+           does_is_nullable_need_update_ ||
+           does_list_length_and_offset_need_update_ ||
+           does_static_type_exactness_state_need_update_;
+  }
+  void DoUpdate();
+
+ private:
+  void ReviewExactnessState();
+  void ReviewGuards();
+
+  intptr_t guarded_cid() { return guarded_cid_; }
+  void set_guarded_cid(intptr_t guarded_cid) {
+    guarded_cid_ = guarded_cid;
+    does_guarded_cid_need_update_ = true;
+  }
+
+  bool is_nullable() { return is_nullable_; }
+  void set_is_nullable(bool is_nullable) {
+    is_nullable_ = is_nullable;
+    does_is_nullable_need_update_ = true;
+  }
+
+  intptr_t guarded_list_length() { return list_length_; }
+  void set_guarded_list_length_and_offset(intptr_t list_length,
+      intptr_t list_length_in_object_offset) {
+    list_length_ = list_length;
+    list_length_in_object_offset_ = list_length_in_object_offset;
+    does_list_length_and_offset_need_update_ = true;
+  }
+
+  StaticTypeExactnessState static_type_exactness_state() {
+    return static_type_exactness_state_;
+  }
+  void set_static_type_exactness_state(StaticTypeExactnessState state) {
+    static_type_exactness_state_ = state;
+    does_static_type_exactness_state_need_update_ = true;
+  }
+
+  const Field* field_;
+  const Object& value_;
+
+  intptr_t guarded_cid_;
+  bool is_nullable_;
+  intptr_t list_length_;
+  intptr_t list_length_in_object_offset_;
+  StaticTypeExactnessState static_type_exactness_state_;
+
+  bool does_guarded_cid_need_update_ = false;
+  bool does_is_nullable_need_update_ = false;
+  bool does_list_length_and_offset_need_update_ = false;
+  bool does_static_type_exactness_state_need_update_ = false;
+};
+
+void FieldGuardUpdater::ReviewGuards() {
+  ASSERT(field_->IsOriginal());
+  const intptr_t cid = value_.GetClassId();
 
   if (guarded_cid() == kIllegalCid) {
-    // Field is assigned first time.
     set_guarded_cid(cid);
     set_is_nullable(cid == kNullCid);
 
     // Start tracking length if needed.
     ASSERT((guarded_list_length() == Field::kUnknownFixedLength) ||
            (guarded_list_length() == Field::kNoFixedLength));
-    if (needs_length_check()) {
+    if (field_->needs_length_check()) {
       ASSERT(guarded_list_length() == Field::kUnknownFixedLength);
-      set_guarded_list_length(GetListLength(value));
-      InitializeGuardedListLengthInObjectOffset();
+      set_guarded_list_length_and_offset(GetListLength(value_),
+                                         GetListLengthOffset(cid));
     }
 
     if (FLAG_trace_field_guards) {
-      THR_Print("    => %s\n", GuardedPropertiesAsCString());
+      THR_Print("    => %s\n", field_->GuardedPropertiesAsCString());
     }
-
-    return false;
+    return;
   }
 
   if ((cid == guarded_cid()) || ((cid == kNullCid) && is_nullable())) {
     // Class id of the assigned value matches expected class id and nullability.
 
     // If we are tracking length check if it has matches.
-    if (needs_length_check() &&
-        (guarded_list_length() != GetListLength(value))) {
+    if (field_->needs_length_check() &&
+        (guarded_list_length() != GetListLength(value_))) {
       ASSERT(guarded_list_length() != Field::kUnknownFixedLength);
-      set_guarded_list_length(Field::kNoFixedLength);
-      set_guarded_list_length_in_object_offset(Field::kUnknownLengthOffset);
-      return true;
+      set_guarded_list_length_and_offset(Field::kNoFixedLength,
+                                         Field::kUnknownLengthOffset);
+      return;
     }
 
     // Everything matches.
-    return false;
+    return;
   }
 
   if ((cid == kNullCid) && !is_nullable()) {
@@ -11288,14 +11345,11 @@
   }
 
   // If we were tracking length drop collected feedback.
-  if (needs_length_check()) {
+  if (field_->needs_length_check()) {
     ASSERT(guarded_list_length() != Field::kUnknownFixedLength);
-    set_guarded_list_length(Field::kNoFixedLength);
-    set_guarded_list_length_in_object_offset(Field::kUnknownLengthOffset);
+    set_guarded_list_length_and_offset(Field::kNoFixedLength,
+                                       Field::kUnknownLengthOffset);
   }
-
-  // Expected class id or nullability of the field changed.
-  return true;
 }
 
 bool Class::FindInstantiationOf(Zone* zone,
@@ -11555,10 +11609,10 @@
   }
 }
 
-bool Field::UpdateGuardedExactnessState(const Object& value) const {
+void FieldGuardUpdater::ReviewExactnessState() {
   if (!static_type_exactness_state().IsExactOrUninitialized()) {
     // Nothing to update.
-    return false;
+    return;
   }
 
   if (guarded_cid() == kDynamicCid) {
@@ -11568,14 +11622,14 @@
           "dynamic\n");
     }
     set_static_type_exactness_state(StaticTypeExactnessState::NotExact());
-    return true;  // Invalidate.
+    return;
   }
 
   // If we are storing null into a field or we have an exact super type
   // then there is nothing to do.
-  if (value.IsNull() || static_type_exactness_state().IsHasExactSuperType() ||
+  if (value_.IsNull() || static_type_exactness_state().IsHasExactSuperType() ||
       static_type_exactness_state().IsHasExactSuperClass()) {
-    return false;
+    return;
   }
 
   // If we are storing a non-null value into a field that is considered
@@ -11583,16 +11637,16 @@
   // type.
   ASSERT(guarded_cid() != kNullCid);
 
-  const Type& field_type = Type::Cast(AbstractType::Handle(type()));
+  const Type& field_type = Type::Cast(AbstractType::Handle(field_->type()));
   const TypeArguments& field_type_args =
       TypeArguments::Handle(field_type.arguments());
 
-  const Instance& instance = Instance::Cast(value);
+  const Instance& instance = Instance::Cast(value_);
   TypeArguments& args = TypeArguments::Handle();
   if (static_type_exactness_state().IsTriviallyExact()) {
     args = instance.GetTypeArguments();
     if (args.ptr() == field_type_args.ptr()) {
-      return false;
+      return;
     }
 
     if (FLAG_trace_field_guards) {
@@ -11601,13 +11655,43 @@
     }
 
     set_static_type_exactness_state(StaticTypeExactnessState::NotExact());
-    return true;
+    return;
   }
 
   ASSERT(static_type_exactness_state().IsUninitialized());
   set_static_type_exactness_state(StaticTypeExactnessState::Compute(
       field_type, instance, FLAG_trace_field_guards));
-  return true;
+  return;
+}
+
+FieldGuardUpdater::FieldGuardUpdater(const Field* field, const Object& value):
+    field_(field),
+    value_(value),
+    guarded_cid_(field->guarded_cid()),
+    is_nullable_(field->is_nullable()),
+    list_length_(field->guarded_list_length()),
+    list_length_in_object_offset_(
+        field->guarded_list_length_in_object_offset()),
+    static_type_exactness_state_(field->static_type_exactness_state()) {
+  ReviewGuards();
+  ReviewExactnessState();
+}
+
+void FieldGuardUpdater::DoUpdate() {
+  if (does_guarded_cid_need_update_) {
+    field_->set_guarded_cid(guarded_cid_);
+  }
+  if (does_is_nullable_need_update_) {
+    field_->set_is_nullable(is_nullable_);
+  }
+  if (does_list_length_and_offset_need_update_) {
+    field_->set_guarded_list_length(list_length_);
+    field_->set_guarded_list_length_in_object_offset(
+        list_length_in_object_offset_);
+  }
+  if (does_static_type_exactness_state_need_update_) {
+    field_->set_static_type_exactness_state(static_type_exactness_state_);
+  }
 }
 
 void Field::RecordStore(const Object& value) const {
@@ -11633,20 +11717,19 @@
               value.ToCString());
   }
 
-  bool invalidate = false;
-  if (UpdateGuardedCidAndLength(value)) {
-    invalidate = true;
-  }
-  if (UpdateGuardedExactnessState(value)) {
-    invalidate = true;
-  }
-
-  if (invalidate) {
+  FieldGuardUpdater updater(this, value);
+  if (updater.IsUpdateNeeded()) {
     if (FLAG_trace_field_guards) {
       THR_Print("    => %s\n", GuardedPropertiesAsCString());
     }
-
-    DeoptimizeDependentCode();
+    // Nobody else could have updated guard state since we are holding write
+    // program lock. But we need to ensure we stop mutators as we update
+    // guard state as we can't have optimized code running with updated fields.
+    auto isolate_group = IsolateGroup::Current();
+    isolate_group->RunWithStoppedMutators([&]() {
+      updater.DoUpdate();
+      DeoptimizeDependentCode(/*are_mutators_stopped=*/true);
+    });
   }
 }
 
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 25d7a8e..668b201 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -4390,7 +4390,7 @@
   void RegisterDependentCode(const Code& code) const;
 
   // Deoptimize all dependent code objects.
-  void DeoptimizeDependentCode() const;
+  void DeoptimizeDependentCode(bool are_mutators_stopped = false) const;
 
   // Used by background compiler to check consistency of field copy with its
   // original.
@@ -4509,15 +4509,6 @@
   class IsNonNullableIntBit
       : public BitField<uint16_t, bool, kIsNonNullableIntBit, 1> {};
 
-  // Update guarded cid and guarded length for this field. Returns true, if
-  // deoptimization of dependent code is required.
-  bool UpdateGuardedCidAndLength(const Object& value) const;
-
-  // Update guarded exactness state for this field. Returns true, if
-  // deoptimization of dependent code is required.
-  // Assumes that guarded cid was already updated.
-  bool UpdateGuardedExactnessState(const Object& value) const;
-
   // Force this field's guard to be dynamic and deoptimize dependent code.
   void ForceDynamicGuardedCidAndLength() const;
 
diff --git a/tests/language/vm/lazy_deopt_with_exception_concurrent_test.dart b/tests/language/vm/lazy_deopt_with_exception_concurrent_test.dart
new file mode 100644
index 0000000..5aa5637
--- /dev/null
+++ b/tests/language/vm/lazy_deopt_with_exception_concurrent_test.dart
@@ -0,0 +1,81 @@
+// Copyright (c) 2016, 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.
+// Test deoptimization on an optimistically hoisted smi check.
+// VMOptions=--optimization-counter-threshold=10  --no-background-compilation
+
+// Test that lazy deoptimization works if the program returns to a function
+// that is scheduled for lazy deoptimization via an exception, even under
+// heavy concurrent load.
+
+import 'dart:async';
+import 'dart:isolate';
+
+import 'package:expect/expect.dart';
+
+class C {
+  dynamic x = 42;
+}
+
+@pragma('vm:never-inline')
+AA(C c, bool b) {
+  if (b) {
+    c.x = 2.5;
+    throw 123;
+  }
+}
+
+@pragma('vm:never-inline')
+T1(C c, bool b) {
+  try {
+    AA(c, b);
+  } on dynamic {}
+  return c.x + 1;
+}
+
+@pragma('vm:never-inline')
+T2(C c, bool b) {
+  try {
+    AA(c, b);
+  } on String {
+    Expect.isTrue(false);
+  } on int catch (e) {
+    Expect.equals(e, 123);
+    Expect.equals(b, true);
+    Expect.equals(c.x, 2.5);
+  }
+  return c.x + 1;
+}
+
+main() async {
+  const count = 10;
+
+  final rp = ReceivePort();
+  for (int i = 0; i < count; ++i) {
+    Isolate.spawn(entry, i, onExit: rp.sendPort);
+  }
+  final si = StreamIterator(rp);
+  int j = 0;
+  while (await si.moveNext()) {
+    j++;
+    if (j == count) break;
+  }
+  print('done');
+
+  if (j != count) throw 'a';
+  si.cancel();
+  rp.close();
+  print('done');
+}
+
+void entry(_) {
+  var c = new C();
+  for (var i = 0; i < 100000; ++i) {
+    T1(c, false);
+    T2(c, false);
+  }
+  Expect.equals(43, T1(c, false));
+  Expect.equals(43, T2(c, false));
+  Expect.equals(3.5, T1(c, true));
+  Expect.equals(3.5, T2(c, true));
+}
diff --git a/tests/language_2/vm/lazy_deopt_with_exception_concurrent_test.dart b/tests/language_2/vm/lazy_deopt_with_exception_concurrent_test.dart
new file mode 100644
index 0000000..3e07cbb
--- /dev/null
+++ b/tests/language_2/vm/lazy_deopt_with_exception_concurrent_test.dart
@@ -0,0 +1,82 @@
+// Copyright (c) 2016, 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.
+// Test deoptimization on an optimistically hoisted smi check.
+// VMOptions=--optimization-counter-threshold=10  --no-background-compilation
+
+// @dart = 2.9
+
+// Test that lazy deoptimization works if the program returns to a function
+// that is scheduled for lazy deoptimization via an exception.
+
+import 'dart:async';
+import 'dart:isolate';
+
+import 'package:expect/expect.dart';
+
+class C {
+  dynamic x = 42;
+}
+
+@pragma('vm:never-inline')
+AA(C c, bool b) {
+  if (b) {
+    c.x = 2.5;
+    throw 123;
+  }
+}
+
+@pragma('vm:never-inline')
+T1(C c, bool b) {
+  try {
+    AA(c, b);
+  } on dynamic {}
+  return c.x + 1;
+}
+
+@pragma('vm:never-inline')
+T2(C c, bool b) {
+  try {
+    AA(c, b);
+  } on String {
+    Expect.isTrue(false);
+  } on int catch (e) {
+    Expect.equals(e, 123);
+    Expect.equals(b, true);
+    Expect.equals(c.x, 2.5);
+  }
+  return c.x + 1;
+}
+
+main() async {
+  const count = 10;
+
+  final rp = ReceivePort();
+  for (int i = 0; i < count; ++i) {
+    Isolate.spawn(entry, i, onExit: rp.sendPort);
+  }
+  final si = StreamIterator(rp);
+  int j = 0;
+  while (await si.moveNext()) {
+    j++;
+    if (j == count) break;
+  }
+  print('done');
+
+  if (j != count) throw 'a';
+  si.cancel();
+  rp.close();
+  print('done');
+}
+
+void entry(_) {
+  var c = new C();
+  for (var i = 0; i < 100000; ++i) {
+    T1(c, false);
+    T2(c, false);
+  }
+  Expect.equals(43, T1(c, false));
+  Expect.equals(43, T2(c, false));
+  Expect.equals(3.5, T1(c, true));
+  Expect.equals(3.5, T2(c, true));
+}
diff --git a/tools/VERSION b/tools/VERSION
index 911a64f..79f9a08 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 17
 PATCH 0
-PRERELEASE 200
+PRERELEASE 201
 PRERELEASE_PATCH 0
\ No newline at end of file