OLD | NEW |
---|---|
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'; | |
10 import 'package:front_end/src/base/performace_logger.dart'; | 13 import 'package:front_end/src/base/performace_logger.dart'; |
11 import 'package:front_end/src/incremental/byte_store.dart'; | 14 import 'package:front_end/src/incremental/byte_store.dart'; |
12 import 'package:front_end/src/simple_error.dart'; | 15 import 'package:front_end/src/simple_error.dart'; |
13 import 'package:package_config/packages_file.dart' as package_config; | 16 import 'package:package_config/packages_file.dart' as package_config; |
14 import 'package:kernel/kernel.dart' show Program, loadProgramFromBytes; | 17 import 'package:kernel/kernel.dart' |
18 show Program, loadProgramFromBytes, CanonicalName; | |
15 | 19 |
16 /// Wrapper around [CompilerOptions] which exposes the options in a form useful | 20 /// Wrapper around [CompilerOptions] which exposes the options in a form useful |
17 /// to the front end implementation. | 21 /// to the front end implementation. |
18 /// | 22 /// |
19 /// The intent is that the front end should immediately wrap any incoming | 23 /// The intent is that the front end should immediately wrap any incoming |
20 /// [CompilerOptions] object in this class before doing further processing, and | 24 /// [CompilerOptions] object in this class before doing further processing, and |
21 /// should thereafter access all options via the wrapper. This ensures that | 25 /// should thereafter access all options via the wrapper. This ensures that |
22 /// options are interpreted in a consistent way and that data derived from | 26 /// options are interpreted in a consistent way and that data derived from |
23 /// options is not unnecessarily recomputed. | 27 /// options is not unnecessarily recomputed. |
24 class ProcessedOptions { | 28 class ProcessedOptions { |
25 /// The raw [CompilerOptions] which this class wraps. | 29 /// The raw [CompilerOptions] which this class wraps. |
26 final CompilerOptions _raw; | 30 final CompilerOptions _raw; |
27 | 31 |
28 /// The package map derived from the options, or `null` if the package map has | 32 /// The package map derived from the options, or `null` if the package map has |
29 /// not been computed yet. | 33 /// not been computed yet. |
30 Map<String, Uri> _packages; | 34 Map<String, Uri> _packages; |
31 | 35 |
32 /// The object that knows how to resolve "package:" and "dart:" URIs, | 36 /// The object that knows how to resolve "package:" and "dart:" URIs, |
33 /// or `null` if it has not been computed yet. | 37 /// or `null` if it has not been computed yet. |
34 TranslateUri _uriTranslator; | 38 TranslateUri _uriTranslator; |
35 | 39 |
36 /// The SDK summary, or `null` if it has not been read yet. | 40 /// The SDK summary, or `null` if it has not been read yet. |
41 /// | |
42 /// A summary, also referred to as "outline" internally, is a [Program] where | |
43 /// all method bodies are left out. In essence, it contains just API | |
44 /// signatures and constants. When strong-mode is enabled, the summary already | |
45 /// includes inferred types. | |
37 Program _sdkSummaryProgram; | 46 Program _sdkSummaryProgram; |
38 | 47 |
39 /// The summary for each uri in `options.inputSummaries`. | 48 /// The summary for each uri in `options.inputSummaries`. |
49 /// | |
50 /// A summary, also referred to as "outline" internally, is a [Program] where | |
51 /// all method bodies are left out. In essence, it contains just API | |
52 /// signatures and constants. When strong-mode is enabled, the summary already | |
53 /// includes inferred types. | |
40 List<Program> _inputSummariesPrograms; | 54 List<Program> _inputSummariesPrograms; |
41 | 55 |
56 /// Other programs that are meant to be linked and compiled with the input | |
57 /// sources. | |
58 List<Program> _linkedDependencies; | |
59 | |
42 /// The location of the SDK, or `null` if the location hasn't been determined | 60 /// The location of the SDK, or `null` if the location hasn't been determined |
43 /// yet. | 61 /// yet. |
44 Uri _sdkRoot; | 62 Uri _sdkRoot; |
63 Uri get sdkRoot => _sdkRoot ??= _normalizeSdkRoot(); | |
45 | 64 |
46 Uri get sdkRoot => _sdkRoot ??= _normalizeSdkRoot(); | 65 Uri _sdkSummary; |
66 Uri get sdkSummary => _sdkSummary ??= _computeSdkSummaryUri(); | |
67 | |
68 Ticker _ticker; | |
69 Ticker get ticker => _ticker ??= new Ticker(isVerbose: _raw.verbose); | |
ahe
2017/07/05 13:29:39
The ticker should be created eagerly. Otherwise it
Siggi Cherem (dart-lang)
2017/07/05 18:42:08
Done.
| |
70 | |
71 bool get verbose => _raw.verbose; | |
72 bool get verify => _raw.verify; | |
73 bool get debugDump => _raw.debugDump; | |
47 | 74 |
48 /// Initializes a [ProcessedOptions] object wrapping the given [rawOptions]. | 75 /// Initializes a [ProcessedOptions] object wrapping the given [rawOptions]. |
49 ProcessedOptions(CompilerOptions rawOptions) : this._raw = rawOptions; | 76 ProcessedOptions(CompilerOptions rawOptions) : this._raw = rawOptions; |
50 | 77 |
51 /// The logger to report compilation progress. | 78 /// The logger to report compilation progress. |
52 PerformanceLog get logger { | 79 PerformanceLog get logger { |
53 return _raw.logger; | 80 return _raw.logger; |
54 } | 81 } |
55 | 82 |
56 /// The byte storage to get and put serialized data. | 83 /// The byte storage to get and put serialized data. |
57 ByteStore get byteStore { | 84 ByteStore get byteStore { |
58 return _raw.byteStore; | 85 return _raw.byteStore; |
59 } | 86 } |
60 | 87 |
61 /// Runs various validations checks on the input options. For instance, | 88 /// 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. | 89 /// if an option is a path to a file, it checks that the file exists. |
63 Future<bool> validateOptions() async { | 90 Future<bool> validateOptions() async { |
64 var fs = _raw.fileSystem; | 91 var fs = _raw.fileSystem; |
65 var root = _raw.sdkRoot; | |
66 | 92 |
67 bool _report(String msg) { | 93 bool _report(String msg) { |
68 _raw.onError(new SimpleError(msg)); | 94 _raw.onError(new SimpleError(msg)); |
69 return false; | 95 return false; |
70 } | 96 } |
71 | 97 |
72 if (root != null && !await fs.entityForUri(root).exists()) { | 98 if (_raw.sdkRoot != null && !await fs.entityForUri(sdkRoot).exists()) { |
73 return _report("SDK root directory not found: ${_raw.sdkRoot}"); | 99 return _report("SDK root directory not found: ${sdkRoot}"); |
74 } | 100 } |
75 | 101 |
76 var summary = _raw.sdkSummary; | 102 var summary = sdkSummary; |
77 if (summary != null && !await fs.entityForUri(summary).exists()) { | 103 if (summary != null && !await fs.entityForUri(summary).exists()) { |
78 return _report("SDK summary not found: ${_raw.sdkSummary}"); | 104 return _report("SDK summary not found: ${summary}"); |
79 } | 105 } |
80 | 106 |
81 // TODO(sigmund): add checks for options that are meant to be disjoint (like | 107 if (compileSdk && summary != null) { |
82 // sdkRoot and sdkSummary). | 108 return _report( |
109 "The compileSdk and sdkSummary options are mutually exclusive"); | |
110 } | |
83 return true; | 111 return true; |
84 } | 112 } |
85 | 113 |
86 /// Determine whether to generate code for the SDK when compiling a | 114 /// Determine whether to generate code for the SDK when compiling a |
87 /// whole-program. | 115 /// whole-program. |
88 bool get compileSdk => _raw.compileSdk; | 116 bool get compileSdk => _raw.compileSdk; |
89 | 117 |
90 /// Get the [FileSystem] which should be used by the front end to access | 118 /// Get the [FileSystem] which should be used by the front end to access |
91 /// files. | 119 /// files. |
92 /// | 120 /// |
93 /// If the client supplied roots using [CompilerOptions.multiRoots], the | 121 /// If the client supplied roots using [CompilerOptions.multiRoots], the |
94 /// returned [FileSystem] will automatically perform the appropriate mapping. | 122 /// returned [FileSystem] will automatically perform the appropriate mapping. |
95 FileSystem get fileSystem { | 123 FileSystem get fileSystem { |
96 // TODO(paulberry): support multiRoots. | 124 // TODO(paulberry): support multiRoots. |
97 assert(_raw.multiRoots.isEmpty); | 125 assert(_raw.multiRoots.isEmpty); |
98 return _raw.fileSystem; | 126 return _raw.fileSystem; |
99 } | 127 } |
100 | 128 |
101 /// Whether to interpret Dart sources in strong-mode. | 129 /// Whether to interpret Dart sources in strong-mode. |
102 bool get strongMode => _raw.strongMode; | 130 bool get strongMode => _raw.strongMode; |
103 | 131 |
104 /// Get an outline program that summarizes the SDK. | 132 Target _target; |
105 Future<Program> get sdkSummaryProgram async { | 133 Target get target => _target ??= |
134 _raw.target ?? new VmFastaTarget(new TargetFlags(strongMode: strongMode)); | |
135 | |
136 /// Get an outline program that summarizes the SDK, if any. | |
137 Future<Program> loadSdkSummary(CanonicalName nameRoot) async { | |
ahe
2017/07/05 13:29:39
This doesn't feel like an option to me.
Siggi Cherem (dart-lang)
2017/07/05 18:42:09
Agree - I don't believe we want to put this separa
| |
106 if (_sdkSummaryProgram == null) { | 138 if (_sdkSummaryProgram == null) { |
107 if (_raw.sdkSummary == null) return null; | 139 if (sdkSummary == null) return null; |
108 _sdkSummaryProgram = await _loadProgram(_raw.sdkSummary); | 140 _sdkSummaryProgram = await loadProgram(sdkSummary, nameRoot); |
109 } | 141 } |
110 return _sdkSummaryProgram; | 142 return _sdkSummaryProgram; |
111 } | 143 } |
112 | 144 |
113 /// Get the summary programs for each of the underlying `inputSummaries` | 145 /// Get the summary programs for each of the underlying `inputSummaries` |
114 /// provided via [CompilerOptions]. | 146 /// provided via [CompilerOptions]. |
115 Future<List<Program>> get inputSummariesPrograms async { | 147 Future<List<Program>> loadInputSummaries(CanonicalName nameRoot) async { |
ahe
2017/07/05 13:29:39
Ditto.
Siggi Cherem (dart-lang)
2017/07/05 18:42:09
Acknowledged.
| |
116 if (_inputSummariesPrograms == null) { | 148 if (_inputSummariesPrograms == null) { |
117 var uris = _raw.inputSummaries; | 149 var uris = _raw.inputSummaries; |
118 if (uris == null || uris.isEmpty) return const <Program>[]; | 150 if (uris == null || uris.isEmpty) return const <Program>[]; |
119 _inputSummariesPrograms = await Future.wait(uris.map(_loadProgram)); | 151 _inputSummariesPrograms = <Program>[]; |
152 await Future.forEach(uris, (uri) async { | |
153 _inputSummariesPrograms.add(await loadProgram(uri, nameRoot)); | |
Paul Berry
2017/06/29 18:51:07
Previously, the use of Future.wait() would mean th
Siggi Cherem (dart-lang)
2017/06/30 04:12:02
It was initially deliberate, but I didn't need to
ahe
2017/07/05 13:29:39
We should throttle the number of concurrent operat
Siggi Cherem (dart-lang)
2017/07/05 18:42:08
Good to know. Added TODO for now.
| |
154 }); | |
120 } | 155 } |
121 return _inputSummariesPrograms; | 156 return _inputSummariesPrograms; |
122 } | 157 } |
123 | 158 |
124 Future<Program> _loadProgram(Uri uri) async { | 159 /// Load each of the [CompilerOptions.linkedDependencies] programs. |
160 Future<List<Program>> loadLinkDependencies(CanonicalName nameRoot) async { | |
ahe
2017/07/05 13:29:39
Also doesn't seem like an option.
Siggi Cherem (dart-lang)
2017/07/05 18:42:08
Acknowledged.
| |
161 if (_linkedDependencies == null) { | |
162 var uris = _raw.linkedDependencies; | |
163 if (uris == null || uris.isEmpty) return const <Program>[]; | |
164 _linkedDependencies = <Program>[]; | |
165 await Future.forEach(uris, (uri) async { | |
166 _linkedDependencies.add(await loadProgram(uri, nameRoot)); | |
Paul Berry
2017/06/29 18:51:07
Similar concern here.
Siggi Cherem (dart-lang)
2017/06/30 04:12:02
Done.
| |
167 }); | |
168 } | |
169 return _linkedDependencies; | |
170 } | |
171 | |
172 /// Helper to load a .dill file from [uri] using the existing [nameRoot]. | |
173 Future<Program> loadProgram(Uri uri, CanonicalName nameRoot) async { | |
125 var bytes = await fileSystem.entityForUri(uri).readAsBytes(); | 174 var bytes = await fileSystem.entityForUri(uri).readAsBytes(); |
126 return loadProgramFromBytes(bytes)..unbindCanonicalNames(); | 175 var result = loadProgramFromBytes(bytes, new Program(nameRoot: nameRoot)); |
Paul Berry
2017/06/29 18:51:07
Nit: why not just
return loadProgramFromBytes(...
Siggi Cherem (dart-lang)
2017/06/30 04:12:02
Thanks - I had an extra debugging step earlier and
| |
176 return result; | |
127 } | 177 } |
128 | 178 |
129 /// Get the [TranslateUri] which resolves "package:" and "dart:" URIs. | 179 /// Get the [TranslateUri] which resolves "package:" and "dart:" URIs. |
130 /// | 180 /// |
131 /// This is an asynchronous method since file system operations may be | 181 /// This is an asynchronous method since file system operations may be |
132 /// required to locate/read the packages file as well as SDK metadata. | 182 /// required to locate/read the packages file as well as SDK metadata. |
133 Future<TranslateUri> getUriTranslator() async { | 183 Future<TranslateUri> getUriTranslator() async { |
134 if (_uriTranslator == null) { | 184 if (_uriTranslator == null) { |
135 await _getPackages(); | 185 await _getPackages(); |
136 // TODO(scheglov) Load SDK libraries from whatever format we decide. | 186 // TODO(scheglov) Load SDK libraries from whatever format we decide. |
137 // TODO(scheglov) Remove the field "_raw.dartLibraries". | 187 // TODO(scheglov) Remove the field "_raw.dartLibraries". |
138 _uriTranslator = new TranslateUri( | 188 var libraries = _raw.dartLibraries ?? await _parseLibraries(); |
139 _packages, _raw.dartLibraries, const <String, List<Uri>>{}); | 189 _uriTranslator = |
140 _uriTranslator.dartLibraries.addAll(_raw.dartLibraries); | 190 new TranslateUri(_packages, libraries, const <String, List<Uri>>{}); |
191 ticker.logMs("Read packages file"); | |
141 } | 192 } |
142 return _uriTranslator; | 193 return _uriTranslator; |
143 } | 194 } |
144 | 195 |
196 Future<Map<String, Uri>> _parseLibraries() async { | |
197 Uri librariesJson = _raw.sdkRoot?.resolve("lib/libraries.json"); | |
198 return await computeLibraries(fileSystem, librariesJson); | |
199 } | |
200 | |
145 /// Get the package map which maps package names to URIs. | 201 /// Get the package map which maps package names to URIs. |
146 /// | 202 /// |
147 /// This is an asynchronous getter since file system operations may be | 203 /// This is an asynchronous getter since file system operations may be |
148 /// required to locate/read the packages file. | 204 /// required to locate/read the packages file. |
149 Future<Map<String, Uri>> _getPackages() async { | 205 Future<Map<String, Uri>> _getPackages() async { |
150 if (_packages == null) { | 206 if (_packages == null) { |
151 if (_raw.packagesFileUri == null) { | 207 if (_raw.packagesFileUri == null) { |
152 throw new UnimplementedError(); // TODO(paulberry): search for .packages | 208 throw new UnimplementedError(); // TODO(paulberry): search for .packages |
ahe
2017/07/05 13:29:39
Could we throw a string with information about wha
Siggi Cherem (dart-lang)
2017/07/05 18:42:08
Done, practically moved the TODO into the error me
| |
153 } else if (_raw.packagesFileUri.path.isEmpty) { | 209 } else if (_raw.packagesFileUri.path.isEmpty) { |
154 _packages = {}; | 210 _packages = {}; |
155 } else { | 211 } else { |
156 var contents = | 212 var contents = |
157 await fileSystem.entityForUri(_raw.packagesFileUri).readAsBytes(); | 213 await fileSystem.entityForUri(_raw.packagesFileUri).readAsBytes(); |
158 _packages = package_config.parse(contents, _raw.packagesFileUri); | 214 _packages = package_config.parse(contents, _raw.packagesFileUri); |
159 } | 215 } |
160 } | 216 } |
161 return _packages; | 217 return _packages; |
162 } | 218 } |
163 | 219 |
164 /// Get the location of the SDK. | 220 /// Get the location of the SDK. |
165 /// | 221 /// |
166 /// This is an asynchronous getter since file system operations may be | 222 /// This is an asynchronous getter since file system operations may be |
ahe
2017/07/05 13:29:39
What is an asynchronous getter?
Siggi Cherem (dart-lang)
2017/07/05 18:42:09
Deleted comment, I believe long ago this used to b
| |
167 /// required to locate the SDK. | 223 /// required to locate the SDK. |
168 Uri _normalizeSdkRoot() { | 224 Uri _normalizeSdkRoot() { |
169 // If an SDK summary location was provided, the SDK itself should not be | 225 // If an SDK summary location was provided, the SDK itself should not be |
170 // needed. | 226 // needed. |
171 assert(_raw.sdkSummary == null); | 227 assert(_raw.sdkSummary == null); |
172 if (_raw.sdkRoot == null) { | 228 if (_raw.sdkRoot == null) { |
173 // TODO(paulberry): implement the algorithm for finding the SDK | 229 // TODO(paulberry): implement the algorithm for finding the SDK |
174 // automagically. | 230 // automagically. |
175 throw new UnimplementedError(); | 231 throw new UnimplementedError(); |
ahe
2017/07/05 13:29:39
Throw string about what isn't implemented?
Siggi Cherem (dart-lang)
2017/07/05 18:42:09
Done.
| |
176 } | 232 } |
177 var root = _raw.sdkRoot; | 233 var root = _raw.sdkRoot; |
178 if (!root.path.endsWith('/')) { | 234 if (!root.path.endsWith('/')) { |
179 root = root.replace(path: _sdkRoot.path + '/'); | 235 root = root.replace(path: root.path + '/'); |
180 } | 236 } |
181 return root; | 237 return root; |
182 } | 238 } |
239 | |
240 /// Get or infer the location of the SDK summary. | |
241 Uri _computeSdkSummaryUri() { | |
242 if (_raw.sdkSummary != null) return _raw.sdkSummary; | |
243 | |
244 // Infer based on the sdkRoot, but only when `compileSdk` is false, | |
245 // otherwise the default intent was to compile the sdk from sources and not | |
246 // to load an sdk summary file. | |
247 if (_raw.compileSdk) return null; | |
248 return sdkRoot.resolve('outline.dill'); | |
249 } | |
183 } | 250 } |
OLD | NEW |