Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(563)

Side by Side Diff: pkg/front_end/lib/src/base/processed_options.dart

Issue 2979003002: support resolving .packages in FE (Closed)
Patch Set: Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698