diff --git a/pkg/front_end/lib/compiler_options.dart b/pkg/front_end/lib/compiler_options.dart index 5230f4e47fb..731344c03dc 100644 --- a/pkg/front_end/lib/compiler_options.dart +++ b/pkg/front_end/lib/compiler_options.dart @@ -18,13 +18,13 @@ typedef void ErrorHandler(CompilationError error); /// /// Not intended to be implemented or extended by clients. class CompilerOptions { - /// The path to the Dart SDK. + /// The URI of the root of the Dart SDK (typically a "file:" URI). /// /// If `null`, the SDK will be searched for using /// [Platform.resolvedExecutable] as a starting point. /// /// This option is mutually exclusive with [sdkSummary]. - String sdkPath; + Uri sdkRoot; /// Callback to which compilation errors should be delivered. /// @@ -32,56 +32,58 @@ class CompilerOptions { /// type [CompilationError]. ErrorHandler onError = defaultErrorHandler; - /// Path to the ".packages" file. + /// URI of the ".packages" file (typically a "file:" URI). /// /// If `null`, the ".packages" file will be found via the standard /// package_config search algorithm. /// - /// If the empty string, no packages file will be used. - String packagesFilePath; + /// If the URI's path component is empty (e.g. `new Uri()`), no packages file + /// will be used. + Uri packagesFileUri; - /// Paths to the input summary files (excluding the SDK summary). These files - /// should all be linked summaries. They should also be closed, in the sense - /// that any libraries they reference should also appear in [inputSummaries] - /// or [sdkSummary]. - List inputSummaries = []; + /// URIs of input summary files (excluding the SDK summary; typically these + /// will be "file:" URIs). These files should all be linked summaries. They + /// should also be closed, in the sense that any libraries they reference + /// should also appear in [inputSummaries] or [sdkSummary]. + List inputSummaries = []; - /// Path to the SDK summary file. + /// URI of the SDK summary file (typically a "file:" URI). /// /// This should be a linked summary. If `null`, the SDK summary will be - /// searched for at a default location within [sdkPath]. + /// searched for at a default location within [sdkRoot]. /// - /// This option is mutually exclusive with [sdkPath]. TODO(paulberry): if the + /// This option is mutually exclusive with [sdkRoot]. TODO(paulberry): if the /// VM does not contain a pickled copy of the SDK, we might need to change /// this. - String sdkSummary; + Uri sdkSummary; /// URI override map. /// - /// This is a map from Uri to file path. Any URI override listed in this map - /// takes precedence over the URI resolution that would be implied by the - /// packages file (see [packagesFilePath]) and/or [bazelRoots]. + /// This is a map from URIs that might appear in import/export/part statements + /// to URIs that should be used to locate the corresponding files in the + /// [fileSystem]. Any URI override listed in this map takes precedence over + /// the URI resolution that would be implied by the packages file (see + /// [packagesFileUri]) and/or [multiRoots]. /// /// If a URI is not listed in this map, then the normal URI resolution /// algorithm will be used. /// /// TODO(paulberry): transition analyzer and dev_compiler to use the - /// "file:///bazel-root" mechanism, and then remove this. + /// "multi-root:" mechanism, and then remove this. @deprecated - Map uriOverride = {}; + Map uriOverride = {}; - /// Bazel roots. + /// Multi-roots. /// - /// Any Uri that resolves to "file:///bazel-root/$rest" will be searched for - /// at "$root/$rest" ("$root\\$rest" in Windows), where "$root" is drawn from - /// this list. If the file is not found at any of those locations, the URI - /// "file:///bazel-root/$rest" will be used directly. + /// Any Uri that resolves to "multi-root:///$rest" will be searched for + /// at "$root/$rest", where "$root" is drawn from this list. /// - /// Intended use: if the Bazel workspace is located at path "$workspace", this - /// could be set to `['$workspace', '$workspace/bazel-bin', - /// '$workspace/bazel-genfiles']`, effectively overlaying source and generated - /// files. - List bazelRoots = []; + /// Intended use: if the user has a Bazel workspace located at path + /// "$workspace", this could be set to the file URIs corresponding to the + /// paths for "$workspace", "$workspace/bazel-bin", + /// and "$workspace/bazel-genfiles", effectively overlaying source and + /// generated files. + List multiRoots = []; /// Sets the platform bit, which determines which patch files should be /// applied to the SDK. @@ -99,7 +101,7 @@ class CompilerOptions { /// /// All file system access performed by the front end goes through this /// mechanism, with one exception: if no value is specified for - /// [packagesFilePath], the packages file is located using the actual physical + /// [packagesFileUri], the packages file is located using the actual physical /// file system. TODO(paulberry): fix this. FileSystem fileSystem = PhysicalFileSystem.instance; diff --git a/pkg/front_end/lib/file_system.dart b/pkg/front_end/lib/file_system.dart index cadf82fddf4..6e57c266c06 100644 --- a/pkg/front_end/lib/file_system.dart +++ b/pkg/front_end/lib/file_system.dart @@ -18,22 +18,17 @@ import 'package:path/path.dart' as path; /// Not intended to be implemented or extended by clients. abstract class FileSystem { /// Returns a path context suitable for use with this [FileSystem]. + /// + /// TODO(paulberry): try to eliminate all usages of this. Since the + /// FileSystem API now uses URIs rather than paths, it should not be needed. path.Context get context; - /// Returns a [FileSystemEntity] corresponding to the given [path]. - /// - /// Uses of `..` and `.` in path are normalized before returning (so, for - /// example, `entityForPath('./foo')` and `entityForPath('foo')` are - /// equivalent). Relative paths are also converted to absolute paths. - /// - /// Does not check whether a file or folder exists at the given location. - FileSystemEntity entityForPath(String path); - /// Returns a [FileSystemEntity] corresponding to the given [uri]. /// /// Uses of `..` and `.` in the URI are normalized before returning. /// - /// If [uri] is not an absolute `file:` URI, an [Error] will be thrown. + /// If the URI scheme is not supported by this file system, an [Error] will be + /// thrown. /// /// Does not check whether a file or folder exists at the given location. FileSystemEntity entityForUri(Uri uri); @@ -46,14 +41,12 @@ abstract class FileSystem { /// /// Not intended to be implemented or extended by clients. abstract class FileSystemEntity { - /// Returns the absolute normalized path represented by this file system + /// Returns the absolute normalized URI represented by this file system /// entity. /// - /// Note: if the [FileSystemEntity] was created using - /// [FileSystem.entityForPath], this is not necessarily the same as the path - /// that was used to create the object, since the path might have been - /// normalized. - String get path; + /// Note: this is not necessarily the same as the URI that was passed to + /// [FileSystem.entityForUri], since the URI might have been normalized. + Uri get uri; /// Attempts to access this file system entity as a file and read its contents /// as raw bytes. diff --git a/pkg/front_end/lib/kernel_generator.dart b/pkg/front_end/lib/kernel_generator.dart index a87bb683b44..348d1f90215 100644 --- a/pkg/front_end/lib/kernel_generator.dart +++ b/pkg/front_end/lib/kernel_generator.dart @@ -59,7 +59,7 @@ Future kernelForProgram(Uri source, CompilerOptions options) async { /// which will be read are those listed in [sources], /// [CompilerOptions.inputSummaries], and [CompilerOptions.sdkSummary]. If a /// source file attempts to refer to a file which is not obtainable from these -/// paths, that will result in an error, even if the file exists on the +/// URIs, that will result in an error, even if the file exists on the /// filesystem. /// /// When [CompilerOptions.chaseDependencies] is true, this default behavior @@ -128,7 +128,8 @@ Future kernelForBuildUnit( Future _createLoader(CompilerOptions options, {Repository repository, Uri entry}) async { var kernelOptions = _convertOptions(options); - var packages = await createPackages(options.packagesFilePath, + var packages = await createPackages( + _uriToPath(options.packagesFileUri, options), discoveryPath: entry?.path); return new DartLoader( repository ?? new Repository(), kernelOptions, packages); @@ -137,11 +138,12 @@ Future _createLoader(CompilerOptions options, DartOptions _convertOptions(CompilerOptions options) { return new DartOptions( strongMode: options.strongMode, - sdk: options.sdkPath, + sdk: _uriToPath(options.sdkRoot, options), // TODO(sigmund): make it possible to use summaries and still compile the // sdk sources. - sdkSummary: options.compileSdk ? null : options.sdkSummary, - packagePath: options.packagesFilePath, + sdkSummary: + options.compileSdk ? null : _uriToPath(options.sdkSummary, options), + packagePath: _uriToPath(options.packagesFileUri, options), declaredVariables: options.declaredVariables); } @@ -152,6 +154,14 @@ void _reportErrors(List errors, ErrorHandler onError) { } } +String _uriToPath(Uri uri, CompilerOptions options) { + if (uri == null) return null; + if (uri.scheme != 'file') { + throw new StateError('Only file URIs are supported'); + } + return options.fileSystem.context.fromUri(uri); +} + // TODO(sigmund): delete this class. Dartk should not format errors itself, we // should just pass them along. class _DartkError implements CompilationError { diff --git a/pkg/front_end/lib/memory_file_system.dart b/pkg/front_end/lib/memory_file_system.dart index 267cbe36a6a..e7382adfb38 100644 --- a/pkg/front_end/lib/memory_file_system.dart +++ b/pkg/front_end/lib/memory_file_system.dart @@ -20,26 +20,29 @@ class MemoryFileSystem implements FileSystem { @override final p.Context context; - final Map _files = {}; + final Map _files = {}; /// The "current directory" in the in-memory virtual file system. /// - /// This is used to convert relative paths to absolute paths. - String currentDirectory; + /// This is used to convert relative URIs to absolute URIs. + /// + /// Always ends in a trailing '/'. + Uri currentDirectory; - MemoryFileSystem(this.context, this.currentDirectory); - - @override - MemoryFileSystemEntity entityForPath(String path) => - new MemoryFileSystemEntity._( - this, context.normalize(context.join(currentDirectory, path))); + MemoryFileSystem(this.context, Uri currentDirectory) + : currentDirectory = _addTrailingSlash(currentDirectory); @override MemoryFileSystemEntity entityForUri(Uri uri) { - if (uri.scheme != 'file') throw new ArgumentError('File URI expected'); - // Note: we don't have to verify that the URI's path is absolute, because - // URIs with non-empty schemes always have absolute paths. - return entityForPath(context.fromUri(uri)); + return new MemoryFileSystemEntity._( + this, currentDirectory.resolveUri(uri).normalizePath()); + } + + static Uri _addTrailingSlash(Uri uri) { + if (!uri.path.endsWith('/')) { + uri = uri.replace(path: uri.path + '/'); + } + return uri; } } @@ -49,22 +52,22 @@ class MemoryFileSystemEntity implements FileSystemEntity { final MemoryFileSystem _fileSystem; @override - final String path; + final Uri uri; - MemoryFileSystemEntity._(this._fileSystem, this.path); + MemoryFileSystemEntity._(this._fileSystem, this.uri); @override - int get hashCode => path.hashCode; + int get hashCode => uri.hashCode; @override bool operator ==(Object other) => other is MemoryFileSystemEntity && - other.path == path && + other.uri == uri && identical(other._fileSystem, _fileSystem); @override Future> readAsBytes() async { - List contents = _fileSystem._files[path]; + List contents = _fileSystem._files[uri]; if (contents != null) { return contents.toList(); } @@ -82,7 +85,7 @@ class MemoryFileSystemEntity implements FileSystemEntity { /// If no file exists, one is created. If a file exists already, it is /// overwritten. void writeAsBytesSync(List bytes) { - _fileSystem._files[path] = new Uint8List.fromList(bytes); + _fileSystem._files[uri] = new Uint8List.fromList(bytes); } /// Writes the given string to this file system entity. @@ -95,6 +98,6 @@ class MemoryFileSystemEntity implements FileSystemEntity { // Note: the return type of UTF8.encode is List, but in practice it // always returns Uint8List. We rely on that for efficiency, so that we // don't have to make an extra copy. - _fileSystem._files[path] = UTF8.encode(s) as Uint8List; + _fileSystem._files[uri] = UTF8.encode(s) as Uint8List; } } diff --git a/pkg/front_end/lib/physical_file_system.dart b/pkg/front_end/lib/physical_file_system.dart index 0ed5d8b0926..757eb60e834 100644 --- a/pkg/front_end/lib/physical_file_system.dart +++ b/pkg/front_end/lib/physical_file_system.dart @@ -23,37 +23,39 @@ class PhysicalFileSystem implements FileSystem { @override p.Context get context => p.context; - @override - FileSystemEntity entityForPath(String path) => - new _PhysicalFileSystemEntity(context.normalize(context.absolute(path))); - @override FileSystemEntity entityForUri(Uri uri) { - if (uri.scheme != 'file') throw new ArgumentError('File URI expected'); + if (uri.scheme != 'file' && uri.scheme != '') { + throw new ArgumentError('File URI expected'); + } // Note: we don't have to verify that the URI's path is absolute, because // URIs with non-empty schemes always have absolute paths. - return entityForPath(context.fromUri(uri)); + var path = context.fromUri(uri); + return new _PhysicalFileSystemEntity( + context.normalize(context.absolute(path))); } } /// Concrete implementation of [FileSystemEntity] for use by /// [PhysicalFileSystem]. class _PhysicalFileSystemEntity implements FileSystemEntity { - @override - final String path; + final String _path; - _PhysicalFileSystemEntity(this.path); + _PhysicalFileSystemEntity(this._path); @override - int get hashCode => path.hashCode; + int get hashCode => _path.hashCode; + + @override + Uri get uri => p.toUri(_path); @override bool operator ==(Object other) => - other is _PhysicalFileSystemEntity && other.path == path; + other is _PhysicalFileSystemEntity && other._path == _path; @override - Future> readAsBytes() => new io.File(path).readAsBytes(); + Future> readAsBytes() => new io.File(_path).readAsBytes(); @override - Future readAsString() => new io.File(path).readAsString(); + Future readAsString() => new io.File(_path).readAsString(); } diff --git a/pkg/front_end/lib/src/base/processed_options.dart b/pkg/front_end/lib/src/base/processed_options.dart index e1a4ef4dcba..360b5fa6a48 100644 --- a/pkg/front_end/lib/src/base/processed_options.dart +++ b/pkg/front_end/lib/src/base/processed_options.dart @@ -39,11 +39,11 @@ class ProcessedOptions { /// Get the [FileSystem] which should be used by the front end to access /// files. /// - /// If the client supplied bazel roots using [CompilerOptions.bazelRoots], the + /// If the client supplied roots using [CompilerOptions.multiRoots], the /// returned [FileSystem] will automatically perform the appropriate mapping. FileSystem get fileSystem { - // TODO(paulberry): support bazelRoots. - assert(_raw.bazelRoots.isEmpty); + // TODO(paulberry): support multiRoots. + assert(_raw.multiRoots.isEmpty); return _raw.fileSystem; } @@ -56,8 +56,7 @@ class ProcessedOptions { await _getPackages(); var sdkLibraries = {}; // TODO(paulberry): support SDK libraries - _uriResolver = - new UriResolver(_packages, sdkLibraries, fileSystem.context); + _uriResolver = new UriResolver(_packages, sdkLibraries); } return _uriResolver; } @@ -68,15 +67,14 @@ class ProcessedOptions { /// required to locate/read the packages file. Future> _getPackages() async { if (_packages == null) { - if (_raw.packagesFilePath == null) { + if (_raw.packagesFileUri == null) { throw new UnimplementedError(); // TODO(paulberry): search for .packages - } else if (_raw.packagesFilePath.isEmpty) { + } else if (_raw.packagesFileUri.path.isEmpty) { _packages = {}; } else { var contents = - await fileSystem.entityForPath(_raw.packagesFilePath).readAsBytes(); - var baseLocation = fileSystem.context.toUri(_raw.packagesFilePath); - _packages = package_config.parse(contents, baseLocation); + await fileSystem.entityForUri(_raw.packagesFileUri).readAsBytes(); + _packages = package_config.parse(contents, _raw.packagesFileUri); } } return _packages; diff --git a/pkg/front_end/lib/src/base/uri_resolver.dart b/pkg/front_end/lib/src/base/uri_resolver.dart index db469f0003d..0c6a4209743 100644 --- a/pkg/front_end/lib/src/base/uri_resolver.dart +++ b/pkg/front_end/lib/src/base/uri_resolver.dart @@ -2,13 +2,15 @@ // 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:path/path.dart' as p; - -/// The class `UriResolver` implements the rules for resolving URIs to file -/// paths. -/// -/// TODO(paulberry): Is it necessary to support the "http" scheme? +/// The class `UriResolver` implements the rules for resolving "dart:" and +/// "package:" URIs. class UriResolver { + /// The URI scheme used for "package" URIs. + static const PACKAGE_SCHEME = 'package'; + + /// The URI scheme used for "dart" URIs. + static const DART_SCHEME = 'dart'; + /// A map from package name to the file URI of the "lib" directory of the /// corresponding package. This is equivalent to the format returned by /// the "package_config" package's parse() function. @@ -18,36 +20,27 @@ class UriResolver { /// of the defining compilation unit of the SDK library. final Map sdkLibraries; - /// The path context which should be used to convert from file URIs to file - /// paths. - final p.Context pathContext; + UriResolver(this.packages, this.sdkLibraries); - /// The URI scheme used for "package" URIs. - static const PACKAGE_SCHEME = 'package'; - - /// The URI scheme used for "dart" URIs. - static const DART_SCHEME = 'dart'; - - /// The URI scheme used for "file" URIs. - static const FILE_SCHEME = 'file'; - - UriResolver(this.packages, this.sdkLibraries, this.pathContext); - - /// Converts a URI to a file path. + /// Converts "package:" and "dart:" URIs to the locations of the corresponding + /// files. /// - /// If the given URI is valid, and of a recognized form, returns the file path - /// it corresponds to. Otherwise returns `null`. It is not necessary for the - /// URI to be absolute (relative URIs will be converted to relative file - /// paths). + /// If the given URI is a "package:" or "dart:" URI, is well formed, and names + /// a package or dart library that is recognized, returns the URI it resolves + /// to. If the given URI is a "package:" or "dart:" URI, and is ill-formed + /// or names a package or dart library that is not recognized, returns `null`. /// - /// Note that no I/O is performed; the file path that is returned will be + /// If the given URI has any scheme other than "package:" or "dart:", it is + /// returned unchanged. + /// + /// It is not necessary for the URI to be absolute (relative URIs will be + /// passed through unchanged). + /// + /// Note that no I/O is performed; the URI that is returned will be /// independent of whether or not any particular file exists on the file /// system. - String resolve(Uri uri) { - Uri fileUri; - if (uri.scheme == FILE_SCHEME) { - fileUri = uri; - } else { + Uri resolve(Uri uri) { + if (uri.scheme == DART_SCHEME || uri.scheme == PACKAGE_SCHEME) { var path = uri.path; var slashIndex = path.indexOf('/'); String prefix; @@ -67,9 +60,9 @@ class UriResolver { libUri = sdkLibraries[prefix]; } if (libUri == null) return null; - fileUri = libUri.resolve(rest); - if (fileUri.scheme != FILE_SCHEME) return null; + return libUri.resolve(rest); + } else { + return uri; } - return pathContext.fromUri(fileUri); } } diff --git a/pkg/front_end/lib/src/dependency_grapher_impl.dart b/pkg/front_end/lib/src/dependency_grapher_impl.dart index 5dbe12d998d..09519315674 100644 --- a/pkg/front_end/lib/src/dependency_grapher_impl.dart +++ b/pkg/front_end/lib/src/dependency_grapher_impl.dart @@ -99,13 +99,14 @@ class _WalkerNode extends Node<_WalkerNode> { Future> computeDependencies() async { var dependencies = <_WalkerNode>[]; // TODO(paulberry): add error recovery if the file can't be read. - var path = walker.uriResolver.resolve(uri); - if (path == null) { + var resolvedUri = walker.uriResolver.resolve(uri); + if (resolvedUri == null) { // TODO(paulberry): If an error reporter was provided, report the error // in the proper way and continue. throw new StateError('Invalid URI: $uri'); } - var contents = await walker.fileSystem.entityForPath(path).readAsString(); + var contents = + await walker.fileSystem.entityForUri(resolvedUri).readAsString(); var scanner = new _Scanner(contents); var token = scanner.tokenize(); // TODO(paulberry): report errors. diff --git a/pkg/front_end/test/dependency_grapher_test.dart b/pkg/front_end/test/dependency_grapher_test.dart index bcfca56ae25..826283d9d81 100644 --- a/pkg/front_end/test/dependency_grapher_test.dart +++ b/pkg/front_end/test/dependency_grapher_test.dart @@ -35,15 +35,17 @@ class DependencyGrapherTest { // If no starting points given, assume the first entry in [contents] is the // single starting point. startingPoints ??= [contents.keys.first]; - var fileSystem = new MemoryFileSystem(pathos.posix, '/'); + var fileSystem = new MemoryFileSystem(pathos.posix, Uri.parse('file:///')); contents.forEach((path, text) { - fileSystem.entityForPath(path).writeAsStringSync(text); + fileSystem.entityForUri(pathos.posix.toUri(path)).writeAsStringSync(text); }); // TODO(paulberry): implement and test other option possibilities. var options = new CompilerOptions() ..fileSystem = fileSystem ..chaseDependencies = true - ..packagesFilePath = packagesFilePath; + ..packagesFileUri = packagesFilePath == '' + ? new Uri() + : pathos.posix.toUri(packagesFilePath); var graph = await graphForProgram( startingPoints.map(pathos.posix.toUri).toList(), options); return graph.topologicallySortedCycles; diff --git a/pkg/front_end/test/memory_file_system_test.dart b/pkg/front_end/test/memory_file_system_test.dart index b9757f3926a..365cd43af76 100644 --- a/pkg/front_end/test/memory_file_system_test.dart +++ b/pkg/front_end/test/memory_file_system_test.dart @@ -30,26 +30,23 @@ class FileTest extends _BaseTestNative { setUp() { super.setUp(); path = join(tempPath, 'file.txt'); - file = fileSystem.entityForPath(path); + file = entityForPath(path); } test_equals_differentPaths() { - expect( - file == fileSystem.entityForPath(join(tempPath, 'file2.txt')), isFalse); + expect(file == entityForPath(join(tempPath, 'file2.txt')), isFalse); } test_equals_samePath() { - expect( - file == fileSystem.entityForPath(join(tempPath, 'file.txt')), isTrue); + expect(file == entityForPath(join(tempPath, 'file.txt')), isTrue); } test_hashCode_samePath() { - expect(file.hashCode, - fileSystem.entityForPath(join(tempPath, 'file.txt')).hashCode); + expect(file.hashCode, entityForPath(join(tempPath, 'file.txt')).hashCode); } test_path() { - expect(file.path, path); + expect(file.uri, fileSystem.context.toUri(path)); } test_readAsBytes_badUtf8() async { @@ -128,40 +125,44 @@ abstract class MemoryFileSystemTestMixin extends _BaseTest { tempUri = fileSystem.context.toUri(tempPath); } - test_entityForPath() { - var path = join(tempPath, 'file.txt'); - expect(fileSystem.entityForPath(path).path, path); + test_currentDirectory_trailingSlash() { + // The currentDirectory should already end in a trailing slash. + expect(fileSystem.currentDirectory.path, endsWith('/')); + // A trailing slash should automatically be appended when creating a + // MemoryFileSystem. + var path = fileSystem.currentDirectory.path; + var currentDirectoryWithoutSlash = fileSystem.currentDirectory + .replace(path: path.substring(0, path.length - 1)); + expect( + new MemoryFileSystem(fileSystem.context, currentDirectoryWithoutSlash) + .currentDirectory, + fileSystem.currentDirectory); + // If the currentDirectory supplied to the MemoryFileSystem constructor + // already has a trailing slash, no further trailing slash should be added. + expect( + new MemoryFileSystem(fileSystem.context, fileSystem.currentDirectory) + .currentDirectory, + fileSystem.currentDirectory); } test_entityForPath_absolutize() { - expect(fileSystem.entityForPath('file.txt').path, - join(fileSystem.currentDirectory, 'file.txt')); + expect(entityForPath('file.txt').uri, + fileSystem.currentDirectory.resolve('file.txt')); } test_entityForPath_normalize_dot() { - expect(fileSystem.entityForPath(join(tempPath, '.', 'file.txt')).path, - join(tempPath, 'file.txt')); + expect(entityForPath(join(tempPath, '.', 'file.txt')).uri, + Uri.parse('$tempUri/file.txt')); } test_entityForPath_normalize_dotDot() { - expect( - fileSystem.entityForPath(join(tempPath, 'foo', '..', 'file.txt')).path, - join(tempPath, 'file.txt')); + expect(entityForPath(join(tempPath, 'foo', '..', 'file.txt')).uri, + Uri.parse('$tempUri/file.txt')); } test_entityForUri() { - expect(fileSystem.entityForUri(Uri.parse('$tempUri/file.txt')).path, - join(tempPath, 'file.txt')); - } - - test_entityForUri_bareUri_absolute() { - expect(() => fileSystem.entityForUri(Uri.parse('/file.txt')), - throwsA(new isInstanceOf())); - } - - test_entityForUri_bareUri_relative() { - expect(() => fileSystem.entityForUri(Uri.parse('file.txt')), - throwsA(new isInstanceOf())); + expect(fileSystem.entityForUri(Uri.parse('$tempUri/file.txt')).uri, + Uri.parse('$tempUri/file.txt')); } test_entityForUri_fileUri_relative() { @@ -184,18 +185,18 @@ abstract class MemoryFileSystemTestMixin extends _BaseTest { } test_entityForUri_nonFileUri() { - expect(() => fileSystem.entityForUri(Uri.parse('package:foo/bar.dart')), - throwsA(new isInstanceOf())); + var uri = Uri.parse('package:foo/bar.dart'); + expect(fileSystem.entityForUri(uri).uri, uri); } test_entityForUri_normalize_dot() { - expect(fileSystem.entityForUri(Uri.parse('$tempUri/./file.txt')).path, - join(tempPath, 'file.txt')); + expect(fileSystem.entityForUri(Uri.parse('$tempUri/./file.txt')).uri, + Uri.parse('$tempUri/file.txt')); } test_entityForUri_normalize_dotDot() { - expect(fileSystem.entityForUri(Uri.parse('$tempUri/foo/../file.txt')).path, - join(tempPath, 'file.txt')); + expect(fileSystem.entityForUri(Uri.parse('$tempUri/foo/../file.txt')).uri, + Uri.parse('$tempUri/file.txt')); } } @@ -213,8 +214,14 @@ class MemoryFileSystemTestWindows extends _BaseTestWindows abstract class _BaseTest { MemoryFileSystem get fileSystem; + String get tempPath; + + MemoryFileSystemEntity entityForPath(String path) => + fileSystem.entityForUri(fileSystem.context.toUri(path)); + String join(String path1, String path2, [String path3, String path4]); + void setUp(); } @@ -227,8 +234,8 @@ class _BaseTestNative extends _BaseTest { setUp() { tempPath = pathos.join(io.Directory.systemTemp.path, 'test_file_system'); - fileSystem = - new MemoryFileSystem(pathos.context, io.Directory.current.path); + fileSystem = new MemoryFileSystem( + pathos.context, pathos.toUri(io.Directory.current.path)); } } @@ -241,7 +248,7 @@ class _BaseTestPosix extends _BaseTest { void setUp() { tempPath = '/test_file_system'; - fileSystem = new MemoryFileSystem(pathos.posix, '/cwd'); + fileSystem = new MemoryFileSystem(pathos.posix, Uri.parse('file:///cwd')); } } @@ -254,6 +261,7 @@ class _BaseTestWindows extends _BaseTest { void setUp() { tempPath = r'c:\test_file_system'; - fileSystem = new MemoryFileSystem(pathos.windows, r'c:\cwd'); + fileSystem = + new MemoryFileSystem(pathos.windows, Uri.parse('file:///c:/cwd')); } } diff --git a/pkg/front_end/test/physical_file_system_test.dart b/pkg/front_end/test/physical_file_system_test.dart index 859e998a58f..2a8cbb6377b 100644 --- a/pkg/front_end/test/physical_file_system_test.dart +++ b/pkg/front_end/test/physical_file_system_test.dart @@ -30,35 +30,19 @@ class FileTest extends _BaseTest { setUp() { super.setUp(); path = p.join(tempPath, 'file.txt'); - file = PhysicalFileSystem.instance.entityForPath(path); + file = PhysicalFileSystem.instance.entityForUri(p.toUri(path)); } test_equals_differentPaths() { - expect( - file == - PhysicalFileSystem.instance - .entityForPath(p.join(tempPath, 'file2.txt')), - isFalse); + expect(file == entityForPath(p.join(tempPath, 'file2.txt')), isFalse); } test_equals_samePath() { - expect( - file == - PhysicalFileSystem.instance - .entityForPath(p.join(tempPath, 'file.txt')), - isTrue); + expect(file == entityForPath(p.join(tempPath, 'file.txt')), isTrue); } test_hashCode_samePath() { - expect( - file.hashCode, - PhysicalFileSystem.instance - .entityForPath(p.join(tempPath, 'file.txt')) - .hashCode); - } - - test_path() { - expect(file.path, path); + expect(file.hashCode, entityForPath(p.join(tempPath, 'file.txt')).hashCode); } test_readAsBytes_badUtf8() async { @@ -98,6 +82,10 @@ class FileTest extends _BaseTest { new io.File(path).writeAsBytesSync(bytes); expect(await file.readAsString(), '\u20ac'); } + + test_uri() { + expect(file.uri, p.toUri(path)); + } } @reflectiveTest @@ -111,48 +99,35 @@ class PhysicalFileSystemTest extends _BaseTest { test_entityForPath() { var path = p.join(tempPath, 'file.txt'); - expect(PhysicalFileSystem.instance.entityForPath(path).path, path); + expect(entityForPath(path).uri, p.toUri(path)); } test_entityForPath_absolutize() { - expect(PhysicalFileSystem.instance.entityForPath('file.txt').path, - new io.File('file.txt').absolute.path); + expect(entityForPath('file.txt').uri, + p.toUri(new io.File('file.txt').absolute.path)); } test_entityForPath_normalize_dot() { - expect( - PhysicalFileSystem.instance - .entityForPath(p.join(tempPath, '.', 'file.txt')) - .path, - p.join(tempPath, 'file.txt')); + expect(entityForPath(p.join(tempPath, '.', 'file.txt')).uri, + p.toUri(p.join(tempPath, 'file.txt'))); } test_entityForPath_normalize_dotDot() { - expect( - PhysicalFileSystem.instance - .entityForPath(p.join(tempPath, 'foo', '..', 'file.txt')) - .path, - p.join(tempPath, 'file.txt')); + expect(entityForPath(p.join(tempPath, 'foo', '..', 'file.txt')).uri, + p.toUri(p.join(tempPath, 'file.txt'))); } test_entityForUri() { expect( PhysicalFileSystem.instance .entityForUri(Uri.parse('$tempUri/file.txt')) - .path, - p.join(tempPath, 'file.txt')); + .uri, + p.toUri(p.join(tempPath, 'file.txt'))); } test_entityForUri_bareUri_absolute() { - expect( - () => PhysicalFileSystem.instance.entityForUri(Uri.parse('/file.txt')), - throwsA(new isInstanceOf())); - } - - test_entityForUri_bareUri_relative() { - expect( - () => PhysicalFileSystem.instance.entityForUri(Uri.parse('file.txt')), - throwsA(new isInstanceOf())); + expect(PhysicalFileSystem.instance.entityForUri(Uri.parse('/file.txt')).uri, + p.toUri(p.fromUri('/file.txt'))); } test_entityForUri_fileUri_relative() { @@ -185,16 +160,16 @@ class PhysicalFileSystemTest extends _BaseTest { expect( PhysicalFileSystem.instance .entityForUri(Uri.parse('$tempUri/./file.txt')) - .path, - p.join(tempPath, 'file.txt')); + .uri, + p.toUri(p.join(tempPath, 'file.txt'))); } test_entityForUri_normalize_dotDot() { expect( PhysicalFileSystem.instance .entityForUri(Uri.parse('$tempUri/foo/../file.txt')) - .path, - p.join(tempPath, 'file.txt')); + .uri, + p.toUri(p.join(tempPath, 'file.txt'))); } } @@ -202,6 +177,9 @@ class _BaseTest { io.Directory tempDirectory; String tempPath; + FileSystemEntity entityForPath(String path) => + PhysicalFileSystem.instance.entityForUri(p.toUri(path)); + setUp() { tempDirectory = io.Directory.systemTemp.createTempSync('test_file_system'); tempPath = tempDirectory.absolute.path; diff --git a/pkg/front_end/test/src/base/processed_options_test.dart b/pkg/front_end/test/src/base/processed_options_test.dart index ff34028afb3..76151dd0339 100644 --- a/pkg/front_end/test/src/base/processed_options_test.dart +++ b/pkg/front_end/test/src/base/processed_options_test.dart @@ -17,7 +17,7 @@ main() { @reflectiveTest class ProcessedOptionsTest { - final fileSystem = new MemoryFileSystem(pathos.posix, '/'); + final fileSystem = new MemoryFileSystem(pathos.posix, Uri.parse('file:///')); test_compileSdk_false() { for (var value in [false, true]) { @@ -37,46 +37,49 @@ class ProcessedOptionsTest { test_getUriResolver_explicitPackagesFile() async { // This .packages file should be ignored. - fileSystem.entityForPath('/.packages').writeAsStringSync('foo:bar\n'); + fileSystem + .entityForUri(Uri.parse('file:///.packages')) + .writeAsStringSync('foo:bar\n'); // This one should be used. fileSystem - .entityForPath('/explicit.packages') + .entityForUri(Uri.parse('file:///explicit.packages')) .writeAsStringSync('foo:baz\n'); var raw = new CompilerOptions() ..fileSystem = fileSystem - ..packagesFilePath = '/explicit.packages'; + ..packagesFileUri = Uri.parse('file:///explicit.packages'); var processed = new ProcessedOptions(raw); var uriResolver = await processed.getUriResolver(); expect(uriResolver.packages, {'foo': Uri.parse('file:///baz/')}); - expect(uriResolver.pathContext, same(fileSystem.context)); } test_getUriResolver_explicitPackagesFile_withBaseLocation() async { // This .packages file should be ignored. - fileSystem.entityForPath('/.packages').writeAsStringSync('foo:bar\n'); + fileSystem + .entityForUri(Uri.parse('file:///.packages')) + .writeAsStringSync('foo:bar\n'); // This one should be used. fileSystem - .entityForPath('/base/location/explicit.packages') + .entityForUri(Uri.parse('file:///base/location/explicit.packages')) .writeAsStringSync('foo:baz\n'); var raw = new CompilerOptions() ..fileSystem = fileSystem - ..packagesFilePath = '/base/location/explicit.packages'; + ..packagesFileUri = Uri.parse('file:///base/location/explicit.packages'); var processed = new ProcessedOptions(raw); var uriResolver = await processed.getUriResolver(); expect( uriResolver.packages, {'foo': Uri.parse('file:///base/location/baz/')}); - expect(uriResolver.pathContext, same(fileSystem.context)); } test_getUriResolver_noPackages() async { // .packages file should be ignored. - fileSystem.entityForPath('/.packages').writeAsStringSync('foo:bar\n'); + fileSystem + .entityForUri(Uri.parse('file:///.packages')) + .writeAsStringSync('foo:bar\n'); var raw = new CompilerOptions() ..fileSystem = fileSystem - ..packagesFilePath = ''; + ..packagesFileUri = new Uri(); var processed = new ProcessedOptions(raw); var uriResolver = await processed.getUriResolver(); expect(uriResolver.packages, isEmpty); - expect(uriResolver.pathContext, same(fileSystem.context)); } } diff --git a/pkg/front_end/test/src/base/uri_resolver_test.dart b/pkg/front_end/test/src/base/uri_resolver_test.dart index 1273a193448..af00240f74d 100644 --- a/pkg/front_end/test/src/base/uri_resolver_test.dart +++ b/pkg/front_end/test/src/base/uri_resolver_test.dart @@ -21,7 +21,7 @@ abstract class UriResolverTest { p.Context get pathContext; void test_badScheme() { - _expectResolution('foo:bar/baz.dart', null); + _expectResolutionUri('foo:bar/baz.dart', Uri.parse('foo:bar/baz.dart')); } void test_dart() { @@ -54,11 +54,11 @@ abstract class UriResolverTest { } void test_noSchemeAbsolute() { - _expectResolution('/foo.dart', null); + _expectResolutionUri('/foo.dart', Uri.parse('/foo.dart')); } void test_noSchemeRelative() { - _expectResolution('foo.dart', null); + _expectResolution('foo.dart', 'foo.dart'); } void test_package() { @@ -102,6 +102,13 @@ abstract class UriResolverTest { /// Verifies that the resolution of [uriString] produces the path /// [expectedResult]. void _expectResolution(String uriString, String expectedResult) { + _expectResolutionUri(uriString, + expectedResult == null ? null : pathContext.toUri(expectedResult)); + } + + /// Verifies that the resolution of [uriString] produces the URI + /// [expectedResult]. + void _expectResolutionUri(String uriString, Uri expectedResult) { var packages = { 'foo': _u('packages/foo/lib/'), 'bar': _u('packages/bar/lib/') @@ -110,7 +117,7 @@ abstract class UriResolverTest { 'core': _u('sdk/lib/core/core.dart'), 'async': _u('sdk/lib/async/async.dart') }; - var uriResolver = new UriResolver(packages, sdkLibraries, pathContext); + var uriResolver = new UriResolver(packages, sdkLibraries); expect(uriResolver.resolve(Uri.parse(uriString)), expectedResult); } diff --git a/pkg/front_end/tool/example.dart b/pkg/front_end/tool/example.dart index 1d49b228759..d81f43746e3 100644 --- a/pkg/front_end/tool/example.dart +++ b/pkg/front_end/tool/example.dart @@ -11,17 +11,19 @@ Future dumpToSink(Program program, StreamSink> sink) { } Future kernelToSink(Uri entry, StreamSink> sink) async { - var program = await kernelForProgram(entry, + var program = await kernelForProgram( + entry, new CompilerOptions() - ..sdkPath = 'sdk' - ..packagesFilePath = '.packages' + ..sdkRoot = new Uri.file('sdk') + ..packagesFileUri = new Uri.file('.packages') ..onError = (e) => print(e.message)); await dumpToSink(program, sink); } main(args) async { - kernelToSink(Uri.base.resolve(args[0]), + kernelToSink( + Uri.base.resolve(args[0]), // TODO(sigmund,hausner): define memory type where to dump binary data. new StreamController>.broadcast().sink); } diff --git a/pkg/front_end/tool/perf.dart b/pkg/front_end/tool/perf.dart index a69251bb818..7c4e4cd1d7b 100644 --- a/pkg/front_end/tool/perf.dart +++ b/pkg/front_end/tool/perf.dart @@ -115,15 +115,16 @@ Future generateKernel(Uri entryUri, var options = new CompilerOptions() ..strongMode = false ..compileSdk = compileSdk - ..packagesFilePath = '.packages' + ..packagesFileUri = new Uri.file('.packages') ..onError = ((e) => print('${e.message}')); if (useSdkSummary) { // TODO(sigmund): adjust path based on the benchmark runner architecture. // Possibly let the runner make the file available at an architecture // independent location. - options.sdkSummary = 'out/ReleaseX64/dart-sdk/lib/_internal/spec.sum'; + options.sdkSummary = + new Uri.file('out/ReleaseX64/dart-sdk/lib/_internal/spec.sum'); } else { - options.sdkPath = 'sdk'; + options.sdkRoot = new Uri.file('sdk'); } Program program = await kernelForProgram(entryUri, options); dartkTimer.stop();