[stable] Issue 51087. Restore canonical URI in PackageBuildFileUriResolver.pathToUri()

Bug: https://github.com/dart-lang/sdk/issues/51087
Change-Id: I1d141ef918fa53a86f31d331f6586367dfb99953
Cherry-pick: https://dart-review.googlesource.com/c/sdk/+/279562
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/280045
Commit-Queue: Kevin Chisholm <kevinjchisholm@google.com>
Reviewed-by: Samuel Rawlins <srawlins@google.com>
diff --git a/pkg/analyzer/lib/src/workspace/package_build.dart b/pkg/analyzer/lib/src/workspace/package_build.dart
index e9ce5dc..338a997c 100644
--- a/pkg/analyzer/lib/src/workspace/package_build.dart
+++ b/pkg/analyzer/lib/src/workspace/package_build.dart
@@ -27,6 +27,28 @@
   PackageBuildFileUriResolver(this.workspace) : super(workspace.provider);
 
   @override
+  Uri pathToUri(String path) {
+    var pathContext = workspace.provider.pathContext;
+    if (pathContext.isWithin(workspace.root, path)) {
+      var relative = pathContext.relative(path, from: workspace.root);
+      var components = pathContext.split(relative);
+      if (components.length > 4 &&
+          components[0] == '.dart_tool' &&
+          components[1] == 'build' &&
+          components[2] == 'generated' &&
+          components[3] == workspace.projectPackageName) {
+        var canonicalPath = pathContext.joinAll([
+          workspace.root,
+          ...components.skip(4),
+        ]);
+        return pathContext.toUri(canonicalPath);
+      }
+    }
+
+    return super.pathToUri(path);
+  }
+
+  @override
   Source? resolveAbsolute(Uri uri) {
     if (!ResourceUriResolver.isFileUri(uri)) {
       return null;
diff --git a/pkg/analyzer/test/src/diagnostics/part_of_different_library_test.dart b/pkg/analyzer/test/src/diagnostics/part_of_different_library_test.dart
index 399f59c..8ba1f62 100644
--- a/pkg/analyzer/test/src/diagnostics/part_of_different_library_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/part_of_different_library_test.dart
@@ -31,6 +31,26 @@
     ]);
   }
 
