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:front_end/compilation_error.dart'; | 7 import 'package:front_end/compilation_error.dart'; |
8 import 'package:front_end/compiler_options.dart'; | 8 import 'package:front_end/compiler_options.dart'; |
9 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'; | 10 import 'package:front_end/src/base/performace_logger.dart'; |
11 import 'package:front_end/src/fasta/fasta_codes.dart'; | 11 import 'package:front_end/src/fasta/fasta_codes.dart'; |
12 import 'package:front_end/src/fasta/ticker.dart'; | 12 import 'package:front_end/src/fasta/ticker.dart'; |
13 import 'package:front_end/src/fasta/uri_translator.dart'; | 13 import 'package:front_end/src/fasta/uri_translator.dart'; |
14 import 'package:front_end/src/fasta/uri_translator_impl.dart'; | 14 import 'package:front_end/src/fasta/uri_translator_impl.dart'; |
15 import 'package:front_end/src/fasta/problems.dart' show unimplemented; | 15 import 'package:front_end/src/fasta/problems.dart' show unimplemented; |
16 import 'package:front_end/src/incremental/byte_store.dart'; | 16 import 'package:front_end/src/incremental/byte_store.dart'; |
17 import 'package:front_end/src/multi_root_file_system.dart'; | 17 import 'package:front_end/src/multi_root_file_system.dart'; |
18 import 'package:kernel/kernel.dart' | 18 import 'package:kernel/kernel.dart' |
19 show Program, loadProgramFromBytes, CanonicalName; | 19 show Program, loadProgramFromBytes, CanonicalName; |
20 import 'package:kernel/target/targets.dart'; | 20 import 'package:kernel/target/targets.dart'; |
21 import 'package:kernel/target/vm_fasta.dart'; | 21 import 'package:kernel/target/vm_fasta.dart'; |
22 import 'package:package_config/packages.dart' show Packages; | |
23 import 'package:package_config/src/packages_impl.dart' | |
24 show NonFilePackagesDirectoryPackages, MapPackages; | |
22 import 'package:package_config/packages_file.dart' as package_config; | 25 import 'package:package_config/packages_file.dart' as package_config; |
23 import 'package:source_span/source_span.dart' show SourceSpan, SourceLocation; | 26 import 'package:source_span/source_span.dart' show SourceSpan, SourceLocation; |
24 | 27 |
25 /// All options needed for the front end implementation. | 28 /// All options needed for the front end implementation. |
26 /// | 29 /// |
27 /// This includes: all of [CompilerOptions] in a form useful to the | 30 /// This includes: all of [CompilerOptions] in a form useful to the |
28 /// implementation, default values for options that were not provided, | 31 /// implementation, default values for options that were not provided, |
29 /// and information derived from how the compiler was invoked (like the | 32 /// and information derived from how the compiler was invoked (like the |
30 /// entry-points given to the compiler and whether a modular or whole-program | 33 /// entry-points given to the compiler and whether a modular or whole-program |
31 /// API was used). | 34 /// API was used). |
32 /// | 35 /// |
33 /// The intent is that the front end should immediately wrap any incoming | 36 /// The intent is that the front end should immediately wrap any incoming |
34 /// [CompilerOptions] object in this class before doing further processing, and | 37 /// [CompilerOptions] object in this class before doing further processing, and |
35 /// should thereafter access all options via the wrapper. This ensures that | 38 /// should thereafter access all options via the wrapper. This ensures that |
36 /// options are interpreted in a consistent way and that data derived from | 39 /// options are interpreted in a consistent way and that data derived from |
37 /// options is not unnecessarily recomputed. | 40 /// options is not unnecessarily recomputed. |
38 class ProcessedOptions { | 41 class ProcessedOptions { |
39 /// The raw [CompilerOptions] which this class wraps. | 42 /// The raw [CompilerOptions] which this class wraps. |
40 final CompilerOptions _raw; | 43 final CompilerOptions _raw; |
41 | 44 |
42 /// The package map derived from the options, or `null` if the package map has | 45 /// The package map derived from the options, or `null` if the package map has |
43 /// not been computed yet. | 46 /// not been computed yet. |
44 Map<String, Uri> _packages; | 47 Packages _packages; |
45 | 48 |
46 /// The object that knows how to resolve "package:" and "dart:" URIs, | 49 /// The object that knows how to resolve "package:" and "dart:" URIs, |
47 /// or `null` if it has not been computed yet. | 50 /// or `null` if it has not been computed yet. |
48 UriTranslatorImpl _uriTranslator; | 51 UriTranslatorImpl _uriTranslator; |
49 | 52 |
50 /// The SDK summary, or `null` if it has not been read yet. | 53 /// The SDK summary, or `null` if it has not been read yet. |
51 /// | 54 /// |
52 /// A summary, also referred to as "outline" internally, is a [Program] where | 55 /// A summary, also referred to as "outline" internally, is a [Program] where |
53 /// all method bodies are left out. In essence, it contains just API | 56 /// all method bodies are left out. In essence, it contains just API |
54 /// signatures and constants. When strong-mode is enabled, the summary already | 57 /// signatures and constants. When strong-mode is enabled, the summary already |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
121 void reportMessage(LocatedMessage message) { | 124 void reportMessage(LocatedMessage message) { |
122 _raw.onError(new _CompilationMessage(message)); | 125 _raw.onError(new _CompilationMessage(message)); |
123 } | 126 } |
124 | 127 |
125 void reportMessageWithoutLocation(Message message) => | 128 void reportMessageWithoutLocation(Message message) => |
126 reportMessage(message.withLocation(null, -1)); | 129 reportMessage(message.withLocation(null, -1)); |
127 | 130 |
128 /// Runs various validations checks on the input options. For instance, | 131 /// Runs various validations checks on the input options. For instance, |
129 /// if an option is a path to a file, it checks that the file exists. | 132 /// if an option is a path to a file, it checks that the file exists. |
130 Future<bool> validateOptions() async { | 133 Future<bool> validateOptions() async { |
134 if (inputs.isEmpty) { | |
135 reportMessageWithoutLocation(messageMissingInputs); | |
ahe
2017/07/14 13:44:57
Remove the "s" from Inputs.
Siggi Cherem (dart-lang)
2017/07/14 19:54:06
Done. Also updated the other messages to say "NotF
| |
136 return false; | |
137 } | |
138 | |
131 for (var source in inputs) { | 139 for (var source in inputs) { |
132 if (source.scheme == 'file' && | 140 // Note: we don't translate Uris at this point because some of the |
141 // validation further below must be done before we even construct an | |
142 // UriTranslator | |
ahe
2017/07/14 13:44:57
Can we make this a TODO and check the inputs later
Siggi Cherem (dart-lang)
2017/07/14 19:54:06
Sure, but it will require some subtle ordering of
| |
143 if (source.scheme != 'dart' && | |
144 source.scheme != 'packages' && | |
133 !await fileSystem.entityForUri(source).exists()) { | 145 !await fileSystem.entityForUri(source).exists()) { |
134 reportMessageWithoutLocation( | 146 reportMessageWithoutLocation( |
135 templateMissingInputFile.withArguments('$source')); | 147 templateMissingInputFile.withArguments('$source')); |
136 return false; | 148 return false; |
137 } | 149 } |
138 } | 150 } |
139 | 151 |
140 if (_raw.sdkRoot != null && | 152 if (_raw.sdkRoot != null && |
141 !await fileSystem.entityForUri(sdkRoot).exists()) { | 153 !await fileSystem.entityForUri(sdkRoot).exists()) { |
142 reportMessageWithoutLocation( | 154 reportMessageWithoutLocation( |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
246 | 258 |
247 Future<Map<String, Uri>> _parseDartLibraries() async { | 259 Future<Map<String, Uri>> _parseDartLibraries() async { |
248 Uri librariesJson = _raw.sdkRoot?.resolve("lib/libraries.json"); | 260 Uri librariesJson = _raw.sdkRoot?.resolve("lib/libraries.json"); |
249 return await computeDartLibraries(fileSystem, librariesJson); | 261 return await computeDartLibraries(fileSystem, librariesJson); |
250 } | 262 } |
251 | 263 |
252 /// Get the package map which maps package names to URIs. | 264 /// Get the package map which maps package names to URIs. |
253 /// | 265 /// |
254 /// This is an asynchronous getter since file system operations may be | 266 /// This is an asynchronous getter since file system operations may be |
255 /// required to locate/read the packages file. | 267 /// required to locate/read the packages file. |
256 Future<Map<String, Uri>> _getPackages() async { | 268 Future<Packages> _getPackages() async { |
257 if (_packages == null) { | 269 if (_packages == null) { |
258 if (_raw.packagesFileUri == null) { | 270 if (_raw.packagesFileUri == null) { |
259 // TODO(sigmund,paulberry): implement | 271 if (inputs.length > 1) { |
260 return unimplemented('search for .packages'); | 272 reportMessageWithoutLocation( |
261 } else if (_raw.packagesFileUri.path.isEmpty) { | 273 templateInternalProblemUnsupported.withArguments( |
262 _packages = {}; | 274 "Cannot infer a .packages file when compiling multiple inputs. ")); |
ahe
2017/07/14 13:44:57
This isn't an internal error, this is a problem wi
Siggi Cherem (dart-lang)
2017/07/14 19:54:06
Done.
Note we have to be careful about using flag
| |
275 _packages = Packages.noPackages; | |
276 } else { | |
277 _packages = await _findPackages(inputs.first); | |
278 } | |
263 } else { | 279 } else { |
264 var contents = | 280 _packages = await createPackagesFromFile(_raw.packagesFileUri); |
265 await fileSystem.entityForUri(_raw.packagesFileUri).readAsBytes(); | |
266 _packages = package_config.parse(contents, _raw.packagesFileUri); | |
267 } | 281 } |
268 } | 282 } |
269 return _packages; | 283 return _packages; |
270 } | 284 } |
271 | 285 |
286 /// Create a [Packages] given the Uri to a `.packages` file. | |
287 Future<Packages> createPackagesFromFile(Uri file) async { | |
288 try { | |
289 List<int> contents = await fileSystem.entityForUri(file).readAsBytes(); | |
290 Map<String, Uri> map = package_config.parse(contents, file); | |
291 return new MapPackages(map); | |
292 } catch (e) { | |
293 reportMessageWithoutLocation( | |
294 templateInvalidPackagesFile.withArguments(file, "$e")); | |
295 return Packages.noPackages; | |
296 } | |
297 } | |
298 | |
299 /// Finds a package resolution strategy using a [FileSystem]. | |
300 /// | |
301 /// The [scriptUri] points to a Dart script with a valid scheme accepted by | |
302 /// the [FileSystem]. | |
303 /// | |
304 /// This function first tries to locate a `.packages` file in the `scriptUri` | |
305 /// directory. If that is not found, it instead checks for the presence of a | |
306 /// `packages/` directory in the same place. If that also fails, it starts | |
307 /// checking parent directories for a `.packages` file, and stops if it finds | |
308 /// it. Otherwise it gives up and returns [Packages.noPackages]. | |
309 /// | |
310 /// Note: this is a fork from `package:package_config/discovery.dart` to adapt | |
311 /// it to use [FileSystem]. The logic here is a mix of the logic in the | |
312 /// `findPackagesFromFile` and `findPackagesFromNonFile`: | |
313 /// | |
314 /// * Like `findPackagesFromFile` resolution searches for parent | |
315 /// directories | |
316 /// | |
317 /// * Like `findPackagesFromNonFile` if we resolve packages as the | |
318 /// `packages/` directory, we can't provide a list of packages that are | |
319 /// visible. | |
320 Future<Packages> _findPackages(Uri scriptUri) async { | |
321 var dir = scriptUri.resolve('.'); | |
322 if (!dir.isAbsolute) { | |
323 reportMessageWithoutLocation(templateInternalProblemUnsupported | |
324 .withArguments("Expected input Uri to be absolute: $scriptUri.")); | |
325 return null; | |
326 } | |
327 if (!await fileSystem.entityForUri(dir).exists()) { | |
328 reportMessageWithoutLocation(templateInternalProblemUnsupported | |
329 .withArguments("Input directory does not exist: $dir.")); | |
330 // TODO: report "Directory does not exist."; | |
331 return null; | |
332 } | |
333 | |
334 Future<Uri> checkInDir(Uri dir) async { | |
335 Uri candidate = dir.resolve('.packages'); | |
336 if (await fileSystem.entityForUri(candidate).exists()) return candidate; | |
337 return null; | |
338 } | |
339 | |
340 // Check for $cwd/.packages | |
341 var candidate = await checkInDir(dir); | |
342 if (candidate != null) return createPackagesFromFile(candidate); | |
343 | |
344 // Check for $cwd/packages/ | |
345 var packagesDir = dir.resolve("packages/"); | |
346 if (await fileSystem.entityForUri(packagesDir).exists()) { | |
347 return new NonFilePackagesDirectoryPackages(packagesDir); | |
348 } | |
349 | |
350 // Check for cwd(/..)+/.packages | |
351 var parentDir = dir.resolve('..'); | |
352 while (parentDir.path != dir.path) { | |
353 candidate = await checkInDir(parentDir); | |
354 if (candidate != null) break; | |
355 dir = parentDir; | |
356 parentDir = dir.resolve('..'); | |
357 } | |
358 | |
359 if (candidate != null) return createPackagesFromFile(candidate); | |
360 return Packages.noPackages; | |
361 } | |
362 | |
272 /// Get the location of the SDK. | 363 /// Get the location of the SDK. |
273 Uri _normalizeSdkRoot() { | 364 Uri _normalizeSdkRoot() { |
274 // If an SDK summary location was provided, the SDK itself should not be | 365 // If an SDK summary location was provided, the SDK itself should not be |
275 // needed. | 366 // needed. |
276 assert(_raw.sdkSummary == null); | 367 assert(_raw.sdkSummary == null); |
277 if (_raw.sdkRoot == null) { | 368 if (_raw.sdkRoot == null) { |
278 // TODO(paulberry): implement the algorithm for finding the SDK | 369 // TODO(paulberry): implement the algorithm for finding the SDK |
279 // automagically. | 370 // automagically. |
280 return unimplemented('infer the default sdk location'); | 371 return unimplemented('infer the default sdk location'); |
281 } | 372 } |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
378 /// Wraps an error message as a [CompilationError] API. | 469 /// Wraps an error message as a [CompilationError] API. |
379 class _StringMessage implements CompilationError { | 470 class _StringMessage implements CompilationError { |
380 final String message; | 471 final String message; |
381 String get tip => null; | 472 String get tip => null; |
382 SourceSpan get span => null; | 473 SourceSpan get span => null; |
383 | 474 |
384 _StringMessage(this.message); | 475 _StringMessage(this.message); |
385 | 476 |
386 String toString() => message; | 477 String toString() => message; |
387 } | 478 } |
OLD | NEW |