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 |