@@ -1067,6 +1067,29 @@ class IsolateManager {
10671067 clientBreakpoint.breakpoint.column == breakpoint.column);
10681068 }
10691069
1070+ /// Converts local Google3 or SDK file paths to URIs VM can recognize.
1071+ ///
1072+ /// ```
1073+ /// sdk-path/lib/core/print.dart -> org-dartlang-sdk://sdk/lib/core/print.dart
1074+ /// google/*/google3/<path> -> google3://<path>
1075+ /// ```
1076+ ///
1077+ /// VM is capable of setting breakpoints using both original (`package`
1078+ /// scheme) URIs or their resolved variants - which means no convertion
1079+ /// is necessary if local path is the same as the resolved path known to the
1080+ /// VM.
1081+ ///
1082+ /// Google3 paths and Dart SDK paths however require special handling:
1083+ /// because in both cases resolved paths we given using *multi-root
1084+ /// filesystem* accessed via a special scheme (`google3` and
1085+ /// `org-dartlang-sdk` respectively) to hide local file layout from the
1086+ /// front-end.
1087+ Uri _fixSDKOrGoogle3Paths (Uri sourcePathUri) {
1088+ return _adapter.convertUriToOrgDartlangSdk (sourcePathUri) ??
1089+ _convertPathToGoogle3Uri (sourcePathUri) ??
1090+ sourcePathUri;
1091+ }
1092+
10701093 /// Creates a breakpoint in [clientUri] for [thread] in the VM that
10711094 /// corresponds to [clientBreakpoint] received from the client.
10721095 Future <void > addBreakpoint (ClientBreakpoint clientBreakpoint,
@@ -1081,12 +1104,7 @@ class IsolateManager {
10811104 try {
10821105 // Some file URIs (like SDK sources) need to be converted to
10831106 // appropriate internal URIs to be able to set breakpoints.
1084- final vmUri = await thread.resolvePathToUri (Uri .parse (clientUri));
1085-
1086- if (vmUri == null ) {
1087- return ;
1088- }
1089-
1107+ final vmUri = _fixSDKOrGoogle3Paths (Uri .parse (clientUri));
10901108 final vmBp = await service.addBreakpointWithScriptUri (
10911109 isolateId, vmUri.toString (), clientBreakpoint.breakpoint.line,
10921110 column: clientBreakpoint.breakpoint.column);
@@ -1385,49 +1403,32 @@ class ThreadInfo with FileUtils {
13851403 return _currentEvaluationZoneId;
13861404 }
13871405
1388- /// Resolves a source file path (or URI) into a URI for the VM .
1406+ /// Resolves a source file URI into a original `package://` or SDK URI .
13891407 ///
1390- /// sdk-path/lib/core/print.dart -> dart:core/print.dart
1408+ /// ```
1409+ /// sdk-path/lib/core/print.dart -> org-dartlang-sdk://sdk/lib/core/print.dart
13911410 /// c:\foo\bar -> package:foo/bar
1392- /// dart-macro+file:///c:/foo/bar -> dart-macro+package:foo/bar
1393- ///
1394- /// This is required so that when the user sets a breakpoint in an SDK source
1395- /// (which they may have navigated to via the Analysis Server) we generate a
1396- /// valid URI that the VM would create a breakpoint for.
1397- ///
1398- /// Because the VM supports using `file:` URIs in many places, we usually do
1399- /// not need to convert file paths into `package:` URIs, however this will
1400- /// be done if [forceResolveFileUris] is `true` .
1401- Future <Uri ?> resolvePathToUri (
1402- Uri sourcePathUri, {
1403- bool forceResolveFileUris = false ,
1404- }) async {
1405- final sdkUri = _manager._adapter.convertUriToOrgDartlangSdk (sourcePathUri);
1406- if (sdkUri != null ) {
1407- return sdkUri;
1411+ /// ```
1412+ ///
1413+ /// This helper is used when trying to find [vm.Script] by matching its
1414+ /// `uri` .
1415+ Future <Uri ?> _convertToPackageOrSdkPath (Uri sourcePathUri) async {
1416+ final uri = _manager._fixSDKOrGoogle3Paths (sourcePathUri);
1417+ if (uri.isScheme ('org-dartlang-sdk' )) {
1418+ return uri; // No package path exists for SDK sources.
14081419 }
14091420
1410- final google3Uri = _convertPathToGoogle3Uri (sourcePathUri);
1411- final uri = google3Uri ?? sourcePathUri;
1412-
1413- // As an optimisation, we don't resolve file -> package URIs in many cases
1414- // because the VM can set breakpoints for file: URIs anyway. However for
1415- // G3 or if [forceResolveFileUris] is set, we will.
1416- final performResolve = google3Uri != null || forceResolveFileUris;
1417-
14181421 // TODO(dantup): Consider caching results for this like we do for
14191422 // resolveUriToPath (and then forceResolveFileUris can be removed and just
14201423 // always used).
1421- final packageUriList = performResolve
1422- ? await _manager._adapter.vmService
1423- ? .lookupPackageUris (isolate.id! , [uri.toString ()])
1424- : null ;
1424+ final packageUriList = await _manager._adapter.vmService
1425+ ? .lookupPackageUris (isolate.id! , [uri.toString ()]);
14251426 final packageUriString = packageUriList? .uris? .firstOrNull;
14261427
14271428 if (packageUriString != null ) {
14281429 // Use package URI if we resolved something
14291430 return Uri .parse (packageUriString);
1430- } else if (google3Uri != null ) {
1431+ } else if (uri. isScheme ( 'google3' ) ) {
14311432 // If we failed to resolve and was a Google3 URI, return null
14321433 return null ;
14331434 } else {
@@ -1614,28 +1615,6 @@ class ThreadInfo with FileUtils {
16141615 /// that are round-tripped to the client.
16151616 int storeData (Object data) => _manager.storeData (this , data);
16161617
1617- Uri ? _convertPathToGoogle3Uri (Uri input) {
1618- // TODO(dantup): Do we need to handle non-file here? Eg. can we have
1619- // dart-macro+file:/// for a google3 path?
1620- if (! input.isScheme ('file' )) {
1621- return null ;
1622- }
1623- final inputPath = input.toFilePath ();
1624-
1625- const search = '/google3/' ;
1626- if (inputPath.startsWith ('/google' ) && inputPath.contains (search)) {
1627- var idx = inputPath.indexOf (search);
1628- var remainingPath = inputPath.substring (idx + search.length);
1629- return Uri (
1630- scheme: 'google3' ,
1631- host: '' ,
1632- path: remainingPath,
1633- );
1634- }
1635-
1636- return null ;
1637- }
1638-
16391618 /// Converts a VM-returned URI to a file-like URI, taking org-dartlang-sdk
16401619 /// schemes into account.
16411620 ///
@@ -1721,12 +1700,9 @@ class ThreadInfo with FileUtils {
17211700 Future <vm.LibraryRef ?> getLibraryForFileUri (Uri scriptFileUri) async {
17221701 // We start with a file URI and need to find the Library (via the script).
17231702 //
1724- // We need to handle msimatched drive letters, and also file vs package
1703+ // We need to handle mismatched drive letters, and also file vs package
17251704 // URIs.
1726- final scriptResolvedUri = await resolvePathToUri (
1727- scriptFileUri,
1728- forceResolveFileUris: true ,
1729- );
1705+ final scriptResolvedUri = await _convertToPackageOrSdkPath (scriptFileUri);
17301706 final candidateUris = {
17311707 scriptFileUri.toString (),
17321708 normalizeUri (scriptFileUri).toString (),
@@ -1867,3 +1843,25 @@ class StoredData {
18671843
18681844 StoredData (this .thread, this .data);
18691845}
1846+
1847+ Uri ? _convertPathToGoogle3Uri (Uri input) {
1848+ // TODO(dantup): Do we need to handle non-file here? Eg. can we have
1849+ // dart-macro+file:/// for a google3 path?
1850+ if (! input.isScheme ('file' )) {
1851+ return null ;
1852+ }
1853+ final inputPath = input.toFilePath ();
1854+
1855+ const search = '/google3/' ;
1856+ if (inputPath.startsWith ('/google' ) && inputPath.contains (search)) {
1857+ var idx = inputPath.indexOf (search);
1858+ var remainingPath = inputPath.substring (idx + search.length);
1859+ return Uri (
1860+ scheme: 'google3' ,
1861+ host: '' ,
1862+ path: remainingPath,
1863+ );
1864+ }
1865+
1866+ return null ;
1867+ }
0 commit comments