| Index: pkg/dev_compiler/lib/src/compiler/code_generator.dart
|
| diff --git a/pkg/dev_compiler/lib/src/compiler/code_generator.dart b/pkg/dev_compiler/lib/src/compiler/code_generator.dart
|
| index 09475570a8ee2963fde5f40ba0bf68d06d23ebc0..bc48e342fb7fc1df283a2dfa272b89b5b8d2f36f 100644
|
| --- a/pkg/dev_compiler/lib/src/compiler/code_generator.dart
|
| +++ b/pkg/dev_compiler/lib/src/compiler/code_generator.dart
|
| @@ -733,7 +733,8 @@ class CodeGenerator extends GeneralizingAstVisitor
|
|
|
| _defineNamedConstructors(ctors, body, className, isCallable);
|
| _emitVirtualFieldSymbols(virtualFieldSymbols, body);
|
| - _emitClassSignature(methods, classElem, ctors, extensions, className, body);
|
| + _emitClassSignature(
|
| + methods, allFields, classElem, ctors, extensions, className, body);
|
| _defineExtensionMembers(extensions, className, body);
|
| _emitClassMetadata(node.metadata, className, body);
|
|
|
| @@ -1650,6 +1651,7 @@ class CodeGenerator extends GeneralizingAstVisitor
|
| /// Emit the signature on the class recording the runtime type information
|
| void _emitClassSignature(
|
| List<MethodDeclaration> methods,
|
| + List<FieldDeclaration> fields,
|
| ClassElement classElem,
|
| List<ConstructorDeclaration> ctors,
|
| List<ExecutableElement> extensions,
|
| @@ -1663,31 +1665,66 @@ class CodeGenerator extends GeneralizingAstVisitor
|
| ]));
|
| }
|
|
|
| - var tStatics = <JS.Property>[];
|
| - var tMethods = <JS.Property>[];
|
| + var tStaticMethods = <JS.Property>[];
|
| + var tInstanceMethods = <JS.Property>[];
|
| + var tStaticGetters = <JS.Property>[];
|
| + var tInstanceGetters = <JS.Property>[];
|
| + var tStaticSetters = <JS.Property>[];
|
| + var tInstanceSetters = <JS.Property>[];
|
| var sNames = <JS.Expression>[];
|
| for (MethodDeclaration node in methods) {
|
| - if (!(node.isSetter || node.isGetter || node.isAbstract)) {
|
| - var name = node.name.name;
|
| - var element = node.element;
|
| - var inheritedElement =
|
| - classElem.lookUpInheritedConcreteMethod(name, currentLibrary);
|
| - if (inheritedElement != null && inheritedElement.type == element.type) {
|
| - continue;
|
| - }
|
| - var memberName = _elementMemberName(element,
|
| + var name = node.name.name;
|
| + var element = node.element;
|
| + // TODO(vsm): Clean up all the nasty duplication.
|
| + if (node.isAbstract) {
|
| + continue;
|
| + }
|
| +
|
| + Function lookup;
|
| + List<JS.Property> tMember;
|
| + JS.Expression type;
|
| + if (node.isGetter) {
|
| + lookup = classElem.lookUpInheritedConcreteGetter;
|
| + tMember = node.isStatic ? tStaticGetters : tInstanceGetters;
|
| + } else if (node.isSetter) {
|
| + lookup = classElem.lookUpInheritedConcreteSetter;
|
| + tMember = node.isStatic ? tStaticSetters : tInstanceSetters;
|
| + } else {
|
| + // Method
|
| + lookup = classElem.lookUpInheritedConcreteMethod;
|
| + tMember = node.isStatic ? tStaticMethods : tInstanceMethods;
|
| + }
|
| +
|
| + type = _emitAnnotatedFunctionType(element.type, node.metadata,
|
| + parameters: node.parameters?.parameters,
|
| + nameType: options.hoistSignatureTypes,
|
| + hoistType: options.hoistSignatureTypes,
|
| + definite: true);
|
| +
|
| + var inheritedElement = lookup(name, currentLibrary);
|
| + if (inheritedElement != null && inheritedElement.type == element.type) {
|
| + continue;
|
| + }
|
| + var memberName = _elementMemberName(element,
|
| + useExtension: _extensionTypes.isNativeClass(classElem));
|
| + var property = new JS.Property(memberName, type);
|
| + tMember.add(property);
|
| + // TODO(vsm): Why do we need this?
|
| + if (node.isStatic && !node.isGetter && !node.isSetter) {
|
| + sNames.add(memberName);
|
| + }
|
| + }
|
| +
|
| + var tInstanceFields = <JS.Property>[];
|
| + var tStaticFields = <JS.Property>[];
|
| + for (FieldDeclaration node in fields) {
|
| + for (VariableDeclaration field in node.fields.variables) {
|
| + var element = field.element as FieldElement;
|
| + var memberName = _elementMemberName(element.getter,
|
| useExtension: _extensionTypes.isNativeClass(classElem));
|
| - var type = _emitFunctionType(element.type,
|
| - nameType: options.hoistSignatureTypes,
|
| - hoistType: options.hoistSignatureTypes,
|
| - definite: true);
|
| + var type = _emitAnnotatedType(element.type, node.metadata);
|
| var property = new JS.Property(memberName, type);
|
| - if (node.isStatic) {
|
| - tStatics.add(property);
|
| - sNames.add(memberName);
|
| - } else {
|
| - tMethods.add(property);
|
| - }
|
| + (node.isStatic ? tStaticFields : tInstanceFields).add(property);
|
| }
|
| }
|
|
|
| @@ -1695,7 +1732,7 @@ class CodeGenerator extends GeneralizingAstVisitor
|
| for (ConstructorDeclaration node in ctors) {
|
| var memberName = _constructorName(node.element);
|
| var element = node.element;
|
| - var type = _emitFunctionType(element.type,
|
| + var type = _emitAnnotatedFunctionType(element.type, node.metadata,
|
| parameters: node.parameters.parameters,
|
| nameType: options.hoistSignatureTypes,
|
| hoistType: options.hoistSignatureTypes,
|
| @@ -1707,18 +1744,42 @@ class CodeGenerator extends GeneralizingAstVisitor
|
| JS.Property build(String name, List<JS.Property> elements) {
|
| var o =
|
| new JS.ObjectInitializer(elements, multiline: elements.length > 1);
|
| + // TODO(vsm): Remove
|
| var e = js.call('() => #', o);
|
| return new JS.Property(_propertyName(name), e);
|
| }
|
|
|
| var sigFields = <JS.Property>[];
|
| - if (!tCtors.isEmpty) sigFields.add(build('constructors', tCtors));
|
| - if (!tMethods.isEmpty) sigFields.add(build('methods', tMethods));
|
| - if (!tStatics.isEmpty) {
|
| + if (!tCtors.isEmpty) {
|
| + sigFields.add(build('constructors', tCtors));
|
| + }
|
| + if (!tInstanceFields.isEmpty) {
|
| + sigFields.add(build('fields', tInstanceFields));
|
| + }
|
| + if (!tInstanceGetters.isEmpty) {
|
| + sigFields.add(build('getters', tInstanceGetters));
|
| + }
|
| + if (!tInstanceSetters.isEmpty) {
|
| + sigFields.add(build('setters', tInstanceSetters));
|
| + }
|
| + if (!tInstanceMethods.isEmpty) {
|
| + sigFields.add(build('methods', tInstanceMethods));
|
| + }
|
| + if (!tStaticFields.isEmpty) {
|
| + sigFields.add(build('sfields', tStaticFields));
|
| + }
|
| + if (!tStaticGetters.isEmpty) {
|
| + sigFields.add(build('sgetters', tStaticGetters));
|
| + }
|
| + if (!tStaticSetters.isEmpty) {
|
| + sigFields.add(build('ssetters', tStaticSetters));
|
| + }
|
| + if (!tStaticMethods.isEmpty) {
|
| assert(!sNames.isEmpty);
|
| + // TODO(vsm): Why do we need this names field?
|
| var aNames = new JS.Property(
|
| _propertyName('names'), new JS.ArrayInitializer(sNames));
|
| - sigFields.add(build('statics', tStatics));
|
| + sigFields.add(build('statics', tStaticMethods));
|
| sigFields.add(aNames);
|
| }
|
| if (!sigFields.isEmpty || extensions.isNotEmpty) {
|
| @@ -2669,21 +2730,33 @@ class CodeGenerator extends GeneralizingAstVisitor
|
| ? p.metadata
|
| : (p as DefaultFormalParameter).parameter.metadata;
|
|
|
| + // Wrap a result - usually a type - with its metadata. The runtime is
|
| + // responsible for unpacking this.
|
| + JS.Expression _emitAnnotatedResult(
|
| + JS.Expression result, List<Annotation> metadata) {
|
| + if (options.emitMetadata && metadata != null && metadata.isNotEmpty) {
|
| + result = new JS.ArrayInitializer(
|
| + [result]..addAll(metadata.map(_instantiateAnnotation)));
|
| + }
|
| + return result;
|
| + }
|
| +
|
| + JS.Expression _emitAnnotatedType(DartType type, List<Annotation> metadata,
|
| + {bool nameType: true, bool hoistType: true}) {
|
| + metadata ??= [];
|
| + var typeName = _emitType(type, nameType: nameType, hoistType: hoistType);
|
| + return _emitAnnotatedResult(typeName, metadata);
|
| + }
|
| +
|
| JS.ArrayInitializer _emitTypeNames(
|
| List<DartType> types, List<FormalParameter> parameters,
|
| {bool nameType: true, bool hoistType: true}) {
|
| var result = <JS.Expression>[];
|
| for (int i = 0; i < types.length; ++i) {
|
| - var metadata =
|
| - parameters != null ? _parameterMetadata(parameters[i]) : [];
|
| - var typeName =
|
| - _emitType(types[i], nameType: nameType, hoistType: hoistType);
|
| - var value = typeName;
|
| - if (options.emitMetadata && metadata.isNotEmpty) {
|
| - value = new JS.ArrayInitializer(
|
| - [typeName]..addAll(metadata.map(_instantiateAnnotation)));
|
| - }
|
| - result.add(value);
|
| + var metadata = parameters != null
|
| + ? _parameterMetadata(parameters[i])
|
| + : <Annotation>[];
|
| + result.add(_emitAnnotatedType(types[i], metadata));
|
| }
|
| return new JS.ArrayInitializer(result);
|
| }
|
| @@ -2718,6 +2791,22 @@ class CodeGenerator extends GeneralizingAstVisitor
|
| hoistType: hoistType, definite: definite);
|
| }
|
|
|
| + JS.Expression _emitAnnotatedFunctionType(
|
| + FunctionType type, List<Annotation> metadata,
|
| + {List<FormalParameter> parameters,
|
| + bool lowerTypedef: false,
|
| + bool nameType: true,
|
| + bool hoistType: true,
|
| + bool definite: false}) {
|
| + var result = _emitFunctionType(type,
|
| + parameters: parameters,
|
| + lowerTypedef: lowerTypedef,
|
| + nameType: nameType,
|
| + hoistType: hoistType,
|
| + definite: definite);
|
| + return _emitAnnotatedResult(result, metadata);
|
| + }
|
| +
|
| /// Emit the pieces of a function type, as an array of return type,
|
| /// regular args, and optional/named args.
|
| List<JS.Expression> _emitFunctionTypeParts(FunctionType type,
|
|
|