Version 2.17.0-186.0.dev

Merge commit 'ce733054118593b2c2e5543423de0c3927274cdd' into 'dev'
diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart
index 6dc9295..6cb63ed 100644
--- a/pkg/analysis_server/lib/src/context_manager.dart
+++ b/pkg/analysis_server/lib/src/context_manager.dart
@@ -330,7 +330,7 @@
     var convertedErrors = const <protocol.AnalysisError>[];
     try {
       var file = resourceProvider.getFile(path);
-      var packageName = file.parent2.parent2.shortName;
+      var packageName = file.parent.parent.shortName;
       var content = _readFile(path);
       var errorListener = RecordingErrorListener();
       var errorReporter = ErrorReporter(errorListener, file.createSource());
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/commands/sort_members.dart b/pkg/analysis_server/lib/src/lsp/handlers/commands/sort_members.dart
index a4c2286..461d11e 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/commands/sort_members.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/commands/sort_members.dart
@@ -36,7 +36,7 @@
     final docIdentifier = server.getVersionedDocumentIdentifier(path);
 
     var driver = server.getAnalysisDriver(path);
-    final result = driver?.parseFileSync(path);
+    final result = await driver?.parseFile(path);
 
     if (cancellationToken.isCancellationRequested) {
       return error(ErrorCodes.RequestCancelled, 'Request was cancelled');
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_definition.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_definition.dart
index 3c54395..4bad778 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_definition.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_definition.dart
@@ -61,7 +61,7 @@
       computeDartNavigation(
           server.resourceProvider, collector, unit, offset, 0);
       if (supportsLocationLink) {
-        _updateTargetsWithCodeLocations(collector);
+        await _updateTargetsWithCodeLocations(collector);
       }
       collector.createRegions();
     }
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 e3acc88..16a3c80 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
@@ -71,7 +71,7 @@
 
   File? _findPubspecFile() {
     var file = resourceProvider.getFile(this.file);
-    for (var folder in file.parent2.withAncestors) {
+    for (var folder in file.parent.withAncestors) {
       var pubspecFile = folder.getChildAssumingFile('pubspec.yaml');
       if (pubspecFile.exists) {
         return pubspecFile;
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_manager.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_manager.dart
index c2f427a..38efa60 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_manager.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/transform_set_manager.dart
@@ -59,7 +59,7 @@
       var parser = TransformSetParser(
           ErrorReporter(
               AnalysisErrorListener.NULL_LISTENER, file.createSource()),
-          file.parent2.parent2.shortName);
+          file.parent.parent.shortName);
       return parser.parse(content);
     } on FileSystemException {
       // Fall through to return `null`.
diff --git a/pkg/analysis_server/test/abstract_context.dart b/pkg/analysis_server/test/abstract_context.dart
index 59847fe..7da4b3c 100644
--- a/pkg/analysis_server/test/abstract_context.dart
+++ b/pkg/analysis_server/test/abstract_context.dart
@@ -229,23 +229,23 @@
 
     if (meta || flutter) {
       var libFolder = MockPackages.instance.addMeta(resourceProvider);
-      config.add(name: 'meta', rootPath: libFolder.parent2.path);
+      config.add(name: 'meta', rootPath: libFolder.parent.path);
     }
 
     if (flutter) {
       {
         var libFolder = MockPackages.instance.addUI(resourceProvider);
-        config.add(name: 'ui', rootPath: libFolder.parent2.path);
+        config.add(name: 'ui', rootPath: libFolder.parent.path);
       }
       {
         var libFolder = MockPackages.instance.addFlutter(resourceProvider);
-        config.add(name: 'flutter', rootPath: libFolder.parent2.path);
+        config.add(name: 'flutter', rootPath: libFolder.parent.path);
       }
     }
 
     if (vector_math) {
       var libFolder = MockPackages.instance.addVectorMath(resourceProvider);
-      config.add(name: 'vector_math', rootPath: libFolder.parent2.path);
+      config.add(name: 'vector_math', rootPath: libFolder.parent.path);
     }
 
     var path = '$testPackageRootPath/.dart_tool/package_config.json';
diff --git a/pkg/analysis_server/test/analysis_server_test.dart b/pkg/analysis_server/test/analysis_server_test.dart
index 9ac113c..4b83983f 100644
--- a/pkg/analysis_server/test/analysis_server_test.dart
+++ b/pkg/analysis_server/test/analysis_server_test.dart
@@ -157,10 +157,10 @@
 
     // Write both packages, in two events so that the first one will trigger
     // a rebuild.
-    config.add(name: 'foo', rootPath: fooLibFolder.parent2.path);
+    config.add(name: 'foo', rootPath: fooLibFolder.parent.path);
     writePackageConfig(projectPackageConfigFile, config);
     await pumpEventQueue(times: 1); // Allow server to begin processing.
-    config.add(name: 'bar', rootPath: barLibFolder.parent2.path);
+    config.add(name: 'bar', rootPath: barLibFolder.parent.path);
     writePackageConfig(projectPackageConfigFile, config);
 
     // Allow the server to catch up with everything.
@@ -344,7 +344,7 @@
   Folder _addSimplePackage(String name, String content) {
     final packagePath = '/packages/$name';
     final file = newFile('$packagePath/lib/$name.dart', content: content);
-    return file.parent2;
+    return file.parent;
   }
 }
 
diff --git a/pkg/analysis_server/test/lsp/server_abstract.dart b/pkg/analysis_server/test/lsp/server_abstract.dart
index 01da792..f2d2833 100644
--- a/pkg/analysis_server/test/lsp/server_abstract.dart
+++ b/pkg/analysis_server/test/lsp/server_abstract.dart
@@ -583,28 +583,28 @@
 
     if (meta || flutter) {
       var libFolder = MockPackages.instance.addMeta(resourceProvider);
-      config.add(name: 'meta', rootPath: libFolder.parent2.path);
+      config.add(name: 'meta', rootPath: libFolder.parent.path);
     }
 
     if (flutter) {
       {
         var libFolder = MockPackages.instance.addUI(resourceProvider);
-        config.add(name: 'ui', rootPath: libFolder.parent2.path);
+        config.add(name: 'ui', rootPath: libFolder.parent.path);
       }
       {
         var libFolder = MockPackages.instance.addFlutter(resourceProvider);
-        config.add(name: 'flutter', rootPath: libFolder.parent2.path);
+        config.add(name: 'flutter', rootPath: libFolder.parent.path);
       }
     }
 
     if (pedantic) {
       var libFolder = MockPackages.instance.addPedantic(resourceProvider);
-      config.add(name: 'pedantic', rootPath: libFolder.parent2.path);
+      config.add(name: 'pedantic', rootPath: libFolder.parent.path);
     }
 
     if (vector_math) {
       var libFolder = MockPackages.instance.addVectorMath(resourceProvider);
-      config.add(name: 'vector_math', rootPath: libFolder.parent2.path);
+      config.add(name: 'vector_math', rootPath: libFolder.parent.path);
     }
 
     var path = '$projectFolderPath/.dart_tool/package_config.json';
diff --git a/pkg/analysis_server/test/src/domains/flutter/base.dart b/pkg/analysis_server/test/src/domains/flutter/base.dart
index 50d2533..3a9360a 100644
--- a/pkg/analysis_server/test/src/domains/flutter/base.dart
+++ b/pkg/analysis_server/test/src/domains/flutter/base.dart
@@ -57,12 +57,12 @@
   void _addFlutterPackage() {
     _addMetaPackage();
     var libFolder = MockPackages.instance.addFlutter(resourceProvider);
-    _addPackageDependency('flutter', libFolder.parent2.path);
+    _addPackageDependency('flutter', libFolder.parent.path);
   }
 
   void _addMetaPackage() {
     var libFolder = MockPackages.instance.addMeta(resourceProvider);
-    _addPackageDependency('meta', libFolder.parent2.path);
+    _addPackageDependency('meta', libFolder.parent.path);
   }
 
   void _addPackageDependency(String name, String rootPath) {
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index aac32ba..261c626 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -2,7 +2,11 @@
 * Deprecated synchronous `getFile`, `getParsedLibrary`, `getParsedLibraryByElement`,
   `getParsedUnit` from `AnalysisSession`. Use corresponding `getXyz2` asynchronous
   methods instead. This change is necessary for the future work on macros.
-* Deprecated synchronous `getFileSync` from `AnalysisDriver`, use `getFile` instead.
+* Deprecated `Resource.parent2`, use `parent` instead.
+* Deprecated `AnalysisDriver.getFileSync`, use `getFile` instead.
+* Deprecated `AnalysisDriver.getParsedLibrary`, use `getParsedLibrary2` instead.
+* Deprecated `AnalysisDriver.getParsedLibraryByUri`, use `getParsedLibraryByUri2` instead.
+* Deprecated `AnalysisDriver.parseFileSync`, use `parseFile` instead.
 
 ## 3.3.1
 * Report HintCode.OVERRIDE_ON_NON_OVERRIDING_xyz on enum.
diff --git a/pkg/analyzer/lib/dart/sdk/build_sdk_summary.dart b/pkg/analyzer/lib/dart/sdk/build_sdk_summary.dart
index c87a35f..279de69 100644
--- a/pkg/analyzer/lib/dart/sdk/build_sdk_summary.dart
+++ b/pkg/analyzer/lib/dart/sdk/build_sdk_summary.dart
@@ -46,7 +46,7 @@
     var map = loadYaml(content) as YamlMap;
     var embedderSdk = EmbedderSdk(
       resourceProvider,
-      {file.parent2: map},
+      {file.parent: map},
       languageVersion: sdk.languageVersion,
     );
     for (var library in embedderSdk.sdkLibraries) {
diff --git a/pkg/analyzer/lib/file_system/file_system.dart b/pkg/analyzer/lib/file_system/file_system.dart
index 96f5b84..e0f9c23 100644
--- a/pkg/analyzer/lib/file_system/file_system.dart
+++ b/pkg/analyzer/lib/file_system/file_system.dart
@@ -156,6 +156,11 @@
 
   /// Return the [Folder] that contains this resource, possibly itself if this
   /// resource is a root folder.
+  Folder get parent;
+
+  /// Return the [Folder] that contains this resource, possibly itself if this
+  /// resource is a root folder.
+  @Deprecated('Use parent instead')
   Folder get parent2;
 
   /// Return the full path to this resource.
@@ -262,7 +267,7 @@
       if (current.isRoot) {
         break;
       }
-      current = current.parent2;
+      current = current.parent;
     }
   }
 }
diff --git a/pkg/analyzer/lib/file_system/memory_file_system.dart b/pkg/analyzer/lib/file_system/memory_file_system.dart
index 53c2a00..17a6103 100644
--- a/pkg/analyzer/lib/file_system/memory_file_system.dart
+++ b/pkg/analyzer/lib/file_system/memory_file_system.dart
@@ -586,12 +586,15 @@
   int get hashCode => path.hashCode;
 
   @override
-  Folder get parent2 {
+  Folder get parent {
     String parentPath = provider.pathContext.dirname(path);
     return provider.getFolder(parentPath);
   }
 
   @override
+  Folder get parent2 => parent;
+
+  @override
   String get shortName => provider.pathContext.basename(path);
 
   @override
diff --git a/pkg/analyzer/lib/file_system/overlay_file_system.dart b/pkg/analyzer/lib/file_system/overlay_file_system.dart
index 2fe9521..710ce97 100644
--- a/pkg/analyzer/lib/file_system/overlay_file_system.dart
+++ b/pkg/analyzer/lib/file_system/overlay_file_system.dart
@@ -122,6 +122,7 @@
   _OverlayFile(OverlayResourceProvider provider, File file)
       : super(provider, file);
 
+  @Deprecated('Use watch() instead')
   @override
   Stream<WatchEvent> get changes => watch().changes;
 
@@ -236,6 +237,7 @@
   _OverlayFolder(OverlayResourceProvider provider, Folder folder)
       : super(provider, folder);
 
+  @Deprecated('Use watch() instead')
   @override
   Stream<WatchEvent> get changes => watch().changes;
 
@@ -351,12 +353,15 @@
   int get hashCode => path.hashCode;
 
   @override
-  Folder get parent2 {
-    var parent = _resource.parent2;
+  Folder get parent {
+    var parent = _resource.parent;
     return _OverlayFolder(provider, parent);
   }
 
   @override
+  Folder get parent2 => parent;
+
+  @override
   String get path => _resource.path;
 
   @override
diff --git a/pkg/analyzer/lib/file_system/physical_file_system.dart b/pkg/analyzer/lib/file_system/physical_file_system.dart
index 5a2c317..c359bdd 100644
--- a/pkg/analyzer/lib/file_system/physical_file_system.dart
+++ b/pkg/analyzer/lib/file_system/physical_file_system.dart
@@ -96,6 +96,7 @@
 class _PhysicalFile extends _PhysicalResource implements File {
   _PhysicalFile(io.File file) : super(file);
 
+  @Deprecated('Use watch() instead')
   @override
   Stream<WatchEvent> get changes => watch().changes;
 
@@ -208,6 +209,7 @@
 class _PhysicalFolder extends _PhysicalResource implements Folder {
   _PhysicalFolder(io.Directory directory) : super(directory);
 
+  @Deprecated('Use watch() instead')
   @override
   Stream<WatchEvent> get changes => watch().changes;
 
@@ -340,12 +342,15 @@
   int get hashCode => path.hashCode;
 
   @override
-  Folder get parent2 {
+  Folder get parent {
     String parentPath = pathContext.dirname(path);
     return _PhysicalFolder(io.Directory(parentPath));
   }
 
   @override
+  Folder get parent2 => parent;
+
+  @override
   String get path => _entry.path;
 
   /// Return the path context used by this resource provider.
diff --git a/pkg/analyzer/lib/src/context/packages.dart b/pkg/analyzer/lib/src/context/packages.dart
index d63d228..78f5bb5 100644
--- a/pkg/analyzer/lib/src/context/packages.dart
+++ b/pkg/analyzer/lib/src/context/packages.dart
@@ -14,7 +14,7 @@
 /// Looks for `.dart_tool/package_config.json` or `.packages` in the given
 /// and parent directories.
 Packages findPackagesFrom(ResourceProvider provider, Resource start) {
-  var startFolder = start is Folder ? start : start.parent2;
+  var startFolder = start is Folder ? start : start.parent;
   for (var current in startFolder.withAncestors) {
     try {
       var jsonFile = current
@@ -122,7 +122,7 @@
     if (isJson) {
       return parsePackageConfigJsonFile(provider, file);
     } else {
-      var relativePackageConfigFile = file.parent2
+      var relativePackageConfigFile = file.parent
           .getChildAssumingFolder('.dart_tool')
           .getChildAssumingFile('package_config.json');
       if (relativePackageConfigFile.exists) {
diff --git a/pkg/analyzer/lib/src/dart/analysis/context_builder.dart b/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
index c999006..2cd6b2e 100644
--- a/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/context_builder.dart
@@ -176,7 +176,7 @@
       );
       if (embedderYamlSource != null) {
         var embedderYamlPath = embedderYamlSource.fullName;
-        var libFolder = resourceProvider.getFile(embedderYamlPath).parent2;
+        var libFolder = resourceProvider.getFile(embedderYamlPath).parent;
         var locator = EmbedderYamlLocator.forLibFolder(libFolder);
         var embedderMap = locator.embedderYamls;
         if (embedderMap.isNotEmpty) {
diff --git a/pkg/analyzer/lib/src/dart/analysis/context_locator.dart b/pkg/analyzer/lib/src/dart/analysis/context_locator.dart
index 245db3d..e16b138 100644
--- a/pkg/analyzer/lib/src/dart/analysis/context_locator.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/context_locator.dart
@@ -125,7 +125,7 @@
     }
 
     for (File file in includedFiles) {
-      Folder parent = file.parent2;
+      Folder parent = file.parent;
 
       var location = _contextRootLocation(
         parent,
@@ -186,7 +186,7 @@
       optionsFile = defaultOptionsFile;
     } else {
       optionsFile = _findOptionsFile(parent);
-      optionsFolderToChooseRoot = optionsFile?.parent2;
+      optionsFolderToChooseRoot = optionsFile?.parent;
     }
 
     File? packagesFile;
@@ -478,7 +478,7 @@
               var excludedComponents = posix.split(excludedPath);
               if (pathContext.isRelative(excludedPath)) {
                 excludedComponents = [
-                  ...pathContext.split(optionsFile.parent2.path),
+                  ...pathContext.split(optionsFile.parent.path),
                   ...excludedComponents,
                 ];
               }
@@ -558,7 +558,7 @@
   }
 
   static Folder _fileSystemRoot(Resource resource) {
-    for (var current = resource.parent2;; current = current.parent2) {
+    for (var current = resource.parent;; current = current.parent) {
       if (current.isRoot) {
         return current;
       }
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 7a3b593..8bdb3d8 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -727,6 +727,7 @@
   /// Return a [ParsedLibraryResult] for the library with the given [path].
   ///
   /// The [path] must be absolute and normalized.
+  @Deprecated('Use getParsedLibrary2() instead')
   SomeParsedLibraryResult getParsedLibrary(String path) {
     if (!_isAbsolutePath(path)) {
       return InvalidPathResult();
@@ -755,7 +756,39 @@
     return ParsedLibraryResultImpl(currentSession, units);
   }
 
+  /// Return a [ParsedLibraryResult] for the library with the given [path].
+  ///
+  /// The [path] must be absolute and normalized.
+  Future<SomeParsedLibraryResult> getParsedLibrary2(String path) async {
+    if (!_isAbsolutePath(path)) {
+      return InvalidPathResult();
+    }
+
+    if (!_fsState.hasUri(path)) {
+      return NotPathOfUriResult();
+    }
+
+    FileState file = _fsState.getFileForPath(path);
+
+    if (file.isPart) {
+      return NotLibraryButPartResult();
+    }
+
+    var units = <ParsedUnitResult>[];
+    for (var unitFile in file.libraryFiles) {
+      var unitPath = unitFile.path;
+      var unitResult = await parseFile(unitPath);
+      if (unitResult is! ParsedUnitResult) {
+        return UnspecifiedInvalidResult();
+      }
+      units.add(unitResult);
+    }
+
+    return ParsedLibraryResultImpl(currentSession, units);
+  }
+
   /// Return a [ParsedLibraryResult] for the library with the given [uri].
+  @Deprecated('Use getParsedLibraryByUri2() instead')
   SomeParsedLibraryResult getParsedLibraryByUri(Uri uri) {
     var fileOr = _fsState.getFileForUri(uri);
     return fileOr.map(
@@ -774,6 +807,25 @@
     );
   }
 
+  /// Return a [ParsedLibraryResult] for the library with the given [uri].
+  Future<SomeParsedLibraryResult> getParsedLibraryByUri2(Uri uri) async {
+    var fileOr = _fsState.getFileForUri(uri);
+    return fileOr.map(
+      (file) {
+        if (file == null) {
+          return CannotResolveUriResult();
+        }
+        if (file.isPart) {
+          return NotLibraryButPartResult();
+        }
+        return getParsedLibrary2(file.path);
+      },
+      (externalLibrary) {
+        return UriOfExternalLibraryResult();
+      },
+    );
+  }
+
   /// Return a [Future] that completes with a [ResolvedLibraryResult] for the
   /// Dart library file with the given [path].  If the file cannot be analyzed,
   /// the [Future] completes with an [InvalidResult].
@@ -960,6 +1012,27 @@
     );
   }
 
+  /// Return a [ParsedUnitResult] for the file with the given [path].
+  ///
+  /// The [path] must be absolute and normalized.
+  ///
+  /// The [path] can be any file - explicitly or implicitly analyzed, or neither.
+  ///
+  /// The parsing is performed in the method itself, and the result is not
+  /// produced through the [results] stream (just because it is not a fully
+  /// resolved unit).
+  Future<SomeParsedUnitResult> parseFile(String path) async {
+    if (!_isAbsolutePath(path)) {
+      return InvalidPathResult();
+    }
+
+    FileState file = _fileTracker.getFile(path);
+    RecordingErrorListener listener = RecordingErrorListener();
+    CompilationUnit unit = file.parse(listener);
+    return ParsedUnitResultImpl(currentSession, file.path, file.uri,
+        file.content, file.lineInfo, file.isPart, unit, listener.errors);
+  }
+
   /// Return a [Future] that completes with a [ParsedUnitResult] for the file
   /// with the given [path].
   ///
@@ -970,7 +1043,7 @@
   /// The parsing is performed in the method itself, and the result is not
   /// produced through the [results] stream (just because it is not a fully
   /// resolved unit).
-  @Deprecated('Use parseFileSync() instead')
+  @Deprecated('Use parseFile() instead')
   Future<SomeParsedUnitResult> parseFile2(String path) async {
     return parseFileSync2(path);
   }
@@ -984,6 +1057,7 @@
   /// The parsing is performed in the method itself, and the result is not
   /// produced through the [results] stream (just because it is not a fully
   /// resolved unit).
+  @Deprecated('Use parseFile() instead')
   SomeParsedUnitResult parseFileSync(String path) {
     if (!_isAbsolutePath(path)) {
       return InvalidPathResult();
@@ -1005,7 +1079,7 @@
   /// The parsing is performed in the method itself, and the result is not
   /// produced through the [results] stream (just because it is not a fully
   /// resolved unit).
-  @Deprecated('Use parseFileSync() instead')
+  @Deprecated('Use parseFile() instead')
   SomeParsedUnitResult parseFileSync2(String path) {
     return parseFileSync(path);
   }
diff --git a/pkg/analyzer/lib/src/dart/analysis/session.dart b/pkg/analyzer/lib/src/dart/analysis/session.dart
index 47df470..c635635 100644
--- a/pkg/analyzer/lib/src/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/session.dart
@@ -89,7 +89,7 @@
   @override
   Future<SomeParsedLibraryResult> getParsedLibrary2(String path) async {
     _checkConsistency();
-    return _driver.getParsedLibrary(path);
+    return _driver.getParsedLibrary2(path);
   }
 
   @Deprecated('Use getParsedLibraryByElement2() instead')
@@ -114,7 +114,7 @@
       return NotElementOfThisSessionResult();
     }
 
-    return _driver.getParsedLibraryByUri(element.source.uri);
+    return _driver.getParsedLibraryByUri2(element.source.uri);
   }
 
   @Deprecated('Use getParsedUnit2() instead')
@@ -127,7 +127,7 @@
   @override
   Future<SomeParsedUnitResult> getParsedUnit2(String path) async {
     _checkConsistency();
-    return _driver.parseFileSync(path);
+    return _driver.parseFile(path);
   }
 
   @override
diff --git a/pkg/analyzer/lib/src/dart/micro/library_graph.dart b/pkg/analyzer/lib/src/dart/micro/library_graph.dart
index 9597bff..3953099 100644
--- a/pkg/analyzer/lib/src/dart/micro/library_graph.dart
+++ b/pkg/analyzer/lib/src/dart/micro/library_graph.dart
@@ -663,7 +663,7 @@
 
     var siblings = <Resource>[];
     try {
-      siblings = resource.parent2.getChildren();
+      siblings = resource.parent.getChildren();
     } catch (_) {}
 
     for (var sibling in siblings) {
diff --git a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
index 73c6f51..df98227 100644
--- a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
+++ b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
@@ -676,7 +676,7 @@
     File? optionsFile;
     if (!isThirdParty) {
       optionsFile = performance.run('findOptionsFile', (_) {
-        var folder = resourceProvider.getFile(path).parent2;
+        var folder = resourceProvider.getFile(path).parent;
         return _findOptionsFile(folder);
       });
     }
diff --git a/pkg/analyzer/lib/src/dart/sdk/sdk.dart b/pkg/analyzer/lib/src/dart/sdk/sdk.dart
index 60cfa66..bf547a3 100644
--- a/pkg/analyzer/lib/src/dart/sdk/sdk.dart
+++ b/pkg/analyzer/lib/src/dart/sdk/sdk.dart
@@ -206,7 +206,7 @@
     var coreSource = mapDartUri('dart:core');
     if (coreSource != null) {
       var coreFile = resourceProvider.getFile(coreSource.fullName);
-      var embeddedFolder = coreFile.parent2.parent2;
+      var embeddedFolder = coreFile.parent.parent;
       try {
         return embeddedFolder
             .getChildAssumingFolder('_internal')
@@ -515,7 +515,7 @@
     try {
       File file = libraryDirectory.getChildAssumingFile(library.path);
       if (relativePath.isNotEmpty) {
-        File relativeFile = file.parent2.getChildAssumingFile(relativePath);
+        File relativeFile = file.parent.getChildAssumingFile(relativePath);
         if (relativeFile.path == file.path) {
           // The relative file is the library, so return a Source for the
           // library rather than the part format.
diff --git a/pkg/analyzer/lib/src/pubspec/validators/flutter_validator.dart b/pkg/analyzer/lib/src/pubspec/validators/flutter_validator.dart
index bb8803b..83f9fc7 100644
--- a/pkg/analyzer/lib/src/pubspec/validators/flutter_validator.dart
+++ b/pkg/analyzer/lib/src/pubspec/validators/flutter_validator.dart
@@ -86,7 +86,7 @@
       return true;
     }
     String fileName = assetFile.shortName;
-    Folder assetFolder = assetFile.parent2;
+    Folder assetFolder = assetFile.parent;
     if (!assetFolder.exists) {
       return false;
     }
diff --git a/pkg/analyzer/lib/src/services/available_declarations.dart b/pkg/analyzer/lib/src/services/available_declarations.dart
index e39cd99..36e3a3b 100644
--- a/pkg/analyzer/lib/src/services/available_declarations.dart
+++ b/pkg/analyzer/lib/src/services/available_declarations.dart
@@ -344,7 +344,7 @@
     for (var path in _analysisContext.contextRoot.analyzedFiles()) {
       if (file_paths.isBazelBuild(pathContext, path)) {
         var file = _tracker._resourceProvider.getFile(path);
-        var packageFolder = file.parent2;
+        var packageFolder = file.parent;
         _packages.add(_Package(packageFolder));
       } else if (file_paths.isPubspecYaml(pathContext, path)) {
         var file = _tracker._resourceProvider.getFile(path);
@@ -352,7 +352,7 @@
         var libPaths = _resolvePackageNamesToLibPaths(dependencies.lib);
         var devPaths = _resolvePackageNamesToLibPaths(dependencies.dev);
 
-        var packageFolder = file.parent2;
+        var packageFolder = file.parent;
         var packagePath = packageFolder.path;
         pubPathPrefixToPathList[packagePath] = [
           ...libPaths,
diff --git a/pkg/analyzer/lib/src/source/custom_resolver.dart b/pkg/analyzer/lib/src/source/custom_resolver.dart
deleted file mode 100644
index c7fabf8..0000000
--- a/pkg/analyzer/lib/src/source/custom_resolver.dart
+++ /dev/null
@@ -1,29 +0,0 @@
-// 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.
-
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/util/uri.dart';
-
-class CustomUriResolver extends UriResolver {
-  final ResourceProvider resourceProvider;
-  final Map<String, String> _urlMappings;
-
-  CustomUriResolver(this.resourceProvider, this._urlMappings);
-
-  @override
-  Source? resolveAbsolute(Uri uri) {
-    var mapping = _urlMappings[uri.toString()];
-    if (mapping == null) {
-      return null;
-    }
-    Uri fileUri = Uri.file(mapping);
-    if (!fileUri.isAbsolute) {
-      return null;
-    }
-    var pathContext = resourceProvider.pathContext;
-    var path = fileUriToNormalizedPath(pathContext, fileUri);
-    return resourceProvider.getFile(path).createSource(uri);
-  }
-}
diff --git a/pkg/analyzer/lib/src/workspace/basic.dart b/pkg/analyzer/lib/src/workspace/basic.dart
index eb412f9..81697c4 100644
--- a/pkg/analyzer/lib/src/workspace/basic.dart
+++ b/pkg/analyzer/lib/src/workspace/basic.dart
@@ -47,7 +47,7 @@
   ) {
     Resource resource = provider.getResource(path);
     if (resource is File) {
-      path = resource.parent2.path;
+      path = resource.parent.path;
     }
     return BasicWorkspace._(provider, packageMap, path);
   }
diff --git a/pkg/analyzer/lib/src/workspace/bazel.dart b/pkg/analyzer/lib/src/workspace/bazel.dart
index 7350937..fb21dfa 100644
--- a/pkg/analyzer/lib/src/workspace/bazel.dart
+++ b/pkg/analyzer/lib/src/workspace/bazel.dart
@@ -447,7 +447,7 @@
     var context = provider.pathContext;
     var startFolder = provider.getFolder(filePath);
     for (var folder in startFolder.withAncestors) {
-      var parent = folder.parent2;
+      var parent = folder.parent;
 
       // Found the READONLY folder, might be a git-based workspace.
       Folder readonlyFolder = parent.getChildAssumingFolder(_READONLY);
diff --git a/pkg/analyzer/lib/src/workspace/gn.dart b/pkg/analyzer/lib/src/workspace/gn.dart
index 8ebed62..8826a1a 100644
--- a/pkg/analyzer/lib/src/workspace/gn.dart
+++ b/pkg/analyzer/lib/src/workspace/gn.dart
@@ -99,7 +99,7 @@
   static GnWorkspace? find(ResourceProvider provider, String filePath) {
     Resource resource = provider.getResource(filePath);
     if (resource is File) {
-      filePath = resource.parent2.path;
+      filePath = resource.parent.path;
     }
 
     var startFolder = provider.getFolder(filePath);
diff --git a/pkg/analyzer/test/file_system/file_system_test_support.dart b/pkg/analyzer/test/file_system/file_system_test_support.dart
index 11cf39f..239b461 100644
--- a/pkg/analyzer/test/file_system/file_system_test_support.dart
+++ b/pkg/analyzer/test/file_system/file_system_test_support.dart
@@ -84,7 +84,7 @@
     Folder destination = provider.getFolder(join(tempPath, 'destination'));
 
     File copy = file.copyTo(destination);
-    expect(copy.parent2, destination);
+    expect(copy.parent, destination);
     expect(copy.shortName, file.shortName);
     expect(copy.exists, isTrue);
     expect(copy.readAsStringSync(), 'contents');
@@ -111,11 +111,11 @@
   test_delete_existing() {
     File file = getFile(exists: true);
     expect(file.exists, isTrue);
-    expect(file.parent2.getChildren(), contains(file));
+    expect(file.parent.getChildren(), contains(file));
 
     file.delete();
     expect(file.exists, isFalse);
-    expect(file.parent2.getChildren(), isNot(contains(file)));
+    expect(file.parent.getChildren(), isNot(contains(file)));
   }
 
   test_delete_notExisting();
@@ -232,7 +232,7 @@
   test_parent2() {
     File file = getFile(exists: true);
 
-    var parent = file.parent2;
+    var parent = file.parent;
     expect(parent.exists, isTrue);
     expect(parent.path, defaultFolderPath);
   }
@@ -497,7 +497,7 @@
         getFolder(exists: true, folderPath: join(tempPath, 'destination'));
 
     Folder copy = source.copyTo(destination);
-    expect(copy.parent2, destination);
+    expect(copy.parent, destination);
     _verifyStructure(copy, source);
   }
 
@@ -512,7 +512,7 @@
   test_delete() {
     File file =
         getFile(exists: true, filePath: join(defaultFolderPath, 'myFile'));
-    var folder = file.parent2;
+    var folder = file.parent;
     expect(folder.exists, isTrue);
     expect(file.exists, isTrue);
 
@@ -781,7 +781,7 @@
   test_parent() {
     Folder folder = getFolder(exists: true);
 
-    var parent = folder.parent2;
+    var parent = folder.parent;
     expect(parent.path, equals(tempPath));
     //
     // Since the OS is in control of where tempPath is, we don't know how far it
@@ -789,7 +789,7 @@
     // in a folder with a shorter path, and that we reach the root eventually.
     //
     while (true) {
-      var grandParent = parent.parent2;
+      var grandParent = parent.parent;
       if (grandParent.isRoot) {
         break;
       }
diff --git a/pkg/analyzer/test/file_system/overlay_file_system_test.dart b/pkg/analyzer/test/file_system/overlay_file_system_test.dart
index dae3df2..6b61a07 100644
--- a/pkg/analyzer/test/file_system/overlay_file_system_test.dart
+++ b/pkg/analyzer/test/file_system/overlay_file_system_test.dart
@@ -38,7 +38,7 @@
     File targetFile =
         provider.getFile(baseProvider.convertPath('/foo/test.dart'));
     expect(targetFile.exists, isFalse);
-    file.copyTo(file.parent2.parent2);
+    file.copyTo(file.parent.parent);
     expect(targetFile.exists, isTrue);
   }
 
@@ -48,7 +48,7 @@
     File targetFile =
         provider.getFile(baseProvider.convertPath('/foo/test.dart'));
     expect(targetFile.exists, isFalse);
-    file.copyTo(file.parent2.parent2);
+    file.copyTo(file.parent.parent);
     expect(targetFile.exists, isTrue);
     expect(targetFile.readAsStringSync(), 'overlay');
     provider.removeOverlay(targetFile.path);
@@ -61,7 +61,7 @@
     File targetFile =
         provider.getFile(baseProvider.convertPath('/foo/test.dart'));
     expect(targetFile.exists, isFalse);
-    file.copyTo(file.parent2.parent2);
+    file.copyTo(file.parent.parent);
     expect(targetFile.exists, isTrue);
     expect(targetFile.readAsStringSync(), 'overlay');
     provider.removeOverlay(targetFile.path);
@@ -166,7 +166,7 @@
   }
 
   test_parent() {
-    var parent = _file(exists: true).parent2;
+    var parent = _file(exists: true).parent;
     expect(parent.exists, isTrue);
     expect(parent.path, defaultFolderPath);
   }
@@ -461,7 +461,7 @@
         provider.getFolder(baseProvider.convertPath('/destination'));
 
     Folder copy = source.copyTo(destination);
-    expect(copy.parent2, destination);
+    expect(copy.parent, destination);
     _verifyStructure(copy, source);
   }
 
@@ -611,7 +611,7 @@
 
   test_getChildren_nonExisting_withOverlay() {
     File file = _file(exists: false, withOverlay: true);
-    List<Resource> children = file.parent2.parent2.getChildren();
+    List<Resource> children = file.parent.parent.getChildren();
     expect(children, hasLength(1));
     expect(children[0], _isFolder);
   }
@@ -632,13 +632,13 @@
   }
 
   test_parent_ofNonRoot() {
-    Folder parent = _folder(exists: true).parent2;
+    Folder parent = _folder(exists: true).parent;
     expect(parent.exists, isTrue);
     expect(parent.path, baseProvider.convertPath('/foo'));
   }
 
   test_parent_ofRoot() {
-    var parent = _folder(exists: true, path: '/').parent2;
+    var parent = _folder(exists: true, path: '/').parent;
     expect(parent.exists, isTrue);
     expect(parent.path, baseProvider.convertPath('/'));
   }
@@ -806,7 +806,7 @@
 
   test_getFolder_notExisting_withOverlay() {
     File file = _file(exists: false, withOverlay: true);
-    Folder folder = file.parent2;
+    Folder folder = file.parent;
     expect(folder, isNotNull);
     expect(folder.path, defaultFolderPath);
     expect(folder.exists, isTrue);
diff --git a/pkg/analyzer/test/file_system/physical_file_system_test.dart b/pkg/analyzer/test/file_system/physical_file_system_test.dart
index 8794f1d..08a7fa5 100644
--- a/pkg/analyzer/test/file_system/physical_file_system_test.dart
+++ b/pkg/analyzer/test/file_system/physical_file_system_test.dart
@@ -70,7 +70,7 @@
   File getFile({required bool exists, String? content, String? filePath}) {
     File file = provider.getFile(filePath ?? defaultFilePath);
     if (exists) {
-      file.parent2.create();
+      file.parent.create();
       file.writeAsStringSync(content ?? defaultFileContent);
     }
     return file;
diff --git a/pkg/analyzer/test/source/package_map_resolver_test.dart b/pkg/analyzer/test/source/package_map_resolver_test.dart
index 27d7a9c..5498a6d 100644
--- a/pkg/analyzer/test/source/package_map_resolver_test.dart
+++ b/pkg/analyzer/test/source/package_map_resolver_test.dart
@@ -71,7 +71,7 @@
     var b = provider.newFile(provider.convertPath('/bbb/b.dart'), '');
     expect(() {
       PackageMapUriResolver(provider, <String, List<Folder>>{
-        'pkg': <Folder>[a.parent2, b.parent2]
+        'pkg': <Folder>[a.parent, b.parent]
       });
     }, throwsArgumentError);
   }
diff --git a/pkg/analyzer/test/src/dart/analysis/context_locator_test.dart b/pkg/analyzer/test/src/dart/analysis/context_locator_test.dart
index efbf9533f..7022464 100644
--- a/pkg/analyzer/test/src/dart/analysis/context_locator_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/context_locator_test.dart
@@ -416,7 +416,7 @@
     expect(outer1Root.optionsFile, outer1OptionsFile);
     expect(outer1Root.packagesFile, outer1PackagesFile);
 
-    ContextRoot outer2Root = findRoot(roots, testFile.parent2);
+    ContextRoot outer2Root = findRoot(roots, testFile.parent);
     expect(outer2Root.includedPaths, unorderedEquals([testFile.path]));
     expect(outer2Root.excludedPaths, isEmpty);
     expect(outer2Root.optionsFile, outer2OptionsFile);
@@ -1090,7 +1090,7 @@
     ContextRoot outerRoot = findRoot(roots, outerRootFolder);
     expect(outerRoot.includedPaths, unorderedEquals([outerRootFolder.path]));
     expect(outerRoot.excludedPaths,
-        unorderedEquals([innerOptionsFile.parent2.path]));
+        unorderedEquals([innerOptionsFile.parent.path]));
     expect(outerRoot.optionsFile, outerOptionsFile);
     expect(outerRoot.packagesFile, outerPackagesFile);
   }
@@ -1461,7 +1461,7 @@
         contextLocator.locateRoots(includedPaths: [testFile.path]);
     expect(roots, hasLength(1));
 
-    ContextRoot package1Root = findRoot(roots, testFile.parent2);
+    ContextRoot package1Root = findRoot(roots, testFile.parent);
     expect(package1Root.includedPaths, unorderedEquals([testFile.path]));
     expect(package1Root.excludedPaths, isEmpty);
     expect(package1Root.optionsFile, optionsFile);
@@ -1477,7 +1477,7 @@
         contextLocator.locateRoots(includedPaths: [testFile.path]);
     expect(roots, hasLength(1));
 
-    ContextRoot package1Root = findRoot(roots, testFile.parent2);
+    ContextRoot package1Root = findRoot(roots, testFile.parent);
     expect(package1Root.includedPaths, unorderedEquals([testFile.path]));
     expect(package1Root.excludedPaths, isEmpty);
     expect(package1Root.optionsFile, optionsFile);
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index 67951ae..6a62c91 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -1666,6 +1666,7 @@
     expect(result, isA<CannotResolveUriResult>());
   }
 
+  @deprecated
   test_getParsedLibrary() async {
     var content = 'class A {}';
     addTestFile(content);
@@ -1678,17 +1679,43 @@
     expect(result.units[0].errors, isEmpty);
   }
 
+  test_getParsedLibrary2() async {
+    var content = 'class A {}';
+    addTestFile(content);
+    var result = await driver.getParsedLibrary2(testFile);
+    result as ParsedLibraryResult;
+    expect(result.units, hasLength(1));
+    expect(result.units[0].path, testFile);
+    expect(result.units[0].content, content);
+    expect(result.units[0].unit, isNotNull);
+    expect(result.units[0].errors, isEmpty);
+  }
+
+  test_getParsedLibrary2_invalidPath_notAbsolute() async {
+    var result = await driver.getParsedLibrary2('not_absolute.dart');
+    expect(result, isA<InvalidPathResult>());
+  }
+
+  test_getParsedLibrary2_notLibraryButPart() async {
+    addTestFile('part of my;');
+    var result = await driver.getParsedLibrary2(testFile);
+    expect(result, isA<NotLibraryButPartResult>());
+  }
+
+  @deprecated
   test_getParsedLibrary_invalidPath_notAbsolute() async {
     var result = driver.getParsedLibrary('not_absolute.dart');
     expect(result, isA<InvalidPathResult>());
   }
 
+  @deprecated
   test_getParsedLibrary_notLibraryButPart() async {
     addTestFile('part of my;');
     var result = driver.getParsedLibrary(testFile);
     expect(result, isA<NotLibraryButPartResult>());
   }
 
+  @deprecated
   test_getParsedLibraryByUri() async {
     var content = 'class A {}';
     addTestFile(content);
@@ -1702,6 +1729,34 @@
     expect(result.units[0].content, content);
   }
 
+  test_getParsedLibraryByUri2() async {
+    var content = 'class A {}';
+    addTestFile(content);
+
+    var uri = Uri.parse('package:test/test.dart');
+    var result = await driver.getParsedLibraryByUri2(uri);
+    result as ParsedLibraryResult;
+    expect(result.units, hasLength(1));
+    expect(result.units[0].uri, uri);
+    expect(result.units[0].path, testFile);
+    expect(result.units[0].content, content);
+  }
+
+  test_getParsedLibraryByUri2_notLibrary() async {
+    addTestFile('part of my;');
+
+    var uri = Uri.parse('package:test/test.dart');
+    var result = await driver.getParsedLibraryByUri2(uri);
+    expect(result, isA<NotLibraryButPartResult>());
+  }
+
+  test_getParsedLibraryByUri2_unresolvedUri() async {
+    var uri = Uri.parse('package:unknown/a.dart');
+    var result = await driver.getParsedLibraryByUri2(uri);
+    expect(result, isA<CannotResolveUriResult>());
+  }
+
+  @deprecated
   test_getParsedLibraryByUri_notLibrary() async {
     addTestFile('part of my;');
 
@@ -1710,6 +1765,7 @@
     expect(result, isA<NotLibraryButPartResult>());
   }
 
+  @deprecated
   test_getParsedLibraryByUri_unresolvedUri() async {
     var uri = Uri.parse('package:unknown/a.dart');
     var result = driver.getParsedLibraryByUri(uri);
@@ -2495,6 +2551,138 @@
     expect(error.errorCode, CompileTimeErrorCode.MISSING_DART_LIBRARY);
   }
 
+  test_parseFile_changedFile() async {
+    var a = convertPath('/test/lib/a.dart');
+    var b = convertPath('/test/lib/b.dart');
+
+    newFile(a, content: '');
+    newFile(b, content: r'''
+import 'a.dart';
+
+void f(A a) {}
+''');
+
+    // Ensure that [a.dart] library cycle is loaded.
+    // So, `a.dart` is in the library context.
+    await driver.getResultValid(a);
+
+    // Update the file, changing its API signature.
+    // Note that we don't call `changeFile`.
+    newFile(a, content: 'class A {}');
+
+    // Parse the file.
+    // We have not called `changeFile(a)`, so we should not read the file.
+    // Moreover, doing this will create a new library cycle [a.dart].
+    // Library cycles are compared by their identity, so we would try to
+    // reload linked summary for [a.dart], and crash.
+    {
+      var parseResult = await driver.parseFile(a) as ParsedUnitResult;
+      expect(parseResult.unit.declarations, isEmpty);
+    }
+
+    // We have not read `a.dart`, so `A` is still not declared.
+    {
+      var bResult = await driver.getResultValid(b);
+      expect(bResult.errors, isNotEmpty);
+    }
+
+    // Notify the driver that the file was changed.
+    driver.changeFile(a);
+
+    // So, `class A {}` is declared now.
+    {
+      var parseResult = await driver.parseFile(a) as ParsedUnitResult;
+      expect(parseResult.unit.declarations, hasLength(1));
+    }
+    {
+      var bResult = await driver.getResultValid(b);
+      expect(bResult.errors, isEmpty);
+    }
+  }
+
+  test_parseFile_doesNotReadImportedFiles() async {
+    var a = convertPath('/test/lib/a.dart');
+    var b = convertPath('/test/lib/b.dart');
+
+    newFile(a, content: '');
+    newFile(b, content: r'''
+import 'a.dart';
+''');
+
+    expect(driver.fsState.knownFilePaths, isEmpty);
+
+    // Don't read `a.dart` when parse.
+    await driver.parseFile(b);
+    expect(driver.fsState.knownFilePaths, unorderedEquals([b]));
+
+    // Still don't read `a.dart` when parse the second time.
+    await driver.parseFile(b);
+    expect(driver.fsState.knownFilePaths, unorderedEquals([b]));
+  }
+
+  test_parseFile_doesNotReadPartedFiles() async {
+    var a = convertPath('/test/lib/a.dart');
+    var b = convertPath('/test/lib/b.dart');
+
+    newFile(a, content: r'''
+part of my;
+''');
+    newFile(b, content: r'''
+library my;
+part 'a.dart';
+''');
+
+    expect(driver.fsState.knownFilePaths, isEmpty);
+
+    // Don't read `a.dart` when parse.
+    await driver.parseFile(b);
+    expect(driver.fsState.knownFilePaths, unorderedEquals([b]));
+
+    // Still don't read `a.dart` when parse the second time.
+    await driver.parseFile(b);
+    expect(driver.fsState.knownFilePaths, unorderedEquals([b]));
+  }
+
+  test_parseFile_languageVersion() async {
+    var path = convertPath('/test/lib/test.dart');
+
+    newFile(path, content: r'''
+// @dart = 2.7
+class A {}
+''');
+
+    var parseResult = await driver.parseFile(path) as ParsedUnitResult;
+    var languageVersion = parseResult.unit.languageVersionToken!;
+    expect(languageVersion.major, 2);
+    expect(languageVersion.minor, 7);
+  }
+
+  test_parseFile_languageVersion_null() async {
+    var path = convertPath('/test/lib/test.dart');
+
+    newFile(path, content: r'''
+class A {}
+''');
+
+    var parseResult = await driver.parseFile(path) as ParsedUnitResult;
+    expect(parseResult.unit.languageVersionToken, isNull);
+  }
+
+  test_parseFile_notAbsolutePath() async {
+    var result = await driver.parseFile('not_absolute.dart');
+    expect(result, isA<InvalidPathResult>());
+  }
+
+  test_parseFile_notDart() async {
+    var p = convertPath('/test/bin/a.txt');
+    newFile(p, content: 'class A {}');
+
+    var parseResult = await driver.parseFile(p) as ParsedUnitResult;
+    expect(parseResult, isNotNull);
+    expect(driver.knownFiles, contains(p));
+  }
+
+  @deprecated
   test_parseFileSync_changedFile() async {
     var a = convertPath('/test/lib/a.dart');
     var b = convertPath('/test/lib/b.dart');
@@ -2544,6 +2732,7 @@
     }
   }
 
+  @deprecated
   test_parseFileSync_doesNotReadImportedFiles() async {
     var a = convertPath('/test/lib/a.dart');
     var b = convertPath('/test/lib/b.dart');
@@ -2564,6 +2753,7 @@
     expect(driver.fsState.knownFilePaths, unorderedEquals([b]));
   }
 
+  @deprecated
   test_parseFileSync_doesNotReadPartedFiles() async {
     var a = convertPath('/test/lib/a.dart');
     var b = convertPath('/test/lib/b.dart');
@@ -2587,6 +2777,7 @@
     expect(driver.fsState.knownFilePaths, unorderedEquals([b]));
   }
 
+  @deprecated
   test_parseFileSync_languageVersion() async {
     var path = convertPath('/test/lib/test.dart');
 
@@ -2601,6 +2792,7 @@
     expect(languageVersion.minor, 7);
   }
 
+  @deprecated
   test_parseFileSync_languageVersion_null() async {
     var path = convertPath('/test/lib/test.dart');
 
@@ -2612,11 +2804,13 @@
     expect(parseResult.unit.languageVersionToken, isNull);
   }
 
+  @deprecated
   test_parseFileSync_notAbsolutePath() async {
     var result = driver.parseFileSync('not_absolute.dart');
     expect(result, isA<InvalidPathResult>());
   }
 
+  @deprecated
   test_parseFileSync_notDart() async {
     var p = convertPath('/test/bin/a.txt');
     newFile(p, content: 'class A {}');
diff --git a/pkg/analyzer_cli/lib/src/driver.dart b/pkg/analyzer_cli/lib/src/driver.dart
index 6c75fd3..b982da9 100644
--- a/pkg/analyzer_cli/lib/src/driver.dart
+++ b/pkg/analyzer_cli/lib/src/driver.dart
@@ -523,14 +523,14 @@
     }
 
     // Exclude patterns are relative to the directory with the options file.
-    return PathFilter(contextRoot.root.path, optionsFile.parent2.path,
+    return PathFilter(contextRoot.root.path, optionsFile.parent.path,
         analysisContext!.analysisOptions.excludePatterns);
   }
 
   void configureForPath(String path) {
     var folder = _resourceProvider.getFolder(path);
     if (!folder.exists) {
-      folder = _resourceProvider.getFile(path).parent2;
+      folder = _resourceProvider.getFile(path).parent;
     }
 
     // In batch mode we are given separate file paths to analyze.
diff --git a/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart b/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
index 803d099..3f13d2a 100644
--- a/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
+++ b/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
@@ -497,14 +497,14 @@
     if (!file.exists) {
       return null;
     }
-    var parent = file.parent2;
-    while (parent != parent.parent2) {
+    var parent = file.parent;
+    while (parent != parent.parent) {
       var examplesFolder = parent.getChildAssumingFolder('examples');
       if (examplesFolder.exists &&
           examplesFolder.getChildAssumingFolder('api').exists) {
         return parent.path;
       }
-      parent = parent.parent2;
+      parent = parent.parent;
     }
     return null;
   }
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart b/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart
index 2606826..5bf8933 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types_resolution.dart
@@ -25,22 +25,11 @@
 abstract class RtiNode {
   Entity get entity;
   Set<RtiNode> _dependencies;
-  int _testState = 0;
-  int _literalState = 0;
+  bool _hasTest = false;
 
   Iterable<RtiNode> get dependencies => _dependencies ?? const [];
 
-  bool get hasDirectTest => _testState & 1 != 0;
-  bool get hasIndirectTest => _testState & 2 != 0;
-
-  bool get hasTest => _testState != 0;
-
-  bool get hasDirectLiteral => _literalState & 1 != 0;
-  bool get hasIndirectLiteral => _literalState & 2 != 0;
-
-  bool get hasLiteral => _literalState != 0;
-
-  bool get hasUse => hasTest || hasLiteral;
+  bool get hasTest => _hasTest;
 
   /// Register that if [entity] needs type arguments then so does `node.entity`.
   bool addDependency(RtiNode node) {
@@ -53,52 +42,13 @@
     return _dependencies.add(node);
   }
 
-  void markTest({bool direct}) {
-    setTestState(direct ? 1 : 2);
-  }
-
-  void markDirectTest() {
-    setTestState(1);
-  }
-
-  void markIndirectTest() {
-    setTestState(2);
-  }
-
-  void setTestState(int value) {
-    if (_testState != value) {
-      if (_testState == 0) {
-        _testState |= value;
-        if (_dependencies != null) {
-          for (RtiNode node in _dependencies) {
-            node.markIndirectTest();
-          }
+  void markTest() {
+    if (!hasTest) {
+      _hasTest = true;
+      if (_dependencies != null) {
+        for (RtiNode node in _dependencies) {
+          node.markTest();
         }
-      } else {
-        _testState = value;
-      }
-    }
-  }
-
-  void markDirectLiteral() {
-    setLiteralState(1);
-  }
-
-  void markIndirectLiteral() {
-    setLiteralState(2);
-  }
-
-  void setLiteralState(int value) {
-    if (_literalState != value) {
-      if (_literalState == 0) {
-        _literalState |= value;
-        if (_dependencies != null) {
-          for (RtiNode node in _dependencies) {
-            node.markIndirectLiteral();
-          }
-        }
-      } else {
-        _literalState = value;
       }
     }
   }
@@ -223,9 +173,6 @@
       : explicitIsChecks = _world.isChecks.toSet() {
     _setupDependencies();
     _propagateTests();
-    if (forRtiNeeds) {
-      _propagateLiterals();
-    }
     _collectResults();
   }
 
@@ -249,18 +196,6 @@
   Iterable<ClassEntity> get classTestsForTesting =>
       _classes.values.where((n) => n.hasTest).map((n) => n.cls).toSet();
 
-  /// Classes that explicitly use their type variables in is-tests.
-  ///
-  /// For instance `A` in:
-  ///
-  ///     class A<T> {
-  ///       m(o) => o is T;
-  ///     }
-  ///     main() => new A<int>().m(0);
-  ///
-  Iterable<ClassEntity> get directClassTestsForTesting =>
-      _classes.values.where((n) => n.hasDirectTest).map((n) => n.cls).toSet();
-
   /// Methods that explicitly or implicitly use their type variables in
   /// is-tests.
   ///
@@ -273,18 +208,6 @@
   Iterable<Entity> get methodTestsForTesting =>
       _methods.values.where((n) => n.hasTest).map((n) => n.function).toSet();
 
-  /// Methods that explicitly use their type variables in is-tests.
-  ///
-  /// For instance `m` in:
-  ///
-  ///     m<T>(o) => o is T;
-  ///     main() => m<int>(0);
-  ///
-  Iterable<Entity> get directMethodTestsForTesting => _methods.values
-      .where((n) => n.hasDirectTest)
-      .map((n) => n.function)
-      .toSet();
-
   /// The entities that need type arguments at runtime if the 'key entity' needs
   /// type arguments.
   ///
@@ -546,23 +469,23 @@
   }
 
   void _propagateTests() {
-    void processTypeVariableType(TypeVariableType type, {bool direct = true}) {
+    void processTypeVariableType(TypeVariableType type) {
       TypeVariableEntity variable = type.element;
       if (variable.typeDeclaration is ClassEntity) {
-        _getClassNode(variable.typeDeclaration).markTest(direct: direct);
+        _getClassNode(variable.typeDeclaration).markTest();
       } else {
-        _getMethodNode(variable.typeDeclaration).markTest(direct: direct);
+        _getMethodNode(variable.typeDeclaration).markTest();
       }
     }
 
-    void processType(DartType type, {bool direct = true}) {
+    void processType(DartType type) {
       var typeWithoutNullability = type.withoutNullability;
       if (typeWithoutNullability is FutureOrType) {
-        _getClassNode(_commonElements.futureClass).markIndirectTest();
-        processType(typeWithoutNullability.typeArgument, direct: false);
+        _getClassNode(_commonElements.futureClass).markTest();
+        processType(typeWithoutNullability.typeArgument);
       } else {
         typeWithoutNullability.forEachTypeVariable((TypeVariableType type) {
-          processTypeVariableType(type, direct: direct);
+          processTypeVariableType(type);
         });
       }
     }
@@ -570,40 +493,14 @@
     _world.isChecks.forEach(processType);
   }
 
-  void _propagateLiterals() {
-    _world.typeVariableTypeLiterals
-        .forEach((TypeVariableType typeVariableType) {
-      TypeVariableEntity variable = typeVariableType.element;
-      if (variable.typeDeclaration is ClassEntity) {
-        _getClassNode(variable.typeDeclaration).markDirectLiteral();
-      } else {
-        _getMethodNode(variable.typeDeclaration).markDirectLiteral();
-      }
-    });
-  }
-
   String dump({bool verbose = false}) {
     StringBuffer sb = StringBuffer();
 
     void addNode(RtiNode node) {
-      if (node.hasUse || node.dependencies.isNotEmpty || verbose) {
+      if (node.hasTest || node.dependencies.isNotEmpty || verbose) {
         sb.write(' $node');
-        String comma = '';
-        if (node._testState & 1 != 0) {
-          sb.write(' direct test');
-          comma = ',';
-        }
-        if (node._testState & 2 != 0) {
-          sb.write('$comma indirect test');
-          comma = ',';
-        }
-        if (node._literalState & 1 != 0) {
-          sb.write('$comma direct literal');
-          comma = ',';
-        }
-        if (node._literalState & 2 != 0) {
-          sb.write('$comma indirect literal');
-          comma = ',';
+        if (node.hasTest) {
+          sb.write(' test');
         }
         if (node.dependencies.isNotEmpty || verbose) {
           sb.writeln(':');
diff --git a/pkg/compiler/test/rti/data/async_foreach.dart b/pkg/compiler/test/rti/data/async_foreach.dart
index 1a14bd2..433b5a1 100644
--- a/pkg/compiler/test/rti/data/async_foreach.dart
+++ b/pkg/compiler/test/rti/data/async_foreach.dart
@@ -6,7 +6,7 @@
 
 import 'package:compiler/src/util/testing.dart';
 
-/*spec.class: Class:direct,explicit=[Class.T*],implicit=[Class.T],needsArgs*/
+/*spec.class: Class:explicit=[Class.T*],implicit=[Class.T],needsArgs,test*/
 /*prod.class: Class:needsArgs*/
 class Class<T> {
   method() {
diff --git a/pkg/compiler/test/rti/data/async_foreach_nonasync.dart b/pkg/compiler/test/rti/data/async_foreach_nonasync.dart
index 0cb5ac1..1e371c6 100644
--- a/pkg/compiler/test/rti/data/async_foreach_nonasync.dart
+++ b/pkg/compiler/test/rti/data/async_foreach_nonasync.dart
@@ -6,7 +6,7 @@
 
 import 'package:compiler/src/util/testing.dart';
 
-/*spec.class: Class:direct,explicit=[Class.T*],implicit=[Class.T],needsArgs*/
+/*spec.class: Class:explicit=[Class.T*],implicit=[Class.T],needsArgs,test*/
 class Class<T> {
   method() {
     var list = <T>[];
diff --git a/pkg/compiler/test/rti/data/call_typed_generic.dart b/pkg/compiler/test/rti/data/call_typed_generic.dart
index cc7b472..6900251 100644
--- a/pkg/compiler/test/rti/data/call_typed_generic.dart
+++ b/pkg/compiler/test/rti/data/call_typed_generic.dart
@@ -6,7 +6,7 @@
 
 import 'package:compiler/src/util/testing.dart';
 
-/*spec.class: A:direct,explicit=[A.T*],needsArgs*/
+/*spec.class: A:explicit=[A.T*],needsArgs,test*/
 class A<T> {
   call(T t) {}
 }
diff --git a/pkg/compiler/test/rti/data/closure.dart b/pkg/compiler/test/rti/data/closure.dart
index 2e728d0..c4301ee 100644
--- a/pkg/compiler/test/rti/data/closure.dart
+++ b/pkg/compiler/test/rti/data/closure.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.7
 
-/*spec.class: A:direct,explicit=[A.T*],needsArgs*/
+/*spec.class: A:explicit=[A.T*],needsArgs,test*/
 /*prod.class: A:needsArgs*/
 class A<T> {
   m() {
diff --git a/pkg/compiler/test/rti/data/closure_generic_unneeded.dart b/pkg/compiler/test/rti/data/closure_generic_unneeded.dart
index 6b0ad84..9f8c2d8 100644
--- a/pkg/compiler/test/rti/data/closure_generic_unneeded.dart
+++ b/pkg/compiler/test/rti/data/closure_generic_unneeded.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.7
 
-/*spec.class: A:direct,explicit=[A.T*],needsArgs*/
+/*spec.class: A:explicit=[A.T*],needsArgs,test*/
 /*prod.class: A:needsArgs*/
 class A<T> {
   @pragma('dart2js:noInline')
diff --git a/pkg/compiler/test/rti/data/closure_unneeded.dart b/pkg/compiler/test/rti/data/closure_unneeded.dart
index 6b0ad84..9f8c2d8 100644
--- a/pkg/compiler/test/rti/data/closure_unneeded.dart
+++ b/pkg/compiler/test/rti/data/closure_unneeded.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.7
 
-/*spec.class: A:direct,explicit=[A.T*],needsArgs*/
+/*spec.class: A:explicit=[A.T*],needsArgs,test*/
 /*prod.class: A:needsArgs*/
 class A<T> {
   @pragma('dart2js:noInline')
diff --git a/pkg/compiler/test/rti/data/dynamic_is.dart b/pkg/compiler/test/rti/data/dynamic_is.dart
index 6c4e5f6..279a58a 100644
--- a/pkg/compiler/test/rti/data/dynamic_is.dart
+++ b/pkg/compiler/test/rti/data/dynamic_is.dart
@@ -5,7 +5,7 @@
 // @dart = 2.7
 
 class A {
-  /*member: A.instanceMethod:direct,explicit=[instanceMethod.T*],needsArgs,selectors=[Selector(call, instanceMethod, arity=1, types=1)]*/
+  /*member: A.instanceMethod:explicit=[instanceMethod.T*],needsArgs,selectors=[Selector(call, instanceMethod, arity=1, types=1)],test*/
   instanceMethod<T>(t) => t is T;
 }
 
diff --git a/pkg/compiler/test/rti/data/dynamic_is2.dart b/pkg/compiler/test/rti/data/dynamic_is2.dart
index 213c6bf..4da18d6 100644
--- a/pkg/compiler/test/rti/data/dynamic_is2.dart
+++ b/pkg/compiler/test/rti/data/dynamic_is2.dart
@@ -6,12 +6,12 @@
 
 /*spec.class: A:explicit=[A*]*/
 class A {
-  /*member: A.instanceMethod:deps=[B.instanceMethod],direct,explicit=[instanceMethod.T*],needsArgs,selectors=[Selector(call, instanceMethod, arity=1, types=1)]*/
+  /*member: A.instanceMethod:deps=[B.instanceMethod],explicit=[instanceMethod.T*],needsArgs,selectors=[Selector(call, instanceMethod, arity=1, types=1)],test*/
   instanceMethod<T>(t) => t is T;
 }
 
 class B {
-  /*member: B.instanceMethod:implicit=[instanceMethod.T],indirect,needsArgs,selectors=[Selector(call, instanceMethod, arity=2, types=1)]*/
+  /*member: B.instanceMethod:implicit=[instanceMethod.T],needsArgs,selectors=[Selector(call, instanceMethod, arity=2, types=1)],test*/
   instanceMethod<T>(A a, t) => a.instanceMethod<T>(t);
 }
 
diff --git a/pkg/compiler/test/rti/data/dynamic_is_closure.dart b/pkg/compiler/test/rti/data/dynamic_is_closure.dart
index d5e213c..3cee2f0 100644
--- a/pkg/compiler/test/rti/data/dynamic_is_closure.dart
+++ b/pkg/compiler/test/rti/data/dynamic_is_closure.dart
@@ -5,7 +5,7 @@
 // @dart = 2.7
 
 class A {
-  /*member: A.instanceMethod:direct,explicit=[instanceMethod.T*],needsArgs,selectors=[Selector(call, instanceMethod, arity=1, types=1)]*/
+  /*member: A.instanceMethod:explicit=[instanceMethod.T*],needsArgs,selectors=[Selector(call, instanceMethod, arity=1, types=1)],test*/
   instanceMethod<T>(t) => t is T;
 }
 
diff --git a/pkg/compiler/test/rti/data/dynamic_is_closure2.dart b/pkg/compiler/test/rti/data/dynamic_is_closure2.dart
index 36482a6..dddff8c 100644
--- a/pkg/compiler/test/rti/data/dynamic_is_closure2.dart
+++ b/pkg/compiler/test/rti/data/dynamic_is_closure2.dart
@@ -5,12 +5,12 @@
 // @dart = 2.7
 
 class A {
-  /*member: A.instanceMethod:deps=[local],direct,explicit=[instanceMethod.T*],needsArgs,selectors=[Selector(call, instanceMethod, arity=1, types=1)]*/
+  /*member: A.instanceMethod:deps=[local],explicit=[instanceMethod.T*],needsArgs,selectors=[Selector(call, instanceMethod, arity=1, types=1)],test*/
   instanceMethod<T>(t) => t is T;
 }
 
 main() {
-  /*implicit=[local.T],indirect,needsArgs,selectors=[Selector(call, call, arity=1, types=1)]*/
+  /*implicit=[local.T],needsArgs,selectors=[Selector(call, call, arity=1, types=1)],test*/
   local<T>(t) {
     var a = new A();
     a.instanceMethod<T>(t);
diff --git a/pkg/compiler/test/rti/data/dynamic_tear_off.dart b/pkg/compiler/test/rti/data/dynamic_tear_off.dart
index baae3e9..2e21118 100644
--- a/pkg/compiler/test/rti/data/dynamic_tear_off.dart
+++ b/pkg/compiler/test/rti/data/dynamic_tear_off.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.7
 
-/*member: staticMethod:direct,explicit=[staticMethod.T*],needsArgs,selectors=[Selector(call, call, arity=1, types=1)]*/
+/*member: staticMethod:explicit=[staticMethod.T*],needsArgs,selectors=[Selector(call, call, arity=1, types=1)],test*/
 staticMethod<T>(t) => t is T;
 
 main() {
diff --git a/pkg/compiler/test/rti/data/dynamic_tear_off2.dart b/pkg/compiler/test/rti/data/dynamic_tear_off2.dart
index 1db565c..ddf36f7 100644
--- a/pkg/compiler/test/rti/data/dynamic_tear_off2.dart
+++ b/pkg/compiler/test/rti/data/dynamic_tear_off2.dart
@@ -4,11 +4,11 @@
 
 // @dart = 2.7
 
-/*member: staticMethod:deps=[B.instanceMethod],direct,explicit=[staticMethod.T*],needsArgs,selectors=[Selector(call, call, arity=1, types=1)]*/
+/*member: staticMethod:deps=[B.instanceMethod],explicit=[staticMethod.T*],needsArgs,selectors=[Selector(call, call, arity=1, types=1)],test*/
 staticMethod<T>(t) => t is T;
 
 class B {
-  /*member: B.instanceMethod:implicit=[instanceMethod.T],indirect,needsArgs,selectors=[Selector(call, instanceMethod, arity=2, types=1)]*/
+  /*member: B.instanceMethod:implicit=[instanceMethod.T],needsArgs,selectors=[Selector(call, instanceMethod, arity=2, types=1)],test*/
   instanceMethod<T>(a, t) => a<T>(t);
 }
 
diff --git a/pkg/compiler/test/rti/data/dynamic_tear_off3.dart b/pkg/compiler/test/rti/data/dynamic_tear_off3.dart
index 8917791..51f06d1 100644
--- a/pkg/compiler/test/rti/data/dynamic_tear_off3.dart
+++ b/pkg/compiler/test/rti/data/dynamic_tear_off3.dart
@@ -6,11 +6,11 @@
 
 /*spec.class: A:explicit=[A*]*/
 class A {
-  /*member: A.instanceMethod:deps=[staticMethod],direct,explicit=[instanceMethod.T*],needsArgs,selectors=[Selector(call, instanceMethod, arity=1, types=1)]*/
+  /*member: A.instanceMethod:deps=[staticMethod],explicit=[instanceMethod.T*],needsArgs,selectors=[Selector(call, instanceMethod, arity=1, types=1)],test*/
   instanceMethod<T>(t) => t is T;
 }
 
-/*member: staticMethod:implicit=[staticMethod.T],indirect,needsArgs,selectors=[Selector(call, call, arity=2, types=1)]*/
+/*member: staticMethod:implicit=[staticMethod.T],needsArgs,selectors=[Selector(call, call, arity=2, types=1)],test*/
 staticMethod<T>(A a, t) => a.instanceMethod<T>(t);
 
 main() {
diff --git a/pkg/compiler/test/rti/data/dynamic_tear_off4.dart b/pkg/compiler/test/rti/data/dynamic_tear_off4.dart
index 462b94d..5ac2dd1 100644
--- a/pkg/compiler/test/rti/data/dynamic_tear_off4.dart
+++ b/pkg/compiler/test/rti/data/dynamic_tear_off4.dart
@@ -4,10 +4,10 @@
 
 // @dart = 2.7
 
-/*member: staticMethod1:deps=[staticMethod2],direct,explicit=[staticMethod1.T*],needsArgs,selectors=[Selector(call, call, arity=1, types=1)]*/
+/*member: staticMethod1:deps=[staticMethod2],explicit=[staticMethod1.T*],needsArgs,selectors=[Selector(call, call, arity=1, types=1)],test*/
 staticMethod1<T>(t) => t is T;
 
-/*member: staticMethod2:implicit=[staticMethod2.T],indirect,needsArgs,selectors=[Selector(call, call, arity=2, types=1)]*/
+/*member: staticMethod2:implicit=[staticMethod2.T],needsArgs,selectors=[Selector(call, call, arity=2, types=1)],test*/
 staticMethod2<T>(a, t) => a<T>(t);
 
 main() {
diff --git a/pkg/compiler/test/rti/data/explicit_as.dart b/pkg/compiler/test/rti/data/explicit_as.dart
index cbfeda5..e90aad4 100644
--- a/pkg/compiler/test/rti/data/explicit_as.dart
+++ b/pkg/compiler/test/rti/data/explicit_as.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.7
 
-/*spec.class: C:direct,explicit=[C.T*,C<String*>*],needsArgs*/
+/*spec.class: C:explicit=[C.T*,C<String*>*],needsArgs,test*/
 class C<T> {
   T field;
 }
diff --git a/pkg/compiler/test/rti/data/function_subtype_local5.dart b/pkg/compiler/test/rti/data/function_subtype_local5.dart
index bf14939..dd30a14 100644
--- a/pkg/compiler/test/rti/data/function_subtype_local5.dart
+++ b/pkg/compiler/test/rti/data/function_subtype_local5.dart
@@ -17,7 +17,7 @@
 typedef int Boz<T>(T a);
 typedef int Biz<T>(T a, int b);
 
-/*class: C:direct,explicit=[int* Function(C.T*)*,int* Function(C.T*,[String*])*,int* Function(C.T*,int*)*,int* Function(C.T*,{,b:String*})*],needsArgs*/
+/*class: C:explicit=[int* Function(C.T*)*,int* Function(C.T*,[String*])*,int* Function(C.T*,int*)*,int* Function(C.T*,{,b:String*})*],needsArgs,test*/
 class C<T> {
   void test(String nameOfT, bool expectedResult) {
     // TODO(johnniwinther): Optimize local function type signature need.
diff --git a/pkg/compiler/test/rti/data/future_or.dart b/pkg/compiler/test/rti/data/future_or.dart
index 40e625c..afdce83 100644
--- a/pkg/compiler/test/rti/data/future_or.dart
+++ b/pkg/compiler/test/rti/data/future_or.dart
@@ -6,7 +6,7 @@
 
 import 'dart:async';
 
-/*spec.class: global#Future:implicit=[Future<A*>],indirect,needsArgs*/
+/*spec.class: global#Future:implicit=[Future<A*>],needsArgs,test*/
 
 /*class: A:explicit=[FutureOr<A*>*],implicit=[A,Future<A*>]*/
 class A {}
diff --git a/pkg/compiler/test/rti/data/future_or_future_or.dart b/pkg/compiler/test/rti/data/future_or_future_or.dart
index f2ff8ff..b7bc862 100644
--- a/pkg/compiler/test/rti/data/future_or_future_or.dart
+++ b/pkg/compiler/test/rti/data/future_or_future_or.dart
@@ -6,7 +6,7 @@
 
 import 'dart:async';
 
-/*spec.class: global#Future:implicit=[Future<A*>,Future<FutureOr<A*>*>],indirect,needsArgs*/
+/*spec.class: global#Future:implicit=[Future<A*>,Future<FutureOr<A*>*>],needsArgs,test*/
 
 /*class: A:explicit=[FutureOr<FutureOr<A*>*>*],implicit=[A,Future<A*>,Future<FutureOr<A*>*>,FutureOr<A*>]*/
 class A {}
diff --git a/pkg/compiler/test/rti/data/future_or_future_or_generic.dart b/pkg/compiler/test/rti/data/future_or_future_or_generic.dart
index 85a79bb..846a4f7 100644
--- a/pkg/compiler/test/rti/data/future_or_future_or_generic.dart
+++ b/pkg/compiler/test/rti/data/future_or_future_or_generic.dart
@@ -6,9 +6,9 @@
 
 import 'dart:async';
 
-/*spec.class: global#Future:deps=[A],implicit=[Future<B<A.T*>*>,Future<C*>],indirect,needsArgs*/
+/*spec.class: global#Future:deps=[A],implicit=[Future<B<A.T*>*>,Future<C*>],needsArgs,test*/
 
-/*class: A:explicit=[FutureOr<B<A.T*>*>*],implicit=[B<A.T*>,Future<B<A.T*>*>],indirect,needsArgs*/
+/*class: A:explicit=[FutureOr<B<A.T*>*>*],implicit=[B<A.T*>,Future<B<A.T*>*>],needsArgs,test*/
 class A<T> {
   m(o) => o is FutureOr<B<T>>;
 }
diff --git a/pkg/compiler/test/rti/data/future_or_generic.dart b/pkg/compiler/test/rti/data/future_or_generic.dart
index 31edda3..b1376f4 100644
--- a/pkg/compiler/test/rti/data/future_or_generic.dart
+++ b/pkg/compiler/test/rti/data/future_or_generic.dart
@@ -6,9 +6,9 @@
 
 import 'dart:async';
 
-/*spec.class: global#Future:deps=[A],implicit=[Future<A.T*>],indirect,needsArgs*/
+/*spec.class: global#Future:deps=[A],implicit=[Future<A.T*>],needsArgs,test*/
 
-/*class: A:explicit=[FutureOr<A.T*>*],implicit=[A.T,Future<A.T*>],indirect,needsArgs*/
+/*class: A:explicit=[FutureOr<A.T*>*],implicit=[A.T,Future<A.T*>],needsArgs,test*/
 class A<T> {
   m(o) => o is FutureOr<T>;
 }
diff --git a/pkg/compiler/test/rti/data/future_or_generic2.dart b/pkg/compiler/test/rti/data/future_or_generic2.dart
index c4d594a..827b8ad 100644
--- a/pkg/compiler/test/rti/data/future_or_generic2.dart
+++ b/pkg/compiler/test/rti/data/future_or_generic2.dart
@@ -6,9 +6,9 @@
 
 import 'dart:async';
 
-/*spec.class: global#Future:deps=[A],implicit=[Future<B<A.T*>*>],indirect,needsArgs*/
+/*spec.class: global#Future:deps=[A],implicit=[Future<B<A.T*>*>],needsArgs,test*/
 
-/*class: A:explicit=[FutureOr<B<A.T*>*>*],implicit=[B<A.T*>,Future<B<A.T*>*>],indirect,needsArgs*/
+/*class: A:explicit=[FutureOr<B<A.T*>*>*],implicit=[B<A.T*>,Future<B<A.T*>*>],needsArgs,test*/
 class A<T> {
   m(o) => o is FutureOr<B<T>>;
 }
diff --git a/pkg/compiler/test/rti/data/generic_class_is.dart b/pkg/compiler/test/rti/data/generic_class_is.dart
index 0268c28..a56334a 100644
--- a/pkg/compiler/test/rti/data/generic_class_is.dart
+++ b/pkg/compiler/test/rti/data/generic_class_is.dart
@@ -7,7 +7,7 @@
 /*class: A:implicit=[A]*/
 class A {}
 
-/*class: B:direct,explicit=[B.T*],needsArgs*/
+/*class: B:explicit=[B.T*],needsArgs,test*/
 class B<T> {
   @pragma('dart2js:noInline')
   method(T t) => t is T;
diff --git a/pkg/compiler/test/rti/data/generic_class_is2.dart b/pkg/compiler/test/rti/data/generic_class_is2.dart
index 2703f47..20864b8 100644
--- a/pkg/compiler/test/rti/data/generic_class_is2.dart
+++ b/pkg/compiler/test/rti/data/generic_class_is2.dart
@@ -12,7 +12,7 @@
 /*spec.class: A1:implicit=[A1]*/
 class A1 implements A<C1> {}
 
-/*class: B:direct,explicit=[B.T*],needsArgs*/
+/*class: B:explicit=[B.T*],needsArgs,test*/
 class B<T> {
   @pragma('dart2js:noInline')
   method(var t) => t is T;
diff --git a/pkg/compiler/test/rti/data/generic_instanceof4.dart b/pkg/compiler/test/rti/data/generic_instanceof4.dart
index bfa2a1f..0bcf276 100644
--- a/pkg/compiler/test/rti/data/generic_instanceof4.dart
+++ b/pkg/compiler/test/rti/data/generic_instanceof4.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.7
 
-/*class: A:deps=[B],direct,explicit=[A.T*],needsArgs*/
+/*class: A:deps=[B],explicit=[A.T*],needsArgs,test*/
 class A<T> {
   @pragma('dart2js:noInline')
   foo(x) {
@@ -15,7 +15,7 @@
 /*class: BB:implicit=[BB]*/
 class BB {}
 
-/*class: B:implicit=[B.T],indirect,needsArgs*/
+/*class: B:implicit=[B.T],needsArgs,test*/
 class B<T> implements BB {
   @pragma('dart2js:noInline')
   foo() {
diff --git a/pkg/compiler/test/rti/data/generic_instanceof4_unused.dart b/pkg/compiler/test/rti/data/generic_instanceof4_unused.dart
index ee06e93..5b45da2 100644
--- a/pkg/compiler/test/rti/data/generic_instanceof4_unused.dart
+++ b/pkg/compiler/test/rti/data/generic_instanceof4_unused.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.7
 
-/*class: A:deps=[B],direct,explicit=[A.T*],needsArgs*/
+/*class: A:deps=[B],explicit=[A.T*],needsArgs,test*/
 class A<T> {
   @pragma('dart2js:noInline')
   foo(x) {
@@ -16,7 +16,7 @@
 // computation of implicit is-tests.
 class BB {}
 
-/*class: B:implicit=[B.T],indirect,needsArgs*/
+/*class: B:implicit=[B.T],needsArgs,test*/
 class B<T> implements BB {
   @pragma('dart2js:noInline')
   foo() {
diff --git a/pkg/compiler/test/rti/data/generic_method1.dart b/pkg/compiler/test/rti/data/generic_method1.dart
index f0f6f81..11237ef 100644
--- a/pkg/compiler/test/rti/data/generic_method1.dart
+++ b/pkg/compiler/test/rti/data/generic_method1.dart
@@ -6,7 +6,7 @@
 
 import 'package:compiler/src/util/testing.dart';
 
-/*class: A:deps=[method2],direct,explicit=[A.T*],needsArgs*/
+/*class: A:deps=[method2],explicit=[A.T*],needsArgs,test*/
 class A<T> {
   @pragma('dart2js:noInline')
   foo(x) {
@@ -17,11 +17,11 @@
 /*class: BB:implicit=[BB]*/
 class BB {}
 
-/*member: method2:deps=[B],implicit=[method2.T],indirect,needsArgs*/
+/*member: method2:deps=[B],implicit=[method2.T],needsArgs,test*/
 @pragma('dart2js:noInline')
 method2<T>() => new A<T>();
 
-/*class: B:deps=[method1],implicit=[B.T],indirect,needsArgs*/
+/*class: B:deps=[method1],implicit=[B.T],needsArgs,test*/
 class B<T> implements BB {
   @pragma('dart2js:noInline')
   foo() {
@@ -29,7 +29,7 @@
   }
 }
 
-/*member: method1:implicit=[method1.T],indirect,needsArgs*/
+/*member: method1:implicit=[method1.T],needsArgs,test*/
 @pragma('dart2js:noInline')
 method1<T>() {
   return new B<T>().foo();
diff --git a/pkg/compiler/test/rti/data/generic_method2.dart b/pkg/compiler/test/rti/data/generic_method2.dart
index 9fc5d87..101c7f7 100644
--- a/pkg/compiler/test/rti/data/generic_method2.dart
+++ b/pkg/compiler/test/rti/data/generic_method2.dart
@@ -6,7 +6,7 @@
 
 import 'package:compiler/src/util/testing.dart';
 
-/*class: A:deps=[B],direct,explicit=[A.T*],needsArgs*/
+/*class: A:deps=[B],explicit=[A.T*],needsArgs,test*/
 class A<T> {
   @pragma('dart2js:noInline')
   foo(x) {
@@ -17,7 +17,7 @@
 /*class: BB:implicit=[BB]*/
 class BB {}
 
-/*class: B:deps=[method1],implicit=[B.T],indirect,needsArgs*/
+/*class: B:deps=[method1],implicit=[B.T],needsArgs,test*/
 class B<T> implements BB {
   @pragma('dart2js:noInline')
   foo() {
@@ -25,7 +25,7 @@
   }
 }
 
-/*member: method1:implicit=[method1.T],indirect,needsArgs*/
+/*member: method1:implicit=[method1.T],needsArgs,test*/
 @pragma('dart2js:noInline')
 method1<T>() {
   return new B<T>().foo();
diff --git a/pkg/compiler/test/rti/data/generic_method3.dart b/pkg/compiler/test/rti/data/generic_method3.dart
index 2bc69b6..d2e7916 100644
--- a/pkg/compiler/test/rti/data/generic_method3.dart
+++ b/pkg/compiler/test/rti/data/generic_method3.dart
@@ -6,7 +6,7 @@
 
 import 'package:compiler/src/util/testing.dart';
 
-/*class: A:deps=[method2],direct,explicit=[A.T*],needsArgs*/
+/*class: A:deps=[method2],explicit=[A.T*],needsArgs,test*/
 class A<T> {
   @pragma('dart2js:noInline')
   foo(x) {
@@ -17,11 +17,11 @@
 /*class: BB:implicit=[BB]*/
 class BB {}
 
-/*member: method2:deps=[B],implicit=[method2.T],indirect,needsArgs*/
+/*member: method2:deps=[B],implicit=[method2.T],needsArgs,test*/
 @pragma('dart2js:noInline')
 method2<T>() => new A<T>();
 
-/*class: B:implicit=[B.T],indirect,needsArgs*/
+/*class: B:implicit=[B.T],needsArgs,test*/
 class B<T> implements BB {
   @pragma('dart2js:noInline')
   foo() {
diff --git a/pkg/compiler/test/rti/data/generic_method4.dart b/pkg/compiler/test/rti/data/generic_method4.dart
index d1b48b4..7e1c616 100644
--- a/pkg/compiler/test/rti/data/generic_method4.dart
+++ b/pkg/compiler/test/rti/data/generic_method4.dart
@@ -6,7 +6,7 @@
 
 import 'package:compiler/src/util/testing.dart';
 
-/*class: A:deps=[C.method2],direct,explicit=[A.T*],needsArgs*/
+/*class: A:deps=[C.method2],explicit=[A.T*],needsArgs,test*/
 class A<T> {
   @pragma('dart2js:noInline')
   foo(x) {
@@ -17,7 +17,7 @@
 /*class: BB:implicit=[BB]*/
 class BB {}
 
-/*class: B:deps=[C.method1],implicit=[B.T],indirect,needsArgs*/
+/*class: B:deps=[C.method1],implicit=[B.T],needsArgs,test*/
 class B<T> implements BB {
   @pragma('dart2js:noInline')
   foo(c) {
@@ -26,13 +26,13 @@
 }
 
 class C {
-  /*member: C.method1:implicit=[method1.T],indirect,needsArgs,selectors=[Selector(call, method1, arity=0, types=1)]*/
+  /*member: C.method1:implicit=[method1.T],needsArgs,selectors=[Selector(call, method1, arity=0, types=1)],test*/
   @pragma('dart2js:noInline')
   method1<T>() {
     return new B<T>().foo(this);
   }
 
-  /*member: C.method2:deps=[B],implicit=[method2.T],indirect,needsArgs,selectors=[Selector(call, method2, arity=0, types=1)]*/
+  /*member: C.method2:deps=[B],implicit=[method2.T],needsArgs,selectors=[Selector(call, method2, arity=0, types=1)],test*/
   @pragma('dart2js:noInline')
   method2<T>() => new A<T>();
 }
diff --git a/pkg/compiler/test/rti/data/generic_method_is.dart b/pkg/compiler/test/rti/data/generic_method_is.dart
index 246e40b..19036845 100644
--- a/pkg/compiler/test/rti/data/generic_method_is.dart
+++ b/pkg/compiler/test/rti/data/generic_method_is.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.7
 
-/*member: method:direct,explicit=[method.T*],needsArgs*/
+/*member: method:explicit=[method.T*],needsArgs,test*/
 method<T>(T t) => t is T;
 
 main() {
diff --git a/pkg/compiler/test/rti/data/generic_method_is2.dart b/pkg/compiler/test/rti/data/generic_method_is2.dart
index 9505896..e67767e 100644
--- a/pkg/compiler/test/rti/data/generic_method_is2.dart
+++ b/pkg/compiler/test/rti/data/generic_method_is2.dart
@@ -47,36 +47,36 @@
 class F3 {}
 
 // Calls to this imply a check of the passed type arguments.
-/*member: topLevelMethod1:direct,explicit=[topLevelMethod1.T*],needsArgs,selectors=[Selector(call, call, arity=2, named=[a1], types=1)]*/
+/*member: topLevelMethod1:explicit=[topLevelMethod1.T*],needsArgs,selectors=[Selector(call, call, arity=2, named=[a1], types=1)],test*/
 bool topLevelMethod1<T>(T t, {a1}) => t is T;
 
 // Calls to this does _not_ imply a check of the passed type arguments.
-/*spec.member: topLevelMethod2:direct,explicit=[topLevelMethod2.T*],needsArgs,selectors=[Selector(call, call, arity=2, named=[a2], types=1)]*/
+/*spec.member: topLevelMethod2:explicit=[topLevelMethod2.T*],needsArgs,selectors=[Selector(call, call, arity=2, named=[a2], types=1)],test*/
 T topLevelMethod2<T>(T t, {a2}) => t;
 
 class Class {
   // Calls to this imply a check of the passed type arguments.
-  /*member: Class.instanceMethod1:direct,explicit=[instanceMethod1.S*],needsArgs,selectors=[Selector(call, call, arity=2, named=[b1], types=1),Selector(call, instanceMethod1, arity=2, named=[b1], types=1)]*/
+  /*member: Class.instanceMethod1:explicit=[instanceMethod1.S*],needsArgs,selectors=[Selector(call, call, arity=2, named=[b1], types=1),Selector(call, instanceMethod1, arity=2, named=[b1], types=1)],test*/
   bool instanceMethod1<S>(S s, {b1}) => s is S;
 
   // Calls to this does _not_ imply a check of the passed type arguments.
-  /*spec.member: Class.instanceMethod2:direct,explicit=[instanceMethod2.S*],needsArgs,selectors=[Selector(call, call, arity=2, named=[b2], types=1),Selector(call, instanceMethod2, arity=2, named=[b2], types=1)]*/
+  /*spec.member: Class.instanceMethod2:explicit=[instanceMethod2.S*],needsArgs,selectors=[Selector(call, call, arity=2, named=[b2], types=1),Selector(call, instanceMethod2, arity=2, named=[b2], types=1)],test*/
   S instanceMethod2<S>(S s, {b2}) => s;
 }
 
 main() {
   // Calls to this imply a check of the passed type arguments.
-  /*direct,explicit=[localFunction1.U*],needsArgs,selectors=[Selector(call, call, arity=2, named=[c1], types=1)]*/
+  /*explicit=[localFunction1.U*],needsArgs,selectors=[Selector(call, call, arity=2, named=[c1], types=1)],test*/
   bool localFunction1<U>(U u, {c1}) => u is U;
 
   // Calls to this does _not_ imply a check of the passed type arguments.
-  /*spec.direct,explicit=[localFunction2.U*],needsArgs,selectors=[Selector(call, call, arity=2, named=[c2], types=1)]*/
+  /*spec.explicit=[localFunction2.U*],needsArgs,selectors=[Selector(call, call, arity=2, named=[c2], types=1)],test*/
   U localFunction2<U>(U u, {c2}) => u;
 
   // Calls to this does _not_ imply a check of the passed type arguments. A
   // call to the .call function on this will, though, since it has the same
   // signature as [localFunction1] which needs its type arguments.
-  /*spec.direct,explicit=[localFunction3.U*],needsArgs,selectors=[Selector(call, call, arity=2, named=[c1], types=1)]*/
+  /*spec.explicit=[localFunction3.U*],needsArgs,selectors=[Selector(call, call, arity=2, named=[c1], types=1)],test*/
   localFunction3<U>(U u, {c1}) => u;
 
   var c = new Class();
diff --git a/pkg/compiler/test/rti/data/generic_methods_dynamic_05.dart b/pkg/compiler/test/rti/data/generic_methods_dynamic_05.dart
index 051894e..17bb4da 100644
--- a/pkg/compiler/test/rti/data/generic_methods_dynamic_05.dart
+++ b/pkg/compiler/test/rti/data/generic_methods_dynamic_05.dart
@@ -8,9 +8,9 @@
 
 // Test derived from language_2/generic_methods_dynamic_test/05
 
-/*spec.class: global#JSArray:deps=[ArrayIterator,List],explicit=[JSArray,JSArray.E,JSArray<ArrayIterator.E>],implicit=[JSArray.E],indirect,needsArgs*/
+/*spec.class: global#JSArray:deps=[ArrayIterator,List],explicit=[JSArray,JSArray.E,JSArray<ArrayIterator.E>],implicit=[JSArray.E],needsArgs,test*/
 /*prod.class: global#JSArray:deps=[List],needsArgs*/
-/*spec.class: global#List:deps=[C.bar,JSArray.markFixedList],explicit=[List,List<B*>*,List<Object>,List<String>?,List<markFixedList.T>],indirect,needsArgs*/
+/*spec.class: global#List:deps=[C.bar,JSArray.markFixedList],explicit=[List,List<B*>*,List<Object>,List<String>?,List<markFixedList.T>],needsArgs,test*/
 /*prod.class: global#List:deps=[C.bar],explicit=[List<B*>*],needsArgs*/
 
 class A {}
@@ -20,7 +20,7 @@
 class B {}
 
 class C {
-  /*spec.member: C.bar:direct,explicit=[Iterable<bar.T*>*],implicit=[bar.T],needsArgs,selectors=[Selector(call, bar, arity=1, types=1)]*/
+  /*spec.member: C.bar:explicit=[Iterable<bar.T*>*],implicit=[bar.T],needsArgs,selectors=[Selector(call, bar, arity=1, types=1)],test*/
   /*prod.member: C.bar:needsArgs,selectors=[Selector(call, bar, arity=1, types=1)]*/
   List<T> bar<T>(Iterable<T> t) => <T>[t.first];
 }
diff --git a/pkg/compiler/test/rti/data/generic_methods_dynamic_05a.dart b/pkg/compiler/test/rti/data/generic_methods_dynamic_05a.dart
index 3226063..7c759ee 100644
--- a/pkg/compiler/test/rti/data/generic_methods_dynamic_05a.dart
+++ b/pkg/compiler/test/rti/data/generic_methods_dynamic_05a.dart
@@ -8,7 +8,7 @@
 
 // Reduced version of generic_methods_dynamic_05a_strong.
 
-/*spec.class: A:deps=[C.bar],direct,explicit=[A.T*,A<B*>*,A<bar.T*>*],needsArgs*/
+/*spec.class: A:deps=[C.bar],explicit=[A.T*,A<B*>*,A<bar.T*>*],needsArgs,test*/
 /*prod.class: A:deps=[C.bar],explicit=[A<B*>*],needsArgs*/
 class A<T> {
   final T field;
@@ -21,7 +21,7 @@
 class B {}
 
 class C {
-  /*spec.member: C.bar:explicit=[A<bar.T*>*],implicit=[bar.T],indirect,needsArgs,selectors=[Selector(call, bar, arity=1, types=1)]*/
+  /*spec.member: C.bar:explicit=[A<bar.T*>*],implicit=[bar.T],needsArgs,selectors=[Selector(call, bar, arity=1, types=1)],test*/
   /*prod.member: C.bar:needsArgs,selectors=[Selector(call, bar, arity=1, types=1)]*/
   A<T> bar<T>(A<T> t) => new A<T>(t.field);
 }
diff --git a/pkg/compiler/test/rti/data/implicit_as.dart b/pkg/compiler/test/rti/data/implicit_as.dart
index ddf0046..0c78cd3 100644
--- a/pkg/compiler/test/rti/data/implicit_as.dart
+++ b/pkg/compiler/test/rti/data/implicit_as.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.7
 
-/*spec.class: C:direct,explicit=[C.T*,C<String*>*],needsArgs*/
+/*spec.class: C:explicit=[C.T*,C<String*>*],needsArgs,test*/
 class C<T> {
   T field;
 }
diff --git a/pkg/compiler/test/rti/data/indirect_through_static.dart b/pkg/compiler/test/rti/data/indirect_through_static.dart
index 2b5b0be..9c7ffc5 100644
--- a/pkg/compiler/test/rti/data/indirect_through_static.dart
+++ b/pkg/compiler/test/rti/data/indirect_through_static.dart
@@ -19,7 +19,7 @@
   map['x'] = new C<B>();
 }
 
-/*member: lookup:direct,explicit=[C<lookup.T*>*],needsArgs*/
+/*member: lookup:explicit=[C<lookup.T*>*],needsArgs,test*/
 C<T> lookup<T>(String key) {
   final value = map[key];
   if (value != null && value is C<T>) {
diff --git a/pkg/compiler/test/rti/data/instantiation1.dart b/pkg/compiler/test/rti/data/instantiation1.dart
index 0ea6b96..6033cf6 100644
--- a/pkg/compiler/test/rti/data/instantiation1.dart
+++ b/pkg/compiler/test/rti/data/instantiation1.dart
@@ -4,13 +4,13 @@
 
 // @dart = 2.7
 
-/*spec.member: f:deps=[B],direct,explicit=[f.T*],needsArgs,needsInst=[<B.S*>]*/
+/*spec.member: f:deps=[B],explicit=[f.T*],needsArgs,needsInst=[<B.S*>],test*/
 /*prod.member: f:deps=[B]*/
 int f<T>(T a) => null;
 
 typedef int F<R>(R a);
 
-/*spec.class: B:explicit=[int* Function(B.S*)*],implicit=[B.S],indirect,needsArgs*/
+/*spec.class: B:explicit=[int* Function(B.S*)*],implicit=[B.S],needsArgs,test*/
 /*prod.class: B:needsArgs*/
 class B<S> {
   F<S> c;
diff --git a/pkg/compiler/test/rti/data/instantiation2.dart b/pkg/compiler/test/rti/data/instantiation2.dart
index 934152a..ef67348 100644
--- a/pkg/compiler/test/rti/data/instantiation2.dart
+++ b/pkg/compiler/test/rti/data/instantiation2.dart
@@ -4,13 +4,13 @@
 
 // @dart = 2.7
 
-/*member: f:deps=[B],direct,explicit=[f.T*],needsArgs,needsInst=[<B.S*>]*/
+/*member: f:deps=[B],explicit=[f.T*],needsArgs,needsInst=[<B.S*>],test*/
 bool f<T>(T a) => a is T;
 
 typedef bool F<R>(R a);
 
-/*spec.class: B:explicit=[bool* Function(B.S*)*],implicit=[B.S],indirect,needsArgs*/
-/*prod.class: B:implicit=[B.S],indirect,needsArgs*/
+/*spec.class: B:explicit=[bool* Function(B.S*)*],implicit=[B.S],needsArgs,test*/
+/*prod.class: B:implicit=[B.S],needsArgs,test*/
 class B<S> {
   F<S> c;
 
diff --git a/pkg/compiler/test/rti/data/instantiation3.dart b/pkg/compiler/test/rti/data/instantiation3.dart
index 4c13f62..5712524 100644
--- a/pkg/compiler/test/rti/data/instantiation3.dart
+++ b/pkg/compiler/test/rti/data/instantiation3.dart
@@ -4,13 +4,13 @@
 
 // @dart = 2.7
 
-/*spec.member: f:deps=[B],direct,explicit=[f.T*],needsArgs,needsInst=[<B.S*>]*/
+/*spec.member: f:deps=[B],explicit=[f.T*],needsArgs,needsInst=[<B.S*>],test*/
 /*prod.member: f:deps=[B]*/
 int f<T>(T a) => null;
 
 typedef int F<R>(R a);
 
-/*spec.class: B:direct,explicit=[int* Function(B.S*)*],implicit=[B.S],needsArgs*/
+/*spec.class: B:explicit=[int* Function(B.S*)*],implicit=[B.S],needsArgs,test*/
 /*prod.class: B:needsArgs*/
 class B<S> {
   F<S> c;
diff --git a/pkg/compiler/test/rti/data/instantiation4.dart b/pkg/compiler/test/rti/data/instantiation4.dart
index af33f43..9f92b96 100644
--- a/pkg/compiler/test/rti/data/instantiation4.dart
+++ b/pkg/compiler/test/rti/data/instantiation4.dart
@@ -4,13 +4,13 @@
 
 // @dart = 2.7
 
-/*member: f:deps=[B],direct,explicit=[f.T*],needsArgs,needsInst=[<B.S*>]*/
+/*member: f:deps=[B],explicit=[f.T*],needsArgs,needsInst=[<B.S*>],test*/
 bool f<T>(T a) => a is T;
 
 typedef bool F<R>(R a);
 
-/*spec.class: B:direct,explicit=[bool* Function(B.S*)*],implicit=[B.S],needsArgs*/
-/*prod.class: B:implicit=[B.S],indirect,needsArgs*/
+/*spec.class: B:explicit=[bool* Function(B.S*)*],implicit=[B.S],needsArgs,test*/
+/*prod.class: B:implicit=[B.S],needsArgs,test*/
 class B<S> {
   F<S> c;
 
diff --git a/pkg/compiler/test/rti/data/instantiation5.dart b/pkg/compiler/test/rti/data/instantiation5.dart
index 3c37996..855d5ab 100644
--- a/pkg/compiler/test/rti/data/instantiation5.dart
+++ b/pkg/compiler/test/rti/data/instantiation5.dart
@@ -4,13 +4,13 @@
 
 // @dart = 2.7
 
-/*spec.member: f:deps=[method],direct,explicit=[f.T*],needsArgs,needsInst=[<method.S*>]*/
+/*spec.member: f:deps=[method],explicit=[f.T*],needsArgs,needsInst=[<method.S*>],test*/
 /*prod.member: f:deps=[method]*/
 int f<T>(T a) => null;
 
 typedef int F<R>(R a);
 
-/*spec.member: method:implicit=[method.S],indirect,needsArgs*/
+/*spec.member: method:implicit=[method.S],needsArgs,test*/
 /*prod.member: method:needsArgs*/
 method<S>() {
   F<S> c;
diff --git a/pkg/compiler/test/rti/data/instantiation6.dart b/pkg/compiler/test/rti/data/instantiation6.dart
index e596af2..d235bca 100644
--- a/pkg/compiler/test/rti/data/instantiation6.dart
+++ b/pkg/compiler/test/rti/data/instantiation6.dart
@@ -4,12 +4,12 @@
 
 // @dart = 2.7
 
-/*member: f:deps=[method],direct,explicit=[f.T*],needsArgs,needsInst=[<method.S*>]*/
+/*member: f:deps=[method],explicit=[f.T*],needsArgs,needsInst=[<method.S*>],test*/
 bool f<T>(T a) => a is T;
 
 typedef bool F<R>(R a);
 
-/*member: method:implicit=[method.S],indirect,needsArgs*/
+/*member: method:implicit=[method.S],needsArgs,test*/
 method<S>() {
   F<S> c;
 
diff --git a/pkg/compiler/test/rti/data/instantiation7.dart b/pkg/compiler/test/rti/data/instantiation7.dart
index 216c83d..5a09574 100644
--- a/pkg/compiler/test/rti/data/instantiation7.dart
+++ b/pkg/compiler/test/rti/data/instantiation7.dart
@@ -4,15 +4,15 @@
 
 // @dart = 2.7
 
-/*spec.member: f1:deps=[method],direct,explicit=[f1.T*],needsArgs,needsInst=[<method.X*>]*/
+/*spec.member: f1:deps=[method],explicit=[f1.T*],needsArgs,needsInst=[<method.X*>],test*/
 /*prod.member: f1:deps=[method]*/
 int f1<T>(T a, T b, T c) => null;
 
-/*spec.member: f2:deps=[method],direct,explicit=[f2.S*,f2.T*],needsArgs,needsInst=[<method.X*,method.Y*>]*/
+/*spec.member: f2:deps=[method],explicit=[f2.S*,f2.T*],needsArgs,needsInst=[<method.X*,method.Y*>],test*/
 /*prod.member: f2:deps=[method]*/
 int f2<T, S>(T a, S b, S c) => null;
 
-/*spec.member: f3:deps=[method],direct,explicit=[f3.S*,f3.T*,f3.U*],needsArgs,needsInst=[<method.X*,method.Y*,method.Z*>]*/
+/*spec.member: f3:deps=[method],explicit=[f3.S*,f3.T*,f3.U*],needsArgs,needsInst=[<method.X*,method.Y*,method.Z*>],test*/
 /*prod.member: f3:deps=[method]*/
 int f3<T, S, U>(T a, S b, U c) => null;
 
@@ -20,7 +20,7 @@
 typedef int F2<R, P>(R a, P b, P c);
 typedef int F3<R, P, Q>(R a, P b, Q c);
 
-/*spec.member: method:implicit=[method.X,method.Y,method.Z],indirect,needsArgs*/
+/*spec.member: method:implicit=[method.X,method.Y,method.Z],needsArgs,test*/
 /*prod.member: method:needsArgs*/
 method<X, Y, Z>() {
   F1<X> c1;
diff --git a/pkg/compiler/test/rti/data/is_type_variable.dart b/pkg/compiler/test/rti/data/is_type_variable.dart
index b188421..96d76ef 100644
--- a/pkg/compiler/test/rti/data/is_type_variable.dart
+++ b/pkg/compiler/test/rti/data/is_type_variable.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.7
 
-/*class: A:direct,explicit=[A.T*],needsArgs*/
+/*class: A:explicit=[A.T*],needsArgs,test*/
 class A<T> {
   m(T t) => t is T;
 }
diff --git a/pkg/compiler/test/rti/data/is_type_variable_super.dart b/pkg/compiler/test/rti/data/is_type_variable_super.dart
index 286e73b..65c7bae 100644
--- a/pkg/compiler/test/rti/data/is_type_variable_super.dart
+++ b/pkg/compiler/test/rti/data/is_type_variable_super.dart
@@ -6,7 +6,7 @@
 
 class A<T> {}
 
-/*class: B:direct,explicit=[B.T*],needsArgs*/
+/*class: B:explicit=[B.T*],needsArgs,test*/
 class B<T> extends A<T> {
   m(T t) => t is T;
 }
diff --git a/pkg/compiler/test/rti/data/is_type_variable_super_complex.dart b/pkg/compiler/test/rti/data/is_type_variable_super_complex.dart
index d512bd1..18f00af 100644
--- a/pkg/compiler/test/rti/data/is_type_variable_super_complex.dart
+++ b/pkg/compiler/test/rti/data/is_type_variable_super_complex.dart
@@ -6,7 +6,7 @@
 
 class A<T> {}
 
-/*class: B:direct,explicit=[B.T*],needsArgs*/
+/*class: B:explicit=[B.T*],needsArgs,test*/
 class B<T> extends A<List<T>> {
   m(T t) => t is T;
 }
diff --git a/pkg/compiler/test/rti/data/list_literal.dart b/pkg/compiler/test/rti/data/list_literal.dart
index c4f9b47..c76451d 100644
--- a/pkg/compiler/test/rti/data/list_literal.dart
+++ b/pkg/compiler/test/rti/data/list_literal.dart
@@ -4,11 +4,11 @@
 
 // @dart = 2.7
 
-/*spec.class: global#List:deps=[Class.m,JSArray.markFixedList],explicit=[List,List<Object>,List<String>?,List<markFixedList.T>],indirect,needsArgs*/
-/*prod.class: global#List:deps=[Class.m],indirect,needsArgs*/
+/*spec.class: global#List:deps=[Class.m,JSArray.markFixedList],explicit=[List,List<Object>,List<String>?,List<markFixedList.T>],needsArgs,test*/
+/*prod.class: global#List:deps=[Class.m],needsArgs,test*/
 
-/*spec.class: global#JSArray:deps=[ArrayIterator,List],explicit=[JSArray,JSArray.E,JSArray<ArrayIterator.E>],implicit=[JSArray.E],indirect,needsArgs*/
-/*prod.class: global#JSArray:deps=[List],implicit=[JSArray.E],indirect,needsArgs*/
+/*spec.class: global#JSArray:deps=[ArrayIterator,List],explicit=[JSArray,JSArray.E,JSArray<ArrayIterator.E>],implicit=[JSArray.E],needsArgs,test*/
+/*prod.class: global#JSArray:deps=[List],implicit=[JSArray.E],needsArgs,test*/
 
 main() {
   var c = new Class();
@@ -18,7 +18,7 @@
 }
 
 class Class {
-  /*member: Class.m:implicit=[m.T],indirect,needsArgs,selectors=[Selector(call, m, arity=0, types=1)]*/
+  /*member: Class.m:implicit=[m.T],needsArgs,selectors=[Selector(call, m, arity=0, types=1)],test*/
   m<T>() {
     return <T>[];
   }
diff --git a/pkg/compiler/test/rti/data/list_to_set.dart b/pkg/compiler/test/rti/data/list_to_set.dart
index 63884f8..c73b735 100644
--- a/pkg/compiler/test/rti/data/list_to_set.dart
+++ b/pkg/compiler/test/rti/data/list_to_set.dart
@@ -4,11 +4,11 @@
 
 // @dart = 2.7
 
-/*spec.class: global#List:deps=[Class,JSArray.markFixedList],explicit=[List,List<Object>,List<String>?,List<markFixedList.T>],indirect,needsArgs*/
-/*prod.class: global#List:deps=[Class],indirect,needsArgs*/
+/*spec.class: global#List:deps=[Class,JSArray.markFixedList],explicit=[List,List<Object>,List<String>?,List<markFixedList.T>],needsArgs,test*/
+/*prod.class: global#List:deps=[Class],needsArgs,test*/
 
-/*spec.class: global#JSArray:deps=[ArrayIterator,List],explicit=[JSArray,JSArray.E,JSArray<ArrayIterator.E>],implicit=[JSArray.E],indirect,needsArgs*/
-/*prod.class: global#JSArray:deps=[List],implicit=[JSArray.E],indirect,needsArgs*/
+/*spec.class: global#JSArray:deps=[ArrayIterator,List],explicit=[JSArray,JSArray.E,JSArray<ArrayIterator.E>],implicit=[JSArray.E],needsArgs,test*/
+/*prod.class: global#JSArray:deps=[List],implicit=[JSArray.E],needsArgs,test*/
 
 main() {
   var c = new Class<int>();
@@ -17,7 +17,7 @@
   set is Set<String>;
 }
 
-/*class: Class:implicit=[Class.T],indirect,needsArgs*/
+/*class: Class:implicit=[Class.T],needsArgs,test*/
 class Class<T> {
   m() {
     return <T>[];
diff --git a/pkg/compiler/test/rti/data/local_function_generic.dart b/pkg/compiler/test/rti/data/local_function_generic.dart
index 80892aa..861d030 100644
--- a/pkg/compiler/test/rti/data/local_function_generic.dart
+++ b/pkg/compiler/test/rti/data/local_function_generic.dart
@@ -7,7 +7,7 @@
 import 'package:compiler/src/util/testing.dart';
 
 method1() {
-  /*spec.direct,explicit=[local.T*],needsArgs,needsSignature*/
+  /*spec.explicit=[local.T*],needsArgs,needsSignature,test*/
   /*prod.needsArgs,needsSignature*/
   T local<T>(T t) => t;
   return local;
diff --git a/pkg/compiler/test/rti/data/local_function_list_literal.dart b/pkg/compiler/test/rti/data/local_function_list_literal.dart
index 3de5b69..0af6116 100644
--- a/pkg/compiler/test/rti/data/local_function_list_literal.dart
+++ b/pkg/compiler/test/rti/data/local_function_list_literal.dart
@@ -6,11 +6,11 @@
 
 import 'package:compiler/src/util/testing.dart';
 
-/*spec.class: global#JSArray:deps=[ArrayIterator,List],explicit=[JSArray,JSArray.E,JSArray<ArrayIterator.E>],implicit=[JSArray.E],indirect,needsArgs*/
+/*spec.class: global#JSArray:deps=[ArrayIterator,List],explicit=[JSArray,JSArray.E,JSArray<ArrayIterator.E>],implicit=[JSArray.E],needsArgs,test*/
 /*prod.class: global#JSArray:deps=[List],needsArgs*/
 
 @pragma('dart2js:noInline')
-/*spec.member: method:implicit=[method.T],indirect,needsArgs*/
+/*spec.member: method:implicit=[method.T],needsArgs,test*/
 /*prod.member: method:needsArgs*/
 method<T>() {
   return /*spec.*/ () => <T>[];
diff --git a/pkg/compiler/test/rti/data/local_function_map_literal.dart b/pkg/compiler/test/rti/data/local_function_map_literal.dart
index a0dca5f..7130d69 100644
--- a/pkg/compiler/test/rti/data/local_function_map_literal.dart
+++ b/pkg/compiler/test/rti/data/local_function_map_literal.dart
@@ -6,11 +6,11 @@
 
 import 'package:compiler/src/util/testing.dart';
 
-/*spec.class: global#LinkedHashMap:deps=[Map],direct,explicit=[LinkedHashMap<LinkedHashMap.K,LinkedHashMap.V>],implicit=[LinkedHashMap.K,LinkedHashMap.V],needsArgs*/
+/*spec.class: global#LinkedHashMap:deps=[Map],explicit=[LinkedHashMap<LinkedHashMap.K,LinkedHashMap.V>],implicit=[LinkedHashMap.K,LinkedHashMap.V],needsArgs,test*/
 /*prod.class: global#LinkedHashMap:deps=[Map],needsArgs*/
 
 @pragma('dart2js:noInline')
-/*spec.member: method:implicit=[method.T],indirect,needsArgs*/
+/*spec.member: method:implicit=[method.T],needsArgs,test*/
 /*prod.member: method:needsArgs*/
 method<T>() {
   return /*spec.needsSignature*/ () => <T, int>{};
diff --git a/pkg/compiler/test/rti/data/local_function_signature2.dart b/pkg/compiler/test/rti/data/local_function_signature2.dart
index 06bcb64..1d06d37 100644
--- a/pkg/compiler/test/rti/data/local_function_signature2.dart
+++ b/pkg/compiler/test/rti/data/local_function_signature2.dart
@@ -24,7 +24,7 @@
 }
 
 class Class2 {
-  /*spec.member: Class2.method4:direct,explicit=[method4.T*],needsArgs,selectors=[Selector(call, method4, arity=0, types=1)]*/
+  /*spec.member: Class2.method4:explicit=[method4.T*],needsArgs,selectors=[Selector(call, method4, arity=0, types=1)],test*/
   /*prod.member: Class2.method4:needsArgs,selectors=[Selector(call, method4, arity=0, types=1)]*/
   method4<T>() {
     /*needsSignature*/
@@ -44,14 +44,14 @@
 
 class Class4 {
   /*prod.member: Class4.method6:needsArgs,selectors=[Selector(call, method6, arity=0, types=1)]*/
-  /*spec.member: Class4.method6:direct,explicit=[method6.T*],needsArgs,selectors=[Selector(call, method6, arity=0, types=1)]*/
+  /*spec.member: Class4.method6:explicit=[method6.T*],needsArgs,selectors=[Selector(call, method6, arity=0, types=1)],test*/
   method6<T>() {
     /*needsSignature*/ num local(num n, T t) => null;
     return local;
   }
 }
 
-/*spec.member: method7:direct,explicit=[method7.T*],needsArgs*/
+/*spec.member: method7:explicit=[method7.T*],needsArgs,test*/
 /*prod.member: method7:needsArgs*/
 method7<T>() {
   /*needsSignature*/
@@ -66,7 +66,7 @@
   return local;
 }
 
-/*spec.member: method9:direct,explicit=[method9.T*],needsArgs*/
+/*spec.member: method9:explicit=[method9.T*],needsArgs,test*/
 /*prod.member: method9:needsArgs*/
 method9<T>() {
   /*needsSignature*/ num local(num n, T t) => null;
@@ -74,7 +74,7 @@
 }
 
 method10() {
-  /*spec.direct,explicit=[local.T*],needsArgs,needsSignature*/
+  /*spec.explicit=[local.T*],needsArgs,needsSignature,test*/
   /*prod.needsArgs,needsSignature*/ num local<T>(T n) => null;
   return local;
 }
@@ -85,7 +85,7 @@
 }
 
 method12() {
-  /*spec.direct,explicit=[local.T*],needsArgs,needsSignature*/
+  /*spec.explicit=[local.T*],needsArgs,needsSignature,test*/
   /*prod.needsArgs,needsSignature*/ num local<T>(num n, T t) => null;
   return local;
 }
diff --git a/pkg/compiler/test/rti/data/local_function_signatures.dart b/pkg/compiler/test/rti/data/local_function_signatures.dart
index ad97152..cacf62d 100644
--- a/pkg/compiler/test/rti/data/local_function_signatures.dart
+++ b/pkg/compiler/test/rti/data/local_function_signatures.dart
@@ -24,7 +24,7 @@
   }
 }
 
-/*spec.class: Class2:direct,explicit=[Class2.T*],needsArgs*/
+/*spec.class: Class2:explicit=[Class2.T*],needsArgs,test*/
 /*prod.class: Class2:needsArgs*/
 class Class2<T> {
   method4() {
@@ -43,7 +43,7 @@
   }
 }
 
-/*spec.class: Class4:direct,explicit=[Class4.T*],needsArgs*/
+/*spec.class: Class4:explicit=[Class4.T*],needsArgs,test*/
 /*prod.class: Class4:needsArgs*/
 class Class4<T> {
   method6() {
diff --git a/pkg/compiler/test/rti/data/local_function_signatures_generic.dart b/pkg/compiler/test/rti/data/local_function_signatures_generic.dart
index fa0d44f..8f651f6 100644
--- a/pkg/compiler/test/rti/data/local_function_signatures_generic.dart
+++ b/pkg/compiler/test/rti/data/local_function_signatures_generic.dart
@@ -27,7 +27,7 @@
 }
 
 class Class2 {
-  /*spec.member: Class2.method4:direct,explicit=[method4.T*],needsArgs,selectors=[Selector(call, method4, arity=0, types=1)]*/
+  /*spec.member: Class2.method4:explicit=[method4.T*],needsArgs,selectors=[Selector(call, method4, arity=0, types=1)],test*/
   /*prod.member: Class2.method4:needsArgs,selectors=[Selector(call, method4, arity=0, types=1)]*/
   method4<T>() {
     /*needsSignature*/
@@ -47,14 +47,14 @@
 
 class Class4 {
   /*prod.member: Class4.method6:needsArgs,selectors=[Selector(call, method6, arity=0, types=1)]*/
-  /*spec.member: Class4.method6:direct,explicit=[method6.T*],needsArgs,selectors=[Selector(call, method6, arity=0, types=1)]*/
+  /*spec.member: Class4.method6:explicit=[method6.T*],needsArgs,selectors=[Selector(call, method6, arity=0, types=1)],test*/
   method6<T>() {
     /*needsSignature*/ num local(num n, T t) => null;
     return local;
   }
 }
 
-/*spec.member: method7:direct,explicit=[method7.T*],needsArgs*/
+/*spec.member: method7:explicit=[method7.T*],needsArgs,test*/
 /*prod.member: method7:needsArgs*/
 method7<T>() {
   /*needsSignature*/
@@ -69,7 +69,7 @@
   return local;
 }
 
-/*spec.member: method9:direct,explicit=[method9.T*],needsArgs*/
+/*spec.member: method9:explicit=[method9.T*],needsArgs,test*/
 /*prod.member: method9:needsArgs*/
 method9<T>() {
   /*needsSignature*/ num local(num n, T t) => null;
@@ -77,7 +77,7 @@
 }
 
 method10() {
-  /*spec.direct,explicit=[local.T*],needsArgs,needsInst=[<dynamic>,<num*>,<num*>],needsSignature*/
+  /*spec.explicit=[local.T*],needsArgs,needsInst=[<dynamic>,<num*>,<num*>],needsSignature,test*/
   /*prod.needsArgs,needsInst=[<dynamic>,<num*>,<num*>],needsSignature*/
   num local<T>(T n) => null;
   return local;
@@ -90,7 +90,7 @@
 }
 
 method12() {
-  /*spec.direct,explicit=[local.T*],needsArgs,needsSignature*/
+  /*spec.explicit=[local.T*],needsArgs,needsSignature,test*/
   /*prod.needsArgs,needsSignature*/ num local<T>(num n, T t) => null;
   return local;
 }
@@ -102,7 +102,7 @@
 }
 
 num Function(num) method14() {
-  /*spec.direct,explicit=[local.T*],needsArgs,needsInst=[<dynamic>,<num*>,<num*>],needsSignature*/
+  /*spec.explicit=[local.T*],needsArgs,needsInst=[<dynamic>,<num*>,<num*>],needsSignature,test*/
   /*prod.needsArgs,needsInst=[<dynamic>,<num*>,<num*>],needsSignature*/
   num local<T>(T n) => null;
   return local;
diff --git a/pkg/compiler/test/rti/data/map_literal.dart b/pkg/compiler/test/rti/data/map_literal.dart
index 988f06e..60568fd 100644
--- a/pkg/compiler/test/rti/data/map_literal.dart
+++ b/pkg/compiler/test/rti/data/map_literal.dart
@@ -5,13 +5,13 @@
 // @dart = 2.7
 
 /*prod.class: global#Map:*/
-/*spec.class: global#Map:explicit=[Map,Map<Object?,Object?>],indirect,needsArgs*/
+/*spec.class: global#Map:explicit=[Map,Map<Object?,Object?>],needsArgs,test*/
 
 /*prod.class: global#LinkedHashMap:deps=[Map]*/
-/*spec.class: global#LinkedHashMap:deps=[Map],direct,explicit=[LinkedHashMap<LinkedHashMap.K,LinkedHashMap.V>],implicit=[LinkedHashMap.K,LinkedHashMap.V],needsArgs*/
+/*spec.class: global#LinkedHashMap:deps=[Map],explicit=[LinkedHashMap<LinkedHashMap.K,LinkedHashMap.V>],implicit=[LinkedHashMap.K,LinkedHashMap.V],needsArgs,test*/
 
 /*prod.class: global#JsLinkedHashMap:deps=[LinkedHashMap]*/
-/*spec.class: global#JsLinkedHashMap:deps=[LinkedHashMap],direct,explicit=[JsLinkedHashMap,JsLinkedHashMap.K,JsLinkedHashMap.V,void Function(JsLinkedHashMap.K,JsLinkedHashMap.V)],implicit=[JsLinkedHashMap.K],needsArgs*/
+/*spec.class: global#JsLinkedHashMap:deps=[LinkedHashMap],explicit=[JsLinkedHashMap,JsLinkedHashMap.K,JsLinkedHashMap.V,void Function(JsLinkedHashMap.K,JsLinkedHashMap.V)],implicit=[JsLinkedHashMap.K],needsArgs,test*/
 
 /*prod.class: global#double:*/
 /*spec.class: global#double:implicit=[double]*/
diff --git a/pkg/compiler/test/rti/data/map_to_set.dart b/pkg/compiler/test/rti/data/map_to_set.dart
index 4c870c3..33c2194 100644
--- a/pkg/compiler/test/rti/data/map_to_set.dart
+++ b/pkg/compiler/test/rti/data/map_to_set.dart
@@ -5,13 +5,13 @@
 // @dart = 2.7
 
 /*prod.class: global#Map:deps=[Class],needsArgs*/
-/*spec.class: global#Map:deps=[Class],explicit=[Map,Map<Object?,Object?>],indirect,needsArgs*/
+/*spec.class: global#Map:deps=[Class],explicit=[Map,Map<Object?,Object?>],needsArgs,test*/
 
 /*prod.class: global#LinkedHashMap:deps=[Map],implicit=[LinkedHashMap.K],needsArgs*/
-/*spec.class: global#LinkedHashMap:deps=[Map],direct,explicit=[LinkedHashMap<LinkedHashMap.K,LinkedHashMap.V>],implicit=[LinkedHashMap.K,LinkedHashMap.V],needsArgs*/
+/*spec.class: global#LinkedHashMap:deps=[Map],explicit=[LinkedHashMap<LinkedHashMap.K,LinkedHashMap.V>],implicit=[LinkedHashMap.K,LinkedHashMap.V],needsArgs,test*/
 
 /*prod.class: global#JsLinkedHashMap:deps=[LinkedHashMap],implicit=[JsLinkedHashMap.K],needsArgs*/
-/*spec.class: global#JsLinkedHashMap:deps=[LinkedHashMap],direct,explicit=[JsLinkedHashMap,JsLinkedHashMap.K,JsLinkedHashMap.V,void Function(JsLinkedHashMap.K,JsLinkedHashMap.V)],implicit=[JsLinkedHashMap.K],needsArgs*/
+/*spec.class: global#JsLinkedHashMap:deps=[LinkedHashMap],explicit=[JsLinkedHashMap,JsLinkedHashMap.K,JsLinkedHashMap.V,void Function(JsLinkedHashMap.K,JsLinkedHashMap.V)],implicit=[JsLinkedHashMap.K],needsArgs,test*/
 
 /*prod.class: global#double:*/
 /*spec.class: global#double:implicit=[double]*/
@@ -25,7 +25,7 @@
   set is Set<String>;
 }
 
-/*spec.class: Class:implicit=[Class.S,Class.T],indirect,needsArgs*/
+/*spec.class: Class:implicit=[Class.S,Class.T],needsArgs,test*/
 /*prod.class: Class:needsArgs*/
 class Class<T, S> {
   m() {
diff --git a/pkg/compiler/test/rti/data/method_signatures.dart b/pkg/compiler/test/rti/data/method_signatures.dart
index 93ab6d2..29baa2f 100644
--- a/pkg/compiler/test/rti/data/method_signatures.dart
+++ b/pkg/compiler/test/rti/data/method_signatures.dart
@@ -17,7 +17,7 @@
   Object method3(num n) => null;
 }
 
-/*spec.class: Class2:direct,explicit=[Class2.T*],needsArgs*/
+/*spec.class: Class2:explicit=[Class2.T*],needsArgs,test*/
 class Class2<T> {
   num method4(T n) => null;
 }
@@ -28,7 +28,7 @@
   T method5(num n) => null;
 }
 
-/*spec.class: Class4:direct,explicit=[Class4.T*],needsArgs*/
+/*spec.class: Class4:explicit=[Class4.T*],needsArgs,test*/
 class Class4<T> {
   /*member: Class4.method6:*/
   num method6(num n, T t) => null;
diff --git a/pkg/compiler/test/rti/data/method_signatures_generic.dart b/pkg/compiler/test/rti/data/method_signatures_generic.dart
index 96dd598..8a8f55b 100644
--- a/pkg/compiler/test/rti/data/method_signatures_generic.dart
+++ b/pkg/compiler/test/rti/data/method_signatures_generic.dart
@@ -18,7 +18,7 @@
 }
 
 class Class2 {
-  /*spec.member: Class2.method4:direct,explicit=[method4.T*],needsArgs,needsInst=[<num*>,<num*>]*/
+  /*spec.member: Class2.method4:explicit=[method4.T*],needsArgs,needsInst=[<num*>,<num*>],test*/
   num method4<T>(T n) => null;
 }
 
@@ -28,17 +28,17 @@
 }
 
 class Class4 {
-  /*spec.member: Class4.method6:direct,explicit=[method6.T*],needsArgs*/
+  /*spec.member: Class4.method6:explicit=[method6.T*],needsArgs,test*/
   num method6<T>(num n, T t) => null;
 }
 
-/*spec.member: method7:direct,explicit=[method7.T*],needsArgs,needsInst=[<num*>,<num*>]*/
+/*spec.member: method7:explicit=[method7.T*],needsArgs,needsInst=[<num*>,<num*>],test*/
 num method7<T>(T n) => null;
 
 /*member: method8:*/
 T method8<T>(num n) => null;
 
-/*spec.member: method9:direct,explicit=[method9.T*],needsArgs*/
+/*spec.member: method9:explicit=[method9.T*],needsArgs,test*/
 num method9<T>(num n, T t) => null;
 
 @pragma('dart2js:noInline')
diff --git a/pkg/compiler/test/rti/data/private_dynamic.dart b/pkg/compiler/test/rti/data/private_dynamic.dart
index 87f1714..f6fbdb8 100644
--- a/pkg/compiler/test/rti/data/private_dynamic.dart
+++ b/pkg/compiler/test/rti/data/private_dynamic.dart
@@ -5,7 +5,7 @@
 // @dart = 2.7
 
 class C {
-  /*member: C._private:direct,explicit=[_private.T*],needsArgs,selectors=[Selector(call, _private, arity=1, types=1)]*/
+  /*member: C._private:explicit=[_private.T*],needsArgs,selectors=[Selector(call, _private, arity=1, types=1)],test*/
   _private<T>(t) => t is T;
 }
 
diff --git a/pkg/compiler/test/rti/data/private_dynamic2.dart b/pkg/compiler/test/rti/data/private_dynamic2.dart
index 2126428..723250a 100644
--- a/pkg/compiler/test/rti/data/private_dynamic2.dart
+++ b/pkg/compiler/test/rti/data/private_dynamic2.dart
@@ -5,12 +5,12 @@
 // @dart = 2.7
 
 class C {
-  /*member: C._private:deps=[D._private2],direct,explicit=[_private.T*],needsArgs,selectors=[Selector(call, _private, arity=1, types=1)]*/
+  /*member: C._private:deps=[D._private2],explicit=[_private.T*],needsArgs,selectors=[Selector(call, _private, arity=1, types=1)],test*/
   _private<T>(t) => t is T;
 }
 
 class D {
-  /*member: D._private2:implicit=[_private2.T],indirect,needsArgs,selectors=[Selector(call, _private2, arity=2, types=1)]*/
+  /*member: D._private2:implicit=[_private2.T],needsArgs,selectors=[Selector(call, _private2, arity=2, types=1)],test*/
   _private2<T>(c, t) => c._private<T>(t);
 }
 
diff --git a/pkg/compiler/test/rti/data/runtime_type_closure_equals2.dart b/pkg/compiler/test/rti/data/runtime_type_closure_equals2.dart
index a9199b1..00ea501 100644
--- a/pkg/compiler/test/rti/data/runtime_type_closure_equals2.dart
+++ b/pkg/compiler/test/rti/data/runtime_type_closure_equals2.dart
@@ -17,7 +17,7 @@
   /*needsArgs,needsSignature*/
   T local1b<T>() => null;
 
-  /*spec.direct,explicit=[local2.T*],needsArgs,needsSignature*/
+  /*spec.explicit=[local2.T*],needsArgs,needsSignature,test*/
   /*prod.needsArgs,needsSignature*/
   T local2<T>(T t, String s) => t;
 
diff --git a/pkg/compiler/test/rti/data/runtime_type_closure_equals3.dart b/pkg/compiler/test/rti/data/runtime_type_closure_equals3.dart
index bba535c..83b4387 100644
--- a/pkg/compiler/test/rti/data/runtime_type_closure_equals3.dart
+++ b/pkg/compiler/test/rti/data/runtime_type_closure_equals3.dart
@@ -8,7 +8,7 @@
 
 String method() => null;
 
-/*spec.class: Class1:direct,explicit=[Class1.T*],needsArgs*/
+/*spec.class: Class1:explicit=[Class1.T*],needsArgs,test*/
 /*prod.class: Class1:needsArgs*/
 class Class1<T> {
   Class1();
diff --git a/pkg/compiler/test/rti/data/runtime_type_closure_equals5.dart b/pkg/compiler/test/rti/data/runtime_type_closure_equals5.dart
index b3477bb..63a7b9e 100644
--- a/pkg/compiler/test/rti/data/runtime_type_closure_equals5.dart
+++ b/pkg/compiler/test/rti/data/runtime_type_closure_equals5.dart
@@ -6,7 +6,7 @@
 
 import 'package:compiler/src/util/testing.dart';
 
-/*spec.class: Class1:direct,explicit=[Class1.T*],needsArgs*/
+/*spec.class: Class1:explicit=[Class1.T*],needsArgs,test*/
 /*prod.class: Class1:needsArgs*/
 class Class1<T> {
   Class1();
diff --git a/pkg/compiler/test/rti/data/runtime_type_closure_equals7.dart b/pkg/compiler/test/rti/data/runtime_type_closure_equals7.dart
index 8ffc992..804a190 100644
--- a/pkg/compiler/test/rti/data/runtime_type_closure_equals7.dart
+++ b/pkg/compiler/test/rti/data/runtime_type_closure_equals7.dart
@@ -12,7 +12,7 @@
 /*member: method1b:*/
 T method1b<T>() => null;
 
-/*spec.member: method2:direct,explicit=[method2.T*],needsArgs*/
+/*spec.member: method2:explicit=[method2.T*],needsArgs,test*/
 T method2<T>(T t, String s) => t;
 
 class Class<T> {
diff --git a/pkg/compiler/test/rti/data/runtime_type_closure_equals8.dart b/pkg/compiler/test/rti/data/runtime_type_closure_equals8.dart
index fae683f..4dde28e 100644
--- a/pkg/compiler/test/rti/data/runtime_type_closure_equals8.dart
+++ b/pkg/compiler/test/rti/data/runtime_type_closure_equals8.dart
@@ -15,7 +15,7 @@
   /*member: Class1.method1b:*/
   T method1b<T>() => null;
 
-  /*spec.member: Class1.method2:direct,explicit=[method2.T*],needsArgs*/
+  /*spec.member: Class1.method2:explicit=[method2.T*],needsArgs,test*/
   T method2<T>(T t, String s) => t;
 }
 
diff --git a/pkg/compiler/test/rti/data/runtime_type_instantiate_to_string1.dart b/pkg/compiler/test/rti/data/runtime_type_instantiate_to_string1.dart
index f8ee428..92ef961 100644
--- a/pkg/compiler/test/rti/data/runtime_type_instantiate_to_string1.dart
+++ b/pkg/compiler/test/rti/data/runtime_type_instantiate_to_string1.dart
@@ -9,7 +9,7 @@
 /*member: global#instantiate1:needsArgs*/
 
 main() {
-  /*spec.direct,explicit=[id.T*],needsArgs,needsInst=[<int*>],needsSignature*/
+  /*spec.explicit=[id.T*],needsArgs,needsInst=[<int*>],needsSignature,test*/
   T id<T>(T t, String s) => t;
   int Function(int, String s) x = id;
   makeLive("${x.runtimeType}");
diff --git a/pkg/compiler/test/rti/data/runtime_type_instantiate_to_string2.dart b/pkg/compiler/test/rti/data/runtime_type_instantiate_to_string2.dart
index 09002a4..f45d037 100644
--- a/pkg/compiler/test/rti/data/runtime_type_instantiate_to_string2.dart
+++ b/pkg/compiler/test/rti/data/runtime_type_instantiate_to_string2.dart
@@ -8,7 +8,7 @@
 
 /*member: global#instantiate1:needsArgs*/
 
-/*spec.member: id:direct,explicit=[id.T*],needsArgs,needsInst=[<int*>]*/
+/*spec.member: id:explicit=[id.T*],needsArgs,needsInst=[<int*>],test*/
 T id<T>(T t, String s) => t;
 
 main() {
diff --git a/pkg/compiler/test/rti/data/runtime_type_instantiate_to_string3.dart b/pkg/compiler/test/rti/data/runtime_type_instantiate_to_string3.dart
index 5de5547..ddcced5 100644
--- a/pkg/compiler/test/rti/data/runtime_type_instantiate_to_string3.dart
+++ b/pkg/compiler/test/rti/data/runtime_type_instantiate_to_string3.dart
@@ -9,7 +9,7 @@
 /*member: global#instantiate1:needsArgs*/
 
 class Class {
-  /*spec.member: Class.id:direct,explicit=[id.T*],needsArgs,needsInst=[<int*>]*/
+  /*spec.member: Class.id:explicit=[id.T*],needsArgs,needsInst=[<int*>],test*/
   T id<T>(T t, String s) => t;
 }
 
diff --git a/pkg/compiler/test/rti/data/tear_off_generic.dart b/pkg/compiler/test/rti/data/tear_off_generic.dart
index 1aa8d04..f2446f1 100644
--- a/pkg/compiler/test/rti/data/tear_off_generic.dart
+++ b/pkg/compiler/test/rti/data/tear_off_generic.dart
@@ -4,7 +4,7 @@
 
 // @dart = 2.7
 
-/*spec.class: A:direct,explicit=[A.T*],needsArgs*/
+/*spec.class: A:explicit=[A.T*],needsArgs,test*/
 class A<T> {
   void m(T t) {}
 
diff --git a/pkg/compiler/test/rti/data/type_variable_function_type.dart b/pkg/compiler/test/rti/data/type_variable_function_type.dart
index d36e45f..2c31bc6 100644
--- a/pkg/compiler/test/rti/data/type_variable_function_type.dart
+++ b/pkg/compiler/test/rti/data/type_variable_function_type.dart
@@ -10,7 +10,7 @@
 
 typedef T Func<T>();
 
-/*class: Foo:direct,explicit=[Foo.S* Function()*],needsArgs*/
+/*class: Foo:explicit=[Foo.S* Function()*],needsArgs,test*/
 class Foo<S> {
   m(x) => x is Func<S>;
 }
diff --git a/pkg/compiler/test/rti/rti_need_test_helper.dart b/pkg/compiler/test/rti/rti_need_test_helper.dart
index 8973cd7..56b4627 100644
--- a/pkg/compiler/test/rti/rti_need_test_helper.dart
+++ b/pkg/compiler/test/rti/rti_need_test_helper.dart
@@ -46,8 +46,7 @@
   static const String dependencies = 'deps';
   static const String explicitTypeCheck = 'explicit';
   static const String implicitTypeCheck = 'implicit';
-  static const String directTypeArgumentTest = 'direct';
-  static const String indirectTypeArgumentTest = 'indirect';
+  static const String typeArgumentTest = 'test';
   static const String typeLiteral = 'exp';
   static const String selectors = 'selectors';
   static const String instantiationsNeedTypeArguments = 'needsInst';
@@ -109,12 +108,9 @@
         .contains(frontendClass)) {
       features.add(Tags.typeLiteral);
     }
-    if (rtiNeedBuilder.typeVariableTestsForTesting.directClassTestsForTesting
+    if (rtiNeedBuilder.typeVariableTestsForTesting.classTestsForTesting
         .contains(frontendClass)) {
-      features.add(Tags.directTypeArgumentTest);
-    } else if (rtiNeedBuilder.typeVariableTestsForTesting.classTestsForTesting
-        .contains(frontendClass)) {
-      features.add(Tags.indirectTypeArgumentTest);
+      features.add(Tags.typeArgumentTest);
     }
     findChecks(features, Tags.explicitTypeCheck, frontendClass,
         rtiNeedBuilder.typeVariableTestsForTesting.explicitIsChecks);
@@ -139,14 +135,9 @@
 
       void addFrontendData(Entity entity) {
         findDependencies(features, entity);
-        if (rtiNeedBuilder
-            .typeVariableTestsForTesting.directMethodTestsForTesting
+        if (rtiNeedBuilder.typeVariableTestsForTesting.methodTestsForTesting
             .contains(entity)) {
-          features.add(Tags.directTypeArgumentTest);
-        } else if (rtiNeedBuilder
-            .typeVariableTestsForTesting.methodTestsForTesting
-            .contains(entity)) {
-          features.add(Tags.indirectTypeArgumentTest);
+          features.add(Tags.typeArgumentTest);
         }
         findChecks(features, Tags.explicitTypeCheck, entity,
             rtiNeedBuilder.typeVariableTestsForTesting.explicitIsChecks);
diff --git a/runtime/vm/compiler/stub_code_compiler_arm.cc b/runtime/vm/compiler/stub_code_compiler_arm.cc
index 3c65323..8c3ce77 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm.cc
@@ -1195,8 +1195,6 @@
 //   R2 : arguments array.
 //   R3 : current thread.
 void StubCodeCompiler::GenerateInvokeDartCodeStub(Assembler* assembler) {
-  // Marker for the profiler.
-  NOT_IN_PRODUCT(READS_RETURN_ADDRESS_FROM_LR(__ Push(LR)));
   SPILLS_LR_TO_FRAME(__ EnterFrame((1 << FP) | (1 << LR), 0));
 
   // Push code object to PC marker slot.
@@ -1319,7 +1317,6 @@
 
   // Restore the frame pointer and return.
   RESTORES_LR_FROM_FRAME(__ LeaveFrame((1 << FP) | (1 << LR)));
-  NOT_IN_PRODUCT(__ Drop(1));  // Drop profiler marker.
   __ Ret();
 }
 
diff --git a/runtime/vm/compiler/stub_code_compiler_arm64.cc b/runtime/vm/compiler/stub_code_compiler_arm64.cc
index e32707b..fe3b109 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm64.cc
@@ -1365,8 +1365,6 @@
   // from over-writing Dart frames.
   __ mov(SP, CSP);
   __ SetupCSPFromThread(R3);
-  // Marker for the profiler.
-  NOT_IN_PRODUCT(READS_RETURN_ADDRESS_FROM_LR(__ Push(LR)));
   __ EnterFrame(0);
 
   // Push code object to PC marker slot.
@@ -1489,7 +1487,6 @@
 
   // Restore the frame pointer and C stack pointer and return.
   __ LeaveFrame();
-  NOT_IN_PRODUCT(__ Drop(1));  // Drop profiler marker.
   __ RestoreCSP();
   __ ret();
 }
diff --git a/runtime/vm/compiler/stub_code_compiler_riscv.cc b/runtime/vm/compiler/stub_code_compiler_riscv.cc
index b8096b3..8283688 100644
--- a/runtime/vm/compiler/stub_code_compiler_riscv.cc
+++ b/runtime/vm/compiler/stub_code_compiler_riscv.cc
@@ -1276,7 +1276,6 @@
 void StubCodeCompiler::GenerateInvokeDartCodeStub(Assembler* assembler) {
   __ Comment("InvokeDartCodeStub");
 
-  NOT_IN_PRODUCT(__ PushRegister(RA));  // Marker for the profiler.
   __ EnterFrame(0);
 
   // Push code object to PC marker slot.
@@ -1396,7 +1395,6 @@
 
   // Restore the frame pointer and C stack pointer and return.
   __ LeaveFrame();
-  NOT_IN_PRODUCT(__ Drop(1));  // Drop profiler marker.
   __ ret();
 }
 
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index 8ff785b..dcf17e7 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -666,6 +666,7 @@
                           SampleBuffer* sample_buffer,
                           uword pc,
                           uword fp,
+                          uword lr,
                           bool allocation_sample,
                           intptr_t skip_count = 0)
       : ProfilerStackWalker((thread->isolate() != NULL)
@@ -676,7 +677,8 @@
                             skip_count),
         thread_(thread),
         pc_(reinterpret_cast<uword*>(pc)),
-        fp_(reinterpret_cast<uword*>(fp)) {}
+        fp_(reinterpret_cast<uword*>(fp)),
+        lr_(reinterpret_cast<uword*>(lr)) {}
 
   void walk() {
     RELEASE_ASSERT(StubCode::HasBeenInitialized());
@@ -695,7 +697,6 @@
       // Skip exit frame.
       pc_ = CallerPC();
       fp_ = CallerFP();
-
     } else {
       if (thread_->vm_tag() == VMTag::kDartTagId) {
         // Running compiled code.
@@ -709,7 +710,12 @@
 
     sample_->set_exit_frame_sample(has_exit_frame);
 
+#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64)
     if (!has_exit_frame && (CallerPC() == EntryMarker())) {
+#else
+    if (!has_exit_frame &&
+        (StubCode::InInvocationStub(reinterpret_cast<uword>(lr_)))) {
+#endif
       // During the prologue of a function, CallerPC will return the caller's
       // caller. For most frames, the missing PC will be added during profile
       // processing. However, during this stack walk, it can cause us to fail
@@ -790,6 +796,7 @@
   Thread* const thread_;
   uword* pc_;
   uword* fp_;
+  uword* lr_;
 };
 
 // The layout of C stack frames.
@@ -1314,6 +1321,7 @@
   uintptr_t sp = OSThread::GetCurrentStackPointer();
   uintptr_t fp = 0;
   uintptr_t pc = OS::GetProgramCounter();
+  uintptr_t lr = 0;
 
   COPY_FP_REGISTER(fp);
 
@@ -1348,7 +1356,7 @@
     native_stack_walker.walk();
   } else if (exited_dart_code) {
     ProfilerDartStackWalker dart_exit_stack_walker(
-        thread, sample, isolate->current_allocation_sample_block(), pc, fp,
+        thread, sample, isolate->current_allocation_sample_block(), pc, fp, lr,
         /* allocation_sample*/ true);
     dart_exit_stack_walker.walk();
   } else {
@@ -1457,6 +1465,7 @@
   uintptr_t sp = 0;
   uintptr_t fp = state.fp;
   uintptr_t pc = state.pc;
+  uintptr_t lr = state.lr;
 #if defined(USING_SIMULATOR)
   Simulator* simulator = NULL;
 #endif
@@ -1468,6 +1477,7 @@
     sp = simulator->get_register(SPREG);
     fp = simulator->get_register(FPREG);
     pc = simulator->get_pc();
+    lr = simulator->get_lr();
 #else
     sp = state.dsp;
 #endif
@@ -1540,9 +1550,9 @@
       sample, isolate->current_sample_block(), stack_lower, stack_upper, pc, fp,
       sp);
   const bool exited_dart_code = thread->HasExitedDartCode();
-  ProfilerDartStackWalker dart_stack_walker(thread, sample,
-                                            isolate->current_sample_block(), pc,
-                                            fp, /* allocation_sample*/ false);
+  ProfilerDartStackWalker dart_stack_walker(
+      thread, sample, isolate->current_sample_block(), pc, fp, lr,
+      /* allocation_sample*/ false);
 
   // All memory access is done inside CollectSample.
   CollectSample(isolate, exited_dart_code, in_dart_code, sample,
diff --git a/runtime/vm/simulator_arm.h b/runtime/vm/simulator_arm.h
index 61beaec..8851f6f 100644
--- a/runtime/vm/simulator_arm.h
+++ b/runtime/vm/simulator_arm.h
@@ -53,6 +53,7 @@
   }
 
   int32_t get_sp() const { return get_register(SPREG); }
+  int32_t get_lr() const { return get_register(R14); }
 
   // Special case of set_register and get_register to access the raw PC value.
   void set_pc(int32_t value);
diff --git a/runtime/vm/simulator_arm64.h b/runtime/vm/simulator_arm64.h
index 7cfbc16..be20b2b 100644
--- a/runtime/vm/simulator_arm64.h
+++ b/runtime/vm/simulator_arm64.h
@@ -67,6 +67,7 @@
   void set_vregister(VRegister reg, const simd_value_t& value);
 
   int64_t get_sp() const { return get_register(SPREG); }
+  int64_t get_lr() const { return get_register(R30); }
 
   uint64_t get_pc() const;
   uint64_t get_last_pc() const;
diff --git a/runtime/vm/simulator_riscv.h b/runtime/vm/simulator_riscv.h
index b63ed39..9a5ca23 100644
--- a/runtime/vm/simulator_riscv.h
+++ b/runtime/vm/simulator_riscv.h
@@ -165,6 +165,7 @@
   uintx_t get_pc() const { return pc_; }
   uintx_t get_sp() const { return get_xreg(SP); }
   uintx_t get_fp() const { return get_xreg(FP); }
+  uintx_t get_lr() const { return get_xreg(RA); }
   void PrintRegisters();
   void PrintStack();
 
diff --git a/tools/VERSION b/tools/VERSION
index 76b2b57..fff819f 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 17
 PATCH 0
-PRERELEASE 185
+PRERELEASE 186
 PRERELEASE_PATCH 0
\ No newline at end of file