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