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 |