OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 library fasta.uri_translator_impl; | 5 library fasta.uri_translator_impl; |
6 | 6 |
7 import 'package:front_end/src/base/libraries_specification.dart' | 7 import 'dart:async' show Future; |
8 show TargetLibrariesSpecification; | 8 import 'dart:convert' show JSON; |
| 9 |
| 10 import 'package:front_end/file_system.dart' |
| 11 show FileSystem, FileSystemException; |
9 import 'package:front_end/src/fasta/compiler_context.dart' show CompilerContext; | 12 import 'package:front_end/src/fasta/compiler_context.dart' show CompilerContext; |
10 import 'package:front_end/src/fasta/fasta_codes.dart'; | 13 import 'package:front_end/src/fasta/fasta_codes.dart'; |
11 import 'package:front_end/src/fasta/severity.dart' show Severity; | 14 import 'package:front_end/src/fasta/severity.dart' show Severity; |
12 import 'package:front_end/src/fasta/uri_translator.dart'; | 15 import 'package:front_end/src/fasta/uri_translator.dart'; |
| 16 import 'package:package_config/packages_file.dart' as packages_file show parse; |
13 import 'package:package_config/packages.dart' show Packages; | 17 import 'package:package_config/packages.dart' show Packages; |
| 18 import 'package:package_config/src/packages_impl.dart' show MapPackages; |
| 19 |
| 20 import 'deprecated_problems.dart' show deprecated_inputError; |
| 21 |
| 22 /// Read the JSON file with defined SDK libraries from the given [uri] in the |
| 23 /// [fileSystem] and return the mapping from parsed Dart library names (e.g. |
| 24 /// `math`) to file URIs. |
| 25 Future<Map<String, Uri>> computeDartLibraries( |
| 26 FileSystem fileSystem, Uri uri) async { |
| 27 if (uri == null) return const <String, Uri>{}; |
| 28 Map<String, String> libraries = JSON |
| 29 .decode(await fileSystem.entityForUri(uri).readAsString())["libraries"]; |
| 30 Map<String, Uri> result = <String, Uri>{}; |
| 31 libraries.forEach((String name, String path) { |
| 32 result[name] = uri.resolveUri(new Uri.file(path)); |
| 33 }); |
| 34 return result; |
| 35 } |
| 36 |
| 37 Future<Map<String, List<Uri>>> computeDartPatches( |
| 38 FileSystem fileSystem, Uri uri) async { |
| 39 // TODO(ahe): Read patch information. |
| 40 return const <String, List<Uri>>{}; |
| 41 } |
14 | 42 |
15 /// Implementation of [UriTranslator] for absolute `dart` and `package` URIs. | 43 /// Implementation of [UriTranslator] for absolute `dart` and `package` URIs. |
16 class UriTranslatorImpl implements UriTranslator { | 44 class UriTranslatorImpl implements UriTranslator { |
17 /// Library information for platform libraries. | 45 /// Mapping from Dart library names (e.g. `math`) to file URIs. |
18 final TargetLibrariesSpecification dartLibraries; | 46 final Map<String, Uri> dartLibraries; |
| 47 |
| 48 // TODO(ahe): We probably want this to be `Map<String, Uri>`, that is, just |
| 49 // one patch library (with parts). |
| 50 /// Mapping from Dart library names to the file URIs of patches to apply. |
| 51 final Map<String, List<Uri>> dartPatches; |
19 | 52 |
20 /// Mapping from package names (e.g. `angular`) to the file URIs. | 53 /// Mapping from package names (e.g. `angular`) to the file URIs. |
21 final Packages packages; | 54 final Packages packages; |
22 | 55 |
23 UriTranslatorImpl(this.dartLibraries, this.packages); | 56 UriTranslatorImpl(this.dartLibraries, this.dartPatches, this.packages); |
24 | 57 |
25 @override | 58 @override |
26 List<Uri> getDartPatches(String libraryName) => | 59 List<Uri> getDartPatches(String libraryName) => dartPatches[libraryName]; |
27 dartLibraries.libraryInfoFor(libraryName)?.patches; | |
28 | 60 |
29 @override | 61 @override |
30 bool isPlatformImplementation(Uri uri) { | 62 bool isPlatformImplementation(Uri uri) { |
31 if (uri.scheme != "dart") return false; | 63 if (uri.scheme != "dart") return false; |
32 String path = uri.path; | 64 String path = uri.path; |
33 return dartLibraries.libraryInfoFor(path) == null || path.startsWith("_"); | 65 return dartLibraries[path] == null || path.startsWith("_"); |
34 } | 66 } |
35 | 67 |
36 @override | 68 @override |
37 // TODO(sigmund, ahe): consider expanding this API to include an error | 69 // TODO(sigmund, ahe): consider expanding this API to include an error |
38 // callback, so we can provide an error location when one is available. For | 70 // callback, so we can provide an error location when one is available. For |
39 // example, if the error occurs in an `import`. | 71 // example, if the error occurs in an `import`. |
40 Uri translate(Uri uri) { | 72 Uri translate(Uri uri) { |
41 if (uri.scheme == "dart") return _translateDartUri(uri); | 73 if (uri.scheme == "dart") return _translateDartUri(uri); |
42 if (uri.scheme == "package") return _translatePackageUri(uri); | 74 if (uri.scheme == "package") return _translatePackageUri(uri); |
43 return null; | 75 return null; |
44 } | 76 } |
45 | 77 |
46 /// Return the file URI that corresponds to the given `dart` URI, or `null` | 78 /// Return the file URI that corresponds to the given `dart` URI, or `null` |
47 /// if there is no corresponding Dart library registered. | 79 /// if there is no corresponding Dart library registered. |
48 Uri _translateDartUri(Uri uri) { | 80 Uri _translateDartUri(Uri uri) { |
49 if (!uri.isScheme('dart')) return null; | 81 if (!uri.isScheme('dart')) return null; |
50 String path = uri.path; | 82 String path = uri.path; |
51 | 83 |
52 int index = path.indexOf('/'); | 84 int index = path.indexOf('/'); |
53 if (index == -1) return dartLibraries.libraryInfoFor(path)?.uri; | 85 if (index == -1) return dartLibraries[path]; |
54 | 86 |
55 String libraryName = path.substring(0, index); | 87 String libraryName = path.substring(0, index); |
56 String relativePath = path.substring(index + 1); | 88 String relativePath = path.substring(index + 1); |
57 Uri libraryFileUri = dartLibraries.libraryInfoFor(libraryName).uri; | 89 Uri libraryFileUri = dartLibraries[libraryName]; |
58 return libraryFileUri?.resolve(relativePath); | 90 return libraryFileUri?.resolve(relativePath); |
59 } | 91 } |
60 | 92 |
61 /// Return the file URI that corresponds to the given `package` URI, or | 93 /// Return the file URI that corresponds to the given `package` URI, or |
62 /// `null` if the `package` [uri] format is invalid, or there is no | 94 /// `null` if the `package` [uri] format is invalid, or there is no |
63 /// corresponding package registered. | 95 /// corresponding package registered. |
64 Uri _translatePackageUri(Uri uri) { | 96 Uri _translatePackageUri(Uri uri) { |
65 try { | 97 try { |
66 // TODO(sigmund): once we remove the `parse` API, we can ensure that | 98 // TODO(sigmund): once we remove the `parse` API, we can ensure that |
67 // packages will never be null and get rid of `?` below. | 99 // packages will never be null and get rid of `?` below. |
68 return packages?.resolve(uri, notFound: _packageUriNotFound); | 100 return packages?.resolve(uri, notFound: _packageUriNotFound); |
69 } on ArgumentError catch (e) { | 101 } on ArgumentError catch (e) { |
70 // TODO(sigmund): catch a more precise error when | 102 // TODO(sigmund): catch a more precise error when |
71 // https://github.com/dart-lang/package_config/issues/40 is fixed. | 103 // https://github.com/dart-lang/package_config/issues/40 is fixed. |
72 CompilerContext.current.reportWithoutLocation( | 104 CompilerContext.current.reportWithoutLocation( |
73 templateInvalidPackageUri.withArguments(uri, '$e'), Severity.error); | 105 templateInvalidPackageUri.withArguments(uri, '$e'), Severity.error); |
74 return null; | 106 return null; |
75 } | 107 } |
76 } | 108 } |
77 | 109 |
78 static Uri _packageUriNotFound(Uri uri) { | 110 static Uri _packageUriNotFound(Uri uri) { |
79 String name = uri.pathSegments.first; | 111 String name = uri.pathSegments.first; |
80 CompilerContext.current.reportWithoutLocation( | 112 CompilerContext.current.reportWithoutLocation( |
81 templatePackageNotFound.withArguments(name, uri), Severity.error); | 113 templatePackageNotFound.withArguments(name, uri), Severity.error); |
82 // TODO(sigmund, ahe): ensure we only report an error once, | 114 // TODO(sigmund, ahe): ensure we only report an error once, |
83 // this null result will likely cause another error further down in the | 115 // this null result will likely cause another error further down in the |
84 // compiler. | 116 // compiler. |
85 return null; | 117 return null; |
86 } | 118 } |
| 119 |
| 120 static Future<UriTranslator> parse(FileSystem fileSystem, Uri sdk, |
| 121 {Uri packages}) async { |
| 122 Uri librariesJson = sdk?.resolve("lib/libraries.json"); |
| 123 |
| 124 // TODO(ahe): Provide a value for this file. |
| 125 Uri patches = null; |
| 126 |
| 127 packages ??= Uri.base.resolve(".packages"); |
| 128 |
| 129 List<int> bytes; |
| 130 try { |
| 131 bytes = await fileSystem.entityForUri(packages).readAsBytes(); |
| 132 } on FileSystemException catch (e) { |
| 133 deprecated_inputError(packages, -1, e.message); |
| 134 } |
| 135 |
| 136 Packages parsedPackages; |
| 137 try { |
| 138 parsedPackages = new MapPackages(packages_file.parse(bytes, packages)); |
| 139 } on FormatException catch (e) { |
| 140 return deprecated_inputError(packages, e.offset, e.message); |
| 141 } |
| 142 |
| 143 var dartLibraries = await computeDartLibraries(fileSystem, librariesJson); |
| 144 return new UriTranslatorImpl(dartLibraries, |
| 145 await computeDartPatches(fileSystem, patches), parsedPackages); |
| 146 } |
87 } | 147 } |
OLD | NEW |