| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 serialization.elements; | 5 library serialization.elements; |
| 6 | 6 |
| 7 import 'package:analyzer/dart/element/element.dart'; | 7 import 'package:analyzer/dart/element/element.dart'; |
| 8 import 'package:analyzer/dart/element/type.dart'; | 8 import 'package:analyzer/dart/element/type.dart'; |
| 9 import 'package:analyzer/src/dart/element/element.dart'; | 9 import 'package:analyzer/src/dart/element/element.dart'; |
| 10 import 'package:analyzer/src/dart/element/type.dart'; | 10 import 'package:analyzer/src/dart/element/type.dart'; |
| 11 import 'package:analyzer/src/generated/ast.dart'; | 11 import 'package:analyzer/src/generated/ast.dart'; |
| 12 import 'package:analyzer/src/generated/resolver.dart'; | 12 import 'package:analyzer/src/generated/resolver.dart'; |
| 13 import 'package:analyzer/src/generated/utilities_dart.dart'; | 13 import 'package:analyzer/src/generated/utilities_dart.dart'; |
| 14 import 'package:analyzer/src/summary/format.dart'; | 14 import 'package:analyzer/src/summary/format.dart'; |
| 15 import 'package:analyzer/src/summary/name_filter.dart'; | 15 import 'package:analyzer/src/summary/name_filter.dart'; |
| 16 import 'package:analyzer/src/summary/summarize_const_expr.dart'; | 16 import 'package:analyzer/src/summary/summarize_const_expr.dart'; |
| 17 | 17 |
| 18 /** | 18 /** |
| 19 * Serialize all the elements in [lib] to a summary using [ctx] as the context | 19 * Serialize all the elements in [lib] to a summary using [ctx] as the context |
| 20 * for building the summary, and using [typeProvider] to find built-in types. | 20 * for building the summary, and using [typeProvider] to find built-in types. |
| 21 */ | 21 */ |
| 22 LibrarySerializationResult serializeLibrary( | 22 LibrarySerializationResult serializeLibrary( |
| 23 LibraryElement lib, TypeProvider typeProvider) { | 23 LibraryElement lib, TypeProvider typeProvider) { |
| 24 var serializer = new _LibrarySerializer(lib, typeProvider); | 24 var serializer = new _LibrarySerializer(lib, typeProvider); |
| 25 LinkedLibraryBuilder linked = serializer.serializeLibrary(); | 25 LinkedLibraryBuilder linked = serializer.serializeLibrary(); |
| 26 return new LibrarySerializationResult( | 26 return new LibrarySerializationResult( |
| 27 linked, serializer.unlinkedUnits, serializer.unitUris); | 27 linked, serializer.unlinkedUnits, serializer.unitUris); |
| 28 } | 28 } |
| 29 | 29 |
| 30 ReferenceKind _getReferenceKind(Element element) { |
| 31 ReferenceKind kind; |
| 32 if (element is PropertyAccessorElement) { |
| 33 kind = ReferenceKind.topLevelPropertyAccessor; |
| 34 } else if (element is FunctionTypeAliasElement) { |
| 35 kind = ReferenceKind.typedef; |
| 36 } else if (element is ClassElement) { |
| 37 kind = ReferenceKind.classOrEnum; |
| 38 } else if (element is FunctionElement) { |
| 39 kind = ReferenceKind.topLevelFunction; |
| 40 } else { |
| 41 throw new Exception('Unexpected element kind: ${element.runtimeType}'); |
| 42 } |
| 43 return kind; |
| 44 } |
| 45 |
| 30 /** | 46 /** |
| 31 * Data structure holding the result of serializing a [LibraryElement]. | 47 * Data structure holding the result of serializing a [LibraryElement]. |
| 32 */ | 48 */ |
| 33 class LibrarySerializationResult { | 49 class LibrarySerializationResult { |
| 34 /** | 50 /** |
| 35 * Linked information the given library. | 51 * Linked information the given library. |
| 36 */ | 52 */ |
| 37 final LinkedLibraryBuilder linked; | 53 final LinkedLibraryBuilder linked; |
| 38 | 54 |
| 39 /** | 55 /** |
| 40 * Unlinked information for the compilation units constituting the library. | 56 * Unlinked information for the compilation units constituting the library. |
| 41 * The zeroth entry in the list is the defining compilation unit; the | 57 * The zeroth entry in the list is the defining compilation unit; the |
| 42 * remaining entries are the parts, in the order listed in the defining | 58 * remaining entries are the parts, in the order listed in the defining |
| 43 * compilation unit's part declarations. | 59 * compilation unit's part declarations. |
| 44 */ | 60 */ |
| 45 final List<UnlinkedUnitBuilder> unlinkedUnits; | 61 final List<UnlinkedUnitBuilder> unlinkedUnits; |
| 46 | 62 |
| 47 /** | 63 /** |
| 48 * Absolute URI of each compilation unit appearing in the library. | 64 * Absolute URI of each compilation unit appearing in the library. |
| 49 */ | 65 */ |
| 50 final List<String> unitUris; | 66 final List<String> unitUris; |
| 51 | 67 |
| 52 LibrarySerializationResult(this.linked, this.unlinkedUnits, this.unitUris); | 68 LibrarySerializationResult(this.linked, this.unlinkedUnits, this.unitUris); |
| 53 } | 69 } |
| 54 | 70 |
| 55 /** | 71 /** |
| 56 * Instances of this class keep track of intermediate state during | 72 * Instances of this class keep track of intermediate state during |
| 57 * serialization of a single constant [Expression]. | 73 * serialization of a single compilation unit. |
| 58 */ | 74 */ |
| 59 class _ConstExprSerializer extends AbstractConstExprSerializer { | 75 class _CompilationUnitSerializer { |
| 60 final _LibrarySerializer serializer; | 76 /** |
| 77 * The [_LibrarySerializer] which is serializing the library of which |
| 78 * [compilationUnit] is a part. |
| 79 */ |
| 80 final _LibrarySerializer librarySerializer; |
| 61 | 81 |
| 62 _ConstExprSerializer(this.serializer); | 82 /** |
| 83 * The [CompilationUnitElement] being serialized. |
| 84 */ |
| 85 final CompilationUnitElement compilationUnit; |
| 63 | 86 |
| 64 TypeRefBuilder serializeIdentifier(Identifier identifier) { | 87 /** |
| 65 Element element = identifier.staticElement; | 88 * The ordinal index of [compilationUnit] within the library, where 0 |
| 66 assert(element != null); | 89 * represents the defining compilation unit. |
| 67 // TODO(scheglov) how to serialize element references? | 90 */ |
| 68 return new TypeRefBuilder( | 91 final int unitNum; |
| 69 reference: serializer._getElementReferenceId(element)); | |
| 70 } | |
| 71 | 92 |
| 72 @override | 93 /** |
| 73 TypeRefBuilder serializeType(TypeName typeName) { | 94 * The final linked summary of the compilation unit. |
| 74 DartType type = typeName != null ? typeName.type : DynamicTypeImpl.instance; | 95 */ |
| 75 return serializer.serializeTypeRef(type, null); | 96 final LinkedUnitBuilder linkedUnit = new LinkedUnitBuilder(); |
| 76 } | 97 |
| 77 } | 98 /** |
| 99 * The final unlinked summary of the compilation unit. |
| 100 */ |
| 101 final UnlinkedUnitBuilder unlinkedUnit = new UnlinkedUnitBuilder(); |
| 78 | 102 |
| 79 /** | 103 /** |
| 80 * Instances of this class keep track of intermediate state during | 104 * Absolute URI of the compilation unit. |
| 81 * serialization of a single library. | |
| 82 */ | 105 */ |
| 83 class _LibrarySerializer { | 106 String unitUri; |
| 84 /** | |
| 85 * The library to be serialized. | |
| 86 */ | |
| 87 final LibraryElement libraryElement; | |
| 88 | |
| 89 /** | |
| 90 * The type provider. This is used to locate the library for `dart:core`. | |
| 91 */ | |
| 92 final TypeProvider typeProvider; | |
| 93 | |
| 94 /** | |
| 95 * List of objects which should be written to [LinkedLibrary.units]. | |
| 96 */ | |
| 97 final List<LinkedUnitBuilder> linkedUnits = <LinkedUnitBuilder>[]; | |
| 98 | |
| 99 /** | |
| 100 * List of unlinked units corresponding to the linked units in | |
| 101 * [linkedUnits], | |
| 102 */ | |
| 103 final List<UnlinkedUnitBuilder> unlinkedUnits = <UnlinkedUnitBuilder>[]; | |
| 104 | |
| 105 /** | |
| 106 * List of absolute URIs of the compilation units in the library. | |
| 107 */ | |
| 108 final List<String> unitUris = <String>[]; | |
| 109 | |
| 110 /** | |
| 111 * Map from [LibraryElement] to the index of the entry in the "dependency | |
| 112 * table" that refers to it. | |
| 113 */ | |
| 114 final Map<LibraryElement, int> dependencyMap = <LibraryElement, int>{}; | |
| 115 | |
| 116 /** | |
| 117 * The "dependency table". This is the list of objects which should be | |
| 118 * written to [LinkedLibrary.dependencies]. | |
| 119 */ | |
| 120 final List<LinkedDependencyBuilder> dependencies = | |
| 121 <LinkedDependencyBuilder>[]; | |
| 122 | |
| 123 /** | |
| 124 * The linked portion of the "imports table". This is the list of ints | |
| 125 * which should be written to [LinkedLibrary.imports]. | |
| 126 */ | |
| 127 final List<int> linkedImports = <int>[]; | |
| 128 | 107 |
| 129 /** | 108 /** |
| 130 * Map from [Element] to the index of the entry in the "references table" | 109 * Map from [Element] to the index of the entry in the "references table" |
| 131 * that refers to it. | 110 * that refers to it. |
| 132 */ | 111 */ |
| 133 final Map<Element, int> referenceMap = <Element, int>{}; | 112 final Map<Element, int> referenceMap = <Element, int>{}; |
| 134 | 113 |
| 135 /** | 114 /** |
| 136 * The unlinked portion of the "references table". This is the list of | 115 * The unlinked portion of the "references table". This is the list of |
| 137 * objects which should be written to [UnlinkedUnit.references]. | 116 * objects which should be written to [UnlinkedUnit.references]. |
| 138 */ | 117 */ |
| 139 List<UnlinkedReferenceBuilder> unlinkedReferences; | 118 List<UnlinkedReferenceBuilder> unlinkedReferences; |
| 140 | 119 |
| 141 /** | 120 /** |
| 142 * The linked portion of the "references table". This is the list of | 121 * The linked portion of the "references table". This is the list of |
| 143 * objects which should be written to [LinkedUnit.references]. | 122 * objects which should be written to [LinkedUnit.references]. |
| 144 */ | 123 */ |
| 145 List<LinkedReferenceBuilder> linkedReferences; | 124 List<LinkedReferenceBuilder> linkedReferences; |
| 146 | 125 |
| 147 //final Map<String, int> prefixIndices = <String, int>{}; | |
| 148 | |
| 149 /** | 126 /** |
| 150 * Index into the "references table" representing an unresolved reference, if | 127 * Index into the "references table" representing an unresolved reference, if |
| 151 * such an index exists. `null` if no such entry has been made in the | 128 * such an index exists. `null` if no such entry has been made in the |
| 152 * references table yet. | 129 * references table yet. |
| 153 */ | 130 */ |
| 154 int unresolvedReferenceIndex = null; | 131 int unresolvedReferenceIndex = null; |
| 155 | 132 |
| 156 /** | 133 _CompilationUnitSerializer( |
| 157 * Set of libraries which have been seen so far while visiting the transitive | 134 this.librarySerializer, this.compilationUnit, this.unitNum); |
| 158 * closure of exports. | |
| 159 */ | |
| 160 final Set<LibraryElement> librariesAddedToTransitiveExportClosure = | |
| 161 new Set<LibraryElement>(); | |
| 162 | |
| 163 /** | |
| 164 * Map from imported element to the prefix which may be used to refer to that | |
| 165 * element; elements for which no prefix is needed are absent from this map. | |
| 166 */ | |
| 167 final Map<Element, PrefixElement> prefixMap = <Element, PrefixElement>{}; | |
| 168 | |
| 169 _LibrarySerializer(this.libraryElement, this.typeProvider) { | |
| 170 dependencies.add(new LinkedDependencyBuilder()); | |
| 171 dependencyMap[libraryElement] = 0; | |
| 172 } | |
| 173 | |
| 174 /** | |
| 175 * Retrieve the library element for `dart:core`. | |
| 176 */ | |
| 177 LibraryElement get coreLibrary => typeProvider.objectType.element.library; | |
| 178 | 135 |
| 179 /** | 136 /** |
| 180 * Add all classes, enums, typedefs, executables, and top level variables | 137 * Add all classes, enums, typedefs, executables, and top level variables |
| 181 * from the given compilation unit [element] to the library summary. | 138 * from the given compilation unit [element] to the compilation unit summary. |
| 182 * [unitNum] indicates the ordinal position of this compilation unit in the | 139 * [unitNum] indicates the ordinal position of this compilation unit in the |
| 183 * library. | 140 * library. |
| 184 */ | 141 */ |
| 185 void addCompilationUnitElements(CompilationUnitElement element, int unitNum) { | 142 void addCompilationUnitElements() { |
| 186 UnlinkedUnitBuilder b = new UnlinkedUnitBuilder(); | |
| 187 referenceMap.clear(); | |
| 188 unlinkedReferences = <UnlinkedReferenceBuilder>[ | 143 unlinkedReferences = <UnlinkedReferenceBuilder>[ |
| 189 new UnlinkedReferenceBuilder() | 144 new UnlinkedReferenceBuilder() |
| 190 ]; | 145 ]; |
| 191 linkedReferences = <LinkedReferenceBuilder>[ | 146 linkedReferences = <LinkedReferenceBuilder>[ |
| 192 new LinkedReferenceBuilder(kind: ReferenceKind.classOrEnum) | 147 new LinkedReferenceBuilder(kind: ReferenceKind.classOrEnum) |
| 193 ]; | 148 ]; |
| 194 List<UnlinkedPublicNameBuilder> names = <UnlinkedPublicNameBuilder>[]; | 149 List<UnlinkedPublicNameBuilder> names = <UnlinkedPublicNameBuilder>[]; |
| 195 for (PropertyAccessorElement accessor in element.accessors) { | 150 for (PropertyAccessorElement accessor in compilationUnit.accessors) { |
| 196 if (accessor.isPublic) { | 151 if (accessor.isPublic) { |
| 197 names.add(new UnlinkedPublicNameBuilder( | 152 names.add(new UnlinkedPublicNameBuilder( |
| 198 kind: ReferenceKind.topLevelPropertyAccessor, | 153 kind: ReferenceKind.topLevelPropertyAccessor, |
| 199 name: accessor.name, | 154 name: accessor.name, |
| 200 numTypeParameters: accessor.typeParameters.length)); | 155 numTypeParameters: accessor.typeParameters.length)); |
| 201 } | 156 } |
| 202 } | 157 } |
| 203 for (ClassElement cls in element.types) { | 158 for (ClassElement cls in compilationUnit.types) { |
| 204 if (cls.isPublic) { | 159 if (cls.isPublic) { |
| 205 names.add(new UnlinkedPublicNameBuilder( | 160 names.add(new UnlinkedPublicNameBuilder( |
| 206 kind: ReferenceKind.classOrEnum, | 161 kind: ReferenceKind.classOrEnum, |
| 207 name: cls.name, | 162 name: cls.name, |
| 208 numTypeParameters: cls.typeParameters.length)); | 163 numTypeParameters: cls.typeParameters.length)); |
| 209 } | 164 } |
| 210 } | 165 } |
| 211 for (ClassElement enm in element.enums) { | 166 for (ClassElement enm in compilationUnit.enums) { |
| 212 if (enm.isPublic) { | 167 if (enm.isPublic) { |
| 213 names.add(new UnlinkedPublicNameBuilder( | 168 names.add(new UnlinkedPublicNameBuilder( |
| 214 kind: ReferenceKind.classOrEnum, name: enm.name)); | 169 kind: ReferenceKind.classOrEnum, name: enm.name)); |
| 215 } | 170 } |
| 216 } | 171 } |
| 217 for (FunctionElement function in element.functions) { | 172 for (FunctionElement function in compilationUnit.functions) { |
| 218 if (function.isPublic) { | 173 if (function.isPublic) { |
| 219 names.add(new UnlinkedPublicNameBuilder( | 174 names.add(new UnlinkedPublicNameBuilder( |
| 220 kind: ReferenceKind.topLevelFunction, | 175 kind: ReferenceKind.topLevelFunction, |
| 221 name: function.name, | 176 name: function.name, |
| 222 numTypeParameters: function.typeParameters.length)); | 177 numTypeParameters: function.typeParameters.length)); |
| 223 } | 178 } |
| 224 } | 179 } |
| 225 for (FunctionTypeAliasElement typedef in element.functionTypeAliases) { | 180 for (FunctionTypeAliasElement typedef |
| 181 in compilationUnit.functionTypeAliases) { |
| 226 if (typedef.isPublic) { | 182 if (typedef.isPublic) { |
| 227 names.add(new UnlinkedPublicNameBuilder( | 183 names.add(new UnlinkedPublicNameBuilder( |
| 228 kind: ReferenceKind.typedef, | 184 kind: ReferenceKind.typedef, |
| 229 name: typedef.name, | 185 name: typedef.name, |
| 230 numTypeParameters: typedef.typeParameters.length)); | 186 numTypeParameters: typedef.typeParameters.length)); |
| 231 } | 187 } |
| 232 } | 188 } |
| 233 if (unitNum == 0) { | 189 if (unitNum == 0) { |
| 190 LibraryElement libraryElement = librarySerializer.libraryElement; |
| 234 if (libraryElement.name.isNotEmpty) { | 191 if (libraryElement.name.isNotEmpty) { |
| 235 b.libraryName = libraryElement.name; | 192 LibraryElement libraryElement = librarySerializer.libraryElement; |
| 236 b.libraryNameOffset = libraryElement.nameOffset; | 193 unlinkedUnit.libraryName = libraryElement.name; |
| 237 b.libraryNameLength = libraryElement.nameLength; | 194 unlinkedUnit.libraryNameOffset = libraryElement.nameOffset; |
| 238 b.libraryDocumentationComment = serializeDocumentation(libraryElement); | 195 unlinkedUnit.libraryNameLength = libraryElement.nameLength; |
| 196 unlinkedUnit.libraryDocumentationComment = |
| 197 serializeDocumentation(libraryElement); |
| 239 } | 198 } |
| 240 b.publicNamespace = new UnlinkedPublicNamespaceBuilder( | 199 unlinkedUnit.publicNamespace = new UnlinkedPublicNamespaceBuilder( |
| 241 exports: libraryElement.exports.map(serializeExportPublic).toList(), | 200 exports: libraryElement.exports.map(serializeExportPublic).toList(), |
| 242 parts: libraryElement.parts | 201 parts: libraryElement.parts |
| 243 .map((CompilationUnitElement e) => e.uri) | 202 .map((CompilationUnitElement e) => e.uri) |
| 244 .toList(), | 203 .toList(), |
| 245 names: names); | 204 names: names); |
| 246 b.exports = libraryElement.exports.map(serializeExportNonPublic).toList(); | 205 unlinkedUnit.exports = |
| 247 b.imports = libraryElement.imports.map(serializeImport).toList(); | 206 libraryElement.exports.map(serializeExportNonPublic).toList(); |
| 248 b.parts = libraryElement.parts | 207 unlinkedUnit.imports = |
| 208 libraryElement.imports.map(serializeImport).toList(); |
| 209 unlinkedUnit.parts = libraryElement.parts |
| 249 .map((CompilationUnitElement e) => | 210 .map((CompilationUnitElement e) => |
| 250 new UnlinkedPartBuilder(uriOffset: e.uriOffset, uriEnd: e.uriEnd)) | 211 new UnlinkedPartBuilder(uriOffset: e.uriOffset, uriEnd: e.uriEnd)) |
| 251 .toList(); | 212 .toList(); |
| 252 } else { | 213 } else { |
| 253 // TODO(paulberry): we need to figure out a way to record library, part, | 214 // TODO(paulberry): we need to figure out a way to record library, part, |
| 254 // import, and export declarations that appear in non-defining | 215 // import, and export declarations that appear in non-defining |
| 255 // compilation units (even though such declarations are prohibited by the | 216 // compilation units (even though such declarations are prohibited by the |
| 256 // language), so that if the user makes code changes that cause a | 217 // language), so that if the user makes code changes that cause a |
| 257 // non-defining compilation unit to become a defining compilation unit, | 218 // non-defining compilation unit to become a defining compilation unit, |
| 258 // we can create a correct summary by simply re-linking. | 219 // we can create a correct summary by simply re-linking. |
| 259 b.publicNamespace = new UnlinkedPublicNamespaceBuilder(names: names); | 220 unlinkedUnit.publicNamespace = |
| 221 new UnlinkedPublicNamespaceBuilder(names: names); |
| 260 } | 222 } |
| 261 b.classes = element.types.map(serializeClass).toList(); | 223 unlinkedUnit.classes = compilationUnit.types.map(serializeClass).toList(); |
| 262 b.enums = element.enums.map(serializeEnum).toList(); | 224 unlinkedUnit.enums = compilationUnit.enums.map(serializeEnum).toList(); |
| 263 b.typedefs = element.functionTypeAliases.map(serializeTypedef).toList(); | 225 unlinkedUnit.typedefs = |
| 226 compilationUnit.functionTypeAliases.map(serializeTypedef).toList(); |
| 264 List<UnlinkedExecutableBuilder> executables = | 227 List<UnlinkedExecutableBuilder> executables = |
| 265 element.functions.map(serializeExecutable).toList(); | 228 compilationUnit.functions.map(serializeExecutable).toList(); |
| 266 for (PropertyAccessorElement accessor in element.accessors) { | 229 for (PropertyAccessorElement accessor in compilationUnit.accessors) { |
| 267 if (!accessor.isSynthetic) { | 230 if (!accessor.isSynthetic) { |
| 268 executables.add(serializeExecutable(accessor)); | 231 executables.add(serializeExecutable(accessor)); |
| 269 } | 232 } |
| 270 } | 233 } |
| 271 b.executables = executables; | 234 unlinkedUnit.executables = executables; |
| 272 List<UnlinkedVariableBuilder> variables = <UnlinkedVariableBuilder>[]; | 235 List<UnlinkedVariableBuilder> variables = <UnlinkedVariableBuilder>[]; |
| 273 for (PropertyAccessorElement accessor in element.accessors) { | 236 for (PropertyAccessorElement accessor in compilationUnit.accessors) { |
| 274 if (accessor.isSynthetic && accessor.isGetter) { | 237 if (accessor.isSynthetic && accessor.isGetter) { |
| 275 PropertyInducingElement variable = accessor.variable; | 238 PropertyInducingElement variable = accessor.variable; |
| 276 if (variable != null) { | 239 if (variable != null) { |
| 277 assert(!variable.isSynthetic); | 240 assert(!variable.isSynthetic); |
| 278 variables.add(serializeVariable(variable)); | 241 variables.add(serializeVariable(variable)); |
| 279 } | 242 } |
| 280 } | 243 } |
| 281 } | 244 } |
| 282 b.variables = variables; | 245 unlinkedUnit.variables = variables; |
| 283 b.references = unlinkedReferences; | 246 unlinkedUnit.references = unlinkedReferences; |
| 284 unlinkedUnits.add(b); | 247 linkedUnit.references = linkedReferences; |
| 285 linkedUnits.add(new LinkedUnitBuilder(references: linkedReferences)); | 248 unitUri = compilationUnit.source.uri.toString(); |
| 286 unitUris.add(element.source.uri.toString()); | |
| 287 unlinkedReferences = null; | |
| 288 linkedReferences = null; | |
| 289 } | 249 } |
| 290 | 250 |
| 291 /** | 251 /** |
| 292 * Add [exportedLibrary] (and the transitive closure of all libraries it | |
| 293 * exports) to the dependency table ([LinkedLibrary.dependencies]). | |
| 294 */ | |
| 295 void addTransitiveExportClosure(LibraryElement exportedLibrary) { | |
| 296 if (librariesAddedToTransitiveExportClosure.add(exportedLibrary)) { | |
| 297 serializeDependency(exportedLibrary); | |
| 298 for (LibraryElement transitiveExport | |
| 299 in exportedLibrary.exportedLibraries) { | |
| 300 addTransitiveExportClosure(transitiveExport); | |
| 301 } | |
| 302 } | |
| 303 } | |
| 304 | |
| 305 /** | |
| 306 * Fill in [prefixMap] using information from [libraryElement.imports]. | |
| 307 */ | |
| 308 void computePrefixMap() { | |
| 309 for (ImportElement import in libraryElement.imports) { | |
| 310 if (import.prefix == null) { | |
| 311 continue; | |
| 312 } | |
| 313 import.importedLibrary.exportNamespace.definedNames | |
| 314 .forEach((String name, Element e) { | |
| 315 if (new NameFilter.forNamespaceCombinators(import.combinators) | |
| 316 .accepts(name)) { | |
| 317 prefixMap[e] = import.prefix; | |
| 318 } | |
| 319 }); | |
| 320 } | |
| 321 } | |
| 322 | |
| 323 /** | |
| 324 * Compute the appropriate De Bruijn index to represent the given type | 252 * Compute the appropriate De Bruijn index to represent the given type |
| 325 * parameter [type]. | 253 * parameter [type]. |
| 326 */ | 254 */ |
| 327 int findTypeParameterIndex(TypeParameterType type, Element context) { | 255 int findTypeParameterIndex(TypeParameterType type, Element context) { |
| 328 int index = 0; | 256 int index = 0; |
| 329 while (context != null) { | 257 while (context != null) { |
| 330 List<TypeParameterElement> typeParameters; | 258 List<TypeParameterElement> typeParameters; |
| 331 if (context is ClassElement) { | 259 if (context is ClassElement) { |
| 332 typeParameters = context.typeParameters; | 260 typeParameters = context.typeParameters; |
| 333 } else if (context is FunctionTypeAliasElement) { | 261 } else if (context is FunctionTypeAliasElement) { |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 414 /** | 342 /** |
| 415 * Serialize the given [expression], creating an [UnlinkedConstBuilder]. | 343 * Serialize the given [expression], creating an [UnlinkedConstBuilder]. |
| 416 */ | 344 */ |
| 417 UnlinkedConstBuilder serializeConstExpr(Expression expression) { | 345 UnlinkedConstBuilder serializeConstExpr(Expression expression) { |
| 418 _ConstExprSerializer serializer = new _ConstExprSerializer(this); | 346 _ConstExprSerializer serializer = new _ConstExprSerializer(this); |
| 419 serializer.serialize(expression); | 347 serializer.serialize(expression); |
| 420 return serializer.toBuilder(); | 348 return serializer.toBuilder(); |
| 421 } | 349 } |
| 422 | 350 |
| 423 /** | 351 /** |
| 424 * Return the index of the entry in the dependency table | |
| 425 * ([LinkedLibrary.dependencies]) for the given [dependentLibrary]. A new | |
| 426 * entry is added to the table if necessary to satisfy the request. | |
| 427 */ | |
| 428 int serializeDependency(LibraryElement dependentLibrary) { | |
| 429 return dependencyMap.putIfAbsent(dependentLibrary, () { | |
| 430 int index = dependencies.length; | |
| 431 List<String> parts = dependentLibrary.parts | |
| 432 .map((CompilationUnitElement e) => e.source.uri.toString()) | |
| 433 .toList(); | |
| 434 dependencies.add(new LinkedDependencyBuilder( | |
| 435 uri: dependentLibrary.source.uri.toString(), parts: parts)); | |
| 436 return index; | |
| 437 }); | |
| 438 } | |
| 439 | |
| 440 /** | |
| 441 * Serialize documentation from the given [element], creating an | 352 * Serialize documentation from the given [element], creating an |
| 442 * [UnlinkedDocumentationComment]. | 353 * [UnlinkedDocumentationComment]. |
| 443 * | 354 * |
| 444 * If [element] has no documentation, `null` is returned. | 355 * If [element] has no documentation, `null` is returned. |
| 445 */ | 356 */ |
| 446 UnlinkedDocumentationCommentBuilder serializeDocumentation(Element element) { | 357 UnlinkedDocumentationCommentBuilder serializeDocumentation(Element element) { |
| 447 if (element.documentationComment == null) { | 358 if (element.documentationComment == null) { |
| 448 return null; | 359 return null; |
| 449 } | 360 } |
| 450 return new UnlinkedDocumentationCommentBuilder( | 361 return new UnlinkedDocumentationCommentBuilder( |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 530 b.uriOffset = exportElement.uriOffset; | 441 b.uriOffset = exportElement.uriOffset; |
| 531 b.uriEnd = exportElement.uriEnd; | 442 b.uriEnd = exportElement.uriEnd; |
| 532 return b; | 443 return b; |
| 533 } | 444 } |
| 534 | 445 |
| 535 /** | 446 /** |
| 536 * Serialize the given [exportElement] into an [UnlinkedExportPublic]. | 447 * Serialize the given [exportElement] into an [UnlinkedExportPublic]. |
| 537 */ | 448 */ |
| 538 UnlinkedExportPublicBuilder serializeExportPublic( | 449 UnlinkedExportPublicBuilder serializeExportPublic( |
| 539 ExportElement exportElement) { | 450 ExportElement exportElement) { |
| 540 addTransitiveExportClosure(exportElement.exportedLibrary); | |
| 541 UnlinkedExportPublicBuilder b = new UnlinkedExportPublicBuilder(); | 451 UnlinkedExportPublicBuilder b = new UnlinkedExportPublicBuilder(); |
| 542 b.uri = exportElement.uri; | 452 b.uri = exportElement.uri; |
| 543 b.combinators = exportElement.combinators.map(serializeCombinator).toList(); | 453 b.combinators = exportElement.combinators.map(serializeCombinator).toList(); |
| 544 return b; | 454 return b; |
| 545 } | 455 } |
| 546 | 456 |
| 547 /** | 457 /** |
| 548 * Serialize the given [importElement] yielding an [UnlinkedImportBuilder]. | 458 * Serialize the given [importElement] yielding an [UnlinkedImportBuilder]. |
| 549 * Also, add linked information about it to the [linkedImports] list. | 459 * Also, add linked information about it to the [linkedImports] list. |
| 550 */ | 460 */ |
| 551 UnlinkedImportBuilder serializeImport(ImportElement importElement) { | 461 UnlinkedImportBuilder serializeImport(ImportElement importElement) { |
| 552 UnlinkedImportBuilder b = new UnlinkedImportBuilder(); | 462 UnlinkedImportBuilder b = new UnlinkedImportBuilder(); |
| 553 b.isDeferred = importElement.isDeferred; | 463 b.isDeferred = importElement.isDeferred; |
| 554 b.offset = importElement.nameOffset; | 464 b.offset = importElement.nameOffset; |
| 555 b.combinators = importElement.combinators.map(serializeCombinator).toList(); | 465 b.combinators = importElement.combinators.map(serializeCombinator).toList(); |
| 556 if (importElement.prefix != null) { | 466 if (importElement.prefix != null) { |
| 557 b.prefixReference = serializePrefix(importElement.prefix); | 467 b.prefixReference = serializePrefix(importElement.prefix); |
| 558 b.prefixOffset = importElement.prefix.nameOffset; | 468 b.prefixOffset = importElement.prefix.nameOffset; |
| 559 } | 469 } |
| 560 if (importElement.isSynthetic) { | 470 if (importElement.isSynthetic) { |
| 561 b.isImplicit = true; | 471 b.isImplicit = true; |
| 562 } else { | 472 } else { |
| 563 b.uri = importElement.uri; | 473 b.uri = importElement.uri; |
| 564 b.uriOffset = importElement.uriOffset; | 474 b.uriOffset = importElement.uriOffset; |
| 565 b.uriEnd = importElement.uriEnd; | 475 b.uriEnd = importElement.uriEnd; |
| 566 } | 476 } |
| 567 addTransitiveExportClosure(importElement.importedLibrary); | |
| 568 linkedImports.add(serializeDependency(importElement.importedLibrary)); | |
| 569 return b; | 477 return b; |
| 570 } | 478 } |
| 571 | 479 |
| 572 /** | 480 /** |
| 573 * Serialize the whole library element into a [LinkedLibrary]. Should be | |
| 574 * called exactly once for each instance of [_LibrarySerializer]. | |
| 575 * | |
| 576 * The unlinked compilation units are stored in [unlinkedUnits], and their | |
| 577 * absolute URIs are stored in [unitUris]. | |
| 578 */ | |
| 579 LinkedLibraryBuilder serializeLibrary() { | |
| 580 computePrefixMap(); | |
| 581 LinkedLibraryBuilder pb = new LinkedLibraryBuilder(); | |
| 582 addCompilationUnitElements(libraryElement.definingCompilationUnit, 0); | |
| 583 for (int i = 0; i < libraryElement.parts.length; i++) { | |
| 584 addCompilationUnitElements(libraryElement.parts[i], i + 1); | |
| 585 } | |
| 586 pb.units = linkedUnits; | |
| 587 pb.dependencies = dependencies; | |
| 588 pb.importDependencies = linkedImports; | |
| 589 List<String> exportedNames = | |
| 590 libraryElement.exportNamespace.definedNames.keys.toList(); | |
| 591 exportedNames.sort(); | |
| 592 List<LinkedExportNameBuilder> exportNames = <LinkedExportNameBuilder>[]; | |
| 593 for (String name in exportedNames) { | |
| 594 if (libraryElement.publicNamespace.definedNames.containsKey(name)) { | |
| 595 continue; | |
| 596 } | |
| 597 Element element = libraryElement.exportNamespace.get(name); | |
| 598 LibraryElement dependentLibrary = element.library; | |
| 599 CompilationUnitElement unitElement = | |
| 600 element.getAncestor((Element e) => e is CompilationUnitElement); | |
| 601 int unit = dependentLibrary.units.indexOf(unitElement); | |
| 602 assert(unit != -1); | |
| 603 ReferenceKind kind = _getReferenceKind(element); | |
| 604 exportNames.add(new LinkedExportNameBuilder( | |
| 605 name: name, | |
| 606 dependency: serializeDependency(dependentLibrary), | |
| 607 unit: unit, | |
| 608 kind: kind)); | |
| 609 } | |
| 610 pb.exportNames = exportNames; | |
| 611 return pb; | |
| 612 } | |
| 613 | |
| 614 /** | |
| 615 * Serialize the given [parameter] into an [UnlinkedParam]. | 481 * Serialize the given [parameter] into an [UnlinkedParam]. |
| 616 */ | 482 */ |
| 617 UnlinkedParamBuilder serializeParam(ParameterElement parameter, | 483 UnlinkedParamBuilder serializeParam(ParameterElement parameter, |
| 618 [Element context]) { | 484 [Element context]) { |
| 619 context ??= parameter; | 485 context ??= parameter; |
| 620 UnlinkedParamBuilder b = new UnlinkedParamBuilder(); | 486 UnlinkedParamBuilder b = new UnlinkedParamBuilder(); |
| 621 b.name = parameter.name; | 487 b.name = parameter.name; |
| 622 b.nameOffset = parameter.nameOffset; | 488 b.nameOffset = parameter.nameOffset; |
| 623 switch (parameter.parameterKind) { | 489 switch (parameter.parameterKind) { |
| 624 case ParameterKind.REQUIRED: | 490 case ParameterKind.REQUIRED: |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 803 int numTypeParameters = 0; | 669 int numTypeParameters = 0; |
| 804 if (element is TypeParameterizedElement) { | 670 if (element is TypeParameterizedElement) { |
| 805 numTypeParameters = element.typeParameters.length; | 671 numTypeParameters = element.typeParameters.length; |
| 806 } | 672 } |
| 807 // Figure out a prefix that may be used to refer to the given type. | 673 // Figure out a prefix that may be used to refer to the given type. |
| 808 // TODO(paulberry): to avoid subtle relinking inconsistencies we | 674 // TODO(paulberry): to avoid subtle relinking inconsistencies we |
| 809 // should use the actual prefix from the AST (a given type may be | 675 // should use the actual prefix from the AST (a given type may be |
| 810 // reachable via multiple prefixes), but sadly, this information is | 676 // reachable via multiple prefixes), but sadly, this information is |
| 811 // not recorded in the element model. | 677 // not recorded in the element model. |
| 812 int prefixReference = 0; | 678 int prefixReference = 0; |
| 813 PrefixElement prefix = prefixMap[element]; | 679 PrefixElement prefix = librarySerializer.prefixMap[element]; |
| 814 if (prefix != null) { | 680 if (prefix != null) { |
| 815 prefixReference = serializePrefix(prefix); | 681 prefixReference = serializePrefix(prefix); |
| 816 } | 682 } |
| 817 int index = unlinkedReferences.length; | 683 int index = unlinkedReferences.length; |
| 818 unlinkedReferences.add(new UnlinkedReferenceBuilder( | 684 unlinkedReferences.add(new UnlinkedReferenceBuilder( |
| 819 name: element.name, prefixReference: prefixReference)); | 685 name: element.name, prefixReference: prefixReference)); |
| 820 linkedReferences.add(new LinkedReferenceBuilder( | 686 linkedReferences.add(new LinkedReferenceBuilder( |
| 821 dependency: serializeDependency(dependentLibrary), | 687 dependency: librarySerializer.serializeDependency(dependentLibrary), |
| 822 kind: _getReferenceKind(element), | 688 kind: _getReferenceKind(element), |
| 823 unit: unit, | 689 unit: unit, |
| 824 numTypeParameters: numTypeParameters)); | 690 numTypeParameters: numTypeParameters)); |
| 825 return index; | 691 return index; |
| 826 }); | 692 }); |
| 827 } | 693 } |
| 828 | |
| 829 ReferenceKind _getReferenceKind(Element element) { | |
| 830 ReferenceKind kind; | |
| 831 if (element is PropertyAccessorElement) { | |
| 832 kind = ReferenceKind.topLevelPropertyAccessor; | |
| 833 } else if (element is FunctionTypeAliasElement) { | |
| 834 kind = ReferenceKind.typedef; | |
| 835 } else if (element is ClassElement) { | |
| 836 kind = ReferenceKind.classOrEnum; | |
| 837 } else if (element is FunctionElement) { | |
| 838 kind = ReferenceKind.topLevelFunction; | |
| 839 } else { | |
| 840 throw new Exception('Unexpected element kind: ${element.runtimeType}'); | |
| 841 } | |
| 842 return kind; | |
| 843 } | |
| 844 } | 694 } |
| 695 |
| 696 /** |
| 697 * Instances of this class keep track of intermediate state during |
| 698 * serialization of a single constant [Expression]. |
| 699 */ |
| 700 class _ConstExprSerializer extends AbstractConstExprSerializer { |
| 701 final _CompilationUnitSerializer serializer; |
| 702 |
| 703 _ConstExprSerializer(this.serializer); |
| 704 |
| 705 TypeRefBuilder serializeIdentifier(Identifier identifier) { |
| 706 Element element = identifier.staticElement; |
| 707 assert(element != null); |
| 708 // TODO(scheglov) how to serialize element references? |
| 709 return new TypeRefBuilder( |
| 710 reference: serializer._getElementReferenceId(element)); |
| 711 } |
| 712 |
| 713 @override |
| 714 TypeRefBuilder serializeType(TypeName typeName) { |
| 715 DartType type = typeName != null ? typeName.type : DynamicTypeImpl.instance; |
| 716 return serializer.serializeTypeRef(type, null); |
| 717 } |
| 718 } |
| 719 |
| 720 /** |
| 721 * Instances of this class keep track of intermediate state during |
| 722 * serialization of a single library. |
| 723 */ |
| 724 class _LibrarySerializer { |
| 725 /** |
| 726 * The library to be serialized. |
| 727 */ |
| 728 final LibraryElement libraryElement; |
| 729 |
| 730 /** |
| 731 * The type provider. This is used to locate the library for `dart:core`. |
| 732 */ |
| 733 final TypeProvider typeProvider; |
| 734 |
| 735 /** |
| 736 * Map from [LibraryElement] to the index of the entry in the "dependency |
| 737 * table" that refers to it. |
| 738 */ |
| 739 final Map<LibraryElement, int> dependencyMap = <LibraryElement, int>{}; |
| 740 |
| 741 /** |
| 742 * The "dependency table". This is the list of objects which should be |
| 743 * written to [LinkedLibrary.dependencies]. |
| 744 */ |
| 745 final List<LinkedDependencyBuilder> dependencies = |
| 746 <LinkedDependencyBuilder>[]; |
| 747 |
| 748 /** |
| 749 * The linked portion of the "imports table". This is the list of ints |
| 750 * which should be written to [LinkedLibrary.imports]. |
| 751 */ |
| 752 final List<int> linkedImports = <int>[]; |
| 753 |
| 754 /** |
| 755 * Set of libraries which have been seen so far while visiting the transitive |
| 756 * closure of exports. |
| 757 */ |
| 758 final Set<LibraryElement> librariesAddedToTransitiveExportClosure = |
| 759 new Set<LibraryElement>(); |
| 760 |
| 761 /** |
| 762 * Map from imported element to the prefix which may be used to refer to that |
| 763 * element; elements for which no prefix is needed are absent from this map. |
| 764 */ |
| 765 final Map<Element, PrefixElement> prefixMap = <Element, PrefixElement>{}; |
| 766 |
| 767 /** |
| 768 * List of serializers for the compilation units constituting this library. |
| 769 */ |
| 770 final List<_CompilationUnitSerializer> compilationUnitSerializers = |
| 771 <_CompilationUnitSerializer>[]; |
| 772 |
| 773 _LibrarySerializer(this.libraryElement, this.typeProvider) { |
| 774 dependencies.add(new LinkedDependencyBuilder()); |
| 775 dependencyMap[libraryElement] = 0; |
| 776 } |
| 777 |
| 778 /** |
| 779 * Retrieve a list of the URIs for the compilation units in the library. |
| 780 */ |
| 781 List<String> get unitUris => compilationUnitSerializers |
| 782 .map((_CompilationUnitSerializer s) => s.unitUri) |
| 783 .toList(); |
| 784 |
| 785 /** |
| 786 * Retrieve a list of the [UnlinkedUnitBuilder]s for the compilation units in |
| 787 * the library. |
| 788 */ |
| 789 List<UnlinkedUnitBuilder> get unlinkedUnits => compilationUnitSerializers |
| 790 .map((_CompilationUnitSerializer s) => s.unlinkedUnit) |
| 791 .toList(); |
| 792 |
| 793 /** |
| 794 * Add [exportedLibrary] (and the transitive closure of all libraries it |
| 795 * exports) to the dependency table ([LinkedLibrary.dependencies]). |
| 796 */ |
| 797 void addTransitiveExportClosure(LibraryElement exportedLibrary) { |
| 798 if (librariesAddedToTransitiveExportClosure.add(exportedLibrary)) { |
| 799 serializeDependency(exportedLibrary); |
| 800 for (LibraryElement transitiveExport |
| 801 in exportedLibrary.exportedLibraries) { |
| 802 addTransitiveExportClosure(transitiveExport); |
| 803 } |
| 804 } |
| 805 } |
| 806 |
| 807 /** |
| 808 * Fill in [prefixMap] using information from [libraryElement.imports]. |
| 809 */ |
| 810 void computePrefixMap() { |
| 811 for (ImportElement import in libraryElement.imports) { |
| 812 if (import.prefix == null) { |
| 813 continue; |
| 814 } |
| 815 import.importedLibrary.exportNamespace.definedNames |
| 816 .forEach((String name, Element e) { |
| 817 if (new NameFilter.forNamespaceCombinators(import.combinators) |
| 818 .accepts(name)) { |
| 819 prefixMap[e] = import.prefix; |
| 820 } |
| 821 }); |
| 822 } |
| 823 } |
| 824 |
| 825 /** |
| 826 * Return the index of the entry in the dependency table |
| 827 * ([LinkedLibrary.dependencies]) for the given [dependentLibrary]. A new |
| 828 * entry is added to the table if necessary to satisfy the request. |
| 829 */ |
| 830 int serializeDependency(LibraryElement dependentLibrary) { |
| 831 return dependencyMap.putIfAbsent(dependentLibrary, () { |
| 832 int index = dependencies.length; |
| 833 List<String> parts = dependentLibrary.parts |
| 834 .map((CompilationUnitElement e) => e.source.uri.toString()) |
| 835 .toList(); |
| 836 dependencies.add(new LinkedDependencyBuilder( |
| 837 uri: dependentLibrary.source.uri.toString(), parts: parts)); |
| 838 return index; |
| 839 }); |
| 840 } |
| 841 |
| 842 /** |
| 843 * Serialize the whole library element into a [LinkedLibrary]. Should be |
| 844 * called exactly once for each instance of [_LibrarySerializer]. |
| 845 * |
| 846 * The unlinked compilation units are stored in [unlinkedUnits], and their |
| 847 * absolute URIs are stored in [unitUris]. |
| 848 */ |
| 849 LinkedLibraryBuilder serializeLibrary() { |
| 850 computePrefixMap(); |
| 851 LinkedLibraryBuilder pb = new LinkedLibraryBuilder(); |
| 852 for (ExportElement exportElement in libraryElement.exports) { |
| 853 addTransitiveExportClosure(exportElement.exportedLibrary); |
| 854 } |
| 855 for (ImportElement importElement in libraryElement.imports) { |
| 856 addTransitiveExportClosure(importElement.importedLibrary); |
| 857 linkedImports.add(serializeDependency(importElement.importedLibrary)); |
| 858 } |
| 859 compilationUnitSerializers.add(new _CompilationUnitSerializer( |
| 860 this, libraryElement.definingCompilationUnit, 0)); |
| 861 for (int i = 0; i < libraryElement.parts.length; i++) { |
| 862 compilationUnitSerializers.add( |
| 863 new _CompilationUnitSerializer(this, libraryElement.parts[i], i + 1)); |
| 864 } |
| 865 for (_CompilationUnitSerializer compilationUnitSerializer |
| 866 in compilationUnitSerializers) { |
| 867 compilationUnitSerializer.addCompilationUnitElements(); |
| 868 } |
| 869 pb.units = compilationUnitSerializers |
| 870 .map((_CompilationUnitSerializer s) => s.linkedUnit) |
| 871 .toList(); |
| 872 pb.dependencies = dependencies; |
| 873 pb.importDependencies = linkedImports; |
| 874 List<String> exportedNames = |
| 875 libraryElement.exportNamespace.definedNames.keys.toList(); |
| 876 exportedNames.sort(); |
| 877 List<LinkedExportNameBuilder> exportNames = <LinkedExportNameBuilder>[]; |
| 878 for (String name in exportedNames) { |
| 879 if (libraryElement.publicNamespace.definedNames.containsKey(name)) { |
| 880 continue; |
| 881 } |
| 882 Element element = libraryElement.exportNamespace.get(name); |
| 883 LibraryElement dependentLibrary = element.library; |
| 884 CompilationUnitElement unitElement = |
| 885 element.getAncestor((Element e) => e is CompilationUnitElement); |
| 886 int unit = dependentLibrary.units.indexOf(unitElement); |
| 887 assert(unit != -1); |
| 888 ReferenceKind kind = _getReferenceKind(element); |
| 889 exportNames.add(new LinkedExportNameBuilder( |
| 890 name: name, |
| 891 dependency: serializeDependency(dependentLibrary), |
| 892 unit: unit, |
| 893 kind: kind)); |
| 894 } |
| 895 pb.exportNames = exportNames; |
| 896 return pb; |
| 897 } |
| 898 } |
| OLD | NEW |