Fix getFileForUri() for not canonical (writable when has generated) URI.
This fixes the completion issue when I run on my desktop with
internal repo.
Change-Id: I4efc137d96c486cc8c9d139cd372ee0df262d057
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/221029
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index a58388c..532447a 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -854,7 +854,7 @@
FileState? file = _uriToFile[uri];
if (file == null) {
- Source? uriSource = _sourceFactory.resolveUri(null, uri.toString());
+ Source? uriSource = _sourceFactory.forUri2(uri);
// If the URI cannot be resolved, for example because the factory
// does not understand the scheme, return the unresolved file instance.
@@ -863,15 +863,22 @@
}
String path = uriSource.fullName;
+
+ // Check if already resolved to this path via different URI.
+ // That different URI must be the canonical one.
+ file = _pathToFile[path];
+ if (file != null) {
+ return Either2.t1(file);
+ }
+
File resource = _resourceProvider.getFile(path);
var rewrittenUri = rewriteFileToPackageUri(_sourceFactory, uri);
if (rewrittenUri == null) {
return Either2.t1(null);
}
- uri = rewrittenUri;
- file = _newFile(resource, path, uri);
+ file = _newFile(resource, path, rewrittenUri);
}
return Either2.t1(file);
}
diff --git a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
index b7e3039..f0a3e1f 100644
--- a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
@@ -23,19 +23,78 @@
import 'package:analyzer/src/source/package_map_resolver.dart';
import 'package:analyzer/src/test_utilities/mock_sdk.dart';
import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
+import 'package:analyzer/src/util/either.dart';
import 'package:analyzer/src/workspace/basic.dart';
import 'package:convert/convert.dart';
import 'package:crypto/crypto.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
+import '../resolution/context_collection_resolution.dart';
+
main() {
defineReflectiveSuite(() {
defineReflectiveTests(FileSystemStateTest);
+ defineReflectiveTests(FileSystemState_BazelWorkspaceTest);
});
}
@reflectiveTest
+class FileSystemState_BazelWorkspaceTest extends BazelWorkspaceResolutionTest {
+ void test_getFileForUri_hasGenerated_askGeneratedFirst() async {
+ var relPath = 'dart/my/test/a.dart';
+ var writablePath = convertPath('$workspaceRootPath/$relPath');
+ var generatedPath = convertPath('$workspaceRootPath/bazel-bin/$relPath');
+
+ // This generated file should be used instead of the writable.
+ newFile(generatedPath);
+
+ var analysisDriver = driverFor(convertPath(testFilePath));
+
+ var fsState = analysisDriver.fsState;
+
+ // The file is the generated file.
+ var generatedUri = toUri(generatedPath);
+ var generatedFile = fsState.getFileForUri(generatedUri).t1!;
+ expect(generatedFile.uri, generatedUri);
+ expect(generatedFile.path, generatedPath);
+
+ // The file is cached under the requested URI.
+ var writableUri = toUri(writablePath);
+ var writableFile1 = fsState.getFileForUri(writableUri).t1!;
+ var writableFile2 = fsState.getFileForUri(writableUri).t1!;
+ expect(writableFile1, same(generatedFile));
+ expect(writableFile2, same(generatedFile));
+ }
+
+ void test_getFileForUri_hasGenerated_askWritableFirst() async {
+ var relPath = 'dart/my/test/a.dart';
+ var writablePath = convertPath('$workspaceRootPath/$relPath');
+ var generatedPath = convertPath('$workspaceRootPath/bazel-bin/$relPath');
+
+ // This generated file should be used instead of the writable.
+ newFile(generatedPath);
+
+ var analysisDriver = driverFor(convertPath(testFilePath));
+
+ var fsState = analysisDriver.fsState;
+
+ // The file is cached under the requested URI.
+ var writableUri = toUri(writablePath);
+ var writableFile1 = fsState.getFileForUri(writableUri).t1!;
+ var writableFile2 = fsState.getFileForUri(writableUri).t1!;
+ expect(writableFile2, same(writableFile1));
+
+ // The file is the generated file.
+ var generatedUri = toUri(generatedPath);
+ var generatedFile = fsState.getFileForUri(generatedUri).t1!;
+ expect(generatedFile.uri, generatedUri);
+ expect(generatedFile.path, generatedPath);
+ expect(writableFile2, same(generatedFile));
+ }
+}
+
+@reflectiveTest
class FileSystemStateTest with ResourceProviderMixin {
final ByteStore byteStore = MemoryByteStore();
final FileContentOverlay contentOverlay = FileContentOverlay();
@@ -756,3 +815,14 @@
throw StateError('Unexpected invocation of ${invocation.memberName}');
}
}
+
+extension _Either2Extension<T1, T2> on Either2<T1, T2> {
+ T1 get t1 {
+ late T1 result;
+ map(
+ (t1) => result = t1,
+ (_) => throw 'Expected T1',
+ );
+ return result;
+ }
+}