Rewrite any URIs to canonical, not only file://.

Change-Id: I690154d54818ec576908563ea6f3ed76799be951
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/222240
Reviewed-by: Samuel Rawlins <srawlins@google.com>
This commit is contained in:
Konstantin Shcheglov 2021-12-06 21:39:57 +00:00
parent ad9e6d2ec3
commit df48d2f744
7 changed files with 83 additions and 21 deletions

View file

@ -873,7 +873,7 @@ class FileSystemState {
File resource = _resourceProvider.getFile(path);
var rewrittenUri = rewriteFileToPackageUri(_sourceFactory, uri);
var rewrittenUri = rewriteToCanonicalUri(_sourceFactory, uri);
if (rewrittenUri == null) {
return Either2.t1(null);
}

View file

@ -783,7 +783,7 @@ class LibraryAnalyzer {
}
var absoluteUri = resolveRelativeUri(_library.uri, relativeUri);
return rewriteFileToPackageUri(_sourceFactory, absoluteUri);
return rewriteToCanonicalUri(_sourceFactory, absoluteUri);
}
/// Return the result of resolve the given [uriContent], reporting errors

View file

@ -1009,7 +1009,7 @@ class ElementBuilder extends ThrowingAstVisitor<void> {
var absoluteUri = resolveRelativeUri(_libraryBuilder.uri, relativeUri);
var sourceFactory = _linker.analysisContext.sourceFactory;
return rewriteFileToPackageUri(sourceFactory, absoluteUri);
return rewriteToCanonicalUri(sourceFactory, absoluteUri);
}
LibraryElement? _selectLibrary(NamespaceDirective node) {

View file

@ -13,23 +13,10 @@ String fileUriToNormalizedPath(Context context, Uri fileUri) {
return path;
}
/// If the [absoluteUri] is a `file` URI that has corresponding `package` URI,
/// return it. If the URI is not valid, e.g. has empty path segments, so
/// does not represent a valid file path, return `null`.
Uri? rewriteFileToPackageUri(SourceFactory sourceFactory, Uri absoluteUri) {
// Only file URIs get rewritten into package URIs.
if (!absoluteUri.isScheme('file')) {
return absoluteUri;
}
// It must be a valid URI, e.g. `file:///home/` is not.
var pathSegments = absoluteUri.pathSegments;
if (pathSegments.isEmpty || pathSegments.last.isEmpty) {
return null;
}
// We ask for Source only because `restoreUri` needs it.
// TODO(scheglov) Add more direct way to convert a path to URI.
/// Return the canonical URI for the given [absoluteUri], for example a `file`
/// URI to the corresponding `package` URI. If the URI is not valid, so does
/// not represent a valid file path, return `null`.
Uri? rewriteToCanonicalUri(SourceFactory sourceFactory, Uri absoluteUri) {
var source = sourceFactory.forUri2(absoluteUri);
if (source == null) {
return null;

View file

@ -28,12 +28,14 @@ import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../../../util/element_type_matchers.dart';
import '../../../utils.dart';
import '../resolution/context_collection_resolution.dart';
import 'base.dart';
main() {
defineReflectiveSuite(() {
defineReflectiveTests(AnalysisDriverSchedulerTest);
defineReflectiveTests(AnalysisDriverTest);
defineReflectiveTests(AnalysisDriver_BazelWorkspaceTest);
});
}
@ -49,6 +51,59 @@ Future pumpEventQueue([int times = 5000]) {
return Future.delayed(Duration.zero, () => pumpEventQueue(times - 1));
}
@reflectiveTest
class AnalysisDriver_BazelWorkspaceTest extends BazelWorkspaceResolutionTest {
void test_nestedLib_notCanonicalUri() async {
var outerLibPath = '$workspaceRootPath/my/outer/lib';
var innerPath = convertPath('$outerLibPath/inner/lib/b.dart');
var innerUri = Uri.parse('package:my.outer.lib.inner/b.dart');
newFile(innerPath, content: 'class B {}');
var analysisSession = contextFor(innerPath).currentSession;
void assertInnerUri(ResolvedUnitResult result) {
var innerLibrary = result.libraryElement.importedLibraries
.where((e) => e.source.fullName == innerPath)
.single;
expect(innerLibrary.source.uri, innerUri);
}
// Reference "inner" using a non-canonical URI.
{
var path = convertPath('$outerLibPath/a.dart');
newFile(path, content: r'''
import 'inner/lib/b.dart';
''');
var result = await analysisSession.getResolvedUnit(path);
result as ResolvedUnitResult;
assertInnerUri(result);
}
// Reference "inner" using the canonical URI, via relative.
{
var path = '$outerLibPath/inner/lib/c.dart';
newFile(path, content: r'''
import 'b.dart';
''');
var result = await analysisSession.getResolvedUnit(path);
result as ResolvedUnitResult;
assertInnerUri(result);
}
// Reference "inner" using the canonical URI, via absolute.
{
var path = '$outerLibPath/inner/lib/d.dart';
newFile(path, content: '''
import '$innerUri';
''');
var result = await analysisSession.getResolvedUnit(path);
result as ResolvedUnitResult;
assertInnerUri(result);
}
}
}
@reflectiveTest
class AnalysisDriverSchedulerTest with ResourceProviderMixin {
final ByteStore byteStore = MemoryByteStore();

View file

@ -92,6 +92,26 @@ class FileSystemState_BazelWorkspaceTest extends BazelWorkspaceResolutionTest {
expect(generatedFile.path, generatedPath);
expect(writableFile2, same(generatedFile));
}
void test_getFileForUri_nestedLib_notCanonicalUri() async {
var outerPath = convertPath('$workspaceRootPath/my/outer/lib/a.dart');
var outerUri = Uri.parse('package:my.outer/a.dart');
var innerPath = convertPath('/workspace/my/outer/lib/inner/lib/b.dart');
var innerUri = Uri.parse('package:my.outer.lib.inner/b.dart');
var analysisDriver = driverFor(outerPath);
var fsState = analysisDriver.fsState;
// User code might use such relative URI.
var innerUri2 = outerUri.resolve('inner/lib/b.dart');
expect(innerUri2, Uri.parse('package:my.outer/inner/lib/b.dart'));
// However the returned file must use the canonical URI.
var innerFile = fsState.getFileForUri(innerUri2).t1!;
expect(innerFile.path, innerPath);
expect(innerFile.uri, innerUri);
}
}
@reflectiveTest

View file

@ -230,7 +230,7 @@ abstract class ResynthesizeAst2Test extends AbstractResynthesizeTest
}
var absoluteUri = resolveRelativeUri(source.uri, relativeUri);
var rewrittenUri = rewriteFileToPackageUri(sourceFactory, absoluteUri);
var rewrittenUri = rewriteToCanonicalUri(sourceFactory, absoluteUri);
if (rewrittenUri == null) {
return;
}