+  /// TODO(scheglov) Extract `package:build` base resolution class, move this.
+  test_packageBuild_generated() async {
+    var package = 'test';
+    newPubspecYamlFile(testPackageRootPath, 'name: $package');
+
+    var testPackageGeneratedPath =
+        '$testPackageRootPath/.dart_tool/build/generated';
+    newFile('$testPackageGeneratedPath/$package/example/foo.g.dart', '''
+part of 'foo.dart';
+''');
+
+    var path = '$testPackageRootPath/example/foo.dart';
+    newFile(path, '''
+part 'foo.g.dart';
+''');
+
+    await resolveFile2(path);
+    assertErrorsInResolvedUnit(result, const []);
+  }
+
   test_partOfName() async {
     newFile('$testPackageLibPath/part.dart', '''
 part of bar;
diff --git a/pkg/analyzer/test/src/workspace/package_build_test.dart b/pkg/analyzer/test/src/workspace/package_build_test.dart
index faf8614..5e89248 100644
--- a/pkg/analyzer/test/src/workspace/package_build_test.dart
+++ b/pkg/analyzer/test/src/workspace/package_build_test.dart
@@ -47,74 +47,96 @@
   late final PackageBuildWorkspace workspace;
   late final PackageBuildFileUriResolver resolver;
 
+  File get testFile => getFile('$testPackageLibPath/test.dart');
+
+  String get testPackageGeneratedLibPath => '$testPackageGeneratedRootPath/lib';
+
+  String get testPackageGeneratedRootPath =>
+      '$testPackageRootPath/.dart_tool/build/generated/test';
+
+  String get testPackageLibPath => '$testPackageRootPath/lib';
+
+  String get testPackageRootPath => '$workspaceRootPath/test';
+
+  String get workspaceRootPath => '/home';
+
   void setUp() {
-    newFolder('/workspace/.dart_tool/build/generated/project/lib');
-    newPubspecYamlFile('/workspace', 'name: project');
+    newFolder(testPackageGeneratedLibPath);
+    newPubspecYamlFile(testPackageRootPath, 'name: test');
 
     workspace = PackageBuildWorkspace.find(
       resourceProvider,
       Packages({
-        'project': Package(
-          name: 'project',
-          rootFolder: getFolder('/workspace'),
-          libFolder: getFolder('/workspace'),
+        'test': Package(
+          name: 'test',
+          rootFolder: getFolder(testPackageRootPath),
+          libFolder: getFolder(testPackageLibPath),
           languageVersion: null,
         ),
       }),
-      convertPath('/workspace'),
+      convertPath(testPackageRootPath),
     )!;
     resolver = PackageBuildFileUriResolver(workspace);
-    newFile('/workspace/test.dart', '');
-    newFile('/workspace/.dart_tool/build/generated/project/gen.dart', '');
     expect(workspace.isBlaze, isFalse);
   }
 
-  void test_pathToUri() {
-    var uri = toUri('/workspace/test.dart');
+  void test_resolveAbsolute_fileUri() {
+    var path = testFile.path;
+    newFile(path, '');
+    _assertResolveUri(toUri(path), path);
+  }
+
+  void test_resolveAbsolute_fileUri_doesNotExist() {
+    var path = testFile.path;
+    _assertResolveUri(toUri(path), path, exists: false);
+  }
+
+  void test_resolveAbsolute_fileUri_folder() {
+    var uri = toUri(testPackageRootPath);
+    var source = resolver.resolveAbsolute(uri);
+    expect(source, isNull);
+  }
+
+  void test_resolveAbsolute_fileUri_generated_lib() {
+    var file = newFile('$testPackageGeneratedLibPath/foo.dart', '');
+    _assertResolveUri(
+      toUri('$testPackageLibPath/foo.dart'),
+      file.path,
+    );
+  }
+
+  void test_resolveAbsolute_fileUri_generated_notLib() {
+    var file = newFile('$testPackageGeneratedRootPath/example/foo.dart', '');
+    _assertResolveUri(
+      toUri('$testPackageRootPath/example/foo.dart'),
+      file.path,
+    );
+  }
+
+  void test_resolveAbsolute_notFileUri_dartUri() {
+    var uri = Uri.parse('dart:core');
+    var source = resolver.resolveAbsolute(uri);
+    expect(source, isNull);
+  }
+
+  void test_resolveAbsolute_notFileUri_httpsUri() {
+    var uri = Uri.parse('https://127.0.0.1/test.dart');
+    var source = resolver.resolveAbsolute(uri);
+    expect(source, isNull);
+  }
+
+  Source _assertResolveUri(
+    Uri uri,
+    String posixPath, {
+    bool exists = true,
+  }) {
     var source = resolver.resolveAbsolute(uri)!;
-    expect(resolver.pathToUri(source.fullName), uri);
-  }
-
-  void test_resolveAbsolute_doesNotExist() {
-    var source = _resolvePath('/workspace/foo.dart')!;
-    expect(source, isNotNull);
-    expect(source.exists(), isFalse);
-    expect(source.fullName, convertPath('/workspace/foo.dart'));
-  }
-
-  void test_resolveAbsolute_file() {
-    var source = _resolvePath('/workspace/test.dart')!;
-    expect(source.exists(), isTrue);
-    expect(source.fullName, convertPath('/workspace/test.dart'));
-  }
-
-  void test_resolveAbsolute_folder() {
-    var source = _resolvePath('/workspace');
-    expect(source, isNull);
-  }
-
-  void test_resolveAbsolute_generated_file_exists_one() {
-    var source = _resolvePath('/workspace/gen.dart')!;
-    expect(source.exists(), isTrue);
-    expect(source.fullName,
-        convertPath('/workspace/.dart_tool/build/generated/project/gen.dart'));
-  }
-
-  void test_resolveAbsolute_notFile_dartUri() {
-    Uri uri = Uri(scheme: 'dart', path: 'core');
-    var source = resolver.resolveAbsolute(uri);
-    expect(source, isNull);
-  }
-
-  void test_resolveAbsolute_notFile_httpsUri() {
-    Uri uri = Uri(scheme: 'https', path: '127.0.0.1/test.dart');
-    var source = resolver.resolveAbsolute(uri);
-    expect(source, isNull);
-  }
-
-  Source? _resolvePath(String path) {
-    Uri uri = toUri(path);
-    return resolver.resolveAbsolute(uri);
+    var path = source.fullName;
+    expect(path, convertPath(posixPath));
+    expect(source.uri, uri);
+    expect(source.exists(), exists);
+    expect(resolver.pathToUri(path), uri);
+    return source;
   }
 }
 
@@ -211,17 +233,17 @@
     resolver = PackageBuildPackageUriResolver(workspace, packageUriResolver);
   }
 
-  Source _assertResolveUri(Uri uri, String posixPath,
-      {bool exists = true, bool restore = true}) {
+  Source _assertResolveUri(
+    Uri uri,
+    String posixPath, {
+    bool exists = true,
+  }) {
     var source = resolver.resolveAbsolute(uri)!;
     var path = source.fullName;
     expect(path, convertPath(posixPath));
     expect(source.uri, uri);
     expect(source.exists(), exists);
-    // If enabled, test also "restoreAbsolute".
-    if (restore) {
-      expect(resolver.pathToUri(path), uri);
-    }
+    expect(resolver.pathToUri(path), uri);
     return source;
   }
 }