Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Unified Diff: pkg/front_end/lib/src/base/processed_options.dart

Issue 2953703002: Tweak public APIs and use them in patch_sdk, dart2js, and kernel-service (Closed)
Patch Set: cl review updates: cleanup in kernel deserialization Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/front_end/lib/kernel_generator.dart ('k') | pkg/front_end/lib/src/fasta/builder/library_builder.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 a42d2b54caa8c554bb705ee450a79a3a61a8ab64..b2e93ab6008cb4553aec0ad17fb6d3d515a3733e 100644
--- a/pkg/front_end/lib/src/base/processed_options.dart
+++ b/pkg/front_end/lib/src/base/processed_options.dart
@@ -4,17 +4,27 @@
import 'dart:async';
+import 'package:front_end/compilation_error.dart';
import 'package:front_end/compiler_options.dart';
import 'package:front_end/file_system.dart';
-import 'package:front_end/src/fasta/translate_uri.dart';
import 'package:front_end/src/base/performace_logger.dart';
+import 'package:front_end/src/fasta/ticker.dart';
+import 'package:front_end/src/fasta/translate_uri.dart';
import 'package:front_end/src/incremental/byte_store.dart';
-import 'package:front_end/src/simple_error.dart';
+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_file.dart' as package_config;
-import 'package:kernel/kernel.dart' show Program, loadProgramFromBytes;
+import 'package:source_span/source_span.dart' show SourceSpan;
-/// Wrapper around [CompilerOptions] which exposes the options in a form useful
-/// to the front end implementation.
+/// All options needed for the front end implementation.
+///
+/// This includes: all of [CompilerOptions] in a form useful to the
+/// implementation, default values for options that were not provided,
+/// and information derived from how the compiler was invoked (like the
+/// entry-points given to the compiler and whether a modular or whole-program
+/// API was used).
///
/// The intent is that the front end should immediately wrap any incoming
/// [CompilerOptions] object in this class before doing further processing, and
@@ -34,19 +44,58 @@ class ProcessedOptions {
TranslateUri _uriTranslator;
/// The SDK summary, or `null` if it has not been read yet.
+ ///
+ /// A summary, also referred to as "outline" internally, is a [Program] where
+ /// all method bodies are left out. In essence, it contains just API
+ /// signatures and constants. When strong-mode is enabled, the summary already
+ /// includes inferred types.
Program _sdkSummaryProgram;
/// The summary for each uri in `options.inputSummaries`.
+ ///
+ /// A summary, also referred to as "outline" internally, is a [Program] where
+ /// all method bodies are left out. In essence, it contains just API
+ /// signatures and constants. When strong-mode is enabled, the summary already
+ /// includes inferred types.
List<Program> _inputSummariesPrograms;
+ /// Other programs that are meant to be linked and compiled with the input
+ /// sources.
+ List<Program> _linkedDependencies;
+
/// The location of the SDK, or `null` if the location hasn't been determined
/// yet.
Uri _sdkRoot;
-
Uri get sdkRoot => _sdkRoot ??= _normalizeSdkRoot();
+ Uri _sdkSummary;
+ Uri get sdkSummary => _sdkSummary ??= _computeSdkSummaryUri();
+
+ Ticker ticker;
+
+ bool get verbose => _raw.verbose;
+
+ bool get verify => _raw.verify;
+
+ bool get debugDump => _raw.debugDump;
+
+ /// Like [CompilerOptions.chaseDependencies] but with the appropriate default
+ /// value filled in.
+ bool get chaseDependencies => _raw.chaseDependencies ?? !_modularApi;
+
+ /// Whether the compiler was invoked with a modular API.
+ ///
+ /// Used to determine the default behavior for [chaseDependencies].
+ final bool _modularApi;
+
+ /// The entry-points provided to the compiler.
+ final List<Uri> inputs;
+
/// Initializes a [ProcessedOptions] object wrapping the given [rawOptions].
- ProcessedOptions(CompilerOptions rawOptions) : this._raw = rawOptions;
+ ProcessedOptions(CompilerOptions rawOptions,
+ [this._modularApi = false, this.inputs = const []])
+ : this._raw = rawOptions,
+ ticker = new Ticker(isVerbose: rawOptions.verbose);
/// The logger to report compilation progress.
PerformanceLog get logger {
@@ -58,28 +107,40 @@ class ProcessedOptions {
return _raw.byteStore;
}
+ // TODO(sigmund): delete. We should use messages with error codes directly
+ // instead.
+ void reportError(String message) {
+ _raw.onError(new _CompilationError(message));
+ }
+
/// 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 {
- var fs = _raw.fileSystem;
- var root = _raw.sdkRoot;
+ for (var source in inputs) {
+ if (source.scheme == 'file' &&
+ !await fileSystem.entityForUri(source).exists()) {
+ reportError("Entry-point file not found: $source");
+ return false;
+ }
+ }
- bool _report(String msg) {
- _raw.onError(new SimpleError(msg));
+ if (_raw.sdkRoot != null &&
+ !await fileSystem.entityForUri(sdkRoot).exists()) {
+ reportError("SDK root directory not found: ${sdkRoot}");
return false;
}
- if (root != null && !await fs.entityForUri(root).exists()) {
- return _report("SDK root directory not found: ${_raw.sdkRoot}");
+ var summary = sdkSummary;
+ if (summary != null && !await fileSystem.entityForUri(summary).exists()) {
+ reportError("SDK summary not found: ${summary}");
+ return false;
}
- var summary = _raw.sdkSummary;
- if (summary != null && !await fs.entityForUri(summary).exists()) {
- return _report("SDK summary not found: ${_raw.sdkSummary}");
+ if (compileSdk && summary != null) {
+ reportError(
+ "The compileSdk and sdkSummary options are mutually exclusive");
+ return false;
}
-
- // TODO(sigmund): add checks for options that are meant to be disjoint (like
- // sdkRoot and sdkSummary).
return true;
}
@@ -87,43 +148,67 @@ class ProcessedOptions {
/// whole-program.
bool get compileSdk => _raw.compileSdk;
+ FileSystem _fileSystem;
+
/// Get the [FileSystem] which should be used by the front end to access
/// files.
///
/// If the client supplied roots using [CompilerOptions.multiRoots], the
/// returned [FileSystem] will automatically perform the appropriate mapping.
- FileSystem get fileSystem {
- // TODO(paulberry): support multiRoots.
- assert(_raw.multiRoots.isEmpty);
- return _raw.fileSystem;
- }
+ FileSystem get fileSystem => _fileSystem ??= _createFileSystem();
/// Whether to interpret Dart sources in strong-mode.
bool get strongMode => _raw.strongMode;
- /// Get an outline program that summarizes the SDK.
- Future<Program> get sdkSummaryProgram async {
+ Target _target;
+ Target get target => _target ??=
+ _raw.target ?? new VmFastaTarget(new TargetFlags(strongMode: strongMode));
+
+ /// Get an outline program that summarizes the SDK, if any.
+ // TODO(sigmund): move, this doesn't feel like an "option".
+ Future<Program> loadSdkSummary(CanonicalName nameRoot) async {
if (_sdkSummaryProgram == null) {
- if (_raw.sdkSummary == null) return null;
- _sdkSummaryProgram = await _loadProgram(_raw.sdkSummary);
+ if (sdkSummary == null) return null;
+ var bytes = await fileSystem.entityForUri(sdkSummary).readAsBytes();
+ _sdkSummaryProgram = loadProgram(bytes, nameRoot);
}
return _sdkSummaryProgram;
}
/// Get the summary programs for each of the underlying `inputSummaries`
/// provided via [CompilerOptions].
- Future<List<Program>> get inputSummariesPrograms async {
+ // TODO(sigmund): move, this doesn't feel like an "option".
+ Future<List<Program>> loadInputSummaries(CanonicalName nameRoot) async {
if (_inputSummariesPrograms == null) {
var uris = _raw.inputSummaries;
if (uris == null || uris.isEmpty) return const <Program>[];
- _inputSummariesPrograms = await Future.wait(uris.map(_loadProgram));
+ // TODO(sigmund): throttle # of concurrent opreations.
+ var allBytes = await Future
+ .wait(uris.map((uri) => fileSystem.entityForUri(uri).readAsBytes()));
+ _inputSummariesPrograms =
+ allBytes.map((bytes) => loadProgram(bytes, nameRoot)).toList();
}
return _inputSummariesPrograms;
}
- Future<Program> _loadProgram(Uri uri) async {
- var bytes = await fileSystem.entityForUri(uri).readAsBytes();
- return loadProgramFromBytes(bytes)..unbindCanonicalNames();
+ /// Load each of the [CompilerOptions.linkedDependencies] programs.
+ // TODO(sigmund): move, this doesn't feel like an "option".
+ Future<List<Program>> loadLinkDependencies(CanonicalName nameRoot) async {
+ if (_linkedDependencies == null) {
+ var uris = _raw.linkedDependencies;
+ if (uris == null || uris.isEmpty) return const <Program>[];
+ // TODO(sigmund): throttle # of concurrent opreations.
+ var allBytes = await Future
+ .wait(uris.map((uri) => fileSystem.entityForUri(uri).readAsBytes()));
+ _linkedDependencies =
+ allBytes.map((bytes) => loadProgram(bytes, nameRoot)).toList();
+ }
+ return _linkedDependencies;
+ }
+
+ /// Helper to load a .dill file from [uri] using the existing [nameRoot].
+ Program loadProgram(List<int> bytes, CanonicalName nameRoot) {
+ return loadProgramFromBytes(bytes, new Program(nameRoot: nameRoot));
}
/// Get the [TranslateUri] which resolves "package:" and "dart:" URIs.
@@ -135,13 +220,19 @@ class ProcessedOptions {
await _getPackages();
// TODO(scheglov) Load SDK libraries from whatever format we decide.
// TODO(scheglov) Remove the field "_raw.dartLibraries".
- _uriTranslator = new TranslateUri(
- _packages, _raw.dartLibraries, const <String, List<Uri>>{});
- _uriTranslator.dartLibraries.addAll(_raw.dartLibraries);
+ var libraries = _raw.dartLibraries ?? await _parseLibraries();
+ _uriTranslator =
+ new TranslateUri(_packages, libraries, const <String, List<Uri>>{});
+ ticker.logMs("Read packages file");
}
return _uriTranslator;
}
+ Future<Map<String, Uri>> _parseLibraries() async {
+ Uri librariesJson = _raw.sdkRoot?.resolve("lib/libraries.json");
+ return await computeLibraries(fileSystem, librariesJson);
+ }
+
/// Get the package map which maps package names to URIs.
///
/// This is an asynchronous getter since file system operations may be
@@ -149,7 +240,8 @@ class ProcessedOptions {
Future<Map<String, Uri>> _getPackages() async {
if (_packages == null) {
if (_raw.packagesFileUri == null) {
- throw new UnimplementedError(); // TODO(paulberry): search for .packages
+ // TODO(sigmund,paulberry): implement
+ throw new UnimplementedError('search for .packages');
} else if (_raw.packagesFileUri.path.isEmpty) {
_packages = {};
} else {
@@ -162,9 +254,6 @@ class ProcessedOptions {
}
/// Get the location of the SDK.
- ///
- /// This is an asynchronous getter since file system operations may be
- /// required to locate the SDK.
Uri _normalizeSdkRoot() {
// If an SDK summary location was provided, the SDK itself should not be
// needed.
@@ -172,12 +261,89 @@ class ProcessedOptions {
if (_raw.sdkRoot == null) {
// TODO(paulberry): implement the algorithm for finding the SDK
// automagically.
- throw new UnimplementedError();
+ throw new UnimplementedError('infer the default sdk location');
}
var root = _raw.sdkRoot;
if (!root.path.endsWith('/')) {
- root = root.replace(path: _sdkRoot.path + '/');
+ root = root.replace(path: root.path + '/');
}
return root;
}
+
+ /// Get or infer the location of the SDK summary.
+ Uri _computeSdkSummaryUri() {
+ if (_raw.sdkSummary != null) return _raw.sdkSummary;
+
+ // Infer based on the sdkRoot, but only when `compileSdk` is false,
+ // otherwise the default intent was to compile the sdk from sources and not
+ // to load an sdk summary file.
+ if (_raw.compileSdk) return null;
+ return sdkRoot.resolve('outline.dill');
+ }
+
+ /// Create a [FileSystem] specific to the current options.
+ ///
+ /// If [chaseDependencies] is false, the resulting file system will be
+ /// hermetic.
+ FileSystem _createFileSystem() {
+ var result = _raw.fileSystem;
+ if (!chaseDependencies) {
+ var allInputs = inputs.toSet();
+ allInputs.addAll(_raw.inputSummaries);
+ allInputs.addAll(_raw.linkedDependencies);
+
+ if (sdkSummary != null) allInputs.add(sdkSummary);
+
+ if (_raw.sdkRoot != null) {
+ // TODO(sigmund): refine this, we should be more explicit about when
+ // sdkRoot and libraries.json are allowed to be used.
+ allInputs.add(sdkRoot);
+ allInputs.add(sdkRoot.resolve("lib/libraries.json"));
+ }
+
+ /// Note: Searching the file-system for the package-config is not
+ /// supported in hermetic builds.
+ if (_raw.packagesFileUri != null) allInputs.add(_raw.packagesFileUri);
+ result = new HermeticFileSystem(allInputs, result);
+ }
+ // TODO(paulberry): support multiRoots.
+ assert(_raw.multiRoots.isEmpty);
+ return result;
+ }
+}
+
+/// A [FileSystem] that only allows access to files that have been explicitly
+/// whitelisted.
+class HermeticFileSystem implements FileSystem {
+ final Set<Uri> includedFiles;
+ final FileSystem _realFileSystem;
+
+ HermeticFileSystem(this.includedFiles, this._realFileSystem);
+
+ FileSystemEntity entityForUri(Uri uri) {
+ if (includedFiles.contains(uri)) return _realFileSystem.entityForUri(uri);
+ throw new HermeticAccessException(uri);
+ }
+}
+
+class HermeticAccessException extends FileSystemException {
+ HermeticAccessException(Uri uri)
+ : super(
+ uri,
+ 'Invalid access to $uri: '
+ 'the file is accessed in a modular hermetic build, '
+ 'but it was not explicitly listed as an input.');
+
+ @override
+ String toString() => message;
+}
+
+/// An error that only contains a message and no error location.
+class _CompilationError implements CompilationError {
+ String get correction => null;
+ SourceSpan get span => null;
+ final String message;
+ _CompilationError(this.message);
+
+ String toString() => message;
}
« no previous file with comments | « pkg/front_end/lib/kernel_generator.dart ('k') | pkg/front_end/lib/src/fasta/builder/library_builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698