OLD | NEW |
| 1 library angular2.src.transform; |
| 2 |
1 import 'dart:collection' show Queue; | 3 import 'dart:collection' show Queue; |
2 import 'package:analyzer/src/generated/element.dart'; | 4 import 'package:analyzer/src/generated/element.dart'; |
3 | 5 |
4 /// Provides a mechanism for checking an element for the provided | 6 /// Provides a mechanism for checking an element for the provided |
5 /// [_annotationClass] and reporting the resulting (element, annotation) pairs. | 7 /// [_annotationClass] and reporting the resulting (element, annotation) pairs. |
6 class AnnotationMatcher { | 8 class AnnotationMatcher { |
7 /// Queue for annotations. | 9 /// Queue for annotations. |
8 final initQueue = new Queue<AnnotationMatch>(); | 10 final matchQueue = new Queue<AnnotationMatch>(); |
9 /// All the annotations we have seen for each element | 11 /// All the annotations we have seen for each element |
10 final _seenAnnotations = new Map<Element, Set<ElementAnnotation>>(); | 12 final _seenAnnotations = new Map<Element, Set<ElementAnnotation>>(); |
11 | 13 |
12 /// The class we are searching for to populate [initQueue]. | 14 /// The class we are searching for to populate [initQueue]. |
13 final ClassElement _annotationClass; | 15 final ClassElement _annotationClass; |
14 | 16 |
15 AnnotationMatcher(this._annotationClass); | 17 AnnotationMatcher(this._annotationClass); |
16 | 18 |
17 /// Records all [_annotationClass] annotations and the [element]s they apply t
o. | 19 /// Records all [_annotationClass] annotations and the [element]s they apply t
o. |
18 /// Returns [true] if 1) [element] is annotated with [_annotationClass] and | 20 /// Returns [true] if 1) [element] is annotated with [_annotationClass] and |
19 /// 2) ([element], [_annotationClass]) has been seen previously. | 21 /// 2) ([element], [_annotationClass]) has not been seen previously. |
20 bool processAnnotations(ClassElement element) { | 22 bool processAnnotations(ClassElement element) { |
21 var found = false; | 23 var found = false; |
22 element.metadata.where((ElementAnnotation meta) { | 24 element.metadata.where((ElementAnnotation meta) { |
23 // Only process [_annotationClass]s. | 25 // Only process [_annotationClass]s. |
24 // TODO(tjblasi): Make this recognize non-ConstructorElement annotations. | 26 // TODO(tjblasi): Make this recognize non-ConstructorElement annotations. |
25 return meta.element is ConstructorElement && | 27 return meta.element is ConstructorElement && |
26 _isAnnotationMatch(meta.element.returnType); | 28 _isAnnotationMatch(meta.element.returnType); |
27 }).where((ElementAnnotation meta) { | 29 }).where((ElementAnnotation meta) { |
28 // Only process ([element], [meta]) combinations we haven't seen previousl
y. | 30 // Only process ([element], [meta]) combinations we haven't seen previousl
y. |
29 return !_seenAnnotations | 31 return !_seenAnnotations |
30 .putIfAbsent(element, () => new Set<ElementAnnotation>()) | 32 .putIfAbsent(element, () => new Set<ElementAnnotation>()) |
31 .contains(meta); | 33 .contains(meta); |
32 }).forEach((ElementAnnotation meta) { | 34 }).forEach((ElementAnnotation meta) { |
33 _seenAnnotations[element].add(meta); | 35 _seenAnnotations[element].add(meta); |
34 initQueue.addLast(new AnnotationMatch(element, meta)); | 36 matchQueue.addLast(new AnnotationMatch(element, meta)); |
35 found = true; | 37 found = true; |
36 }); | 38 }); |
37 return found; | 39 return found; |
38 } | 40 } |
39 | 41 |
40 /// Whether [type], its superclass, or one of its interfaces matches [_annotat
ionClass]. | 42 /// Whether [type], its superclass, or one of its interfaces matches [_annotat
ionClass]. |
41 bool _isAnnotationMatch(InterfaceType type) { | 43 bool _isAnnotationMatch(InterfaceType type) { |
42 if (type == null || type.element == null) return false; | 44 if (type == null || type.element == null) return false; |
43 if (type.element.type == _annotationClass.type) return true; | 45 if (type.element.type == _annotationClass.type) return true; |
44 if (_isAnnotationMatch(type.superclass)) return true; | 46 if (_isAnnotationMatch(type.superclass)) return true; |
45 for (var interface in type.interfaces) { | 47 for (var interface in type.interfaces) { |
46 if (_isAnnotationMatch(interface)) return true; | 48 if (_isAnnotationMatch(interface)) return true; |
47 } | 49 } |
48 return false; | 50 return false; |
49 } | 51 } |
50 } | 52 } |
51 | 53 |
52 // Element/ElementAnnotation pair. | 54 // Element/ElementAnnotation pair. |
53 class AnnotationMatch { | 55 class AnnotationMatch { |
54 final Element element; | 56 final Element element; |
55 final ElementAnnotation annotation; | 57 final ElementAnnotation annotation; |
56 | 58 |
57 AnnotationMatch(this.element, this.annotation); | 59 AnnotationMatch(this.element, this.annotation); |
58 } | 60 } |
OLD | NEW |