| 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 /** |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 * prelinked. | 46 * prelinked. |
| 47 * | 47 * |
| 48 * If no file exists at the given uri, `null` should be returned. | 48 * If no file exists at the given uri, `null` should be returned. |
| 49 */ | 49 */ |
| 50 typedef UnlinkedUnit GetPartCallback(String relativeUri); | 50 typedef UnlinkedUnit GetPartCallback(String relativeUri); |
| 51 | 51 |
| 52 /** | 52 /** |
| 53 * A [_Meaning] representing a class. | 53 * A [_Meaning] representing a class. |
| 54 */ | 54 */ |
| 55 class _ClassMeaning extends _Meaning { | 55 class _ClassMeaning extends _Meaning { |
| 56 final Map<String, _Meaning> namespace; | 56 final _Namespace namespace; |
| 57 | 57 |
| 58 _ClassMeaning(int unit, int dependency, int numTypeParameters, this.namespace) | 58 _ClassMeaning(int unit, int dependency, int numTypeParameters, this.namespace) |
| 59 : super(unit, ReferenceKind.classOrEnum, dependency, numTypeParameters); | 59 : super(unit, ReferenceKind.classOrEnum, dependency, numTypeParameters); |
| 60 } | 60 } |
| 61 | 61 |
| 62 /** | 62 /** |
| 63 * A [_Meaning] stores all the information necessary to find the declaration | 63 * A [_Meaning] stores all the information necessary to find the declaration |
| 64 * referred to by a name in a namespace. | 64 * referred to by a name in a namespace. |
| 65 */ | 65 */ |
| 66 class _Meaning { | 66 class _Meaning { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 102 LinkedReferenceBuilder encodeReference() { | 102 LinkedReferenceBuilder encodeReference() { |
| 103 return new LinkedReferenceBuilder( | 103 return new LinkedReferenceBuilder( |
| 104 unit: unit, | 104 unit: unit, |
| 105 kind: kind, | 105 kind: kind, |
| 106 dependency: dependency, | 106 dependency: dependency, |
| 107 numTypeParameters: numTypeParameters); | 107 numTypeParameters: numTypeParameters); |
| 108 } | 108 } |
| 109 } | 109 } |
| 110 | 110 |
| 111 /** | 111 /** |
| 112 * Mapping from names to corresponding unique [_Meaning]s. |
| 113 */ |
| 114 class _Namespace { |
| 115 final Set<String> namesWithConflictingDefinitions = new Set<String>(); |
| 116 final Set<String> libraryNames = new Set<String>(); |
| 117 final Map<String, _Meaning> map = <String, _Meaning>{}; |
| 118 |
| 119 /** |
| 120 * Return the [_Meaning] of the name, or `null` is not defined. |
| 121 */ |
| 122 _Meaning operator [](String name) { |
| 123 return map[name]; |
| 124 } |
| 125 |
| 126 /** |
| 127 * Define that the [name] has the given [value]. If the [name] already been |
| 128 * defined with a different value, then it becomes undefined. |
| 129 */ |
| 130 void add(String name, _Meaning value) { |
| 131 // Already determined to be a conflict. |
| 132 if (namesWithConflictingDefinitions.contains(name)) { |
| 133 return; |
| 134 } |
| 135 |
| 136 _Meaning currentValue = map[name]; |
| 137 if (currentValue == null) { |
| 138 map[name] = value; |
| 139 } else if (currentValue == value) { |
| 140 // The same value, ignore. |
| 141 } else { |
| 142 // A conflict, remember it, and un-define the name. |
| 143 namesWithConflictingDefinitions.add(name); |
| 144 map.remove(name); |
| 145 } |
| 146 } |
| 147 |
| 148 /** |
| 149 * Return `true` if the [name] was defined before [rememberLibraryNames] |
| 150 * invocation. |
| 151 */ |
| 152 bool definesLibraryName(String name) => libraryNames.contains(name); |
| 153 |
| 154 /** |
| 155 * Return `true` if the [name] is already defined. |
| 156 */ |
| 157 bool definesName(String name) => map.containsKey(name); |
| 158 |
| 159 /** |
| 160 * Apply [f] to each name-meaning pair. |
| 161 */ |
| 162 void forEach(void f(String key, _Meaning value)) { |
| 163 map.forEach(f); |
| 164 } |
| 165 |
| 166 /** |
| 167 * This method should be invoked after defining all names that are defined |
| 168 * in a library, before defining imported names. |
| 169 */ |
| 170 void rememberLibraryNames() { |
| 171 libraryNames.addAll(map.keys); |
| 172 } |
| 173 } |
| 174 |
| 175 /** |
| 112 * A [_Meaning] representing a prefix introduced by an import directive. | 176 * A [_Meaning] representing a prefix introduced by an import directive. |
| 113 */ | 177 */ |
| 114 class _PrefixMeaning extends _Meaning { | 178 class _PrefixMeaning extends _Meaning { |
| 115 final Map<String, _Meaning> namespace = <String, _Meaning>{}; | 179 final _Namespace namespace = new _Namespace(); |
| 116 | 180 |
| 117 _PrefixMeaning() : super(0, ReferenceKind.prefix, 0, 0); | 181 _PrefixMeaning() : super(0, ReferenceKind.prefix, 0, 0); |
| 118 } | 182 } |
| 119 | 183 |
| 120 /** | 184 /** |
| 121 * Helper class containing temporary data structures needed to prelink a single | 185 * Helper class containing temporary data structures needed to prelink a single |
| 122 * library. | 186 * library. |
| 123 * | 187 * |
| 124 * Note: throughout this class, a `null` value for a relative URI represents | 188 * Note: throughout this class, a `null` value for a relative URI represents |
| 125 * the defining compilation unit of the library being prelinked. | 189 * the defining compilation unit of the library being prelinked. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 137 <String, UnlinkedPublicNamespace>{}; | 201 <String, UnlinkedPublicNamespace>{}; |
| 138 | 202 |
| 139 /** | 203 /** |
| 140 * Cache of values returned by [getPart]. | 204 * Cache of values returned by [getPart]. |
| 141 */ | 205 */ |
| 142 final Map<String, UnlinkedUnit> partCache = <String, UnlinkedUnit>{}; | 206 final Map<String, UnlinkedUnit> partCache = <String, UnlinkedUnit>{}; |
| 143 | 207 |
| 144 /** | 208 /** |
| 145 * Names defined inside the library being prelinked. | 209 * Names defined inside the library being prelinked. |
| 146 */ | 210 */ |
| 147 final Map<String, _Meaning> privateNamespace = <String, _Meaning>{ | 211 final _Namespace privateNamespace = new _Namespace() |
| 148 'dynamic': new _Meaning(0, ReferenceKind.classOrEnum, 0, 0), | 212 ..add('dynamic', new _Meaning(0, ReferenceKind.classOrEnum, 0, 0)) |
| 149 'void': new _Meaning(0, ReferenceKind.classOrEnum, 0, 0) | 213 ..add('void', new _Meaning(0, ReferenceKind.classOrEnum, 0, 0)); |
| 150 }; | |
| 151 | 214 |
| 152 /** | 215 /** |
| 153 * 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 |
| 154 * to [LinkedLibrary.dependencies]. | 217 * to [LinkedLibrary.dependencies]. |
| 155 */ | 218 */ |
| 156 final List<LinkedDependencyBuilder> dependencies = <LinkedDependencyBuilder>[ | 219 final List<LinkedDependencyBuilder> dependencies = <LinkedDependencyBuilder>[ |
| 157 new LinkedDependencyBuilder() | 220 new LinkedDependencyBuilder() |
| 158 ]; | 221 ]; |
| 159 | 222 |
| 160 /** | 223 /** |
| 161 * Map from the relative URI of a dependent library to the index of the | 224 * Map from the relative URI of a dependent library to the index of the |
| 162 * corresponding entry in [dependencies]. | 225 * corresponding entry in [dependencies]. |
| 163 */ | 226 */ |
| 164 final Map<String, int> uriToDependency = <String, int>{null: 0}; | 227 final Map<String, int> uriToDependency = <String, int>{null: 0}; |
| 165 | 228 |
| 166 /** | 229 /** |
| 167 * List of public namespaces corresponding to each entry in [dependencies]. | 230 * List of public namespaces corresponding to each entry in [dependencies]. |
| 168 */ | 231 */ |
| 169 final List<Map<String, _Meaning>> dependencyToPublicNamespace = | 232 final List<_Namespace> dependencyToPublicNamespace = <_Namespace>[null]; |
| 170 <Map<String, _Meaning>>[null]; | |
| 171 | 233 |
| 172 _Prelinker(this.definingUnit, this.getPart, this.getImport, | 234 _Prelinker(this.definingUnit, this.getPart, this.getImport, |
| 173 this.getDeclaredVariable) { | 235 this.getDeclaredVariable) { |
| 174 partCache[null] = definingUnit; | 236 partCache[null] = definingUnit; |
| 175 importCache[null] = definingUnit.publicNamespace; | 237 importCache[null] = definingUnit.publicNamespace; |
| 176 } | 238 } |
| 177 | 239 |
| 178 /** | 240 /** |
| 179 * Compute the public namespace for the library whose URI is reachable from | 241 * Compute the public namespace for the library whose URI is reachable from |
| 180 * [definingUnit] via [relativeUri], by aggregating together public namespace | 242 * [definingUnit] via [relativeUri], by aggregating together public namespace |
| 181 * information from all of its parts. | 243 * information from all of its parts. |
| 182 */ | 244 */ |
| 183 Map<String, _Meaning> aggregatePublicNamespace(String relativeUri) { | 245 _Namespace aggregatePublicNamespace(String relativeUri) { |
| 184 if (uriToDependency.containsKey(relativeUri)) { | 246 if (uriToDependency.containsKey(relativeUri)) { |
| 185 return dependencyToPublicNamespace[uriToDependency[relativeUri]]; | 247 return dependencyToPublicNamespace[uriToDependency[relativeUri]]; |
| 186 } | 248 } |
| 187 assert(dependencies.length == dependencyToPublicNamespace.length); | 249 assert(dependencies.length == dependencyToPublicNamespace.length); |
| 188 int dependency = dependencies.length; | 250 int dependency = dependencies.length; |
| 189 uriToDependency[relativeUri] = dependency; | 251 uriToDependency[relativeUri] = dependency; |
| 190 List<String> unitUris = getUnitUris(relativeUri); | 252 List<String> unitUris = getUnitUris(relativeUri); |
| 191 LinkedDependencyBuilder linkedDependency = new LinkedDependencyBuilder( | 253 LinkedDependencyBuilder linkedDependency = new LinkedDependencyBuilder( |
| 192 uri: relativeUri, parts: unitUris.sublist(1)); | 254 uri: relativeUri, parts: unitUris.sublist(1)); |
| 193 dependencies.add(linkedDependency); | 255 dependencies.add(linkedDependency); |
| 194 | 256 |
| 195 Map<String, _Meaning> aggregated = <String, _Meaning>{}; | 257 _Namespace aggregated = new _Namespace(); |
| 196 | 258 |
| 197 for (int unitNum = 0; unitNum < unitUris.length; unitNum++) { | 259 for (int unitNum = 0; unitNum < unitUris.length; unitNum++) { |
| 198 String unitUri = unitUris[unitNum]; | 260 String unitUri = unitUris[unitNum]; |
| 199 UnlinkedPublicNamespace importedNamespace = getImportCached(unitUri); | 261 UnlinkedPublicNamespace importedNamespace = getImportCached(unitUri); |
| 200 if (importedNamespace == null) { | 262 if (importedNamespace == null) { |
| 201 continue; | 263 continue; |
| 202 } | 264 } |
| 203 for (UnlinkedPublicName name in importedNamespace.names) { | 265 for (UnlinkedPublicName name in importedNamespace.names) { |
| 204 aggregated.putIfAbsent(name.name, () { | 266 if (name.kind == ReferenceKind.classOrEnum) { |
| 205 if (name.kind == ReferenceKind.classOrEnum) { | 267 _Namespace namespace = new _Namespace(); |
| 206 Map<String, _Meaning> namespace = <String, _Meaning>{}; | 268 name.members.forEach((executable) { |
| 207 name.members.forEach((executable) { | 269 namespace.add( |
| 208 namespace[executable.name] = new _Meaning( | 270 executable.name, |
| 209 unitNum, executable.kind, 0, executable.numTypeParameters); | 271 new _Meaning( |
| 210 }); | 272 unitNum, executable.kind, 0, executable.numTypeParameters)); |
| 211 return new _ClassMeaning( | 273 }); |
| 212 unitNum, dependency, name.numTypeParameters, namespace); | 274 aggregated.add( |
| 213 } | 275 name.name, |
| 214 return new _Meaning( | 276 new _ClassMeaning( |
| 215 unitNum, name.kind, dependency, name.numTypeParameters); | 277 unitNum, dependency, name.numTypeParameters, namespace)); |
| 216 }); | 278 } else { |
| 279 aggregated.add( |
| 280 name.name, |
| 281 new _Meaning( |
| 282 unitNum, name.kind, dependency, name.numTypeParameters)); |
| 283 } |
| 217 } | 284 } |
| 218 } | 285 } |
| 219 | 286 |
| 220 dependencyToPublicNamespace.add(aggregated); | 287 dependencyToPublicNamespace.add(aggregated); |
| 221 return aggregated; | 288 return aggregated; |
| 222 } | 289 } |
| 223 | 290 |
| 224 /** | 291 /** |
| 225 * Compute the export namespace for the library whose URI is reachable from | 292 * Compute the export namespace for the library whose URI is reachable from |
| 226 * [definingUnit] via [relativeUri], by aggregating together public namespace | 293 * [definingUnit] via [relativeUri], by aggregating together public namespace |
| 227 * information from the library and the transitive closure of its exports. | 294 * information from the library and the transitive closure of its exports. |
| 228 * | 295 * |
| 229 * If [relativeUri] is `null` (meaning the export namespace of [definingUnit] | 296 * If [relativeUri] is `null` (meaning the export namespace of [definingUnit] |
| 230 * should be computed), then names defined in [definingUnit] are ignored. | 297 * should be computed), then names defined in [definingUnit] are ignored. |
| 231 */ | 298 */ |
| 232 Map<String, _Meaning> computeExportNamespace(String relativeUri) { | 299 _Namespace computeExportNamespace(String relativeUri) { |
| 233 Map<String, _Meaning> exportNamespace = relativeUri == null | 300 _Namespace exportNamespace = relativeUri == null |
| 234 ? <String, _Meaning>{} | 301 ? new _Namespace() |
| 235 : aggregatePublicNamespace(relativeUri); | 302 : aggregatePublicNamespace(relativeUri); |
| 236 void chaseExports( | 303 void chaseExports( |
| 237 NameFilter filter, String relativeUri, Set<String> seenUris) { | 304 NameFilter filter, String relativeUri, Set<String> seenUris) { |
| 238 if (seenUris.add(relativeUri)) { | 305 if (seenUris.add(relativeUri)) { |
| 239 UnlinkedPublicNamespace exportedNamespace = | 306 UnlinkedPublicNamespace exportedNamespace = |
| 240 getImportCached(relativeUri); | 307 getImportCached(relativeUri); |
| 241 if (exportedNamespace != null) { | 308 if (exportedNamespace != null) { |
| 242 for (UnlinkedExportPublic export in exportedNamespace.exports) { | 309 for (UnlinkedExportPublic export in exportedNamespace.exports) { |
| 243 String relativeExportUri = | 310 String relativeExportUri = |
| 244 _selectUri(export.uri, export.configurations); | 311 _selectUri(export.uri, export.configurations); |
| 245 String exportUri = resolveUri(relativeUri, relativeExportUri); | 312 String exportUri = resolveUri(relativeUri, relativeExportUri); |
| 246 NameFilter newFilter = filter.merge( | 313 NameFilter newFilter = filter.merge( |
| 247 new NameFilter.forUnlinkedCombinators(export.combinators)); | 314 new NameFilter.forUnlinkedCombinators(export.combinators)); |
| 248 aggregatePublicNamespace(exportUri) | 315 aggregatePublicNamespace(exportUri) |
| 249 .forEach((String name, _Meaning meaning) { | 316 .forEach((String name, _Meaning meaning) { |
| 250 if (newFilter.accepts(name) && | 317 if (newFilter.accepts(name)) { |
| 251 !exportNamespace.containsKey(name)) { | 318 exportNamespace.add(name, meaning); |
| 252 exportNamespace[name] = meaning; | |
| 253 } | 319 } |
| 254 }); | 320 }); |
| 255 chaseExports(newFilter, exportUri, seenUris); | 321 chaseExports(newFilter, exportUri, seenUris); |
| 256 } | 322 } |
| 257 } | 323 } |
| 258 seenUris.remove(relativeUri); | 324 seenUris.remove(relativeUri); |
| 259 } | 325 } |
| 260 } | 326 } |
| 261 | 327 |
| 262 chaseExports(NameFilter.identity, relativeUri, new Set<String>()); | 328 chaseExports(NameFilter.identity, relativeUri, new Set<String>()); |
| 263 return exportNamespace; | 329 return exportNamespace; |
| 264 } | 330 } |
| 265 | 331 |
| 266 /** | 332 /** |
| 267 * Extract all the names defined in [unit] (which is the [unitNum]th unit in | 333 * Extract all the names defined in [unit] (which is the [unitNum]th unit in |
| 268 * the library being prelinked) and store them in [privateNamespace]. | 334 * the library being prelinked) and store them in [privateNamespace]. |
| 269 * Excludes names introduced by `import` statements. | 335 * Excludes names introduced by `import` statements. |
| 270 */ | 336 */ |
| 271 void extractPrivateNames(UnlinkedUnit unit, int unitNum) { | 337 void extractPrivateNames(UnlinkedUnit unit, int unitNum) { |
| 272 for (UnlinkedClass cls in unit.classes) { | 338 for (UnlinkedClass cls in unit.classes) { |
| 273 privateNamespace.putIfAbsent(cls.name, () { | 339 _Namespace namespace = new _Namespace(); |
| 274 Map<String, _Meaning> namespace = <String, _Meaning>{}; | 340 cls.fields.forEach((field) { |
| 275 cls.fields.forEach((field) { | 341 if (field.isStatic && field.isConst) { |
| 276 if (field.isStatic && field.isConst) { | 342 namespace.add(field.name, |
| 277 namespace[field.name] = | 343 new _Meaning(unitNum, ReferenceKind.propertyAccessor, 0, 0)); |
| 278 new _Meaning(unitNum, ReferenceKind.propertyAccessor, 0, 0); | 344 } |
| 279 } | |
| 280 }); | |
| 281 cls.executables.forEach((executable) { | |
| 282 ReferenceKind kind = null; | |
| 283 if (executable.kind == UnlinkedExecutableKind.constructor) { | |
| 284 kind = ReferenceKind.constructor; | |
| 285 } else if (executable.kind == | |
| 286 UnlinkedExecutableKind.functionOrMethod && | |
| 287 executable.isStatic) { | |
| 288 kind = ReferenceKind.method; | |
| 289 } else if (executable.kind == UnlinkedExecutableKind.getter && | |
| 290 executable.isStatic) { | |
| 291 kind = ReferenceKind.propertyAccessor; | |
| 292 } | |
| 293 if (kind != null && executable.name.isNotEmpty) { | |
| 294 namespace[executable.name] = new _Meaning( | |
| 295 unitNum, kind, 0, executable.typeParameters.length); | |
| 296 } | |
| 297 }); | |
| 298 return new _ClassMeaning( | |
| 299 unitNum, 0, cls.typeParameters.length, namespace); | |
| 300 }); | 345 }); |
| 346 cls.executables.forEach((executable) { |
| 347 ReferenceKind kind = null; |
| 348 if (executable.kind == UnlinkedExecutableKind.constructor) { |
| 349 kind = ReferenceKind.constructor; |
| 350 } else if (executable.kind == UnlinkedExecutableKind.functionOrMethod && |
| 351 executable.isStatic) { |
| 352 kind = ReferenceKind.method; |
| 353 } else if (executable.kind == UnlinkedExecutableKind.getter && |
| 354 executable.isStatic) { |
| 355 kind = ReferenceKind.propertyAccessor; |
| 356 } |
| 357 if (kind != null && executable.name.isNotEmpty) { |
| 358 namespace.add(executable.name, |
| 359 new _Meaning(unitNum, kind, 0, executable.typeParameters.length)); |
| 360 } |
| 361 }); |
| 362 privateNamespace.add(cls.name, |
| 363 new _ClassMeaning(unitNum, 0, cls.typeParameters.length, namespace)); |
| 301 } | 364 } |
| 302 for (UnlinkedEnum enm in unit.enums) { | 365 for (UnlinkedEnum enm in unit.enums) { |
| 303 privateNamespace.putIfAbsent(enm.name, () { | 366 _Namespace namespace = new _Namespace(); |
| 304 Map<String, _Meaning> namespace = <String, _Meaning>{}; | 367 enm.values.forEach((UnlinkedEnumValue value) { |
| 305 enm.values.forEach((UnlinkedEnumValue value) { | 368 namespace.add(value.name, |
| 306 namespace[value.name] = | 369 new _Meaning(unitNum, ReferenceKind.propertyAccessor, 0, 0)); |
| 307 new _Meaning(unitNum, ReferenceKind.propertyAccessor, 0, 0); | |
| 308 }); | |
| 309 namespace['values'] = | |
| 310 new _Meaning(unitNum, ReferenceKind.propertyAccessor, 0, 0); | |
| 311 return new _ClassMeaning(unitNum, 0, 0, namespace); | |
| 312 }); | 370 }); |
| 371 namespace.add('values', |
| 372 new _Meaning(unitNum, ReferenceKind.propertyAccessor, 0, 0)); |
| 373 privateNamespace.add( |
| 374 enm.name, new _ClassMeaning(unitNum, 0, 0, namespace)); |
| 313 } | 375 } |
| 314 for (UnlinkedExecutable executable in unit.executables) { | 376 for (UnlinkedExecutable executable in unit.executables) { |
| 315 privateNamespace.putIfAbsent( | 377 privateNamespace.add( |
| 316 executable.name, | 378 executable.name, |
| 317 () => new _Meaning( | 379 new _Meaning( |
| 318 unitNum, | 380 unitNum, |
| 319 executable.kind == UnlinkedExecutableKind.functionOrMethod | 381 executable.kind == UnlinkedExecutableKind.functionOrMethod |
| 320 ? ReferenceKind.topLevelFunction | 382 ? ReferenceKind.topLevelFunction |
| 321 : ReferenceKind.topLevelPropertyAccessor, | 383 : ReferenceKind.topLevelPropertyAccessor, |
| 322 0, | 384 0, |
| 323 executable.typeParameters.length)); | 385 executable.typeParameters.length)); |
| 324 } | 386 } |
| 325 for (UnlinkedTypedef typedef in unit.typedefs) { | 387 for (UnlinkedTypedef typedef in unit.typedefs) { |
| 326 privateNamespace.putIfAbsent( | 388 privateNamespace.add( |
| 327 typedef.name, | 389 typedef.name, |
| 328 () => new _Meaning(unitNum, ReferenceKind.typedef, 0, | 390 new _Meaning(unitNum, ReferenceKind.typedef, 0, |
| 329 typedef.typeParameters.length)); | 391 typedef.typeParameters.length)); |
| 330 } | 392 } |
| 331 for (UnlinkedVariable variable in unit.variables) { | 393 for (UnlinkedVariable variable in unit.variables) { |
| 332 privateNamespace.putIfAbsent( | 394 privateNamespace.add(variable.name, |
| 333 variable.name, | 395 new _Meaning(unitNum, ReferenceKind.topLevelPropertyAccessor, 0, 0)); |
| 334 () => new _Meaning( | |
| 335 unitNum, ReferenceKind.topLevelPropertyAccessor, 0, 0)); | |
| 336 if (!(variable.isConst || variable.isFinal)) { | 396 if (!(variable.isConst || variable.isFinal)) { |
| 337 privateNamespace.putIfAbsent( | 397 privateNamespace.add( |
| 338 variable.name + '=', | 398 variable.name + '=', |
| 339 () => new _Meaning( | 399 new _Meaning( |
| 340 unitNum, ReferenceKind.topLevelPropertyAccessor, 0, 0)); | 400 unitNum, ReferenceKind.topLevelPropertyAccessor, 0, 0)); |
| 341 } | 401 } |
| 342 } | 402 } |
| 343 } | 403 } |
| 344 | 404 |
| 345 /** | 405 /** |
| 346 * Filter the export namespace for the library whose URI is reachable from | 406 * Filter the export namespace for the library whose URI is reachable from |
| 347 * [definingUnit] via [relativeUri], retaining only those names accepted by | 407 * [definingUnit] via [relativeUri], retaining only those names accepted by |
| 348 * [combinators], and store the resulting names in [result]. Names that | 408 * [combinators], and store the resulting names in [result]. Names that |
| 349 * already exist in [result] are not overwritten. | 409 * already exist in [result] are not overwritten. |
| 350 */ | 410 */ |
| 351 void filterExportNamespace(String relativeUri, | 411 void filterExportNamespace(String relativeUri, |
| 352 List<UnlinkedCombinator> combinators, Map<String, _Meaning> result) { | 412 List<UnlinkedCombinator> combinators, _Namespace result) { |
| 353 Map<String, _Meaning> exportNamespace = computeExportNamespace(relativeUri); | 413 _Namespace exportNamespace = computeExportNamespace(relativeUri); |
| 354 if (result == null) { | 414 if (result == null) { |
| 355 // This can happen if the import prefix was shadowed by a local name, so | 415 // This can happen if the import prefix was shadowed by a local name, so |
| 356 // the imported symbols are inaccessible. | 416 // the imported symbols are inaccessible. |
| 357 return; | 417 return; |
| 358 } | 418 } |
| 359 NameFilter filter = new NameFilter.forUnlinkedCombinators(combinators); | 419 NameFilter filter = new NameFilter.forUnlinkedCombinators(combinators); |
| 360 exportNamespace.forEach((String name, _Meaning meaning) { | 420 exportNamespace.forEach((String name, _Meaning meaning) { |
| 361 if (filter.accepts(name) && !result.containsKey(name)) { | 421 if (filter.accepts(name) && !result.definesLibraryName(name)) { |
| 362 result[name] = meaning; | 422 result.add(name, meaning); |
| 363 } | 423 } |
| 364 }); | 424 }); |
| 365 } | 425 } |
| 366 | 426 |
| 367 /** | 427 /** |
| 368 * Wrapper around [getImport] that caches the return value in [importCache]. | 428 * Wrapper around [getImport] that caches the return value in [importCache]. |
| 369 */ | 429 */ |
| 370 UnlinkedPublicNamespace getImportCached(String relativeUri) { | 430 UnlinkedPublicNamespace getImportCached(String relativeUri) { |
| 371 return importCache.putIfAbsent(relativeUri, () => getImport(relativeUri)); | 431 return importCache.putIfAbsent(relativeUri, () => getImport(relativeUri)); |
| 372 } | 432 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 398 } | 458 } |
| 399 | 459 |
| 400 /** | 460 /** |
| 401 * Process a single `import` declaration in the library being prelinked. The | 461 * Process a single `import` declaration in the library being prelinked. The |
| 402 * return value is the index of the imported library in [dependencies]. | 462 * return value is the index of the imported library in [dependencies]. |
| 403 */ | 463 */ |
| 404 int handleImport(UnlinkedImport import) { | 464 int handleImport(UnlinkedImport import) { |
| 405 String uri = import.isImplicit | 465 String uri = import.isImplicit |
| 406 ? 'dart:core' | 466 ? 'dart:core' |
| 407 : _selectUri(import.uri, import.configurations); | 467 : _selectUri(import.uri, import.configurations); |
| 408 Map<String, _Meaning> targetNamespace = null; | 468 _Namespace targetNamespace = null; |
| 409 if (import.prefixReference != 0) { | 469 if (import.prefixReference != 0) { |
| 410 // The name introduced by an import declaration can't have a prefix of | 470 // The name introduced by an import declaration can't have a prefix of |
| 411 // its own. | 471 // its own. |
| 412 assert( | 472 assert( |
| 413 definingUnit.references[import.prefixReference].prefixReference == 0); | 473 definingUnit.references[import.prefixReference].prefixReference == 0); |
| 414 String prefix = definingUnit.references[import.prefixReference].name; | 474 String prefix = definingUnit.references[import.prefixReference].name; |
| 415 _Meaning prefixMeaning = privateNamespace[prefix]; | 475 _Meaning prefixMeaning = privateNamespace[prefix]; |
| 416 if (prefixMeaning is _PrefixMeaning) { | 476 if (prefixMeaning is _PrefixMeaning) { |
| 417 targetNamespace = prefixMeaning.namespace; | 477 targetNamespace = prefixMeaning.namespace; |
| 418 } | 478 } |
| 419 } else { | 479 } else { |
| 420 targetNamespace = privateNamespace; | 480 targetNamespace = privateNamespace; |
| 421 } | 481 } |
| 422 filterExportNamespace(uri, import.combinators, targetNamespace); | 482 filterExportNamespace(uri, import.combinators, targetNamespace); |
| 423 return uriToDependency[uri]; | 483 return uriToDependency[uri]; |
| 424 } | 484 } |
| 425 | 485 |
| 426 /** | 486 /** |
| 427 * Produce a [LinkedUnit] for the given [unit], by resolving every one of | 487 * Produce a [LinkedUnit] for the given [unit], by resolving every one of |
| 428 * its references. | 488 * its references. |
| 429 */ | 489 */ |
| 430 LinkedUnitBuilder linkUnit(UnlinkedUnit unit) { | 490 LinkedUnitBuilder linkUnit(UnlinkedUnit unit) { |
| 431 if (unit == null) { | 491 if (unit == null) { |
| 432 return new LinkedUnitBuilder(); | 492 return new LinkedUnitBuilder(); |
| 433 } | 493 } |
| 434 Map<int, Map<String, _Meaning>> prefixNamespaces = | 494 Map<int, _Namespace> prefixNamespaces = <int, _Namespace>{}; |
| 435 <int, Map<String, _Meaning>>{}; | |
| 436 List<LinkedReferenceBuilder> references = <LinkedReferenceBuilder>[]; | 495 List<LinkedReferenceBuilder> references = <LinkedReferenceBuilder>[]; |
| 437 for (int i = 0; i < unit.references.length; i++) { | 496 for (int i = 0; i < unit.references.length; i++) { |
| 438 UnlinkedReference reference = unit.references[i]; | 497 UnlinkedReference reference = unit.references[i]; |
| 439 Map<String, _Meaning> namespace; | 498 _Namespace namespace; |
| 440 if (reference.prefixReference == 0) { | 499 if (reference.prefixReference == 0) { |
| 441 namespace = privateNamespace; | 500 namespace = privateNamespace; |
| 442 } else { | 501 } else { |
| 443 // Prefix references must always point backward. | 502 // Prefix references must always point backward. |
| 444 assert(reference.prefixReference < i); | 503 assert(reference.prefixReference < i); |
| 445 namespace = prefixNamespaces[reference.prefixReference]; | 504 namespace = prefixNamespaces[reference.prefixReference]; |
| 446 // Expressions like 'a.b.c.d' cannot be prelinked. | 505 // Expressions like 'a.b.c.d' cannot be prelinked. |
| 447 namespace ??= const <String, _Meaning>{}; | 506 namespace ??= new _Namespace(); |
| 448 } | 507 } |
| 449 _Meaning meaning = namespace[reference.name]; | 508 _Meaning meaning = namespace[reference.name]; |
| 450 if (meaning != null) { | 509 if (meaning != null) { |
| 451 if (meaning is _PrefixMeaning) { | 510 if (meaning is _PrefixMeaning) { |
| 452 prefixNamespaces[i] = meaning.namespace; | 511 prefixNamespaces[i] = meaning.namespace; |
| 453 } else if (meaning is _ClassMeaning) { | 512 } else if (meaning is _ClassMeaning) { |
| 454 prefixNamespaces[i] = meaning.namespace; | 513 prefixNamespaces[i] = meaning.namespace; |
| 455 } | 514 } |
| 456 references.add(meaning.encodeReference()); | 515 references.add(meaning.encodeReference()); |
| 457 } else { | 516 } else { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 478 if (unit != null) { | 537 if (unit != null) { |
| 479 extractPrivateNames(unit, unitNum); | 538 extractPrivateNames(unit, unitNum); |
| 480 } | 539 } |
| 481 } | 540 } |
| 482 | 541 |
| 483 // Fill in exported names. This must be done before filling in prefixes | 542 // Fill in exported names. This must be done before filling in prefixes |
| 484 // defined in import declarations, because prefixes shouldn't shadow | 543 // defined in import declarations, because prefixes shouldn't shadow |
| 485 // exports. | 544 // exports. |
| 486 List<LinkedExportNameBuilder> exportNames = <LinkedExportNameBuilder>[]; | 545 List<LinkedExportNameBuilder> exportNames = <LinkedExportNameBuilder>[]; |
| 487 computeExportNamespace(null).forEach((String name, _Meaning meaning) { | 546 computeExportNamespace(null).forEach((String name, _Meaning meaning) { |
| 488 if (!privateNamespace.containsKey(name)) { | 547 if (!privateNamespace.definesName(name)) { |
| 489 exportNames.add(meaning.encodeExportName(name)); | 548 exportNames.add(meaning.encodeExportName(name)); |
| 490 } | 549 } |
| 491 }); | 550 }); |
| 492 | 551 |
| 493 // Fill in prefixes defined in import declarations. | 552 // Fill in prefixes defined in import declarations. |
| 494 for (UnlinkedImport import in units[0].imports) { | 553 for (UnlinkedImport import in units[0].imports) { |
| 495 if (import.prefixReference != 0) { | 554 if (import.prefixReference != 0) { |
| 496 privateNamespace.putIfAbsent( | 555 String name = units[0].references[import.prefixReference].name; |
| 497 units[0].references[import.prefixReference].name, | 556 if (!privateNamespace.definesName(name)) { |
| 498 () => new _PrefixMeaning()); | 557 privateNamespace.add(name, new _PrefixMeaning()); |
| 558 } |
| 499 } | 559 } |
| 500 } | 560 } |
| 501 | 561 |
| 562 // All the names defined so far are library local, they take precedence |
| 563 // over anything imported from other libraries. |
| 564 privateNamespace.rememberLibraryNames(); |
| 565 |
| 502 // Fill in imported and exported names. | 566 // Fill in imported and exported names. |
| 503 List<int> importDependencies = | 567 List<int> importDependencies = |
| 504 definingUnit.imports.map(handleImport).toList(); | 568 definingUnit.imports.map(handleImport).toList(); |
| 505 List<int> exportDependencies = | 569 List<int> exportDependencies = |
| 506 definingUnit.publicNamespace.exports.map((UnlinkedExportPublic exp) { | 570 definingUnit.publicNamespace.exports.map((UnlinkedExportPublic exp) { |
| 507 String uri = _selectUri(exp.uri, exp.configurations); | 571 String uri = _selectUri(exp.uri, exp.configurations); |
| 508 return uriToDependency[uri]; | 572 return uriToDependency[uri]; |
| 509 }).toList(); | 573 }).toList(); |
| 510 | 574 |
| 511 // Link each compilation unit. | 575 // Link each compilation unit. |
| (...skipping 28 matching lines...) Expand all Loading... |
| 540 String _selectUri( | 604 String _selectUri( |
| 541 String defaultUri, List<UnlinkedConfiguration> configurations) { | 605 String defaultUri, List<UnlinkedConfiguration> configurations) { |
| 542 for (UnlinkedConfiguration configuration in configurations) { | 606 for (UnlinkedConfiguration configuration in configurations) { |
| 543 if (getDeclaredVariable(configuration.name) == configuration.value) { | 607 if (getDeclaredVariable(configuration.name) == configuration.value) { |
| 544 return configuration.uri; | 608 return configuration.uri; |
| 545 } | 609 } |
| 546 } | 610 } |
| 547 return defaultUri; | 611 return defaultUri; |
| 548 } | 612 } |
| 549 } | 613 } |
| OLD | NEW |