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 a2060b97bdc6987724ba6c600458473165b8793a..f60bac5d52bf35123cf86d5e643ffd4a5af92aff 100644 |
--- a/pkg/front_end/lib/src/base/processed_options.dart |
+++ b/pkg/front_end/lib/src/base/processed_options.dart |
@@ -4,13 +4,14 @@ |
import 'dart:async'; |
-import 'package:analyzer/src/summary/idl.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/incremental/byte_store.dart'; |
+import 'package:front_end/src/simple_error.dart'; |
import 'package:package_config/packages_file.dart' as package_config; |
+import 'package:kernel/kernel.dart' show Program, loadProgramFromBytes; |
/// Wrapper around [CompilerOptions] which exposes the options in a form useful |
/// to the front end implementation. |
@@ -32,13 +33,18 @@ class ProcessedOptions { |
/// or `null` if it has not been computed yet. |
TranslateUri _uriTranslator; |
- /// The summary bundle for the SDK, or `null` if it has not been read yet. |
- PackageBundle _sdkSummary; |
+ /// The SDK summary, or `null` if it has not been read yet. |
+ Program _sdkSummaryProgram; |
+ |
+ /// The summary for each uri in `options.inputSummaries`. |
+ List<Program> _inputSummariesPrograms; |
/// The location of the SDK, or `null` if the location hasn't been determined |
/// yet. |
Uri _sdkRoot; |
+ Uri get sdkRoot => _sdkRoot ??= _normalizeSdkRoot(); |
+ |
/// Initializes a [ProcessedOptions] object wrapping the given [rawOptions]. |
ProcessedOptions(CompilerOptions rawOptions) : this._raw = rawOptions; |
@@ -52,6 +58,31 @@ class ProcessedOptions { |
return _raw.byteStore; |
} |
+ /// 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; |
+ |
+ bool _report(String msg) { |
+ _raw.onError(new SimpleError(msg)); |
+ return false; |
+ } |
+ |
+ if (root != null && !await fs.entityForUri(root).exists()) { |
+ return _report("SDK root directory not found: ${_raw.sdkRoot}"); |
+ } |
+ |
+ var summary = _raw.sdkSummary; |
+ if (summary != null && !await fs.entityForUri(summary).exists()) { |
+ return _report("SDK summary not found: ${_raw.sdkSummary}"); |
+ } |
+ |
+ // TODO(sigmund): add checks for options that are meant to be disjoint (like |
+ // sdkRoot and sdkSummary). |
+ return true; |
+ } |
+ |
/// Determine whether to generate code for the SDK when compiling a |
/// whole-program. |
bool get compileSdk => _raw.compileSdk; |
@@ -70,28 +101,29 @@ class ProcessedOptions { |
/// Whether to interpret Dart sources in strong-mode. |
bool get strongMode => _raw.strongMode; |
- /// Get the summary bundle for the SDK. |
- /// |
- /// This is an asynchronous getter since file system operations are required. |
- Future<PackageBundle> getSdkSummary() async { |
- if (_sdkSummary == null) { |
- Uri summaryLocation; |
- if (_raw.sdkSummary != null) { |
- // Options sdkSummary and sdkRoot are mutually exclusive. |
- assert(_raw.sdkRoot == null); |
- // No need to look for the SDK; we were told where the SDK summary is. |
- summaryLocation = _raw.sdkSummary; |
- } else { |
- // Need to look for the SDK summary inside the SDK. |
- var sdkRoot = await _getSdkRoot(); |
- summaryLocation = sdkRoot.resolve( |
- 'lib/_internal/' + (_raw.strongMode ? 'strong.sum' : 'spec.sum')); |
- } |
- var summaryBytes = |
- await fileSystem.entityForUri(summaryLocation).readAsBytes(); |
- _sdkSummary = new PackageBundle.fromBuffer(summaryBytes); |
+ /// Get an outline program that summarizes the SDK. |
+ Future<Program> get sdkSummaryProgram async { |
+ if (_sdkSummaryProgram == null) { |
+ if (_raw.sdkSummary == null) return null; |
+ _sdkSummaryProgram = await _loadProgram(_raw.sdkSummary); |
+ } |
+ return _sdkSummaryProgram; |
+ } |
+ |
+ /// Get the summary programs for each of the underlying `inputSummaries` |
+ /// provided via [CompilerOptions]. |
+ Future<List<Program>> get inputSummariesPrograms async { |
+ if (_inputSummariesPrograms == null) { |
+ var uris = _raw.inputSummaries; |
+ if (uris == null || uris.isEmpty) return const <Program>[]; |
+ _inputSummariesPrograms = await Future.wait(uris.map(_loadProgram)); |
} |
- return _sdkSummary; |
+ return _inputSummariesPrograms; |
+ } |
+ |
+ Future<Program> _loadProgram(Uri uri) async { |
+ var bytes = await fileSystem.entityForUri(uri).readAsBytes(); |
+ return loadProgramFromBytes(bytes)..unbindCanonicalNames(); |
} |
/// Get the [TranslateUri] which resolves "package:" and "dart:" URIs. |
@@ -132,21 +164,19 @@ class ProcessedOptions { |
/// |
/// This is an asynchronous getter since file system operations may be |
/// required to locate the SDK. |
- Future<Uri> _getSdkRoot() async { |
- if (_sdkRoot == null) { |
- // If an SDK summary location was provided, the SDK itself should not be |
- // needed. |
- assert(_raw.sdkSummary == null); |
- if (_raw.sdkRoot == null) { |
- // TODO(paulberry): implement the algorithm for finding the SDK |
- // automagically. |
- throw new UnimplementedError(); |
- } |
- _sdkRoot = _raw.sdkRoot; |
- if (!_sdkRoot.path.endsWith('/')) { |
- _sdkRoot = _sdkRoot.replace(path: _sdkRoot.path + '/'); |
- } |
+ Uri _normalizeSdkRoot() { |
+ // If an SDK summary location was provided, the SDK itself should not be |
+ // needed. |
+ assert(_raw.sdkSummary == null); |
+ if (_raw.sdkRoot == null) { |
+ // TODO(paulberry): implement the algorithm for finding the SDK |
+ // automagically. |
+ throw new UnimplementedError(); |
+ } |
+ var root = _raw.sdkRoot; |
+ if (!root.path.endsWith('/')) { |
+ root = root.replace(path: _sdkRoot.path + '/'); |
} |
- return _sdkRoot; |
+ return root; |
} |
} |