Chromium Code Reviews| 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 |