| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 part of dart2js.js_emitter; | 5 part of dart2js.js_emitter; |
| 6 | 6 |
| 7 class MetadataEmitter extends CodeEmitterHelper { | 7 class MetadataCollector { |
| 8 final Compiler _compiler; |
| 9 final Emitter _emitter; |
| 10 |
| 8 /// A list of JS expressions that represent metadata, parameter names and | 11 /// A list of JS expressions that represent metadata, parameter names and |
| 9 /// type, and return types. | 12 /// type, and return types. |
| 10 final List<String> globalMetadata = []; | 13 final List<String> globalMetadata = []; |
| 11 | 14 |
| 12 /// A map used to canonicalize the entries of globalMetadata. | 15 /// A map used to canonicalize the entries of globalMetadata. |
| 13 final Map<String, int> globalMetadataMap = <String, int>{}; | 16 final Map<String, int> _globalMetadataMap = <String, int>{}; |
| 14 | 17 |
| 15 bool mustEmitMetadataFor(Element element) { | 18 MetadataCollector(this._compiler, this._emitter); |
| 16 return backend.mustRetainMetadata && | 19 |
| 17 backend.referencedFromMirrorSystem(element); | 20 JavaScriptBackend get _backend => _compiler.backend; |
| 21 TypeVariableHandler get _typeVariableHandler => _backend.typeVariableHandler; |
| 22 |
| 23 bool _mustEmitMetadataFor(Element element) { |
| 24 return _backend.mustRetainMetadata && |
| 25 _backend.referencedFromMirrorSystem(element); |
| 18 } | 26 } |
| 19 | 27 |
| 20 /// The metadata function returns the metadata associated with | 28 /// The metadata function returns the metadata associated with |
| 21 /// [element] in generated code. The metadata needs to be wrapped | 29 /// [element] in generated code. The metadata needs to be wrapped |
| 22 /// in a function as it refers to constants that may not have been | 30 /// in a function as it refers to constants that may not have been |
| 23 /// constructed yet. For example, a class is allowed to be | 31 /// constructed yet. For example, a class is allowed to be |
| 24 /// annotated with itself. The metadata function is used by | 32 /// annotated with itself. The metadata function is used by |
| 25 /// mirrors_patch to implement DeclarationMirror.metadata. | 33 /// mirrors_patch to implement DeclarationMirror.metadata. |
| 26 jsAst.Fun buildMetadataFunction(Element element) { | 34 jsAst.Fun buildMetadataFunction(Element element) { |
| 27 if (!mustEmitMetadataFor(element)) return null; | 35 if (!_mustEmitMetadataFor(element)) return null; |
| 28 return compiler.withCurrentElement(element, () { | 36 return _compiler.withCurrentElement(element, () { |
| 29 List<jsAst.Expression> metadata = <jsAst.Expression>[]; | 37 List<jsAst.Expression> metadata = <jsAst.Expression>[]; |
| 30 Link link = element.metadata; | 38 Link link = element.metadata; |
| 31 // TODO(ahe): Why is metadata sometimes null? | 39 // TODO(ahe): Why is metadata sometimes null? |
| 32 if (link != null) { | 40 if (link != null) { |
| 33 for (; !link.isEmpty; link = link.tail) { | 41 for (; !link.isEmpty; link = link.tail) { |
| 34 MetadataAnnotation annotation = link.head; | 42 MetadataAnnotation annotation = link.head; |
| 35 ConstantExpression constant = | 43 ConstantExpression constant = |
| 36 backend.constants.getConstantForMetadata(annotation); | 44 _backend.constants.getConstantForMetadata(annotation); |
| 37 if (constant == null) { | 45 if (constant == null) { |
| 38 compiler.internalError(annotation, 'Annotation value is null.'); | 46 _compiler.internalError(annotation, 'Annotation value is null.'); |
| 39 } else { | 47 } else { |
| 40 metadata.add(emitter.constantReference(constant.value)); | 48 metadata.add(_emitter.constantReference(constant.value)); |
| 41 } | 49 } |
| 42 } | 50 } |
| 43 } | 51 } |
| 44 if (metadata.isEmpty) return null; | 52 if (metadata.isEmpty) return null; |
| 45 return js('function() { return # }', | 53 return js('function() { return # }', |
| 46 new jsAst.ArrayInitializer(metadata)); | 54 new jsAst.ArrayInitializer(metadata)); |
| 47 }); | 55 }); |
| 48 } | 56 } |
| 49 | 57 |
| 50 List<int> reifyDefaultArguments(FunctionElement function) { | 58 List<int> reifyDefaultArguments(FunctionElement function) { |
| 51 FunctionSignature signature = function.functionSignature; | 59 FunctionSignature signature = function.functionSignature; |
| 52 if (signature.optionalParameterCount == 0) return const []; | 60 if (signature.optionalParameterCount == 0) return const []; |
| 53 List<int> defaultValues = <int>[]; | 61 List<int> defaultValues = <int>[]; |
| 54 for (ParameterElement element in signature.optionalParameters) { | 62 for (ParameterElement element in signature.optionalParameters) { |
| 55 ConstantExpression constant = | 63 ConstantExpression constant = |
| 56 backend.constants.getConstantForVariable(element); | 64 _backend.constants.getConstantForVariable(element); |
| 57 String stringRepresentation = (constant == null) | 65 String stringRepresentation = (constant == null) |
| 58 ? "null" | 66 ? "null" |
| 59 : jsAst.prettyPrint( | 67 : jsAst.prettyPrint( |
| 60 emitter.constantReference(constant.value), compiler).getText(); | 68 _emitter.constantReference(constant.value), _compiler).getText(); |
| 61 defaultValues.add(addGlobalMetadata(stringRepresentation)); | 69 defaultValues.add(addGlobalMetadata(stringRepresentation)); |
| 62 } | 70 } |
| 63 return defaultValues; | 71 return defaultValues; |
| 64 } | 72 } |
| 65 | 73 |
| 66 int reifyMetadata(MetadataAnnotation annotation) { | 74 int reifyMetadata(MetadataAnnotation annotation) { |
| 67 ConstantExpression constant = | 75 ConstantExpression constant = |
| 68 backend.constants.getConstantForMetadata(annotation); | 76 _backend.constants.getConstantForMetadata(annotation); |
| 69 if (constant == null) { | 77 if (constant == null) { |
| 70 compiler.internalError(annotation, 'Annotation value is null.'); | 78 _compiler.internalError(annotation, 'Annotation value is null.'); |
| 71 return -1; | 79 return -1; |
| 72 } | 80 } |
| 73 return addGlobalMetadata( | 81 return addGlobalMetadata( |
| 74 jsAst.prettyPrint( | 82 jsAst.prettyPrint( |
| 75 emitter.constantReference(constant.value), compiler).getText()); | 83 _emitter.constantReference(constant.value), _compiler).getText()); |
| 76 } | 84 } |
| 77 | 85 |
| 78 int reifyType(DartType type) { | 86 int reifyType(DartType type) { |
| 79 jsAst.Expression representation = | 87 jsAst.Expression representation = |
| 80 backend.rti.getTypeRepresentation( | 88 _backend.rti.getTypeRepresentation( |
| 81 type, | 89 type, |
| 82 (variable) { | 90 (variable) { |
| 83 return js.number( | 91 return js.number( |
| 84 emitter.typeVariableHandler.reifyTypeVariable( | 92 _typeVariableHandler.reifyTypeVariable( |
| 85 variable.element)); | 93 variable.element)); |
| 86 }, | 94 }, |
| 87 (TypedefType typedef) { | 95 (TypedefType typedef) { |
| 88 return backend.isAccessibleByReflection(typedef.element); | 96 return _backend.isAccessibleByReflection(typedef.element); |
| 89 }); | 97 }); |
| 90 | 98 |
| 91 return addGlobalMetadata( | 99 return addGlobalMetadata( |
| 92 jsAst.prettyPrint(representation, compiler).getText()); | 100 jsAst.prettyPrint(representation, _compiler).getText()); |
| 93 } | 101 } |
| 94 | 102 |
| 95 int reifyName(String name) { | 103 int reifyName(String name) { |
| 96 return addGlobalMetadata('"$name"'); | 104 return addGlobalMetadata('"$name"'); |
| 97 } | 105 } |
| 98 | 106 |
| 99 int addGlobalMetadata(String string) { | 107 int addGlobalMetadata(String string) { |
| 100 return globalMetadataMap.putIfAbsent(string, () { | 108 return _globalMetadataMap.putIfAbsent(string, () { |
| 101 globalMetadata.add(string); | 109 globalMetadata.add(string); |
| 102 return globalMetadata.length - 1; | 110 return globalMetadata.length - 1; |
| 103 }); | 111 }); |
| 104 } | 112 } |
| 105 | 113 |
| 106 List<int> computeMetadata(FunctionElement element) { | 114 List<int> computeMetadata(FunctionElement element) { |
| 107 return compiler.withCurrentElement(element, () { | 115 return _compiler.withCurrentElement(element, () { |
| 108 if (!mustEmitMetadataFor(element)) return const <int>[]; | 116 if (!_mustEmitMetadataFor(element)) return const <int>[]; |
| 109 List<int> metadata = <int>[]; | 117 List<int> metadata = <int>[]; |
| 110 Link link = element.metadata; | 118 Link link = element.metadata; |
| 111 // TODO(ahe): Why is metadata sometimes null? | 119 // TODO(ahe): Why is metadata sometimes null? |
| 112 if (link != null) { | 120 if (link != null) { |
| 113 for (; !link.isEmpty; link = link.tail) { | 121 for (; !link.isEmpty; link = link.tail) { |
| 114 metadata.add(reifyMetadata(link.head)); | 122 metadata.add(reifyMetadata(link.head)); |
| 115 } | 123 } |
| 116 } | 124 } |
| 117 return metadata; | 125 return metadata; |
| 118 }); | 126 }); |
| 119 } | 127 } |
| 120 } | 128 } |
| OLD | NEW |