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

Side by Side 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: add zone and crash report 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 import 'dart:async'; 5 import 'dart:async';
6 6
7 import 'package:kernel/target/targets.dart';
8 import 'package:kernel/target/vm_fasta.dart';
7 import 'package:front_end/compiler_options.dart'; 9 import 'package:front_end/compiler_options.dart';
8 import 'package:front_end/file_system.dart'; 10 import 'package:front_end/file_system.dart';
9 import 'package:front_end/src/fasta/translate_uri.dart'; 11 import 'package:front_end/src/fasta/translate_uri.dart';
12 import 'package:front_end/src/fasta/ticker.dart';
13 import 'package:front_end/src/fasta/errors.dart';
10 import 'package:front_end/src/base/performace_logger.dart'; 14 import 'package:front_end/src/base/performace_logger.dart';
11 import 'package:front_end/src/incremental/byte_store.dart'; 15 import 'package:front_end/src/incremental/byte_store.dart';
12 import 'package:front_end/src/simple_error.dart'; 16 import 'package:front_end/src/simple_error.dart';
13 import 'package:package_config/packages_file.dart' as package_config; 17 import 'package:package_config/packages_file.dart' as package_config;
14 import 'package:kernel/kernel.dart' show Program, loadProgramFromBytes; 18 import 'package:kernel/kernel.dart'
19 show Program, loadProgramFromBytes, CanonicalName;
15 20
16 /// Wrapper around [CompilerOptions] which exposes the options in a form useful 21 /// All options needed for the front end implementation.
17 /// to the front end implementation. 22 ///
23 /// This includes: all of [CompilerOptions] in a form useful to the
24 /// implementation, default values for options that were not provided,
25 /// and information derived from how the compiler was invoked (like the
26 /// entry-points given to the compiler and whether a modular or whole-program
27 /// API was used).
18 /// 28 ///
19 /// The intent is that the front end should immediately wrap any incoming 29 /// The intent is that the front end should immediately wrap any incoming
20 /// [CompilerOptions] object in this class before doing further processing, and 30 /// [CompilerOptions] object in this class before doing further processing, and
21 /// should thereafter access all options via the wrapper. This ensures that 31 /// should thereafter access all options via the wrapper. This ensures that
22 /// options are interpreted in a consistent way and that data derived from 32 /// options are interpreted in a consistent way and that data derived from
23 /// options is not unnecessarily recomputed. 33 /// options is not unnecessarily recomputed.
24 class ProcessedOptions { 34 class ProcessedOptions {
25 /// The raw [CompilerOptions] which this class wraps. 35 /// The raw [CompilerOptions] which this class wraps.
26 final CompilerOptions _raw; 36 final CompilerOptions _raw;
27 37
28 /// The package map derived from the options, or `null` if the package map has 38 /// The package map derived from the options, or `null` if the package map has
29 /// not been computed yet. 39 /// not been computed yet.
30 Map<String, Uri> _packages; 40 Map<String, Uri> _packages;
31 41
32 /// The object that knows how to resolve "package:" and "dart:" URIs, 42 /// The object that knows how to resolve "package:" and "dart:" URIs,
33 /// or `null` if it has not been computed yet. 43 /// or `null` if it has not been computed yet.
34 TranslateUri _uriTranslator; 44 TranslateUri _uriTranslator;
35 45
36 /// The SDK summary, or `null` if it has not been read yet. 46 /// The SDK summary, or `null` if it has not been read yet.
47 ///
48 /// A summary, also referred to as "outline" internally, is a [Program] where
49 /// all method bodies are left out. In essence, it contains just API
50 /// signatures and constants. When strong-mode is enabled, the summary already
51 /// includes inferred types.
37 Program _sdkSummaryProgram; 52 Program _sdkSummaryProgram;
38 53
39 /// The summary for each uri in `options.inputSummaries`. 54 /// The summary for each uri in `options.inputSummaries`.
55 ///
56 /// A summary, also referred to as "outline" internally, is a [Program] where
57 /// all method bodies are left out. In essence, it contains just API
58 /// signatures and constants. When strong-mode is enabled, the summary already
59 /// includes inferred types.
40 List<Program> _inputSummariesPrograms; 60 List<Program> _inputSummariesPrograms;
41 61
62 /// Other programs that are meant to be linked and compiled with the input
63 /// sources.
64 List<Program> _linkedDependencies;
65
42 /// The location of the SDK, or `null` if the location hasn't been determined 66 /// The location of the SDK, or `null` if the location hasn't been determined
43 /// yet. 67 /// yet.
44 Uri _sdkRoot; 68 Uri _sdkRoot;
45
46 Uri get sdkRoot => _sdkRoot ??= _normalizeSdkRoot(); 69 Uri get sdkRoot => _sdkRoot ??= _normalizeSdkRoot();
47 70
71 Uri _sdkSummary;
72 Uri get sdkSummary => _sdkSummary ??= _computeSdkSummaryUri();
73
74 Ticker _ticker;
75 Ticker get ticker => _ticker ??= new Ticker(isVerbose: _raw.verbose);
76
77 bool get verbose => _raw.verbose;
78
79 bool get verify => _raw.verify;
80
81 bool get debugDump => _raw.debugDump;
82
83 /// Like [CompilerOptions.chaseDependencies] but with the appropriate default
84 /// value filled in.
85 bool get chaseDependencies => _raw.chaseDependencies ?? !modularApi;
86
87 /// Whether the compiler was invoked with a modular API.
88 ///
89 /// Used to determine the default behavior for [chaseDependencies].
90 final bool modularApi;
Paul Berry 2017/07/04 15:12:14 Nit: consider making this private. Any reference
Siggi Cherem (dart-lang) 2017/07/05 18:42:12 Done.
91
92 /// The entry-points provided to the compiler.
93 final List<Uri> inputs;
94
48 /// Initializes a [ProcessedOptions] object wrapping the given [rawOptions]. 95 /// Initializes a [ProcessedOptions] object wrapping the given [rawOptions].
49 ProcessedOptions(CompilerOptions rawOptions) : this._raw = rawOptions; 96 ProcessedOptions(CompilerOptions rawOptions,
97 [this.modularApi = false, this.inputs = const []])
98 : this._raw = rawOptions;
50 99
51 /// The logger to report compilation progress. 100 /// The logger to report compilation progress.
52 PerformanceLog get logger { 101 PerformanceLog get logger {
53 return _raw.logger; 102 return _raw.logger;
54 } 103 }
55 104
56 /// The byte storage to get and put serialized data. 105 /// The byte storage to get and put serialized data.
57 ByteStore get byteStore { 106 ByteStore get byteStore {
58 return _raw.byteStore; 107 return _raw.byteStore;
59 } 108 }
60 109
110 void reportError(String message) {
111 _raw.onError(new SimpleError(message));
112 }
113
61 /// Runs various validations checks on the input options. For instance, 114 /// Runs various validations checks on the input options. For instance,
62 /// if an option is a path to a file, it checks that the file exists. 115 /// if an option is a path to a file, it checks that the file exists.
63 Future<bool> validateOptions() async { 116 Future<bool> validateOptions() async {
64 var fs = _raw.fileSystem; 117 for (var source in inputs) {
65 var root = _raw.sdkRoot; 118 if (source.scheme == 'file' &&
119 !await fileSystem.entityForUri(source).exists()) {
120 reportError("Entry-point file not found: $source");
121 return false;
122 }
123 }
66 124
67 bool _report(String msg) { 125 if (_raw.sdkRoot != null &&
68 _raw.onError(new SimpleError(msg)); 126 !await fileSystem.entityForUri(sdkRoot).exists()) {
127 reportError("SDK root directory not found: ${sdkRoot}");
69 return false; 128 return false;
70 } 129 }
71 130
72 if (root != null && !await fs.entityForUri(root).exists()) { 131 var summary = sdkSummary;
73 return _report("SDK root directory not found: ${_raw.sdkRoot}"); 132 if (summary != null && !await fileSystem.entityForUri(summary).exists()) {
133 reportError("SDK summary not found: ${summary}");
134 return false;
74 } 135 }
75 136
76 var summary = _raw.sdkSummary; 137 if (compileSdk && summary != null) {
77 if (summary != null && !await fs.entityForUri(summary).exists()) { 138 reportError(
78 return _report("SDK summary not found: ${_raw.sdkSummary}"); 139 "The compileSdk and sdkSummary options are mutually exclusive");
140 return false;
79 } 141 }
80
81 // TODO(sigmund): add checks for options that are meant to be disjoint (like
82 // sdkRoot and sdkSummary).
83 return true; 142 return true;
84 } 143 }
85 144
86 /// Determine whether to generate code for the SDK when compiling a 145 /// Determine whether to generate code for the SDK when compiling a
87 /// whole-program. 146 /// whole-program.
88 bool get compileSdk => _raw.compileSdk; 147 bool get compileSdk => _raw.compileSdk;
89 148
149 FileSystem _fileSystem;
150
90 /// Get the [FileSystem] which should be used by the front end to access 151 /// Get the [FileSystem] which should be used by the front end to access
91 /// files. 152 /// files.
92 /// 153 ///
93 /// If the client supplied roots using [CompilerOptions.multiRoots], the 154 /// If the client supplied roots using [CompilerOptions.multiRoots], the
94 /// returned [FileSystem] will automatically perform the appropriate mapping. 155 /// returned [FileSystem] will automatically perform the appropriate mapping.
95 FileSystem get fileSystem { 156 FileSystem get fileSystem => _fileSystem ??= _createFileSystem();
96 // TODO(paulberry): support multiRoots.
97 assert(_raw.multiRoots.isEmpty);
98 return _raw.fileSystem;
99 }
100 157
101 /// Whether to interpret Dart sources in strong-mode. 158 /// Whether to interpret Dart sources in strong-mode.
102 bool get strongMode => _raw.strongMode; 159 bool get strongMode => _raw.strongMode;
103 160
104 /// Get an outline program that summarizes the SDK. 161 Target _target;
105 Future<Program> get sdkSummaryProgram async { 162 Target get target => _target ??=
163 _raw.target ?? new VmFastaTarget(new TargetFlags(strongMode: strongMode));
164
165 /// Get an outline program that summarizes the SDK, if any.
166 Future<Program> loadSdkSummary(CanonicalName nameRoot) async {
106 if (_sdkSummaryProgram == null) { 167 if (_sdkSummaryProgram == null) {
107 if (_raw.sdkSummary == null) return null; 168 if (sdkSummary == null) return null;
108 _sdkSummaryProgram = await _loadProgram(_raw.sdkSummary); 169 var bytes = await fileSystem.entityForUri(sdkSummary).readAsBytes();
170 _sdkSummaryProgram = loadProgram(bytes, nameRoot);
109 } 171 }
110 return _sdkSummaryProgram; 172 return _sdkSummaryProgram;
111 } 173 }
112 174
113 /// Get the summary programs for each of the underlying `inputSummaries` 175 /// Get the summary programs for each of the underlying `inputSummaries`
114 /// provided via [CompilerOptions]. 176 /// provided via [CompilerOptions].
115 Future<List<Program>> get inputSummariesPrograms async { 177 Future<List<Program>> loadInputSummaries(CanonicalName nameRoot) async {
116 if (_inputSummariesPrograms == null) { 178 if (_inputSummariesPrograms == null) {
117 var uris = _raw.inputSummaries; 179 var uris = _raw.inputSummaries;
118 if (uris == null || uris.isEmpty) return const <Program>[]; 180 if (uris == null || uris.isEmpty) return const <Program>[];
119 _inputSummariesPrograms = await Future.wait(uris.map(_loadProgram)); 181 var allBytes = await Future
182 .wait(uris.map((uri) => fileSystem.entityForUri(uri).readAsBytes()));
183 _inputSummariesPrograms =
184 allBytes.map((bytes) => loadProgram(bytes, nameRoot)).toList();
120 } 185 }
121 return _inputSummariesPrograms; 186 return _inputSummariesPrograms;
122 } 187 }
123 188
124 Future<Program> _loadProgram(Uri uri) async { 189 /// Load each of the [CompilerOptions.linkedDependencies] programs.
125 var bytes = await fileSystem.entityForUri(uri).readAsBytes(); 190 Future<List<Program>> loadLinkDependencies(CanonicalName nameRoot) async {
126 return loadProgramFromBytes(bytes)..unbindCanonicalNames(); 191 if (_linkedDependencies == null) {
192 var uris = _raw.linkedDependencies;
193 if (uris == null || uris.isEmpty) return const <Program>[];
194 var allBytes = await Future
195 .wait(uris.map((uri) => fileSystem.entityForUri(uri).readAsBytes()));
196 _linkedDependencies =
197 allBytes.map((bytes) => loadProgram(bytes, nameRoot)).toList();
198 }
199 return _linkedDependencies;
200 }
201
202 /// Helper to load a .dill file from [uri] using the existing [nameRoot].
203 Program loadProgram(List<int> bytes, CanonicalName nameRoot) {
204 return loadProgramFromBytes(bytes, new Program(nameRoot: nameRoot));
127 } 205 }
128 206
129 /// Get the [TranslateUri] which resolves "package:" and "dart:" URIs. 207 /// Get the [TranslateUri] which resolves "package:" and "dart:" URIs.
130 /// 208 ///
131 /// This is an asynchronous method since file system operations may be 209 /// This is an asynchronous method since file system operations may be
132 /// required to locate/read the packages file as well as SDK metadata. 210 /// required to locate/read the packages file as well as SDK metadata.
133 Future<TranslateUri> getUriTranslator() async { 211 Future<TranslateUri> getUriTranslator() async {
134 if (_uriTranslator == null) { 212 if (_uriTranslator == null) {
135 await _getPackages(); 213 await _getPackages();
136 // TODO(scheglov) Load SDK libraries from whatever format we decide. 214 // TODO(scheglov) Load SDK libraries from whatever format we decide.
137 // TODO(scheglov) Remove the field "_raw.dartLibraries". 215 // TODO(scheglov) Remove the field "_raw.dartLibraries".
138 _uriTranslator = new TranslateUri( 216 var libraries = _raw.dartLibraries ?? await _parseLibraries();
139 _packages, _raw.dartLibraries, const <String, List<Uri>>{}); 217 _uriTranslator =
140 _uriTranslator.dartLibraries.addAll(_raw.dartLibraries); 218 new TranslateUri(_packages, libraries, const <String, List<Uri>>{});
219 ticker.logMs("Read packages file");
141 } 220 }
142 return _uriTranslator; 221 return _uriTranslator;
143 } 222 }
144 223
224 Future<Map<String, Uri>> _parseLibraries() async {
225 Uri librariesJson = _raw.sdkRoot?.resolve("lib/libraries.json");
226 return await computeLibraries(fileSystem, librariesJson);
227 }
228
145 /// Get the package map which maps package names to URIs. 229 /// Get the package map which maps package names to URIs.
146 /// 230 ///
147 /// This is an asynchronous getter since file system operations may be 231 /// This is an asynchronous getter since file system operations may be
148 /// required to locate/read the packages file. 232 /// required to locate/read the packages file.
149 Future<Map<String, Uri>> _getPackages() async { 233 Future<Map<String, Uri>> _getPackages() async {
150 if (_packages == null) { 234 if (_packages == null) {
151 if (_raw.packagesFileUri == null) { 235 if (_raw.packagesFileUri == null) {
152 throw new UnimplementedError(); // TODO(paulberry): search for .packages 236 throw new UnimplementedError(); // TODO(paulberry): search for .packages
153 } else if (_raw.packagesFileUri.path.isEmpty) { 237 } else if (_raw.packagesFileUri.path.isEmpty) {
154 _packages = {}; 238 _packages = {};
(...skipping 14 matching lines...) Expand all
169 // If an SDK summary location was provided, the SDK itself should not be 253 // If an SDK summary location was provided, the SDK itself should not be
170 // needed. 254 // needed.
171 assert(_raw.sdkSummary == null); 255 assert(_raw.sdkSummary == null);
172 if (_raw.sdkRoot == null) { 256 if (_raw.sdkRoot == null) {
173 // TODO(paulberry): implement the algorithm for finding the SDK 257 // TODO(paulberry): implement the algorithm for finding the SDK
174 // automagically. 258 // automagically.
175 throw new UnimplementedError(); 259 throw new UnimplementedError();
176 } 260 }
177 var root = _raw.sdkRoot; 261 var root = _raw.sdkRoot;
178 if (!root.path.endsWith('/')) { 262 if (!root.path.endsWith('/')) {
179 root = root.replace(path: _sdkRoot.path + '/'); 263 root = root.replace(path: root.path + '/');
180 } 264 }
181 return root; 265 return root;
182 } 266 }
267
268 /// Get or infer the location of the SDK summary.
269 Uri _computeSdkSummaryUri() {
270 if (_raw.sdkSummary != null) return _raw.sdkSummary;
271
272 // Infer based on the sdkRoot, but only when `compileSdk` is false,
273 // otherwise the default intent was to compile the sdk from sources and not
274 // to load an sdk summary file.
275 if (_raw.compileSdk) return null;
276 return sdkRoot.resolve('outline.dill');
277 }
278
279 /// Create a [FileSystem] specific to the current options.
280 ///
281 /// If [chaseDependencies] is false, the resulting file system will be
282 /// hermetic.
283 FileSystem _createFileSystem() {
284 var result = _raw.fileSystem;
285 if (!chaseDependencies) {
286 var allInputs = inputs.toSet();
287 allInputs.addAll(_raw.inputSummaries);
288 allInputs.addAll(_raw.linkedDependencies);
289
290 if (sdkSummary != null) allInputs.add(sdkSummary);
291
292 if (_raw.sdkRoot != null) {
293 // TODO(sigmund): refine this, we should be more explicit about when
294 // sdkRoot and libraries.json are allowed to be used.
295 allInputs.add(sdkRoot);
296 allInputs.add(sdkRoot.resolve("lib/libraries.json"));
297 }
298
299 /// Note: Searching the file-system for the package-config is not
300 /// supported in hermetic builds.
301 if (_raw.packagesFileUri != null) allInputs.add(_raw.packagesFileUri);
302 result = new HermeticFileSystem(allInputs, result);
303 }
304 // TODO(paulberry): support multiRoots.
305 assert(_raw.multiRoots.isEmpty);
306 return result;
307 }
183 } 308 }
309
310 /// A [FileSystem] that only allows access to files that have been explicitly
311 /// whitelisted.
312 class HermeticFileSystem implements FileSystem {
313 final Set<Uri> includedFiles;
314 final FileSystem _realFileSystem;
315
316 HermeticFileSystem(this.includedFiles, this._realFileSystem);
317
318 FileSystemEntity entityForUri(Uri uri) {
319 if (includedFiles.contains(uri)) return _realFileSystem.entityForUri(uri);
320 return inputError(
321 null,
322 -1,
323 'Invalid access to $uri: '
324 'the file is accessed in a modular hermetic build '
325 '(where chaseDependencies is false), but it was not '
Paul Berry 2017/07/04 15:12:14 Is this going to be a user-visible error message?
Siggi Cherem (dart-lang) 2017/07/05 18:42:11 Good point. removed.
326 'explicitly listed as an input.');
327 }
328 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698