Chromium Code Reviews| 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 [definingUnitUri] |
| 12 * [definingUnit], which should be the defining compilation unit for a library. | 12 * and [definingUnit], which should be the defining compilation unit for a |
| 13 * Compilation units referenced by the defining compilation unit via `part` | 13 * library. Compilation units referenced by the defining compilation unit via |
| 14 * declarations will be retrieved using [getPart]. Public namespaces for | 14 * `part` declarations will be retrieved using [getPart]. Public namespaces |
| 15 * libraries referenced by the defining compilation unit via `import` | 15 * for 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( |
| 20 GetImportCallback getImport, GetDeclaredVariable getDeclaredVariable) { | 20 String definingUnitUri, |
| 21 return new _Prelinker(definingUnit, getPart, getImport, getDeclaredVariable) | 21 UnlinkedUnit definingUnit, |
| 22 GetPartCallback getPart, | |
| 23 GetImportCallback getImport, | |
| 24 GetDeclaredVariable getDeclaredVariable) { | |
| 25 return new _Prelinker(definingUnitUri, definingUnit, getPart, getImport, | |
| 26 getDeclaredVariable) | |
| 22 .prelink(); | 27 .prelink(); |
| 23 } | 28 } |
| 24 | 29 |
| 25 /** | 30 /** |
| 26 * Return the raw string value of the variable with the given [name], | 31 * Return the raw string value of the variable with the given [name], |
| 27 * or `null` of the variable is not defined. | 32 * or `null` of the variable is not defined. |
| 28 */ | 33 */ |
| 29 typedef String GetDeclaredVariable(String name); | 34 typedef String GetDeclaredVariable(String name); |
| 30 | 35 |
| 31 /** | 36 /** |
| 32 * Type of the callback used by the prelinker to obtain public namespace | 37 * Type of the callback used by the prelinker to obtain public namespace |
| 33 * information about libraries imported by the library to be prelinked (and | 38 * information about libraries with the given [absoluteUri] imported by the |
| 34 * the transitive closure of parts and exports reachable from those libraries). | 39 * library to be prelinked (and the transitive closure of parts and exports |
| 35 * [relativeUri] should be interpreted relative to the defining compilation | 40 * reachable from those libraries). |
| 36 * unit of the library being prelinked. | |
| 37 * | 41 * |
| 38 * If no file exists at the given uri, `null` should be returned. | 42 * If no file exists at the given uri, `null` should be returned. |
| 39 */ | 43 */ |
| 40 typedef UnlinkedPublicNamespace GetImportCallback(String relativeUri); | 44 typedef UnlinkedPublicNamespace GetImportCallback(String absoluteUri); |
| 41 | 45 |
| 42 /** | 46 /** |
| 43 * Type of the callback used by the prelinker to obtain unlinked summaries of | 47 * Type of the callback used by the prelinker to obtain unlinked summaries of |
| 44 * part files of the library to be prelinked. [relativeUri] should be | 48 * part files of the library to be prelinked. |
| 45 * interpreted relative to the defining compilation unit of the library being | |
| 46 * prelinked. | |
| 47 * | 49 * |
| 48 * If no file exists at the given uri, `null` should be returned. | 50 * If no file exists at the given uri, `null` should be returned. |
| 49 */ | 51 */ |
| 50 typedef UnlinkedUnit GetPartCallback(String relativeUri); | 52 typedef UnlinkedUnit GetPartCallback(String absoluteUri); |
| 51 | 53 |
| 52 /** | 54 /** |
| 53 * A [_Meaning] representing a class. | 55 * A [_Meaning] representing a class. |
| 54 */ | 56 */ |
| 55 class _ClassMeaning extends _Meaning { | 57 class _ClassMeaning extends _Meaning { |
| 56 final _Namespace namespace; | 58 final _Namespace namespace; |
| 57 | 59 |
| 58 _ClassMeaning(int unit, int dependency, int numTypeParameters, this.namespace) | 60 _ClassMeaning(int unit, int dependency, int numTypeParameters, this.namespace) |
| 59 : super(unit, ReferenceKind.classOrEnum, dependency, numTypeParameters); | 61 : super(unit, ReferenceKind.classOrEnum, dependency, numTypeParameters); |
| 60 } | 62 } |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 177 */ | 179 */ |
| 178 class _PrefixMeaning extends _Meaning { | 180 class _PrefixMeaning extends _Meaning { |
| 179 final _Namespace namespace = new _Namespace(); | 181 final _Namespace namespace = new _Namespace(); |
| 180 | 182 |
| 181 _PrefixMeaning() : super(0, ReferenceKind.prefix, 0, 0); | 183 _PrefixMeaning() : super(0, ReferenceKind.prefix, 0, 0); |
| 182 } | 184 } |
| 183 | 185 |
| 184 /** | 186 /** |
| 185 * Helper class containing temporary data structures needed to prelink a single | 187 * Helper class containing temporary data structures needed to prelink a single |
| 186 * library. | 188 * library. |
| 187 * | |
| 188 * Note: throughout this class, a `null` value for a relative URI represents | |
| 189 * the defining compilation unit of the library being prelinked. | |
| 190 */ | 189 */ |
| 191 class _Prelinker { | 190 class _Prelinker { |
| 191 final String definingUnitUri; | |
| 192 final UnlinkedUnit definingUnit; | 192 final UnlinkedUnit definingUnit; |
| 193 final GetPartCallback getPart; | 193 final GetPartCallback getPart; |
| 194 final GetImportCallback getImport; | 194 final GetImportCallback getImport; |
| 195 final GetDeclaredVariable getDeclaredVariable; | 195 final GetDeclaredVariable getDeclaredVariable; |
| 196 | 196 |
| 197 /** | 197 /** |
| 198 * Cache of values returned by [getImport]. | 198 * Cache of values returned by [getImport]. |
| 199 */ | 199 */ |
| 200 final Map<String, UnlinkedPublicNamespace> importCache = | 200 final Map<String, UnlinkedPublicNamespace> importCache = |
| 201 <String, UnlinkedPublicNamespace>{}; | 201 <String, UnlinkedPublicNamespace>{}; |
| 202 | 202 |
| 203 /** | 203 /** |
| 204 * Cache of values returned by [getPart]. | 204 * Cache of values returned by [getPart]. |
| 205 */ | 205 */ |
| 206 final Map<String, UnlinkedUnit> partCache = <String, UnlinkedUnit>{}; | 206 final Map<String, UnlinkedUnit> partCache = <String, UnlinkedUnit>{}; |
| 207 | 207 |
| 208 /** | 208 /** |
| 209 * Names defined inside the library being prelinked. | 209 * Names defined inside the library being prelinked. |
| 210 */ | 210 */ |
| 211 final _Namespace privateNamespace = new _Namespace() | 211 final _Namespace privateNamespace = new _Namespace() |
| 212 ..add('dynamic', new _Meaning(0, ReferenceKind.classOrEnum, 0, 0)) | 212 ..add('dynamic', new _Meaning(0, ReferenceKind.classOrEnum, 0, 0)) |
| 213 ..add('void', new _Meaning(0, ReferenceKind.classOrEnum, 0, 0)); | 213 ..add('void', new _Meaning(0, ReferenceKind.classOrEnum, 0, 0)); |
| 214 | 214 |
| 215 /** | 215 /** |
| 216 * List of dependencies of the library being prelinked. This will be output | 216 * List of dependencies of the library being prelinked. This will be output |
| 217 * to [LinkedLibrary.dependencies]. | 217 * to [LinkedLibrary.dependencies]. |
| 218 */ | 218 */ |
| 219 final List<LinkedDependencyBuilder> dependencies = <LinkedDependencyBuilder>[ | 219 final List<LinkedDependencyBuilder> dependencies = |
| 220 new LinkedDependencyBuilder() | 220 <LinkedDependencyBuilder>[]; |
| 221 ]; | |
| 222 | 221 |
| 223 /** | 222 /** |
| 224 * Map from the relative URI of a dependent library to the index of the | 223 * Map from the absolute URI of a dependent library to the index of the |
| 225 * corresponding entry in [dependencies]. | 224 * corresponding entry in [dependencies]. |
| 226 */ | 225 */ |
| 227 final Map<String, int> uriToDependency = <String, int>{null: 0}; | 226 final Map<String, int> uriToDependency = <String, int>{}; |
|
Paul Berry
2017/02/16 22:17:50
I don't understand this change. Why don't we need
scheglov
2017/02/16 22:32:36
computeExportNamespace() needs to use absolute URI
Paul Berry
2017/02/16 22:55:26
Ok, thanks.
| |
| 228 | 227 |
| 229 /** | 228 /** |
| 230 * List of public namespaces corresponding to each entry in [dependencies]. | 229 * List of public namespaces corresponding to each entry in [dependencies]. |
| 231 */ | 230 */ |
| 232 final List<_Namespace> dependencyToPublicNamespace = <_Namespace>[null]; | 231 final List<_Namespace> dependencyToPublicNamespace = <_Namespace>[]; |
| 233 | 232 |
| 234 _Prelinker(this.definingUnit, this.getPart, this.getImport, | 233 _Prelinker(this.definingUnitUri, this.definingUnit, this.getPart, |
| 235 this.getDeclaredVariable) { | 234 this.getImport, this.getDeclaredVariable) { |
| 236 partCache[null] = definingUnit; | 235 partCache[definingUnitUri] = definingUnit; |
| 237 importCache[null] = definingUnit.publicNamespace; | 236 importCache[definingUnitUri] = definingUnit.publicNamespace; |
| 238 } | 237 } |
| 239 | 238 |
| 240 /** | 239 /** |
| 241 * Compute the public namespace for the library whose URI is reachable from | 240 * Compute the public namespace for the library whose URI is reachable from |
| 242 * [definingUnit] via [relativeUri], by aggregating together public namespace | 241 * [definingUnit] via [absoluteUri], by aggregating together public namespace |
| 243 * information from all of its parts. | 242 * information from all of its parts. |
| 244 */ | 243 */ |
| 245 _Namespace aggregatePublicNamespace(String relativeUri) { | 244 _Namespace aggregatePublicNamespace(String absoluteUri) { |
| 246 if (uriToDependency.containsKey(relativeUri)) { | 245 if (uriToDependency.containsKey(absoluteUri)) { |
| 247 return dependencyToPublicNamespace[uriToDependency[relativeUri]]; | 246 return dependencyToPublicNamespace[uriToDependency[absoluteUri]]; |
| 248 } | 247 } |
| 249 assert(dependencies.length == dependencyToPublicNamespace.length); | 248 assert(dependencies.length == dependencyToPublicNamespace.length); |
| 250 int dependency = dependencies.length; | 249 int dependency = dependencies.length; |
| 251 uriToDependency[relativeUri] = dependency; | 250 uriToDependency[absoluteUri] = dependency; |
| 252 List<String> unitUris = getUnitUris(relativeUri); | 251 List<String> unitUris = getUnitUris(absoluteUri); |
| 253 LinkedDependencyBuilder linkedDependency = new LinkedDependencyBuilder( | 252 LinkedDependencyBuilder linkedDependency = new LinkedDependencyBuilder( |
| 254 uri: relativeUri, parts: unitUris.sublist(1)); | 253 uri: absoluteUri, |
| 254 parts: unitUris.skip(1).map((uri) => uri ?? '').toList()); | |
| 255 dependencies.add(linkedDependency); | 255 dependencies.add(linkedDependency); |
| 256 | 256 |
| 257 _Namespace aggregated = new _Namespace(); | 257 _Namespace aggregated = new _Namespace(); |
| 258 | 258 |
| 259 for (int unitNum = 0; unitNum < unitUris.length; unitNum++) { | 259 for (int unitNum = 0; unitNum < unitUris.length; unitNum++) { |
| 260 String unitUri = unitUris[unitNum]; | 260 String unitUri = unitUris[unitNum]; |
| 261 UnlinkedPublicNamespace importedNamespace = getImportCached(unitUri); | 261 UnlinkedPublicNamespace importedNamespace = getImportCached(unitUri); |
| 262 if (importedNamespace == null) { | 262 if (importedNamespace == null) { |
| 263 continue; | 263 continue; |
| 264 } | 264 } |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 285 } | 285 } |
| 286 | 286 |
| 287 aggregated.rememberLibraryNames(); | 287 aggregated.rememberLibraryNames(); |
| 288 | 288 |
| 289 dependencyToPublicNamespace.add(aggregated); | 289 dependencyToPublicNamespace.add(aggregated); |
| 290 return aggregated; | 290 return aggregated; |
| 291 } | 291 } |
| 292 | 292 |
| 293 /** | 293 /** |
| 294 * Compute the export namespace for the library whose URI is reachable from | 294 * Compute the export namespace for the library whose URI is reachable from |
| 295 * [definingUnit] via [relativeUri], by aggregating together public namespace | 295 * [definingUnit] via [absoluteUri], by aggregating together public namespace |
| 296 * information from the library and the transitive closure of its exports. | 296 * information from the library and the transitive closure of its exports. |
| 297 * | |
| 298 * If [relativeUri] is `null` (meaning the export namespace of [definingUnit] | |
| 299 * should be computed), then names defined in [definingUnit] are ignored. | |
| 300 */ | 297 */ |
| 301 _Namespace computeExportNamespace(String relativeUri) { | 298 _Namespace computeExportNamespace(String absoluteUri) { |
| 302 Set<String> seenUris = new Set<String>(); | 299 Set<String> seenUris = new Set<String>(); |
| 303 _Namespace chaseExports(String relativeUri, NameFilter filter) { | 300 _Namespace chaseExports(String absoluteUri, NameFilter filter) { |
| 304 _Namespace exportedNamespace = relativeUri == null | 301 _Namespace exportedNamespace = aggregatePublicNamespace(absoluteUri); |
| 305 ? new _Namespace() | 302 if (seenUris.add(absoluteUri)) { |
| 306 : aggregatePublicNamespace(relativeUri); | 303 UnlinkedPublicNamespace publicNamespace = getImportCached(absoluteUri); |
| 307 if (seenUris.add(relativeUri)) { | |
| 308 UnlinkedPublicNamespace publicNamespace = getImportCached(relativeUri); | |
| 309 if (publicNamespace != null) { | 304 if (publicNamespace != null) { |
| 310 for (UnlinkedExportPublic export in publicNamespace.exports) { | 305 for (UnlinkedExportPublic export in publicNamespace.exports) { |
| 311 String relativeExportUri = | 306 String unlinkedExportUri = |
| 312 _selectUri(export.uri, export.configurations); | 307 _selectUri(export.uri, export.configurations); |
| 313 String exportUri = resolveUri(relativeUri, relativeExportUri); | 308 String exportUri = resolveUri(absoluteUri, unlinkedExportUri); |
| 314 NameFilter newFilter = filter.merge( | 309 if (exportUri != null) { |
| 315 new NameFilter.forUnlinkedCombinators(export.combinators)); | 310 NameFilter newFilter = filter.merge( |
| 316 _Namespace exportNamespace = chaseExports(exportUri, newFilter); | 311 new NameFilter.forUnlinkedCombinators(export.combinators)); |
| 317 exportNamespace.forEach((String name, _Meaning meaning) { | 312 _Namespace exportNamespace = chaseExports(exportUri, newFilter); |
| 318 if (newFilter.accepts(name) && | 313 exportNamespace.forEach((String name, _Meaning meaning) { |
| 319 !exportedNamespace.definesLibraryName(name)) { | 314 if (newFilter.accepts(name) && |
| 320 exportedNamespace.add(name, meaning); | 315 !exportedNamespace.definesLibraryName(name)) { |
| 321 } | 316 exportedNamespace.add(name, meaning); |
| 322 }); | 317 } |
| 318 }); | |
| 319 } | |
| 323 } | 320 } |
| 324 } | 321 } |
| 325 seenUris.remove(relativeUri); | 322 seenUris.remove(absoluteUri); |
| 326 } | 323 } |
| 327 return exportedNamespace; | 324 return exportedNamespace; |
| 328 } | 325 } |
| 329 | 326 |
| 330 return chaseExports(relativeUri, NameFilter.identity); | 327 return chaseExports(absoluteUri, NameFilter.identity); |
| 331 } | 328 } |
| 332 | 329 |
| 333 /** | 330 /** |
| 334 * Extract all the names defined in [unit] (which is the [unitNum]th unit in | 331 * Extract all the names defined in [unit] (which is the [unitNum]th unit in |
| 335 * the library being prelinked) and store them in [privateNamespace]. | 332 * the library being prelinked) and store them in [privateNamespace]. |
| 336 * Excludes names introduced by `import` statements. | 333 * Excludes names introduced by `import` statements. |
| 337 */ | 334 */ |
| 338 void extractPrivateNames(UnlinkedUnit unit, int unitNum) { | 335 void extractPrivateNames(UnlinkedUnit unit, int unitNum) { |
| 339 for (UnlinkedClass cls in unit.classes) { | 336 for (UnlinkedClass cls in unit.classes) { |
| 340 _Namespace namespace = new _Namespace(); | 337 _Namespace namespace = new _Namespace(); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 397 if (!(variable.isConst || variable.isFinal)) { | 394 if (!(variable.isConst || variable.isFinal)) { |
| 398 privateNamespace.add( | 395 privateNamespace.add( |
| 399 variable.name + '=', | 396 variable.name + '=', |
| 400 new _Meaning( | 397 new _Meaning( |
| 401 unitNum, ReferenceKind.topLevelPropertyAccessor, 0, 0)); | 398 unitNum, ReferenceKind.topLevelPropertyAccessor, 0, 0)); |
| 402 } | 399 } |
| 403 } | 400 } |
| 404 } | 401 } |
| 405 | 402 |
| 406 /** | 403 /** |
| 407 * Filter the export namespace for the library whose URI is reachable from | 404 * Filter the export namespace for the library whose URI is reachable the |
| 408 * [definingUnit] via [relativeUri], retaining only those names accepted by | 405 * given [absoluteUri], retaining only those names accepted by |
| 409 * [combinators], and store the resulting names in [result]. Names that | 406 * [combinators], and store the resulting names in [result]. Names that |
| 410 * already exist in [result] are not overwritten. | 407 * already exist in [result] are not overwritten. |
| 411 */ | 408 */ |
| 412 void filterExportNamespace(String relativeUri, | 409 void filterExportNamespace(String absoluteUri, |
| 413 List<UnlinkedCombinator> combinators, _Namespace result) { | 410 List<UnlinkedCombinator> combinators, _Namespace result) { |
| 414 _Namespace exportNamespace = computeExportNamespace(relativeUri); | 411 _Namespace exportNamespace = computeExportNamespace(absoluteUri); |
| 415 if (result == null) { | 412 if (result == null) { |
| 416 // This can happen if the import prefix was shadowed by a local name, so | 413 // This can happen if the import prefix was shadowed by a local name, so |
| 417 // the imported symbols are inaccessible. | 414 // the imported symbols are inaccessible. |
| 418 return; | 415 return; |
| 419 } | 416 } |
| 420 NameFilter filter = new NameFilter.forUnlinkedCombinators(combinators); | 417 NameFilter filter = new NameFilter.forUnlinkedCombinators(combinators); |
| 421 exportNamespace.forEach((String name, _Meaning meaning) { | 418 exportNamespace.forEach((String name, _Meaning meaning) { |
| 422 if (filter.accepts(name) && !result.definesLibraryName(name)) { | 419 if (filter.accepts(name) && !result.definesLibraryName(name)) { |
| 423 result.add(name, meaning); | 420 result.add(name, meaning); |
| 424 } | 421 } |
| 425 }); | 422 }); |
| 426 } | 423 } |
| 427 | 424 |
| 428 /** | 425 /** |
| 429 * Wrapper around [getImport] that caches the return value in [importCache]. | 426 * Wrapper around [getImport] that caches the return value in [importCache]. |
| 430 */ | 427 */ |
| 431 UnlinkedPublicNamespace getImportCached(String relativeUri) { | 428 UnlinkedPublicNamespace getImportCached(String absoluteUri) { |
| 432 return importCache.putIfAbsent(relativeUri, () => getImport(relativeUri)); | 429 return importCache.putIfAbsent(absoluteUri, () => getImport(absoluteUri)); |
| 433 } | 430 } |
| 434 | 431 |
| 435 /** | 432 /** |
| 436 * Wrapper around [getPart] that caches the return value in [partCache] and | 433 * Wrapper around [getPart] that caches the return value in [partCache] and |
| 437 * updates [importCache] appropriately. | 434 * updates [importCache] appropriately. |
| 438 */ | 435 */ |
| 439 UnlinkedUnit getPartCached(String relativeUri) { | 436 UnlinkedUnit getPartCached(String absoluteUri) { |
| 440 return partCache.putIfAbsent(relativeUri, () { | 437 return partCache.putIfAbsent(absoluteUri, () { |
| 441 UnlinkedUnit unit = getPart(relativeUri); | 438 UnlinkedUnit unit = getPart(absoluteUri); |
| 442 importCache[relativeUri] = unit?.publicNamespace; | 439 importCache[absoluteUri] = unit?.publicNamespace; |
| 443 return unit; | 440 return unit; |
| 444 }); | 441 }); |
| 445 } | 442 } |
| 446 | 443 |
| 447 /** | 444 /** |
| 448 * Compute the set of relative URIs of all the compilation units in the | 445 * Compute the set of absolute URIs of all the compilation units in the |
| 449 * library whose URI is reachable from [definingUnit] via [relativeUri]. | 446 * library whose URI is reachable from [definingUnit] via [absoluteUri]. |
| 450 */ | 447 */ |
| 451 List<String> getUnitUris(String relativeUri) { | 448 List<String> getUnitUris(String absoluteUri) { |
| 452 List<String> result = <String>[relativeUri]; | 449 List<String> result = <String>[absoluteUri]; |
| 453 UnlinkedPublicNamespace publicNamespace = getImportCached(relativeUri); | 450 UnlinkedPublicNamespace publicNamespace = getImportCached(absoluteUri); |
| 454 if (publicNamespace != null) { | 451 if (publicNamespace != null) { |
| 455 result.addAll(publicNamespace.parts | 452 result.addAll(publicNamespace.parts.map((String uri) { |
| 456 .map((String uri) => resolveUri(relativeUri, uri))); | 453 return resolveUri(absoluteUri, uri); |
| 454 })); | |
| 457 } | 455 } |
| 458 return result; | 456 return result; |
| 459 } | 457 } |
| 460 | 458 |
| 461 /** | 459 /** |
| 462 * Process a single `import` declaration in the library being prelinked. The | 460 * Process a single `import` declaration in the library being prelinked. The |
| 463 * return value is the index of the imported library in [dependencies]. | 461 * return value is the index of the imported library in [dependencies]. |
| 464 */ | 462 */ |
| 465 int handleImport(UnlinkedImport import) { | 463 int handleImport(UnlinkedImport import) { |
| 466 String uri = import.isImplicit | 464 String unlinkedUri = import.isImplicit |
| 467 ? 'dart:core' | 465 ? 'dart:core' |
| 468 : _selectUri(import.uri, import.configurations); | 466 : _selectUri(import.uri, import.configurations); |
| 467 String absoluteUri = resolveUri(definingUnitUri, unlinkedUri); | |
| 468 | |
| 469 _Namespace targetNamespace = null; | 469 _Namespace targetNamespace = null; |
| 470 if (import.prefixReference != 0) { | 470 if (import.prefixReference != 0) { |
| 471 // The name introduced by an import declaration can't have a prefix of | 471 // The name introduced by an import declaration can't have a prefix of |
| 472 // its own. | 472 // its own. |
| 473 assert( | 473 assert( |
| 474 definingUnit.references[import.prefixReference].prefixReference == 0); | 474 definingUnit.references[import.prefixReference].prefixReference == 0); |
| 475 String prefix = definingUnit.references[import.prefixReference].name; | 475 String prefix = definingUnit.references[import.prefixReference].name; |
| 476 _Meaning prefixMeaning = privateNamespace[prefix]; | 476 _Meaning prefixMeaning = privateNamespace[prefix]; |
| 477 if (prefixMeaning is _PrefixMeaning) { | 477 if (prefixMeaning is _PrefixMeaning) { |
| 478 targetNamespace = prefixMeaning.namespace; | 478 targetNamespace = prefixMeaning.namespace; |
| 479 } | 479 } |
| 480 } else { | 480 } else { |
| 481 targetNamespace = privateNamespace; | 481 targetNamespace = privateNamespace; |
| 482 } | 482 } |
| 483 filterExportNamespace(uri, import.combinators, targetNamespace); | 483 filterExportNamespace(absoluteUri, import.combinators, targetNamespace); |
| 484 return uriToDependency[uri]; | 484 return uriToDependency[absoluteUri]; |
| 485 } | 485 } |
| 486 | 486 |
| 487 /** | 487 /** |
| 488 * Produce a [LinkedUnit] for the given [unit], by resolving every one of | 488 * Produce a [LinkedUnit] for the given [unit], by resolving every one of |
| 489 * its references. | 489 * its references. |
| 490 */ | 490 */ |
| 491 LinkedUnitBuilder linkUnit(UnlinkedUnit unit) { | 491 LinkedUnitBuilder linkUnit(UnlinkedUnit unit) { |
| 492 if (unit == null) { | 492 if (unit == null) { |
| 493 return new LinkedUnitBuilder(); | 493 return new LinkedUnitBuilder(); |
| 494 } | 494 } |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 520 } | 520 } |
| 521 } | 521 } |
| 522 return new LinkedUnitBuilder(references: references); | 522 return new LinkedUnitBuilder(references: references); |
| 523 } | 523 } |
| 524 | 524 |
| 525 /** | 525 /** |
| 526 * Form the [LinkedLibrary] for the [definingUnit] that was passed to the | 526 * Form the [LinkedLibrary] for the [definingUnit] that was passed to the |
| 527 * constructor. | 527 * constructor. |
| 528 */ | 528 */ |
| 529 LinkedLibraryBuilder prelink() { | 529 LinkedLibraryBuilder prelink() { |
| 530 aggregatePublicNamespace(definingUnitUri); | |
| 531 | |
| 530 // Gather up the unlinked summaries for all the compilation units in the | 532 // Gather up the unlinked summaries for all the compilation units in the |
| 531 // library. | 533 // library. |
| 532 List<UnlinkedUnit> units = getUnitUris(null).map(getPartCached).toList(); | 534 List<String> unitUris = getUnitUris(definingUnitUri); |
| 535 List<UnlinkedUnit> units = unitUris.map(getPartCached).toList(); | |
| 533 | 536 |
| 534 // Create the private namespace for the library by gathering all the names | 537 // Create the private namespace for the library by gathering all the names |
| 535 // defined in its compilation units. | 538 // defined in its compilation units. |
| 536 for (int unitNum = 0; unitNum < units.length; unitNum++) { | 539 for (int unitNum = 0; unitNum < units.length; unitNum++) { |
| 537 UnlinkedUnit unit = units[unitNum]; | 540 UnlinkedUnit unit = units[unitNum]; |
| 538 if (unit != null) { | 541 if (unit != null) { |
| 539 extractPrivateNames(unit, unitNum); | 542 extractPrivateNames(unit, unitNum); |
| 540 } | 543 } |
| 541 } | 544 } |
| 542 | 545 |
| 543 // Fill in exported names. This must be done before filling in prefixes | 546 // Fill in exported names. This must be done before filling in prefixes |
| 544 // defined in import declarations, because prefixes shouldn't shadow | 547 // defined in import declarations, because prefixes shouldn't shadow |
| 545 // exports. | 548 // exports. |
| 546 List<LinkedExportNameBuilder> exportNames = <LinkedExportNameBuilder>[]; | 549 List<LinkedExportNameBuilder> exportNames = <LinkedExportNameBuilder>[]; |
| 547 computeExportNamespace(null).forEach((String name, _Meaning meaning) { | 550 computeExportNamespace(definingUnitUri) |
| 551 .forEach((String name, _Meaning meaning) { | |
| 548 if (!privateNamespace.definesName(name)) { | 552 if (!privateNamespace.definesName(name)) { |
| 549 exportNames.add(meaning.encodeExportName(name)); | 553 exportNames.add(meaning.encodeExportName(name)); |
| 550 } | 554 } |
| 551 }); | 555 }); |
| 552 | 556 |
| 553 // Fill in prefixes defined in import declarations. | 557 // Fill in prefixes defined in import declarations. |
| 554 for (UnlinkedImport import in units[0].imports) { | 558 for (UnlinkedImport import in units[0].imports) { |
| 555 if (import.prefixReference != 0) { | 559 if (import.prefixReference != 0) { |
| 556 String name = units[0].references[import.prefixReference].name; | 560 String name = units[0].references[import.prefixReference].name; |
| 557 if (!privateNamespace.definesName(name)) { | 561 if (!privateNamespace.definesName(name)) { |
| 558 privateNamespace.add(name, new _PrefixMeaning()); | 562 privateNamespace.add(name, new _PrefixMeaning()); |
| 559 } | 563 } |
| 560 } | 564 } |
| 561 } | 565 } |
| 562 | 566 |
| 563 // All the names defined so far are library local, they take precedence | 567 // All the names defined so far are library local, they take precedence |
| 564 // over anything imported from other libraries. | 568 // over anything imported from other libraries. |
| 565 privateNamespace.rememberLibraryNames(); | 569 privateNamespace.rememberLibraryNames(); |
| 566 | 570 |
| 567 // Fill in imported and exported names. | 571 // Fill in imported and exported names. |
| 568 List<int> importDependencies = | 572 List<int> importDependencies = |
| 569 definingUnit.imports.map(handleImport).toList(); | 573 definingUnit.imports.map(handleImport).toList(); |
| 570 List<int> exportDependencies = | 574 List<int> exportDependencies = definingUnit.publicNamespace.exports |
| 571 definingUnit.publicNamespace.exports.map((UnlinkedExportPublic exp) { | 575 .map((UnlinkedExportPublic exp) { |
| 572 String uri = _selectUri(exp.uri, exp.configurations); | 576 String unlinkedUri = _selectUri(exp.uri, exp.configurations); |
| 573 return uriToDependency[uri]; | 577 String absoluteUri = resolveUri(definingUnitUri, unlinkedUri); |
| 574 }).toList(); | 578 return uriToDependency[absoluteUri]; |
| 579 }) | |
| 580 .where((dependency) => dependency != null) | |
| 581 .toList(); | |
| 575 | 582 |
| 576 // Link each compilation unit. | 583 // Link each compilation unit. |
| 577 List<LinkedUnitBuilder> linkedUnits = units.map(linkUnit).toList(); | 584 List<LinkedUnitBuilder> linkedUnits = units.map(linkUnit).toList(); |
| 578 | 585 |
| 579 return new LinkedLibraryBuilder( | 586 return new LinkedLibraryBuilder( |
| 580 units: linkedUnits, | 587 units: linkedUnits, |
| 581 dependencies: dependencies, | 588 dependencies: dependencies, |
| 582 importDependencies: importDependencies, | 589 importDependencies: importDependencies, |
| 583 exportDependencies: exportDependencies, | 590 exportDependencies: exportDependencies, |
| 584 exportNames: exportNames, | 591 exportNames: exportNames, |
| 585 numPrelinkedDependencies: dependencies.length); | 592 numPrelinkedDependencies: dependencies.length); |
| 586 } | 593 } |
| 587 | 594 |
| 588 /** | 595 /** |
| 589 * Resolve [relativeUri] relative to [sourceUri]. Works correctly if | 596 * Resolve [relativeUri] relative to [containingUri]. Return `null` if |
| 590 * [sourceUri] is also relative. | 597 * [relativeUri] is invalid or empty, so cannot be resolved. |
| 591 */ | 598 */ |
| 592 String resolveUri(String sourceUri, String relativeUri) { | 599 String resolveUri(String containingUri, String relativeUri) { |
| 593 if (sourceUri == null) { | 600 if (relativeUri == '') { |
| 594 return relativeUri; | 601 return null; |
| 595 } else { | 602 } |
| 596 return resolveRelativeUri(Uri.parse(sourceUri), Uri.parse(relativeUri)) | 603 try { |
| 597 .toString(); | 604 Uri containingUriObj = Uri.parse(containingUri); |
| 605 Uri relativeUriObj = Uri.parse(relativeUri); | |
| 606 return resolveRelativeUri(containingUriObj, relativeUriObj).toString(); | |
| 607 } on FormatException { | |
| 608 return null; | |
| 598 } | 609 } |
| 599 } | 610 } |
| 600 | 611 |
| 601 /** | 612 /** |
| 602 * Return the URI of the first configuration from the given [configurations] | 613 * Return the URI of the first configuration from the given [configurations] |
| 603 * which condition is satisfied, or the [defaultUri]. | 614 * which condition is satisfied, or the [defaultUri]. |
| 604 */ | 615 */ |
| 605 String _selectUri( | 616 String _selectUri( |
| 606 String defaultUri, List<UnlinkedConfiguration> configurations) { | 617 String defaultUri, List<UnlinkedConfiguration> configurations) { |
| 607 for (UnlinkedConfiguration configuration in configurations) { | 618 for (UnlinkedConfiguration configuration in configurations) { |
| 608 if (getDeclaredVariable(configuration.name) == configuration.value) { | 619 if (getDeclaredVariable(configuration.name) == configuration.value) { |
| 609 return configuration.uri; | 620 return configuration.uri; |
| 610 } | 621 } |
| 611 } | 622 } |
| 612 return defaultUri; | 623 return defaultUri; |
| 613 } | 624 } |
| 614 } | 625 } |
| OLD | NEW |