|  | // Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file | 
|  | // for details. All rights reserved. Use of this source code is governed by a | 
|  | // BSD-style license that can be found in the LICENSE file. | 
|  |  | 
|  | library dart2js.js_emitter.full_emitter.class_builder; | 
|  |  | 
|  | import '../../elements/entities.dart'; | 
|  | import '../../js/js.dart' as jsAst; | 
|  | import '../../js/js.dart' show js; | 
|  | import '../../js_backend/js_backend.dart' show Namer; | 
|  |  | 
|  | /** | 
|  | * A data structure for collecting fragments of a class definition. | 
|  | */ | 
|  | class ClassBuilder { | 
|  | final List<jsAst.Property> properties = <jsAst.Property>[]; | 
|  | final List<jsAst.Literal> fields = <jsAst.Literal>[]; | 
|  |  | 
|  | jsAst.Name superName; | 
|  | jsAst.Node functionType; | 
|  | List<jsAst.Expression> fieldMetadata; | 
|  |  | 
|  | final Entity element; | 
|  | final Namer namer; | 
|  | final bool isForActualClass; | 
|  |  | 
|  | ClassBuilder.forLibrary(LibraryEntity library, this.namer) | 
|  | : isForActualClass = false, | 
|  | element = library; | 
|  |  | 
|  | ClassBuilder.forClass(ClassEntity cls, this.namer) | 
|  | : isForActualClass = true, | 
|  | element = cls; | 
|  |  | 
|  | ClassBuilder.forStatics(this.element, this.namer) : isForActualClass = false; | 
|  |  | 
|  | jsAst.Property addProperty(jsAst.Literal name, jsAst.Expression value) { | 
|  | jsAst.Property property = new jsAst.Property(js.quoteName(name), value); | 
|  | properties.add(property); | 
|  | return property; | 
|  | } | 
|  |  | 
|  | jsAst.Property addPropertyByName(String name, jsAst.Expression value) { | 
|  | jsAst.Property property = new jsAst.Property(js.string(name), value); | 
|  | properties.add(property); | 
|  | return property; | 
|  | } | 
|  |  | 
|  | void addField(jsAst.Literal field) { | 
|  | fields.add(field); | 
|  | } | 
|  |  | 
|  | static String functionTypeEncodingDescription = | 
|  | 'For simple function types the function type is stored in the metadata ' | 
|  | 'and the index is encoded into the superclass field.'; | 
|  |  | 
|  | static String fieldEncodingDescription = | 
|  | 'Fields are encoded as a comma separated list. If there is a superclass ' | 
|  | '(and possibly a function type encoding) the fields are separated from ' | 
|  | 'the superclass by a semicolon.'; | 
|  |  | 
|  | jsAst.ObjectInitializer toObjectInitializer( | 
|  | {bool emitClassDescriptor: true}) { | 
|  | List<jsAst.Literal> parts = <jsAst.Literal>[]; | 
|  | if (isForActualClass) { | 
|  | if (superName != null) { | 
|  | parts.add(superName); | 
|  | if (functionType != null) { | 
|  | // See [functionTypeEncodingDescription] above. | 
|  | parts.add(js.stringPart(':')); | 
|  | parts.add(functionType); | 
|  | } | 
|  | } | 
|  | parts.add(js.stringPart(';')); | 
|  | } | 
|  | // See [fieldEncodingDescription] above. | 
|  | parts.addAll(js.joinLiterals(fields, js.stringPart(','))); | 
|  | dynamic classData = js.concatenateStrings(parts, addQuotes: true); | 
|  | if (fieldMetadata != null) { | 
|  | // If we need to store fieldMetadata, classData is turned into an array, | 
|  | // and the field metadata is appended. So if classData is just a string, | 
|  | // there is no field metadata. | 
|  | classData = | 
|  | new jsAst.ArrayInitializer([classData]..addAll(fieldMetadata)); | 
|  | } | 
|  | List<jsAst.Property> fieldsAndProperties; | 
|  | if (emitClassDescriptor) { | 
|  | fieldsAndProperties = <jsAst.Property>[]; | 
|  | fieldsAndProperties.add(new jsAst.Property( | 
|  | js.string(namer.classDescriptorProperty), classData)); | 
|  | fieldsAndProperties.addAll(properties); | 
|  | } else { | 
|  | fieldsAndProperties = properties; | 
|  | } | 
|  | return new jsAst.ObjectInitializer(fieldsAndProperties, isOneLiner: false); | 
|  | } | 
|  | } |