| OLD | NEW |
| (Empty) | |
| 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 |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 library dart2js.serialization.elements; |
| 6 |
| 7 import '../constants/expressions.dart'; |
| 8 import '../dart_types.dart'; |
| 9 import '../dart2jslib.dart' show SourceSpan; |
| 10 import '../elements/elements.dart'; |
| 11 import '../tree/tree.dart'; |
| 12 import 'constant_serialization.dart'; |
| 13 import 'keys.dart'; |
| 14 import 'modelz.dart'; |
| 15 import 'serialization.dart'; |
| 16 |
| 17 /// Enum kinds used for encoding [Element]s. |
| 18 enum SerializedElementKind { |
| 19 LIBRARY, |
| 20 COMPILATION_UNIT, |
| 21 CLASS, |
| 22 GENERATIVE_CONSTRUCTOR, |
| 23 FACTORY_CONSTRUCTOR, |
| 24 TOPLEVEL_FIELD, |
| 25 STATIC_FIELD, |
| 26 INSTANCE_FIELD, |
| 27 TOPLEVEL_FUNCTION, |
| 28 TOPLEVEL_GETTER, |
| 29 TOPLEVEL_SETTER, |
| 30 STATIC_FUNCTION, |
| 31 STATIC_GETTER, |
| 32 STATIC_SETTER, |
| 33 INSTANCE_FUNCTION, |
| 34 INSTANCE_GETTER, |
| 35 INSTANCE_SETTER, |
| 36 TYPEDEF, |
| 37 TYPEVARIABLE, |
| 38 PARAMETER, |
| 39 INITIALIZING_FORMAL, |
| 40 } |
| 41 |
| 42 /// Set of serializers used to serialize different kinds of elements by |
| 43 /// encoding into them into [ObjectEncoder]s. |
| 44 /// |
| 45 /// This class is called from the [Serializer] when an [Element] needs |
| 46 /// serialization. The [ObjectEncoder] ensures that any [Element], [DartType], |
| 47 /// and [ConstantExpression] that the serialized [Element] depends upon are also |
| 48 /// serialized. |
| 49 const List<ElementSerializer> ELEMENT_SERIALIZERS = const [ |
| 50 const LibrarySerializer(), |
| 51 const CompilationUnitSerializer(), |
| 52 const ClassSerializer(), |
| 53 const ConstructorSerializer(), |
| 54 const FieldSerializer(), |
| 55 const FunctionSerializer(), |
| 56 const TypedefSerializer(), |
| 57 const TypeVariableSerializer(), |
| 58 const ParameterSerializer(), |
| 59 ]; |
| 60 |
| 61 /// Interface for a function that can serialize a set of element kinds. |
| 62 abstract class ElementSerializer { |
| 63 /// Returns the [SerializedElementKind] for [element] if this serializer |
| 64 /// supports serialization of [element] or `null` otherwise. |
| 65 SerializedElementKind getSerializedKind(Element element); |
| 66 |
| 67 /// Serializes [element] into the [encoder] using the [kind] computed |
| 68 /// by [getSerializedKind]. |
| 69 void serialize(Element element, |
| 70 ObjectEncoder encoder, |
| 71 SerializedElementKind kind); |
| 72 } |
| 73 |
| 74 class SerializerUtil { |
| 75 /// Serialize the declared members of [element] into [encoder]. |
| 76 static void serializeMembers(ScopeContainerElement element, |
| 77 ObjectEncoder encoder) { |
| 78 MapEncoder mapEncoder = encoder.createMap(Key.MEMBERS); |
| 79 element.forEachLocalMember((Element member) { |
| 80 String name = member.name; |
| 81 if (member.isSetter) { |
| 82 name = '$name,='; |
| 83 } |
| 84 mapEncoder.setElement(name, member); |
| 85 }); |
| 86 } |
| 87 |
| 88 /// Serialize the source position of [element] into [encoder]. |
| 89 static void serializePosition(Element element, ObjectEncoder encoder) { |
| 90 if (element.sourcePosition != null) { |
| 91 SourceSpan position = element.sourcePosition; |
| 92 encoder.setInt(Key.OFFSET, position.begin); |
| 93 if (position.uri != element.compilationUnit.script.resourceUri) { |
| 94 // TODO(johnniwinther): What is the base URI in the case? |
| 95 encoder.setUri(Key.URI, element.library.canonicalUri, position.uri); |
| 96 } |
| 97 int length = position.end - position.begin; |
| 98 if (element.name.length != length) { |
| 99 encoder.setInt(Key.LENGTH, length); |
| 100 } |
| 101 } |
| 102 } |
| 103 |
| 104 /// Serialize the parameters of [element] into [encoder]. |
| 105 static void serializeParameters(FunctionElement element, |
| 106 ObjectEncoder encoder) { |
| 107 FunctionType type = element.type; |
| 108 encoder.setType(Key.RETURN_TYPE, type.returnType); |
| 109 encoder.setElements(Key.PARAMETERS, element.parameters); |
| 110 } |
| 111 |
| 112 /// Returns a function that adds the underlying declared elements for a |
| 113 /// particular element into [list]. |
| 114 /// |
| 115 /// For instance, for an [AbstractFieldElement] the getter and setter elements |
| 116 /// are added, if available. |
| 117 static flattenElements(List<Element> list) { |
| 118 return (Element element) { |
| 119 // TODO(johnniwinther): Handle ambiguous elements. |
| 120 if (element.isAmbiguous) return; |
| 121 if (element.isAbstractField) { |
| 122 AbstractFieldElement abstractField = element; |
| 123 if (abstractField.getter != null) { |
| 124 list.add(abstractField.getter); |
| 125 } |
| 126 if (abstractField.setter != null) { |
| 127 list.add(abstractField.setter); |
| 128 } |
| 129 } else { |
| 130 list.add(element); |
| 131 } |
| 132 }; |
| 133 } |
| 134 } |
| 135 |
| 136 class LibrarySerializer implements ElementSerializer { |
| 137 const LibrarySerializer(); |
| 138 |
| 139 SerializedElementKind getSerializedKind(Element element) { |
| 140 if (element.isLibrary) { |
| 141 return SerializedElementKind.LIBRARY; |
| 142 } |
| 143 return null; |
| 144 } |
| 145 |
| 146 void serialize(LibraryElement element, |
| 147 ObjectEncoder encoder, |
| 148 SerializedElementKind kind) { |
| 149 encoder.setUri( |
| 150 Key.CANONICAL_URI, element.canonicalUri, element.canonicalUri); |
| 151 encoder.setString(Key.LIBRARY_NAME, element.getLibraryName()); |
| 152 SerializerUtil.serializeMembers(element, encoder); |
| 153 encoder.setElement(Key.COMPILATION_UNIT, element.entryCompilationUnit); |
| 154 encoder.setElements( |
| 155 Key.COMPILATION_UNITS, element.compilationUnits.toList()); |
| 156 ListEncoder tags = encoder.createList(Key.TAGS); |
| 157 |
| 158 for (LibraryTag tag in element.tags) { |
| 159 if (tag is Import) { |
| 160 ObjectEncoder importTag = tags.createObject(); |
| 161 importTag.setString(Key.KIND, 'import'); |
| 162 importTag.setElement(Key.LIBRARY, element.getLibraryFromTag(tag)); |
| 163 } else if (tag is Export) { |
| 164 ObjectEncoder exportTag = tags.createObject(); |
| 165 exportTag.setString(Key.KIND, 'export'); |
| 166 exportTag.setElement(Key.LIBRARY, element.getLibraryFromTag(tag)); |
| 167 } |
| 168 } |
| 169 |
| 170 List<Element> imports = <Element>[]; |
| 171 element.forEachImport(SerializerUtil.flattenElements(imports)); |
| 172 encoder.setElements(Key.IMPORTS, imports); |
| 173 |
| 174 List<Element> exports = <Element>[]; |
| 175 element.forEachExport(SerializerUtil.flattenElements(exports)); |
| 176 encoder.setElements(Key.EXPORTS, exports); |
| 177 } |
| 178 } |
| 179 |
| 180 class CompilationUnitSerializer implements ElementSerializer { |
| 181 const CompilationUnitSerializer(); |
| 182 |
| 183 SerializedElementKind getSerializedKind(Element element) { |
| 184 if (element.isCompilationUnit) { |
| 185 return SerializedElementKind.COMPILATION_UNIT; |
| 186 } |
| 187 return null; |
| 188 } |
| 189 |
| 190 void serialize(CompilationUnitElement element, |
| 191 ObjectEncoder encoder, |
| 192 SerializedElementKind kind) { |
| 193 encoder.setElement(Key.LIBRARY, element.library); |
| 194 encoder.setUri( |
| 195 Key.URI, element.library.canonicalUri, element.script.resourceUri); |
| 196 List<Element> elements = <Element>[]; |
| 197 element.forEachLocalMember((e) => elements.add(e)); |
| 198 encoder.setElements(Key.ELEMENTS, elements); |
| 199 } |
| 200 } |
| 201 |
| 202 class ClassSerializer implements ElementSerializer { |
| 203 const ClassSerializer(); |
| 204 |
| 205 SerializedElementKind getSerializedKind(Element element) { |
| 206 if (element.isClass) { |
| 207 return SerializedElementKind.CLASS; |
| 208 } |
| 209 return null; |
| 210 } |
| 211 |
| 212 void serialize(ClassElement element, |
| 213 ObjectEncoder encoder, |
| 214 SerializedElementKind kind) { |
| 215 encoder.setElement(Key.LIBRARY, element.library); |
| 216 encoder.setElement(Key.COMPILATION_UNIT, element.compilationUnit); |
| 217 encoder.setString(Key.NAME, element.name); |
| 218 SerializerUtil.serializePosition(element, encoder); |
| 219 encoder.setTypes(Key.TYPE_VARIABLES, element.typeVariables); |
| 220 encoder.setBool(Key.IS_ABSTRACT, element.isAbstract); |
| 221 if (element.supertype != null) { |
| 222 encoder.setType(Key.SUPERTYPE, element.supertype); |
| 223 } |
| 224 // TODO(johnniwinther): Make [OrderedTypeSet] easier to (de)serialize. |
| 225 ObjectEncoder supertypes = encoder.createObject(Key.SUPERTYPES); |
| 226 supertypes.setTypes(Key.TYPES, |
| 227 element.allSupertypesAndSelf.types.toList()); |
| 228 supertypes.setTypes(Key.SUPERTYPES, |
| 229 element.allSupertypesAndSelf.supertypes.toList()); |
| 230 supertypes.setInts(Key.OFFSETS, element.allSupertypesAndSelf.levelOffsets); |
| 231 encoder.setTypes(Key.INTERFACES, element.interfaces.toList()); |
| 232 SerializerUtil.serializeMembers(element, encoder); |
| 233 } |
| 234 } |
| 235 |
| 236 class ConstructorSerializer implements ElementSerializer { |
| 237 const ConstructorSerializer(); |
| 238 |
| 239 SerializedElementKind getSerializedKind(Element element) { |
| 240 if (element.isGenerativeConstructor) { |
| 241 return SerializedElementKind.GENERATIVE_CONSTRUCTOR; |
| 242 } else if (element.isFactoryConstructor) { |
| 243 return SerializedElementKind.FACTORY_CONSTRUCTOR; |
| 244 } |
| 245 return null; |
| 246 } |
| 247 |
| 248 void serialize(ConstructorElement element, |
| 249 ObjectEncoder encoder, |
| 250 SerializedElementKind kind) { |
| 251 encoder.setElement(Key.CLASS, element.enclosingClass); |
| 252 encoder.setType(Key.TYPE, element.type); |
| 253 encoder.setString(Key.NAME, element.name); |
| 254 SerializerUtil.serializePosition(element, encoder); |
| 255 SerializerUtil.serializeParameters(element, encoder); |
| 256 encoder.setBool(Key.IS_CONST, element.isConst); |
| 257 // TODO(johnniwinther): Handle external constructors. |
| 258 encoder.setBool(Key.IS_EXTERNAL, element.isExternal); |
| 259 if (element.isExternal) return; |
| 260 if (element.isConst && !element.isFromEnvironmentConstructor) { |
| 261 ConstantConstructor constantConstructor = element.constantConstructor; |
| 262 ObjectEncoder constantEncoder = |
| 263 encoder.createObject(Key.CONSTRUCTOR); |
| 264 const ConstantConstructorSerializer().visit( |
| 265 constantConstructor, constantEncoder); |
| 266 } |
| 267 } |
| 268 } |
| 269 |
| 270 class FieldSerializer implements ElementSerializer { |
| 271 const FieldSerializer(); |
| 272 |
| 273 SerializedElementKind getSerializedKind(Element element) { |
| 274 if (element.isField) { |
| 275 if (element.isTopLevel) return SerializedElementKind.TOPLEVEL_FIELD; |
| 276 if (element.isStatic) return SerializedElementKind.STATIC_FIELD; |
| 277 if (element.isInstanceMember) return SerializedElementKind.INSTANCE_FIELD; |
| 278 } |
| 279 return null; |
| 280 } |
| 281 |
| 282 void serialize(FieldElement element, |
| 283 ObjectEncoder encoder, |
| 284 SerializedElementKind kind) { |
| 285 encoder.setString(Key.NAME, element.name); |
| 286 SerializerUtil.serializePosition(element, encoder); |
| 287 encoder.setType(Key.TYPE, element.type); |
| 288 encoder.setBool(Key.IS_FINAL, element.isFinal); |
| 289 encoder.setBool(Key.IS_CONST, element.isConst); |
| 290 if (element.isConst) { |
| 291 ConstantExpression constant = element.constant; |
| 292 encoder.setConstant(Key.CONSTANT, constant); |
| 293 } |
| 294 if (kind != SerializedElementKind.TOPLEVEL_FIELD) { |
| 295 encoder.setElement(Key.CLASS, element.enclosingClass); |
| 296 } else { |
| 297 encoder.setElement(Key.LIBRARY, element.library); |
| 298 encoder.setElement(Key.COMPILATION_UNIT, element.compilationUnit); |
| 299 } |
| 300 } |
| 301 } |
| 302 |
| 303 class FunctionSerializer implements ElementSerializer { |
| 304 const FunctionSerializer(); |
| 305 |
| 306 SerializedElementKind getSerializedKind(Element element) { |
| 307 if (element.isFunction) { |
| 308 if (element.isTopLevel) return SerializedElementKind.TOPLEVEL_FUNCTION; |
| 309 if (element.isStatic) return SerializedElementKind.STATIC_FUNCTION; |
| 310 if (element.isInstanceMember) { |
| 311 return SerializedElementKind.INSTANCE_FUNCTION; |
| 312 } |
| 313 } |
| 314 if (element.isGetter) { |
| 315 if (element.isTopLevel) return SerializedElementKind.TOPLEVEL_GETTER; |
| 316 if (element.isStatic) return SerializedElementKind.STATIC_GETTER; |
| 317 if (element.isInstanceMember) { |
| 318 return SerializedElementKind.INSTANCE_GETTER; |
| 319 } |
| 320 } |
| 321 if (element.isSetter) { |
| 322 if (element.isTopLevel) return SerializedElementKind.TOPLEVEL_SETTER; |
| 323 if (element.isStatic) return SerializedElementKind.STATIC_SETTER; |
| 324 if (element.isInstanceMember) { |
| 325 return SerializedElementKind.INSTANCE_SETTER; |
| 326 } |
| 327 } |
| 328 return null; |
| 329 } |
| 330 |
| 331 void serialize(FunctionElement element, |
| 332 ObjectEncoder encoder, |
| 333 SerializedElementKind kind) { |
| 334 encoder.setString(Key.NAME, element.name); |
| 335 SerializerUtil.serializePosition(element, encoder); |
| 336 SerializerUtil.serializeParameters(element, encoder); |
| 337 encoder.setType(Key.TYPE, element.type); |
| 338 if (element.isFunction) { |
| 339 encoder.setBool(Key.IS_OPERATOR, element.isOperator); |
| 340 } |
| 341 if (element.enclosingClass != null) { |
| 342 encoder.setElement(Key.CLASS, element.enclosingClass); |
| 343 } else { |
| 344 encoder.setElement(Key.LIBRARY, element.library); |
| 345 encoder.setElement(Key.COMPILATION_UNIT, element.compilationUnit); |
| 346 } |
| 347 } |
| 348 } |
| 349 |
| 350 class TypedefSerializer implements ElementSerializer { |
| 351 const TypedefSerializer(); |
| 352 |
| 353 SerializedElementKind getSerializedKind(Element element) { |
| 354 if (element.isTypedef) { |
| 355 return SerializedElementKind.TYPEDEF; |
| 356 } |
| 357 return null; |
| 358 } |
| 359 |
| 360 void serialize(TypedefElement element, |
| 361 ObjectEncoder encoder, |
| 362 SerializedElementKind kind) { |
| 363 encoder.setString(Key.NAME, element.name); |
| 364 SerializerUtil.serializePosition(element, encoder); |
| 365 encoder.setType(Key.ALIAS, element.alias); |
| 366 encoder.setElement(Key.LIBRARY, element.library); |
| 367 encoder.setTypes(Key.TYPE_VARIABLES, element.typeVariables); |
| 368 encoder.setElement(Key.COMPILATION_UNIT, element.compilationUnit); |
| 369 } |
| 370 } |
| 371 |
| 372 class TypeVariableSerializer implements ElementSerializer { |
| 373 const TypeVariableSerializer(); |
| 374 |
| 375 SerializedElementKind getSerializedKind(Element element) { |
| 376 if (element.isTypeVariable) { |
| 377 return SerializedElementKind.TYPEVARIABLE; |
| 378 } |
| 379 return null; |
| 380 } |
| 381 |
| 382 void serialize(TypeVariableElement element, |
| 383 ObjectEncoder encoder, |
| 384 SerializedElementKind kind) { |
| 385 encoder.setElement(Key.TYPE_DECLARATION, element.typeDeclaration); |
| 386 encoder.setString(Key.NAME, element.name); |
| 387 SerializerUtil.serializePosition(element, encoder); |
| 388 TypeDeclarationElement typeDeclaration = element.typeDeclaration; |
| 389 encoder.setType(Key.TYPE, element.type); |
| 390 encoder.setInt(Key.INDEX, element.index); |
| 391 encoder.setType(Key.BOUND, element.bound); |
| 392 } |
| 393 } |
| 394 |
| 395 class ParameterSerializer implements ElementSerializer { |
| 396 const ParameterSerializer(); |
| 397 |
| 398 SerializedElementKind getSerializedKind(Element element) { |
| 399 if (element.isParameter) { |
| 400 return SerializedElementKind.PARAMETER; |
| 401 } else if (element.isInitializingFormal) { |
| 402 return SerializedElementKind.INITIALIZING_FORMAL; |
| 403 } |
| 404 return null; |
| 405 } |
| 406 |
| 407 void serialize(ParameterElement element, |
| 408 ObjectEncoder encoder, |
| 409 SerializedElementKind kind) { |
| 410 encoder.setElement(Key.FUNCTION, element.functionDeclaration); |
| 411 encoder.setString(Key.NAME, element.name); |
| 412 SerializerUtil.serializePosition(element, encoder); |
| 413 encoder.setType(Key.TYPE, element.type); |
| 414 encoder.setBool(Key.IS_OPTIONAL, element.isOptional); |
| 415 encoder.setBool(Key.IS_NAMED, element.isNamed); |
| 416 if (element.isOptional) { |
| 417 encoder.setConstant(Key.CONSTANT, element.constant); |
| 418 } |
| 419 if (element.isInitializingFormal) { |
| 420 InitializingFormalElement initializingFormal = element; |
| 421 encoder.setElement(Key.FIELD, initializingFormal.fieldElement); |
| 422 } |
| 423 } |
| 424 } |
| 425 |
| 426 /// Utility class for deserializing [Element]s. |
| 427 /// |
| 428 /// This is used by the [Deserializer]. |
| 429 class ElementDeserializer { |
| 430 |
| 431 /// Deserializes an [Element] from an [ObjectDecoder]. |
| 432 /// |
| 433 /// The class is called from the [Deserializer] when an [Element] |
| 434 /// needs deserialization. The [ObjectDecoder] ensures that any [Element], |
| 435 /// [DartType], and [ConstantExpression] that the deserialized [Element] |
| 436 /// depends upon are available. |
| 437 static Element deserialize(ObjectDecoder decoder) { |
| 438 SerializedElementKind elementKind = |
| 439 decoder.getEnum(Key.KIND, SerializedElementKind.values); |
| 440 switch (elementKind) { |
| 441 case SerializedElementKind.LIBRARY: |
| 442 return new LibraryElementZ(decoder); |
| 443 case SerializedElementKind.COMPILATION_UNIT: |
| 444 return new CompilationUnitElementZ(decoder); |
| 445 case SerializedElementKind.CLASS: |
| 446 return new ClassElementZ(decoder); |
| 447 case SerializedElementKind.TOPLEVEL_FIELD: |
| 448 return new TopLevelFieldElementZ(decoder); |
| 449 case SerializedElementKind.STATIC_FIELD: |
| 450 return new StaticFieldElementZ(decoder); |
| 451 case SerializedElementKind.INSTANCE_FIELD: |
| 452 return new InstanceFieldElementZ(decoder); |
| 453 case SerializedElementKind.GENERATIVE_CONSTRUCTOR: |
| 454 return new GenerativeConstructorElementZ(decoder); |
| 455 case SerializedElementKind.FACTORY_CONSTRUCTOR: |
| 456 return new FactoryConstructorElementZ(decoder); |
| 457 case SerializedElementKind.TOPLEVEL_FUNCTION: |
| 458 return new TopLevelFunctionElementZ(decoder); |
| 459 case SerializedElementKind.STATIC_FUNCTION: |
| 460 return new StaticFunctionElementZ(decoder); |
| 461 case SerializedElementKind.INSTANCE_FUNCTION: |
| 462 return new InstanceFunctionElementZ(decoder); |
| 463 case SerializedElementKind.TOPLEVEL_GETTER: |
| 464 return new TopLevelGetterElementZ(decoder); |
| 465 case SerializedElementKind.STATIC_GETTER: |
| 466 return new StaticGetterElementZ(decoder); |
| 467 case SerializedElementKind.INSTANCE_GETTER: |
| 468 return new InstanceGetterElementZ(decoder); |
| 469 case SerializedElementKind.TOPLEVEL_SETTER: |
| 470 return new TopLevelSetterElementZ(decoder); |
| 471 case SerializedElementKind.STATIC_SETTER: |
| 472 return new StaticSetterElementZ(decoder); |
| 473 case SerializedElementKind.INSTANCE_SETTER: |
| 474 return new InstanceSetterElementZ(decoder); |
| 475 case SerializedElementKind.TYPEDEF: |
| 476 return new TypedefElementZ(decoder); |
| 477 case SerializedElementKind.TYPEVARIABLE: |
| 478 return new TypeVariableElementZ(decoder); |
| 479 case SerializedElementKind.PARAMETER: |
| 480 return new ParameterElementZ(decoder); |
| 481 case SerializedElementKind.INITIALIZING_FORMAL: |
| 482 return new InitializingFormalElementZ(decoder); |
| 483 } |
| 484 throw new UnsupportedError("Unexpected element kind '${elementKind}."); |
| 485 } |
| 486 } |
| OLD | NEW |