OLD | NEW |
(Empty) | |
| 1 library angular.core_dynamic; |
| 2 |
| 3 import 'dart:mirrors'; |
| 4 import 'package:angular/core/annotation_src.dart'; |
| 5 import 'package:angular/core/registry.dart'; |
| 6 |
| 7 export 'package:angular/core/registry.dart' show |
| 8 MetadataExtractor; |
| 9 |
| 10 var _fieldMetadataCache = new Map<Type, Map<String, DirectiveAnnotation>>(); |
| 11 |
| 12 class DynamicMetadataExtractor implements MetadataExtractor { |
| 13 final _fieldAnnotations = [ |
| 14 reflectType(NgAttr), |
| 15 reflectType(NgOneWay), |
| 16 reflectType(NgOneWayOneTime), |
| 17 reflectType(NgTwoWay), |
| 18 reflectType(NgCallback) |
| 19 ]; |
| 20 |
| 21 Iterable call(Type type) { |
| 22 if (reflectType(type) is TypedefMirror) return []; |
| 23 var metadata = reflectClass(type).metadata; |
| 24 if (metadata == null) { |
| 25 metadata = []; |
| 26 } else { |
| 27 metadata = metadata.map((InstanceMirror im) => map(type, im.reflectee)); |
| 28 } |
| 29 return metadata; |
| 30 } |
| 31 |
| 32 map(Type type, obj) { |
| 33 if (obj is Directive) { |
| 34 return mapDirectiveAnnotation(type, obj); |
| 35 } else { |
| 36 return obj; |
| 37 } |
| 38 } |
| 39 |
| 40 Directive mapDirectiveAnnotation(Type type, Directive annotation) { |
| 41 var match; |
| 42 var fieldMetadata = fieldMetadataExtractor(type); |
| 43 if (fieldMetadata.isNotEmpty) { |
| 44 var newMap = annotation.map == null ? {} : new Map.from(annotation.map); |
| 45 fieldMetadata.forEach((String fieldName, DirectiveAnnotation ann) { |
| 46 var attrName = ann.attrName; |
| 47 if (newMap.containsKey(attrName)) { |
| 48 throw 'Mapping for attribute $attrName is already defined (while ' |
| 49 'processing annottation for field $fieldName of $type)'; |
| 50 } |
| 51 newMap[attrName] = '${mappingSpec(ann)}$fieldName'; |
| 52 }); |
| 53 annotation = cloneWithNewMap(annotation, newMap); |
| 54 } |
| 55 return annotation; |
| 56 } |
| 57 |
| 58 |
| 59 Map<String, DirectiveAnnotation> fieldMetadataExtractor(Type type) => |
| 60 _fieldMetadataCache.putIfAbsent(type, () => _fieldMetadataExtractor(reflec
tType(type))); |
| 61 |
| 62 Map<String, DirectiveAnnotation> _fieldMetadataExtractor(ClassMirror cm) { |
| 63 var fields = <String, DirectiveAnnotation>{}; |
| 64 if(cm.superclass != null) { |
| 65 fields.addAll(_fieldMetadataExtractor(cm.superclass)); |
| 66 } else { |
| 67 fields = {}; |
| 68 } |
| 69 Map<Symbol, DeclarationMirror> declarations = cm.declarations; |
| 70 declarations.forEach((symbol, dm) { |
| 71 if(dm is VariableMirror || |
| 72 dm is MethodMirror && (dm.isGetter || dm.isSetter)) { |
| 73 var fieldName = MirrorSystem.getName(symbol); |
| 74 if (dm is MethodMirror && dm.isSetter) { |
| 75 // Remove "=" from the end of the setter. |
| 76 fieldName = fieldName.substring(0, fieldName.length - 1); |
| 77 } |
| 78 dm.metadata.forEach((InstanceMirror meta) { |
| 79 if (_fieldAnnotations.contains(meta.type)) { |
| 80 if (fields.containsKey(fieldName)) { |
| 81 throw 'Attribute annotation for $fieldName is defined more ' |
| 82 'than once in ${cm.reflectedType}'; |
| 83 } |
| 84 fields[fieldName] = meta.reflectee as DirectiveAnnotation; |
| 85 } |
| 86 }); |
| 87 } |
| 88 }); |
| 89 return fields; |
| 90 } |
| 91 } |
OLD | NEW |