Index: pkg/front_end/lib/src/base/processed_options.dart |
diff --git a/pkg/front_end/lib/src/base/processed_options.dart b/pkg/front_end/lib/src/base/processed_options.dart |
index a762812b7286264841246efb9153006f33f8a9dd..d7555b07614bbce56d638a1ec1aa61a405235f83 100644 |
--- a/pkg/front_end/lib/src/base/processed_options.dart |
+++ b/pkg/front_end/lib/src/base/processed_options.dart |
@@ -19,6 +19,9 @@ import 'package:kernel/kernel.dart' |
show Program, loadProgramFromBytes, CanonicalName; |
import 'package:kernel/target/targets.dart'; |
import 'package:kernel/target/vm_fasta.dart'; |
+import 'package:package_config/packages.dart' show Packages; |
+import 'package:package_config/src/packages_impl.dart' |
+ show NonFilePackagesDirectoryPackages, MapPackages; |
import 'package:package_config/packages_file.dart' as package_config; |
import 'package:source_span/source_span.dart' show SourceSpan, SourceLocation; |
@@ -41,7 +44,7 @@ class ProcessedOptions { |
/// The package map derived from the options, or `null` if the package map has |
/// not been computed yet. |
- Map<String, Uri> _packages; |
+ Packages _packages; |
/// The object that knows how to resolve "package:" and "dart:" URIs, |
/// or `null` if it has not been computed yet. |
@@ -128,8 +131,17 @@ class ProcessedOptions { |
/// Runs various validations checks on the input options. For instance, |
/// if an option is a path to a file, it checks that the file exists. |
Future<bool> validateOptions() async { |
+ if (inputs.isEmpty) { |
+ reportMessageWithoutLocation(messageMissingInputs); |
ahe
2017/07/14 13:44:57
Remove the "s" from Inputs.
Siggi Cherem (dart-lang)
2017/07/14 19:54:06
Done. Also updated the other messages to say "NotF
|
+ return false; |
+ } |
+ |
for (var source in inputs) { |
- if (source.scheme == 'file' && |
+ // Note: we don't translate Uris at this point because some of the |
+ // validation further below must be done before we even construct an |
+ // UriTranslator |
ahe
2017/07/14 13:44:57
Can we make this a TODO and check the inputs later
Siggi Cherem (dart-lang)
2017/07/14 19:54:06
Sure, but it will require some subtle ordering of
|
+ if (source.scheme != 'dart' && |
+ source.scheme != 'packages' && |
!await fileSystem.entityForUri(source).exists()) { |
reportMessageWithoutLocation( |
templateMissingInputFile.withArguments('$source')); |
@@ -253,22 +265,101 @@ class ProcessedOptions { |
/// |
/// This is an asynchronous getter since file system operations may be |
/// required to locate/read the packages file. |
- Future<Map<String, Uri>> _getPackages() async { |
+ Future<Packages> _getPackages() async { |
if (_packages == null) { |
if (_raw.packagesFileUri == null) { |
- // TODO(sigmund,paulberry): implement |
- return unimplemented('search for .packages'); |
- } else if (_raw.packagesFileUri.path.isEmpty) { |
- _packages = {}; |
+ if (inputs.length > 1) { |
+ reportMessageWithoutLocation( |
+ templateInternalProblemUnsupported.withArguments( |
+ "Cannot infer a .packages file when compiling multiple inputs.")); |
ahe
2017/07/14 13:44:57
This isn't an internal error, this is a problem wi
Siggi Cherem (dart-lang)
2017/07/14 19:54:06
Done.
Note we have to be careful about using flag
|
+ _packages = Packages.noPackages; |
+ } else { |
+ _packages = await _findPackages(inputs.first); |
+ } |
} else { |
- var contents = |
- await fileSystem.entityForUri(_raw.packagesFileUri).readAsBytes(); |
- _packages = package_config.parse(contents, _raw.packagesFileUri); |
+ _packages = await createPackagesFromFile(_raw.packagesFileUri); |
} |
} |
return _packages; |
} |
+ /// Create a [Packages] given the Uri to a `.packages` file. |
+ Future<Packages> createPackagesFromFile(Uri file) async { |
+ try { |
+ List<int> contents = await fileSystem.entityForUri(file).readAsBytes(); |
+ Map<String, Uri> map = package_config.parse(contents, file); |
+ return new MapPackages(map); |
+ } catch (e) { |
+ reportMessageWithoutLocation( |
+ templateInvalidPackagesFile.withArguments(file, "$e")); |
+ return Packages.noPackages; |
+ } |
+ } |
+ |
+ /// Finds a package resolution strategy using a [FileSystem]. |
+ /// |
+ /// The [scriptUri] points to a Dart script with a valid scheme accepted by |
+ /// the [FileSystem]. |
+ /// |
+ /// This function first tries to locate a `.packages` file in the `scriptUri` |
+ /// directory. If that is not found, it instead checks for the presence of a |
+ /// `packages/` directory in the same place. If that also fails, it starts |
+ /// checking parent directories for a `.packages` file, and stops if it finds |
+ /// it. Otherwise it gives up and returns [Packages.noPackages]. |
+ /// |
+ /// Note: this is a fork from `package:package_config/discovery.dart` to adapt |
+ /// it to use [FileSystem]. The logic here is a mix of the logic in the |
+ /// `findPackagesFromFile` and `findPackagesFromNonFile`: |
+ /// |
+ /// * Like `findPackagesFromFile` resolution searches for parent |
+ /// directories |
+ /// |
+ /// * Like `findPackagesFromNonFile` if we resolve packages as the |
+ /// `packages/` directory, we can't provide a list of packages that are |
+ /// visible. |
+ Future<Packages> _findPackages(Uri scriptUri) async { |
+ var dir = scriptUri.resolve('.'); |
+ if (!dir.isAbsolute) { |
+ reportMessageWithoutLocation(templateInternalProblemUnsupported |
+ .withArguments("Expected input Uri to be absolute: $scriptUri.")); |
+ return null; |
+ } |
+ if (!await fileSystem.entityForUri(dir).exists()) { |
+ reportMessageWithoutLocation(templateInternalProblemUnsupported |
+ .withArguments("Input directory does not exist: $dir.")); |
+ // TODO: report "Directory does not exist."; |
+ return null; |
+ } |
+ |
+ Future<Uri> checkInDir(Uri dir) async { |
+ Uri candidate = dir.resolve('.packages'); |
+ if (await fileSystem.entityForUri(candidate).exists()) return candidate; |
+ return null; |
+ } |
+ |
+ // Check for $cwd/.packages |
+ var candidate = await checkInDir(dir); |
+ if (candidate != null) return createPackagesFromFile(candidate); |
+ |
+ // Check for $cwd/packages/ |
+ var packagesDir = dir.resolve("packages/"); |
+ if (await fileSystem.entityForUri(packagesDir).exists()) { |
+ return new NonFilePackagesDirectoryPackages(packagesDir); |
+ } |
+ |
+ // Check for cwd(/..)+/.packages |
+ var parentDir = dir.resolve('..'); |
+ while (parentDir.path != dir.path) { |
+ candidate = await checkInDir(parentDir); |
+ if (candidate != null) break; |
+ dir = parentDir; |
+ parentDir = dir.resolve('..'); |
+ } |
+ |
+ if (candidate != null) return createPackagesFromFile(candidate); |
+ return Packages.noPackages; |
+ } |
+ |
/// Get the location of the SDK. |
Uri _normalizeSdkRoot() { |
// If an SDK summary location was provided, the SDK itself should not be |