@@ -2,176 +2,97 @@ library angular2.transform.common.annotation_matcher;
22
33import 'package:analyzer/src/generated/ast.dart' ;
44import 'package:barback/barback.dart' show AssetId;
5- import 'package:code_transformers/assets.dart' ;
6- import 'package:path/path.dart' as path;
7- import 'logging.dart' show logger;
5+ import 'class_matcher_base.dart' ;
86
9- /// [AnnotationDescriptor] s for the default angular annotations that can appear
7+ export 'class_matcher_base.dart' show ClassDescriptor;
8+
9+ /// [ClassDescriptor] s for the default angular annotations that can appear
1010/// on a class. These classes are re-exported in many places so this covers all
1111/// the possible libraries which could provide them.
1212const INJECTABLES = const [
13- const AnnotationDescriptor (
14- 'Injectable' , 'package:angular2/src/di/decorators.dart' , null ),
15- const AnnotationDescriptor ('Injectable' , 'package:angular2/di.dart' , null ),
16- const AnnotationDescriptor (
17- 'Injectable' , 'package:angular2/angular2.dart' , null ),
13+ const ClassDescriptor (
14+ 'Injectable' , 'package:angular2/src/di/decorators.dart' ),
15+ const ClassDescriptor ('Injectable' , 'package:angular2/di.dart' ),
16+ const ClassDescriptor ('Injectable' , 'package:angular2/angular2.dart' ),
1817];
1918
2019const DIRECTIVES = const [
21- const AnnotationDescriptor ('Directive' ,
22- 'package:angular2/src/core/annotations/annotations.dart' , 'Injectable' ),
23- const AnnotationDescriptor ('Directive' ,
24- 'package:angular2/src/core/annotations/decorators.dart' , 'Injectable' ),
25- const AnnotationDescriptor ('Directive' ,
20+ const ClassDescriptor (
21+ 'Directive' , 'package:angular2/src/core/annotations/annotations.dart' ,
22+ superClass: 'Injectable' ),
23+ const ClassDescriptor (
24+ 'Directive' , 'package:angular2/src/core/annotations/decorators.dart' ,
25+ superClass: 'Injectable' ),
26+ const ClassDescriptor ('Directive' ,
2627 'package:angular2/src/core/annotations_impl/annotations.dart' ,
27- 'Injectable' ),
28- const AnnotationDescriptor (
29- 'Directive' , 'package:angular2/annotations.dart' , 'Injectable' ),
30- const AnnotationDescriptor (
31- 'Directive' , 'package:angular2/angular2.dart' , 'Injectable' ),
32- const AnnotationDescriptor (
33- 'Directive' , 'package:angular2/core.dart' , 'Injectable' ),
28+ superClass : 'Injectable' ),
29+ const ClassDescriptor ( 'Directive' , 'package:angular2/annotations.dart' ,
30+ superClass : 'Injectable' ),
31+ const ClassDescriptor ( 'Directive' , 'package:angular2/angular2.dart' ,
32+ superClass : 'Injectable' ),
33+ const ClassDescriptor ( 'Directive' , 'package:angular2/core.dart' ,
34+ superClass : 'Injectable' ),
3435];
3536
3637const COMPONENTS = const [
37- const AnnotationDescriptor ('Component' ,
38- 'package:angular2/src/core/annotations/annotations.dart' , 'Directive' ),
39- const AnnotationDescriptor ('Component' ,
40- 'package:angular2/src/core/annotations/decorators.dart' , 'Directive' ),
41- const AnnotationDescriptor ('Component' ,
38+ const ClassDescriptor (
39+ 'Component' , 'package:angular2/src/core/annotations/annotations.dart' ,
40+ superClass: 'Directive' ),
41+ const ClassDescriptor (
42+ 'Component' , 'package:angular2/src/core/annotations/decorators.dart' ,
43+ superClass: 'Directive' ),
44+ const ClassDescriptor ('Component' ,
4245 'package:angular2/src/core/annotations_impl/annotations.dart' ,
43- 'Directive' ),
44- const AnnotationDescriptor (
45- 'Component' , 'package:angular2/annotations.dart' , 'Directive' ),
46- const AnnotationDescriptor (
47- 'Component' , 'package:angular2/angular2.dart' , 'Directive' ),
48- const AnnotationDescriptor (
49- 'Component' , 'package:angular2/core.dart' , 'Directive' ),
46+ superClass : 'Directive' ),
47+ const ClassDescriptor ( 'Component' , 'package:angular2/annotations.dart' ,
48+ superClass : 'Directive' ),
49+ const ClassDescriptor ( 'Component' , 'package:angular2/angular2.dart' ,
50+ superClass : 'Directive' ),
51+ const ClassDescriptor ( 'Component' , 'package:angular2/core.dart' ,
52+ superClass : 'Directive' ),
5053];
5154
5255const VIEWS = const [
53- const AnnotationDescriptor ('View' , 'package:angular2/view.dart' , null ),
54- const AnnotationDescriptor ('View' , 'package:angular2/angular2.dart' , null ),
55- const AnnotationDescriptor ('View' , 'package:angular2/core.dart' , null ),
56- const AnnotationDescriptor (
57- 'View' , 'package:angular2/src/core/annotations/view.dart' , null ),
58- const AnnotationDescriptor (
59- 'View' , 'package:angular2/src/core/annotations_impl/view.dart' , null ),
56+ const ClassDescriptor ('View' , 'package:angular2/view.dart' ),
57+ const ClassDescriptor ('View' , 'package:angular2/angular2.dart' ),
58+ const ClassDescriptor ('View' , 'package:angular2/core.dart' ),
59+ const ClassDescriptor (
60+ 'View' , 'package:angular2/src/core/annotations/view.dart' ),
61+ const ClassDescriptor (
62+ 'View' , 'package:angular2/src/core/annotations_impl/view.dart' ),
6063];
6164
6265/// Checks if a given [Annotation] matches any of the given
63- /// [AnnotationDescriptors] .
64- class AnnotationMatcher {
65- /// Always start out with the default angular [AnnotationDescriptor] s.
66- final List <AnnotationDescriptor > _annotations = []
67- ..addAll (VIEWS )
68- ..addAll (COMPONENTS )
69- ..addAll (INJECTABLES )
70- ..addAll (DIRECTIVES );
71-
72- AnnotationMatcher ();
73-
74- /// Adds a new [AnnotationDescriptor] .
75- void add (AnnotationDescriptor annotation) => _annotations.add (annotation);
76-
77- /// Adds a number of [AnnotationDescriptor] s.
78- void addAll (Iterable <AnnotationDescriptor > annotations) =>
79- _annotations.addAll (annotations);
80-
81- /// Returns the first [AnnotationDescriptor] that matches the given
82- /// [Annotation] node which appears in `assetId` .
83- AnnotationDescriptor firstMatch (Annotation annotation, AssetId assetId) =>
84- _annotations.firstWhere ((a) => _matchAnnotation (annotation, a, assetId),
85- orElse: () => null );
66+ /// [ClassDescriptors] .
67+ class AnnotationMatcher extends ClassMatcherBase {
68+ AnnotationMatcher ._(classDescriptors) : super (classDescriptors);
69+
70+ factory AnnotationMatcher () {
71+ return new AnnotationMatcher ._([]
72+ ..addAll (COMPONENTS )
73+ ..addAll (DIRECTIVES )
74+ ..addAll (INJECTABLES )
75+ ..addAll (VIEWS ));
76+ }
8677
87- /// Checks whether an [Annotation] node matches any [AnnotationDescriptor] .
88- bool hasMatch (Annotation annotation, AssetId assetId) =>
89- _annotations.any ((a) => _matchAnnotation (annotation, a, assetId));
78+ bool _implementsWithWarning (
79+ ClassDescriptor descriptor, List <ClassDescriptor > interfaces) =>
80+ implements (descriptor, interfaces,
81+ missingSuperClassWarning: 'Missing `custom_annotation` entry for `${descriptor .superClass }`.' );
9082
9183 /// Checks if an [Annotation] node implements [Injectable] .
9284 bool isInjectable (Annotation annotation, AssetId assetId) =>
93- _implements (firstMatch (annotation, assetId), INJECTABLES );
85+ _implementsWithWarning (firstMatch (annotation.name , assetId), INJECTABLES );
9486
9587 /// Checks if an [Annotation] node implements [Directive] .
9688 bool isDirective (Annotation annotation, AssetId assetId) =>
97- _implements (firstMatch (annotation, assetId), DIRECTIVES );
89+ _implementsWithWarning (firstMatch (annotation.name , assetId), DIRECTIVES );
9890
9991 /// Checks if an [Annotation] node implements [Component] .
10092 bool isComponent (Annotation annotation, AssetId assetId) =>
101- _implements (firstMatch (annotation, assetId), COMPONENTS );
93+ _implementsWithWarning (firstMatch (annotation.name , assetId), COMPONENTS );
10294
10395 /// Checks if an [Annotation] node implements [View] .
10496 bool isView (Annotation annotation, AssetId assetId) =>
105- _implements (firstMatch (annotation, assetId), VIEWS );
106-
107- /// Checks if `descriptor` extends or is any of the supplied `interfaces` .
108- bool _implements (
109- AnnotationDescriptor descriptor, List <AnnotationDescriptor > interfaces) {
110- if (descriptor == null ) return false ;
111- if (interfaces.contains (descriptor)) return true ;
112- if (descriptor.superClass == null ) return false ;
113- var superClass = _annotations.firstWhere (
114- (a) => a.name == descriptor.superClass, orElse: () => null );
115- if (superClass == null ) {
116- logger.warning (
117- 'Missing `custom_annotation` entry for `${descriptor .superClass }`.' );
118- return false ;
119- }
120- return _implements (superClass, interfaces);
121- }
122-
123- // Checks if an [Annotation] matches an [AnnotationDescriptor].
124- static bool _matchAnnotation (
125- Annotation annotation, AnnotationDescriptor descriptor, AssetId assetId) {
126- String name;
127- Identifier prefix;
128- if (annotation.name is PrefixedIdentifier ) {
129- // TODO(jakemac): Shouldn't really need a cast here, remove once
130- // https://github.com/dart-lang/sdk/issues/23798 is fixed.
131- var prefixedName = annotation.name as PrefixedIdentifier ;
132- name = prefixedName.identifier.name;
133- prefix = prefixedName.prefix;
134- } else {
135- name = annotation.name.name;
136- }
137- if (name != descriptor.name) return false ;
138- return (annotation.root as CompilationUnit ).directives
139- .where ((d) => d is ImportDirective )
140- .any ((ImportDirective i) {
141- var importMatch = false ;
142- var uriString = i.uri.stringValue;
143- if (uriString == descriptor.import) {
144- importMatch = true ;
145- } else if (uriString.startsWith ('package:' ) ||
146- uriString.startsWith ('dart:' )) {
147- return false ;
148- } else {
149- importMatch = descriptor.assetId ==
150- uriToAssetId (assetId, uriString, logger, null );
151- }
152-
153- if (! importMatch) return false ;
154- if (prefix == null ) return i.prefix == null ;
155- if (i.prefix == null ) return false ;
156- return prefix.name == i.prefix.name;
157- });
158- }
159- }
160-
161- /// String based description of an annotation class and its location.
162- class AnnotationDescriptor {
163- /// The name of the class.
164- final String name;
165- /// A `package:` style import path to the file where the class is defined.
166- final String import;
167- /// The class that this class extends or implements. This is the only optional
168- /// field.
169- final String superClass;
170-
171- AssetId get assetId => new AssetId (package, packagePath);
172- String get package => path.split (import.replaceFirst ('package:' , '' )).first;
173- String get packagePath => path.joinAll (['lib' ]
174- ..addAll (path.split (import.replaceFirst ('package:' , '' ))..removeAt (0 )));
175-
176- const AnnotationDescriptor (this .name, this .import, this .superClass);
97+ _implementsWithWarning (firstMatch (annotation.name, assetId), VIEWS );
17798}
0 commit comments