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