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

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: 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 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:front_end/compilation_error.dart';
7 import 'package:front_end/compiler_options.dart'; 8 import 'package:front_end/compiler_options.dart';
8 import 'package:front_end/file_system.dart'; 9 import 'package:front_end/file_system.dart';
10 import 'package:front_end/src/base/performace_logger.dart';
11 import 'package:front_end/src/fasta/ticker.dart';
9 import 'package:front_end/src/fasta/translate_uri.dart'; 12 import 'package:front_end/src/fasta/translate_uri.dart';
10 import 'package:front_end/src/base/performace_logger.dart';
11 import 'package:front_end/src/incremental/byte_store.dart'; 13 import 'package:front_end/src/incremental/byte_store.dart';
12 import 'package:front_end/src/simple_error.dart'; 14 import 'package:kernel/kernel.dart'
15 show Program, loadProgramFromBytes, CanonicalName;
16 import 'package:kernel/target/targets.dart';
17 import 'package:kernel/target/vm_fasta.dart';
13 import 'package:package_config/packages_file.dart' as package_config; 18 import 'package:package_config/packages_file.dart' as package_config;
14 import 'package:kernel/kernel.dart' show Program, loadProgramFromBytes; 19 import 'package:source_span/source_span.dart' show SourceSpan;
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
76 bool get verbose => _raw.verbose;
77
78 bool get verify => _raw.verify;
79
80 bool get debugDump => _raw.debugDump;
81
82 /// Like [CompilerOptions.chaseDependencies] but with the appropriate default
83 /// value filled in.
84 bool get chaseDependencies => _raw.chaseDependencies ?? !_modularApi;
85
86 /// Whether the compiler was invoked with a modular API.
87 ///
88 /// Used to determine the default behavior for [chaseDependencies].
89 final bool _modularApi;
90
91 /// The entry-points provided to the compiler.
92 final List<Uri> inputs;
93
48 /// Initializes a [ProcessedOptions] object wrapping the given [rawOptions]. 94 /// Initializes a [ProcessedOptions] object wrapping the given [rawOptions].
49 ProcessedOptions(CompilerOptions rawOptions) : this._raw = rawOptions; 95 ProcessedOptions(CompilerOptions rawOptions,
96 [this._modularApi = false, this.inputs = const []])
97 : this._raw = rawOptions,
98 ticker = new Ticker(isVerbose: rawOptions.verbose);
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 // TODO(sigmund): delete. We should use messages with error codes directly
111 // instead.
112 void reportError(String message) {
113 _raw.onError(new _CompilationError(message));
114 }
115
61 /// Runs various validations checks on the input options. For instance, 116 /// 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. 117 /// if an option is a path to a file, it checks that the file exists.
63 Future<bool> validateOptions() async { 118 Future<bool> validateOptions() async {
64 var fs = _raw.fileSystem; 119 for (var source in inputs) {
65 var root = _raw.sdkRoot; 120 if (source.scheme == 'file' &&
121 !await fileSystem.entityForUri(source).exists()) {
122 reportError("Entry-point file not found: $source");
123 return false;
124 }
125 }
66 126
67 bool _report(String msg) { 127 if (_raw.sdkRoot != null &&
68 _raw.onError(new SimpleError(msg)); 128 !await fileSystem.entityForUri(sdkRoot).exists()) {
129 reportError("SDK root directory not found: ${sdkRoot}");
69 return false; 130 return false;
70 } 131 }
71 132
72 if (root != null && !await fs.entityForUri(root).exists()) { 133 var summary = sdkSummary;
73 return _report("SDK root directory not found: ${_raw.sdkRoot}"); 134 if (summary != null && !await fileSystem.entityForUri(summary).exists()) {
135 reportError("SDK summary not found: ${summary}");
136 return false;
74 } 137 }
75 138
76 var summary = _raw.sdkSummary; 139 if (compileSdk && summary != null) {
77 if (summary != null && !await fs.entityForUri(summary).exists()) { 140 reportError(
78 return _report("SDK summary not found: ${_raw.sdkSummary}"); 141 "The compileSdk and sdkSummary options are mutually exclusive");
142 return false;
79 } 143 }
80
81 // TODO(sigmund): add checks for options that are meant to be disjoint (like
82 // sdkRoot and sdkSummary).
83 return true; 144 return true;
84 } 145 }
85 146
86 /// Determine whether to generate code for the SDK when compiling a 147 /// Determine whether to generate code for the SDK when compiling a
87 /// whole-program. 148 /// whole-program.
88 bool get compileSdk => _raw.compileSdk; 149 bool get compileSdk => _raw.compileSdk;
89 150
151 FileSystem _fileSystem;
152
90 /// Get the [FileSystem] which should be used by the front end to access 153 /// Get the [FileSystem] which should be used by the front end to access
91 /// files. 154 /// files.
92 /// 155 ///
93 /// If the client supplied roots using [CompilerOptions.multiRoots], the 156 /// If the client supplied roots using [CompilerOptions.multiRoots], the
94 /// returned [FileSystem] will automatically perform the appropriate mapping. 157 /// returned [FileSystem] will automatically perform the appropriate mapping.
95 FileSystem get fileSystem { 158 FileSystem get fileSystem => _fileSystem ??= _createFileSystem();
96 // TODO(paulberry): support multiRoots.
97 assert(_raw.multiRoots.isEmpty);
98 return _raw.fileSystem;
99 }
100 159
101 /// Whether to interpret Dart sources in strong-mode. 160 /// Whether to interpret Dart sources in strong-mode.
102 bool get strongMode => _raw.strongMode; 161 bool get strongMode => _raw.strongMode;
103 162
104 /// Get an outline program that summarizes the SDK. 163 Target _target;
105 Future<Program> get sdkSummaryProgram async { 164 Target get target => _target ??=
165 _raw.target ?? new VmFastaTarget(new TargetFlags(strongMode: strongMode));
166
167 /// Get an outline program that summarizes the SDK, if any.
168 // TODO(sigmund): move, this doesn't feel like an "option".
169 Future<Program> loadSdkSummary(CanonicalName nameRoot) async {
106 if (_sdkSummaryProgram == null) { 170 if (_sdkSummaryProgram == null) {
107 if (_raw.sdkSummary == null) return null; 171 if (sdkSummary == null) return null;
108 _sdkSummaryProgram = await _loadProgram(_raw.sdkSummary); 172 var bytes = await fileSystem.entityForUri(sdkSummary).readAsBytes();
173 _sdkSummaryProgram = loadProgram(bytes, nameRoot);
109 } 174 }
110 return _sdkSummaryProgram; 175 return _sdkSummaryProgram;
111 } 176 }
112 177
113 /// Get the summary programs for each of the underlying `inputSummaries` 178 /// Get the summary programs for each of the underlying `inputSummaries`
114 /// provided via [CompilerOptions]. 179 /// provided via [CompilerOptions].
115 Future<List<Program>> get inputSummariesPrograms async { 180 // TODO(sigmund): move, this doesn't feel like an "option".
181 Future<List<Program>> loadInputSummaries(CanonicalName nameRoot) async {
116 if (_inputSummariesPrograms == null) { 182 if (_inputSummariesPrograms == null) {
117 var uris = _raw.inputSummaries; 183 var uris = _raw.inputSummaries;
118 if (uris == null || uris.isEmpty) return const <Program>[]; 184 if (uris == null || uris.isEmpty) return const <Program>[];
119 _inputSummariesPrograms = await Future.wait(uris.map(_loadProgram)); 185 // TODO(sigmund): throttle # of concurrent opreations.
186 var allBytes = await Future
187 .wait(uris.map((uri) => fileSystem.entityForUri(uri).readAsBytes()));
188 _inputSummariesPrograms =
189 allBytes.map((bytes) => loadProgram(bytes, nameRoot)).toList();
120 } 190 }
121 return _inputSummariesPrograms; 191 return _inputSummariesPrograms;
122 } 192 }
123 193
124 Future<Program> _loadProgram(Uri uri) async { 194 /// Load each of the [CompilerOptions.linkedDependencies] programs.
125 var bytes = await fileSystem.entityForUri(uri).readAsBytes(); 195 // TODO(sigmund): move, this doesn't feel like an "option".
126 return loadProgramFromBytes(bytes)..unbindCanonicalNames(); 196 Future<List<Program>> loadLinkDependencies(CanonicalName nameRoot) async {
197 if (_linkedDependencies == null) {
198 var uris = _raw.linkedDependencies;
199 if (uris == null || uris.isEmpty) return const <Program>[];
200 // TODO(sigmund): throttle # of concurrent opreations.
201 var allBytes = await Future
202 .wait(uris.map((uri) => fileSystem.entityForUri(uri).readAsBytes()));
203 _linkedDependencies =
204 allBytes.map((bytes) => loadProgram(bytes, nameRoot)).toList();
205 }
206 return _linkedDependencies;
207 }
208
209 /// Helper to load a .dill file from [uri] using the existing [nameRoot].
210 Program loadProgram(List<int> bytes, CanonicalName nameRoot) {
211 return loadProgramFromBytes(bytes, new Program(nameRoot: nameRoot));
127 } 212 }
128 213
129 /// Get the [TranslateUri] which resolves "package:" and "dart:" URIs. 214 /// Get the [TranslateUri] which resolves "package:" and "dart:" URIs.
130 /// 215 ///
131 /// This is an asynchronous method since file system operations may be 216 /// This is an asynchronous method since file system operations may be
132 /// required to locate/read the packages file as well as SDK metadata. 217 /// required to locate/read the packages file as well as SDK metadata.
133 Future<TranslateUri> getUriTranslator() async { 218 Future<TranslateUri> getUriTranslator() async {
134 if (_uriTranslator == null) { 219 if (_uriTranslator == null) {
135 await _getPackages(); 220 await _getPackages();
136 // TODO(scheglov) Load SDK libraries from whatever format we decide. 221 // TODO(scheglov) Load SDK libraries from whatever format we decide.
137 // TODO(scheglov) Remove the field "_raw.dartLibraries". 222 // TODO(scheglov) Remove the field "_raw.dartLibraries".
138 _uriTranslator = new TranslateUri( 223 var libraries = _raw.dartLibraries ?? await _parseLibraries();
139 _packages, _raw.dartLibraries, const <String, List<Uri>>{}); 224 _uriTranslator =
140 _uriTranslator.dartLibraries.addAll(_raw.dartLibraries); 225 new TranslateUri(_packages, libraries, const <String, List<Uri>>{});
226 ticker.logMs("Read packages file");
141 } 227 }
142 return _uriTranslator; 228 return _uriTranslator;
143 } 229 }
144 230
231 Future<Map<String, Uri>> _parseLibraries() async {
232 Uri librariesJson = _raw.sdkRoot?.resolve("lib/libraries.json");
233 return await computeLibraries(fileSystem, librariesJson);
234 }
235
145 /// Get the package map which maps package names to URIs. 236 /// Get the package map which maps package names to URIs.
146 /// 237 ///
147 /// This is an asynchronous getter since file system operations may be 238 /// This is an asynchronous getter since file system operations may be
148 /// required to locate/read the packages file. 239 /// required to locate/read the packages file.
149 Future<Map<String, Uri>> _getPackages() async { 240 Future<Map<String, Uri>> _getPackages() async {
150 if (_packages == null) { 241 if (_packages == null) {
151 if (_raw.packagesFileUri == null) { 242 if (_raw.packagesFileUri == null) {
152 throw new UnimplementedError(); // TODO(paulberry): search for .packages 243 // TODO(sigmund,paulberry): implement
244 throw new UnimplementedError('search for .packages');
153 } else if (_raw.packagesFileUri.path.isEmpty) { 245 } else if (_raw.packagesFileUri.path.isEmpty) {
154 _packages = {}; 246 _packages = {};
155 } else { 247 } else {
156 var contents = 248 var contents =
157 await fileSystem.entityForUri(_raw.packagesFileUri).readAsBytes(); 249 await fileSystem.entityForUri(_raw.packagesFileUri).readAsBytes();
158 _packages = package_config.parse(contents, _raw.packagesFileUri); 250 _packages = package_config.parse(contents, _raw.packagesFileUri);
159 } 251 }
160 } 252 }
161 return _packages; 253 return _packages;
162 } 254 }
163 255
164 /// Get the location of the SDK. 256 /// Get the location of the SDK.
165 ///
166 /// This is an asynchronous getter since file system operations may be
167 /// required to locate the SDK.
168 Uri _normalizeSdkRoot() { 257 Uri _normalizeSdkRoot() {
169 // If an SDK summary location was provided, the SDK itself should not be 258 // If an SDK summary location was provided, the SDK itself should not be
170 // needed. 259 // needed.
171 assert(_raw.sdkSummary == null); 260 assert(_raw.sdkSummary == null);
172 if (_raw.sdkRoot == null) { 261 if (_raw.sdkRoot == null) {
173 // TODO(paulberry): implement the algorithm for finding the SDK 262 // TODO(paulberry): implement the algorithm for finding the SDK
174 // automagically. 263 // automagically.
175 throw new UnimplementedError(); 264 throw new UnimplementedError('infer the default sdk location');
176 } 265 }
177 var root = _raw.sdkRoot; 266 var root = _raw.sdkRoot;
178 if (!root.path.endsWith('/')) { 267 if (!root.path.endsWith('/')) {
179 root = root.replace(path: _sdkRoot.path + '/'); 268 root = root.replace(path: root.path + '/');
180 } 269 }
181 return root; 270 return root;
182 } 271 }
272
273 /// Get or infer the location of the SDK summary.
274 Uri _computeSdkSummaryUri() {
275 if (_raw.sdkSummary != null) return _raw.sdkSummary;
276
277 // Infer based on the sdkRoot, but only when `compileSdk` is false,
278 // otherwise the default intent was to compile the sdk from sources and not
279 // to load an sdk summary file.
280 if (_raw.compileSdk) return null;
281 return sdkRoot.resolve('outline.dill');
282 }
283
284 /// Create a [FileSystem] specific to the current options.
285 ///
286 /// If [chaseDependencies] is false, the resulting file system will be
287 /// hermetic.
288 FileSystem _createFileSystem() {
289 var result = _raw.fileSystem;
290 if (!chaseDependencies) {
291 var allInputs = inputs.toSet();
292 allInputs.addAll(_raw.inputSummaries);
293 allInputs.addAll(_raw.linkedDependencies);
294
295 if (sdkSummary != null) allInputs.add(sdkSummary);
296
297 if (_raw.sdkRoot != null) {
298 // TODO(sigmund): refine this, we should be more explicit about when
299 // sdkRoot and libraries.json are allowed to be used.
300 allInputs.add(sdkRoot);
301 allInputs.add(sdkRoot.resolve("lib/libraries.json"));
302 }
303
304 /// Note: Searching the file-system for the package-config is not
305 /// supported in hermetic builds.
306 if (_raw.packagesFileUri != null) allInputs.add(_raw.packagesFileUri);
307 result = new HermeticFileSystem(allInputs, result);
308 }
309 // TODO(paulberry): support multiRoots.
310 assert(_raw.multiRoots.isEmpty);
311 return result;
312 }
183 } 313 }
314
315 /// A [FileSystem] that only allows access to files that have been explicitly
316 /// whitelisted.
317 class HermeticFileSystem implements FileSystem {
318 final Set<Uri> includedFiles;
319 final FileSystem _realFileSystem;
320
321 HermeticFileSystem(this.includedFiles, this._realFileSystem);
322
323 FileSystemEntity entityForUri(Uri uri) {
324 if (includedFiles.contains(uri)) return _realFileSystem.entityForUri(uri);
325 throw new HermeticAccessException(uri);
326 }
327 }
328
329 class HermeticAccessException extends FileSystemException {
330 HermeticAccessException(Uri uri)
331 : super(
332 uri,
333 'Invalid access to $uri: '
334 'the file is accessed in a modular hermetic build, '
335 'but it was not explicitly listed as an input.');
336
337 @override
338 String toString() => message;
339 }
340
341 /// An error that only contains a message and no error location.
342 class _CompilationError implements CompilationError {
343 String get correction => null;
344 SourceSpan get span => null;
345 final String message;
346 _CompilationError(this.message);
347
348 String toString() => message;
349 }
OLDNEW
« 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