| 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:analyzer/src/summary/idl.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'; |
| 9 import 'package:front_end/src/fasta/translate_uri.dart'; | 10 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/base/performace_logger.dart'; |
| 11 import 'package:front_end/src/incremental/byte_store.dart'; | 12 import 'package:front_end/src/incremental/byte_store.dart'; |
| 12 import 'package:front_end/src/simple_error.dart'; | |
| 13 import 'package:package_config/packages_file.dart' as package_config; | 13 import 'package:package_config/packages_file.dart' as package_config; |
| 14 import 'package:kernel/kernel.dart' show Program, loadProgramFromBytes; | |
| 15 | 14 |
| 16 /// Wrapper around [CompilerOptions] which exposes the options in a form useful | 15 /// Wrapper around [CompilerOptions] which exposes the options in a form useful |
| 17 /// to the front end implementation. | 16 /// to the front end implementation. |
| 18 /// | 17 /// |
| 19 /// The intent is that the front end should immediately wrap any incoming | 18 /// The intent is that the front end should immediately wrap any incoming |
| 20 /// [CompilerOptions] object in this class before doing further processing, and | 19 /// [CompilerOptions] object in this class before doing further processing, and |
| 21 /// should thereafter access all options via the wrapper. This ensures that | 20 /// should thereafter access all options via the wrapper. This ensures that |
| 22 /// options are interpreted in a consistent way and that data derived from | 21 /// options are interpreted in a consistent way and that data derived from |
| 23 /// options is not unnecessarily recomputed. | 22 /// options is not unnecessarily recomputed. |
| 24 class ProcessedOptions { | 23 class ProcessedOptions { |
| 25 /// The raw [CompilerOptions] which this class wraps. | 24 /// The raw [CompilerOptions] which this class wraps. |
| 26 final CompilerOptions _raw; | 25 final CompilerOptions _raw; |
| 27 | 26 |
| 28 /// The package map derived from the options, or `null` if the package map has | 27 /// The package map derived from the options, or `null` if the package map has |
| 29 /// not been computed yet. | 28 /// not been computed yet. |
| 30 Map<String, Uri> _packages; | 29 Map<String, Uri> _packages; |
| 31 | 30 |
| 32 /// The object that knows how to resolve "package:" and "dart:" URIs, | 31 /// The object that knows how to resolve "package:" and "dart:" URIs, |
| 33 /// or `null` if it has not been computed yet. | 32 /// or `null` if it has not been computed yet. |
| 34 TranslateUri _uriTranslator; | 33 TranslateUri _uriTranslator; |
| 35 | 34 |
| 36 /// The SDK summary, or `null` if it has not been read yet. | 35 /// The summary bundle for the SDK, or `null` if it has not been read yet. |
| 37 Program _sdkSummaryProgram; | 36 PackageBundle _sdkSummary; |
| 38 | |
| 39 /// The summary for each uri in `options.inputSummaries`. | |
| 40 List<Program> _inputSummariesPrograms; | |
| 41 | 37 |
| 42 /// The location of the SDK, or `null` if the location hasn't been determined | 38 /// The location of the SDK, or `null` if the location hasn't been determined |
| 43 /// yet. | 39 /// yet. |
| 44 Uri _sdkRoot; | 40 Uri _sdkRoot; |
| 45 | 41 |
| 46 Uri get sdkRoot => _sdkRoot ??= _normalizeSdkRoot(); | |
| 47 | |
| 48 /// Initializes a [ProcessedOptions] object wrapping the given [rawOptions]. | 42 /// Initializes a [ProcessedOptions] object wrapping the given [rawOptions]. |
| 49 ProcessedOptions(CompilerOptions rawOptions) : this._raw = rawOptions; | 43 ProcessedOptions(CompilerOptions rawOptions) : this._raw = rawOptions; |
| 50 | 44 |
| 51 /// The logger to report compilation progress. | 45 /// The logger to report compilation progress. |
| 52 PerformanceLog get logger { | 46 PerformanceLog get logger { |
| 53 return _raw.logger; | 47 return _raw.logger; |
| 54 } | 48 } |
| 55 | 49 |
| 56 /// The byte storage to get and put serialized data. | 50 /// The byte storage to get and put serialized data. |
| 57 ByteStore get byteStore { | 51 ByteStore get byteStore { |
| 58 return _raw.byteStore; | 52 return _raw.byteStore; |
| 59 } | 53 } |
| 60 | 54 |
| 61 /// 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. | |
| 63 Future<bool> validateOptions() async { | |
| 64 var fs = _raw.fileSystem; | |
| 65 var root = _raw.sdkRoot; | |
| 66 | |
| 67 bool _report(String msg) { | |
| 68 _raw.onError(new SimpleError(msg)); | |
| 69 return false; | |
| 70 } | |
| 71 | |
| 72 if (root != null && !await fs.entityForUri(root).exists()) { | |
| 73 return _report("SDK root directory not found: ${_raw.sdkRoot}"); | |
| 74 } | |
| 75 | |
| 76 var summary = _raw.sdkSummary; | |
| 77 if (summary != null && !await fs.entityForUri(summary).exists()) { | |
| 78 return _report("SDK summary not found: ${_raw.sdkSummary}"); | |
| 79 } | |
| 80 | |
| 81 // TODO(sigmund): add checks for options that are meant to be disjoint (like | |
| 82 // sdkRoot and sdkSummary). | |
| 83 return true; | |
| 84 } | |
| 85 | |
| 86 /// Determine whether to generate code for the SDK when compiling a | 55 /// Determine whether to generate code for the SDK when compiling a |
| 87 /// whole-program. | 56 /// whole-program. |
| 88 bool get compileSdk => _raw.compileSdk; | 57 bool get compileSdk => _raw.compileSdk; |
| 89 | 58 |
| 90 /// Get the [FileSystem] which should be used by the front end to access | 59 /// Get the [FileSystem] which should be used by the front end to access |
| 91 /// files. | 60 /// files. |
| 92 /// | 61 /// |
| 93 /// If the client supplied roots using [CompilerOptions.multiRoots], the | 62 /// If the client supplied roots using [CompilerOptions.multiRoots], the |
| 94 /// returned [FileSystem] will automatically perform the appropriate mapping. | 63 /// returned [FileSystem] will automatically perform the appropriate mapping. |
| 95 FileSystem get fileSystem { | 64 FileSystem get fileSystem { |
| 96 // TODO(paulberry): support multiRoots. | 65 // TODO(paulberry): support multiRoots. |
| 97 assert(_raw.multiRoots.isEmpty); | 66 assert(_raw.multiRoots.isEmpty); |
| 98 return _raw.fileSystem; | 67 return _raw.fileSystem; |
| 99 } | 68 } |
| 100 | 69 |
| 101 /// Whether to interpret Dart sources in strong-mode. | 70 /// Whether to interpret Dart sources in strong-mode. |
| 102 bool get strongMode => _raw.strongMode; | 71 bool get strongMode => _raw.strongMode; |
| 103 | 72 |
| 104 /// Get an outline program that summarizes the SDK. | 73 /// Get the summary bundle for the SDK. |
| 105 Future<Program> get sdkSummaryProgram async { | 74 /// |
| 106 if (_sdkSummaryProgram == null) { | 75 /// This is an asynchronous getter since file system operations are required. |
| 107 if (_raw.sdkSummary == null) return null; | 76 Future<PackageBundle> getSdkSummary() async { |
| 108 _sdkSummaryProgram = await _loadProgram(_raw.sdkSummary); | 77 if (_sdkSummary == null) { |
| 78 Uri summaryLocation; |
| 79 if (_raw.sdkSummary != null) { |
| 80 // Options sdkSummary and sdkRoot are mutually exclusive. |
| 81 assert(_raw.sdkRoot == null); |
| 82 // No need to look for the SDK; we were told where the SDK summary is. |
| 83 summaryLocation = _raw.sdkSummary; |
| 84 } else { |
| 85 // Need to look for the SDK summary inside the SDK. |
| 86 var sdkRoot = await _getSdkRoot(); |
| 87 summaryLocation = sdkRoot.resolve( |
| 88 'lib/_internal/' + (_raw.strongMode ? 'strong.sum' : 'spec.sum')); |
| 89 } |
| 90 var summaryBytes = |
| 91 await fileSystem.entityForUri(summaryLocation).readAsBytes(); |
| 92 _sdkSummary = new PackageBundle.fromBuffer(summaryBytes); |
| 109 } | 93 } |
| 110 return _sdkSummaryProgram; | 94 return _sdkSummary; |
| 111 } | |
| 112 | |
| 113 /// Get the summary programs for each of the underlying `inputSummaries` | |
| 114 /// provided via [CompilerOptions]. | |
| 115 Future<List<Program>> get inputSummariesPrograms async { | |
| 116 if (_inputSummariesPrograms == null) { | |
| 117 var uris = _raw.inputSummaries; | |
| 118 if (uris == null || uris.isEmpty) return const <Program>[]; | |
| 119 _inputSummariesPrograms = await Future.wait(uris.map(_loadProgram)); | |
| 120 } | |
| 121 return _inputSummariesPrograms; | |
| 122 } | |
| 123 | |
| 124 Future<Program> _loadProgram(Uri uri) async { | |
| 125 var bytes = await fileSystem.entityForUri(uri).readAsBytes(); | |
| 126 return loadProgramFromBytes(bytes)..unbindCanonicalNames(); | |
| 127 } | 95 } |
| 128 | 96 |
| 129 /// Get the [TranslateUri] which resolves "package:" and "dart:" URIs. | 97 /// Get the [TranslateUri] which resolves "package:" and "dart:" URIs. |
| 130 /// | 98 /// |
| 131 /// This is an asynchronous method since file system operations may be | 99 /// This is an asynchronous method since file system operations may be |
| 132 /// required to locate/read the packages file as well as SDK metadata. | 100 /// required to locate/read the packages file as well as SDK metadata. |
| 133 Future<TranslateUri> getUriTranslator() async { | 101 Future<TranslateUri> getUriTranslator() async { |
| 134 if (_uriTranslator == null) { | 102 if (_uriTranslator == null) { |
| 135 await _getPackages(); | 103 await _getPackages(); |
| 136 // TODO(scheglov) Load SDK libraries from whatever format we decide. | 104 // TODO(scheglov) Load SDK libraries from whatever format we decide. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 157 _packages = package_config.parse(contents, _raw.packagesFileUri); | 125 _packages = package_config.parse(contents, _raw.packagesFileUri); |
| 158 } | 126 } |
| 159 } | 127 } |
| 160 return _packages; | 128 return _packages; |
| 161 } | 129 } |
| 162 | 130 |
| 163 /// Get the location of the SDK. | 131 /// Get the location of the SDK. |
| 164 /// | 132 /// |
| 165 /// This is an asynchronous getter since file system operations may be | 133 /// This is an asynchronous getter since file system operations may be |
| 166 /// required to locate the SDK. | 134 /// required to locate the SDK. |
| 167 Uri _normalizeSdkRoot() { | 135 Future<Uri> _getSdkRoot() async { |
| 168 // If an SDK summary location was provided, the SDK itself should not be | 136 if (_sdkRoot == null) { |
| 169 // needed. | 137 // If an SDK summary location was provided, the SDK itself should not be |
| 170 assert(_raw.sdkSummary == null); | 138 // needed. |
| 171 if (_raw.sdkRoot == null) { | 139 assert(_raw.sdkSummary == null); |
| 172 // TODO(paulberry): implement the algorithm for finding the SDK | 140 if (_raw.sdkRoot == null) { |
| 173 // automagically. | 141 // TODO(paulberry): implement the algorithm for finding the SDK |
| 174 throw new UnimplementedError(); | 142 // automagically. |
| 143 throw new UnimplementedError(); |
| 144 } |
| 145 _sdkRoot = _raw.sdkRoot; |
| 146 if (!_sdkRoot.path.endsWith('/')) { |
| 147 _sdkRoot = _sdkRoot.replace(path: _sdkRoot.path + '/'); |
| 148 } |
| 175 } | 149 } |
| 176 var root = _raw.sdkRoot; | 150 return _sdkRoot; |
| 177 if (!root.path.endsWith('/')) { | |
| 178 root = root.replace(path: _sdkRoot.path + '/'); | |
| 179 } | |
| 180 return root; | |
| 181 } | 151 } |
| 182 } | 152 } |
| OLD | NEW |