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 import 'package:analyzer/src/generated/utilities_dart.dart'; | 5 import 'package:analyzer/src/generated/utilities_dart.dart'; |
6 import 'package:analyzer/src/summary/format.dart'; | 6 import 'package:analyzer/src/summary/format.dart'; |
7 import 'package:analyzer/src/summary/idl.dart'; | 7 import 'package:analyzer/src/summary/idl.dart'; |
8 import 'package:analyzer/src/summary/name_filter.dart'; | 8 import 'package:analyzer/src/summary/name_filter.dart'; |
9 | 9 |
10 /** | 10 /** |
11 * Create a [LinkedLibraryBuilder] corresponding to the given | 11 * Create a [LinkedLibraryBuilder] corresponding to the given |
12 * [definingUnit], which should be the defining compilation unit for a library. | 12 * [definingUnit], which should be the defining compilation unit for a library. |
13 * Compilation units referenced by the defining compilation unit via `part` | 13 * Compilation units referenced by the defining compilation unit via `part` |
14 * declarations will be retrieved using [getPart]. Public namespaces for | 14 * declarations will be retrieved using [getPart]. Public namespaces for |
15 * libraries referenced by the defining compilation unit via `import` | 15 * libraries referenced by the defining compilation unit via `import` |
16 * declarations (and files reachable from them via `part` and `export` | 16 * declarations (and files reachable from them via `part` and `export` |
17 * declarations) will be retrieved using [getImport]. | 17 * declarations) will be retrieved using [getImport]. |
18 */ | 18 */ |
19 LinkedLibraryBuilder prelink(UnlinkedUnit definingUnit, GetPartCallback getPart, | 19 LinkedLibraryBuilder prelink(UnlinkedUnit definingUnit, GetPartCallback getPart, |
20 GetImportCallback getImport) { | 20 GetImportCallback getImport, GetDeclaredVariable getDeclaredVariable) { |
21 return new _Prelinker(definingUnit, getPart, getImport).prelink(); | 21 return new _Prelinker(definingUnit, getPart, getImport, getDeclaredVariable) |
| 22 .prelink(); |
22 } | 23 } |
23 | 24 |
24 /** | 25 /** |
| 26 * Return the raw string value of the variable with the given [name], |
| 27 * or `null` of the variable is not defined. |
| 28 */ |
| 29 typedef String GetDeclaredVariable(String name); |
| 30 |
| 31 /** |
25 * Type of the callback used by the prelinker to obtain public namespace | 32 * Type of the callback used by the prelinker to obtain public namespace |
26 * information about libraries imported by the library to be prelinked (and | 33 * information about libraries imported by the library to be prelinked (and |
27 * the transitive closure of parts and exports reachable from those libraries). | 34 * the transitive closure of parts and exports reachable from those libraries). |
28 * [relativeUri] should be interpreted relative to the defining compilation | 35 * [relativeUri] should be interpreted relative to the defining compilation |
29 * unit of the library being prelinked. | 36 * unit of the library being prelinked. |
30 * | 37 * |
31 * If no file exists at the given uri, `null` should be returned. | 38 * If no file exists at the given uri, `null` should be returned. |
32 */ | 39 */ |
33 typedef UnlinkedPublicNamespace GetImportCallback(String relativeUri); | 40 typedef UnlinkedPublicNamespace GetImportCallback(String relativeUri); |
34 | 41 |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 * Helper class containing temporary data structures needed to prelink a single | 121 * Helper class containing temporary data structures needed to prelink a single |
115 * library. | 122 * library. |
116 * | 123 * |
117 * Note: throughout this class, a `null` value for a relative URI represents | 124 * Note: throughout this class, a `null` value for a relative URI represents |
118 * the defining compilation unit of the library being prelinked. | 125 * the defining compilation unit of the library being prelinked. |
119 */ | 126 */ |
120 class _Prelinker { | 127 class _Prelinker { |
121 final UnlinkedUnit definingUnit; | 128 final UnlinkedUnit definingUnit; |
122 final GetPartCallback getPart; | 129 final GetPartCallback getPart; |
123 final GetImportCallback getImport; | 130 final GetImportCallback getImport; |
| 131 final GetDeclaredVariable getDeclaredVariable; |
124 | 132 |
125 /** | 133 /** |
126 * Cache of values returned by [getImport]. | 134 * Cache of values returned by [getImport]. |
127 */ | 135 */ |
128 final Map<String, UnlinkedPublicNamespace> importCache = | 136 final Map<String, UnlinkedPublicNamespace> importCache = |
129 <String, UnlinkedPublicNamespace>{}; | 137 <String, UnlinkedPublicNamespace>{}; |
130 | 138 |
131 /** | 139 /** |
132 * Cache of values returned by [getPart]. | 140 * Cache of values returned by [getPart]. |
133 */ | 141 */ |
(...skipping 20 matching lines...) Expand all Loading... |
154 * corresponding entry in [dependencies]. | 162 * corresponding entry in [dependencies]. |
155 */ | 163 */ |
156 final Map<String, int> uriToDependency = <String, int>{null: 0}; | 164 final Map<String, int> uriToDependency = <String, int>{null: 0}; |
157 | 165 |
158 /** | 166 /** |
159 * List of public namespaces corresponding to each entry in [dependencies]. | 167 * List of public namespaces corresponding to each entry in [dependencies]. |
160 */ | 168 */ |
161 final List<Map<String, _Meaning>> dependencyToPublicNamespace = | 169 final List<Map<String, _Meaning>> dependencyToPublicNamespace = |
162 <Map<String, _Meaning>>[null]; | 170 <Map<String, _Meaning>>[null]; |
163 | 171 |
164 _Prelinker(this.definingUnit, this.getPart, this.getImport) { | 172 _Prelinker(this.definingUnit, this.getPart, this.getImport, |
| 173 this.getDeclaredVariable) { |
165 partCache[null] = definingUnit; | 174 partCache[null] = definingUnit; |
166 importCache[null] = definingUnit.publicNamespace; | 175 importCache[null] = definingUnit.publicNamespace; |
167 } | 176 } |
168 | 177 |
169 /** | 178 /** |
170 * Compute the public namespace for the library whose URI is reachable from | 179 * Compute the public namespace for the library whose URI is reachable from |
171 * [definingUnit] via [relativeUri], by aggregating together public namespace | 180 * [definingUnit] via [relativeUri], by aggregating together public namespace |
172 * information from all of its parts. | 181 * information from all of its parts. |
173 */ | 182 */ |
174 Map<String, _Meaning> aggregatePublicNamespace(String relativeUri) { | 183 Map<String, _Meaning> aggregatePublicNamespace(String relativeUri) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 Map<String, _Meaning> exportNamespace = relativeUri == null | 233 Map<String, _Meaning> exportNamespace = relativeUri == null |
225 ? <String, _Meaning>{} | 234 ? <String, _Meaning>{} |
226 : aggregatePublicNamespace(relativeUri); | 235 : aggregatePublicNamespace(relativeUri); |
227 void chaseExports( | 236 void chaseExports( |
228 NameFilter filter, String relativeUri, Set<String> seenUris) { | 237 NameFilter filter, String relativeUri, Set<String> seenUris) { |
229 if (seenUris.add(relativeUri)) { | 238 if (seenUris.add(relativeUri)) { |
230 UnlinkedPublicNamespace exportedNamespace = | 239 UnlinkedPublicNamespace exportedNamespace = |
231 getImportCached(relativeUri); | 240 getImportCached(relativeUri); |
232 if (exportedNamespace != null) { | 241 if (exportedNamespace != null) { |
233 for (UnlinkedExportPublic export in exportedNamespace.exports) { | 242 for (UnlinkedExportPublic export in exportedNamespace.exports) { |
234 String exportUri = resolveUri(relativeUri, export.uri); | 243 String relativeExportUri = |
| 244 _selectUri(export.uri, export.configurations); |
| 245 String exportUri = resolveUri(relativeUri, relativeExportUri); |
235 NameFilter newFilter = filter.merge( | 246 NameFilter newFilter = filter.merge( |
236 new NameFilter.forUnlinkedCombinators(export.combinators)); | 247 new NameFilter.forUnlinkedCombinators(export.combinators)); |
237 aggregatePublicNamespace(exportUri) | 248 aggregatePublicNamespace(exportUri) |
238 .forEach((String name, _Meaning meaning) { | 249 .forEach((String name, _Meaning meaning) { |
239 if (newFilter.accepts(name) && | 250 if (newFilter.accepts(name) && |
240 !exportNamespace.containsKey(name)) { | 251 !exportNamespace.containsKey(name)) { |
241 exportNamespace[name] = meaning; | 252 exportNamespace[name] = meaning; |
242 } | 253 } |
243 }); | 254 }); |
244 chaseExports(newFilter, exportUri, seenUris); | 255 chaseExports(newFilter, exportUri, seenUris); |
245 } | 256 } |
246 } | 257 } |
247 seenUris.remove(relativeUri); | 258 seenUris.remove(relativeUri); |
248 } | 259 } |
249 } | 260 } |
| 261 |
250 chaseExports(NameFilter.identity, relativeUri, new Set<String>()); | 262 chaseExports(NameFilter.identity, relativeUri, new Set<String>()); |
251 return exportNamespace; | 263 return exportNamespace; |
252 } | 264 } |
253 | 265 |
254 /** | 266 /** |
255 * Extract all the names defined in [unit] (which is the [unitNum]th unit in | 267 * Extract all the names defined in [unit] (which is the [unitNum]th unit in |
256 * the library being prelinked) and store them in [privateNamespace]. | 268 * the library being prelinked) and store them in [privateNamespace]. |
257 * Excludes names introduced by `import` statements. | 269 * Excludes names introduced by `import` statements. |
258 */ | 270 */ |
259 void extractPrivateNames(UnlinkedUnit unit, int unitNum) { | 271 void extractPrivateNames(UnlinkedUnit unit, int unitNum) { |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
378 .map((String uri) => resolveUri(relativeUri, uri))); | 390 .map((String uri) => resolveUri(relativeUri, uri))); |
379 } | 391 } |
380 return result; | 392 return result; |
381 } | 393 } |
382 | 394 |
383 /** | 395 /** |
384 * Process a single `import` declaration in the library being prelinked. The | 396 * Process a single `import` declaration in the library being prelinked. The |
385 * return value is the index of the imported library in [dependencies]. | 397 * return value is the index of the imported library in [dependencies]. |
386 */ | 398 */ |
387 int handleImport(UnlinkedImport import) { | 399 int handleImport(UnlinkedImport import) { |
388 String uri = import.isImplicit ? 'dart:core' : import.uri; | 400 String uri = import.isImplicit |
| 401 ? 'dart:core' |
| 402 : _selectUri(import.uri, import.configurations); |
389 Map<String, _Meaning> targetNamespace = null; | 403 Map<String, _Meaning> targetNamespace = null; |
390 if (import.prefixReference != 0) { | 404 if (import.prefixReference != 0) { |
391 // The name introduced by an import declaration can't have a prefix of | 405 // The name introduced by an import declaration can't have a prefix of |
392 // its own. | 406 // its own. |
393 assert( | 407 assert( |
394 definingUnit.references[import.prefixReference].prefixReference == 0); | 408 definingUnit.references[import.prefixReference].prefixReference == 0); |
395 String prefix = definingUnit.references[import.prefixReference].name; | 409 String prefix = definingUnit.references[import.prefixReference].name; |
396 _Meaning prefixMeaning = privateNamespace[prefix]; | 410 _Meaning prefixMeaning = privateNamespace[prefix]; |
397 if (prefixMeaning is _PrefixMeaning) { | 411 if (prefixMeaning is _PrefixMeaning) { |
398 targetNamespace = prefixMeaning.namespace; | 412 targetNamespace = prefixMeaning.namespace; |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
476 if (import.prefixReference != 0) { | 490 if (import.prefixReference != 0) { |
477 privateNamespace.putIfAbsent( | 491 privateNamespace.putIfAbsent( |
478 units[0].references[import.prefixReference].name, | 492 units[0].references[import.prefixReference].name, |
479 () => new _PrefixMeaning()); | 493 () => new _PrefixMeaning()); |
480 } | 494 } |
481 } | 495 } |
482 | 496 |
483 // Fill in imported and exported names. | 497 // Fill in imported and exported names. |
484 List<int> importDependencies = | 498 List<int> importDependencies = |
485 definingUnit.imports.map(handleImport).toList(); | 499 definingUnit.imports.map(handleImport).toList(); |
486 List<int> exportDependencies = definingUnit.publicNamespace.exports | 500 List<int> exportDependencies = |
487 .map((UnlinkedExportPublic exp) => uriToDependency[exp.uri]) | 501 definingUnit.publicNamespace.exports.map((UnlinkedExportPublic exp) { |
488 .toList(); | 502 String uri = _selectUri(exp.uri, exp.configurations); |
| 503 return uriToDependency[uri]; |
| 504 }).toList(); |
489 | 505 |
490 // Link each compilation unit. | 506 // Link each compilation unit. |
491 List<LinkedUnitBuilder> linkedUnits = units.map(linkUnit).toList(); | 507 List<LinkedUnitBuilder> linkedUnits = units.map(linkUnit).toList(); |
492 | 508 |
493 return new LinkedLibraryBuilder( | 509 return new LinkedLibraryBuilder( |
494 units: linkedUnits, | 510 units: linkedUnits, |
495 dependencies: dependencies, | 511 dependencies: dependencies, |
496 importDependencies: importDependencies, | 512 importDependencies: importDependencies, |
497 exportDependencies: exportDependencies, | 513 exportDependencies: exportDependencies, |
498 exportNames: exportNames, | 514 exportNames: exportNames, |
499 numPrelinkedDependencies: dependencies.length); | 515 numPrelinkedDependencies: dependencies.length); |
500 } | 516 } |
501 | 517 |
502 /** | 518 /** |
503 * Resolve [relativeUri] relative to [sourceUri]. Works correctly if | 519 * Resolve [relativeUri] relative to [sourceUri]. Works correctly if |
504 * [sourceUri] is also relative. | 520 * [sourceUri] is also relative. |
505 */ | 521 */ |
506 String resolveUri(String sourceUri, String relativeUri) { | 522 String resolveUri(String sourceUri, String relativeUri) { |
507 if (sourceUri == null) { | 523 if (sourceUri == null) { |
508 return relativeUri; | 524 return relativeUri; |
509 } else { | 525 } else { |
510 return resolveRelativeUri(Uri.parse(sourceUri), Uri.parse(relativeUri)) | 526 return resolveRelativeUri(Uri.parse(sourceUri), Uri.parse(relativeUri)) |
511 .toString(); | 527 .toString(); |
512 } | 528 } |
513 } | 529 } |
| 530 |
| 531 /** |
| 532 * Return the URI of the first configuration from the given [configurations] |
| 533 * which condition is satisfied, or the [defaultUri]. |
| 534 */ |
| 535 String _selectUri( |
| 536 String defaultUri, List<UnlinkedConfiguration> configurations) { |
| 537 for (UnlinkedConfiguration configuration in configurations) { |
| 538 if (getDeclaredVariable(configuration.name) == configuration.value) { |
| 539 return configuration.uri; |
| 540 } |
| 541 } |
| 542 return defaultUri; |
| 543 } |
514 } | 544 } |
OLD | NEW |