@@ -2,6 +2,8 @@ library angular_spec;
2
2
3
3
import '_specs.dart' ;
4
4
import 'package:angular/utils.dart' ;
5
+ import 'dart:mirrors' ;
6
+ //import 'package:angular/angular.dart' as angular;
5
7
6
8
main () {
7
9
describe ('angular.dart unittests' , () {
@@ -40,4 +42,280 @@ main() {
40
42
}).toThrow ('Unknown function type, expecting 0 to 5 args.' );
41
43
});
42
44
});
45
+
46
+
47
+
48
+ _getSymbolsFromLibrary (String libraryName) {
49
+ var names = [];
50
+ var SYMBOL_NAME = new RegExp ('"(.*)"' );
51
+ _unwrapSymbol (sym) => SYMBOL_NAME .firstMatch (sym.toString ()).group (1 );
52
+
53
+ var seen = {};
54
+
55
+
56
+
57
+ extractSymbols (LibraryMirror lib) {
58
+ lib.declarations.forEach ((symbol, _) {
59
+ names.add ([_unwrapSymbol (symbol), _unwrapSymbol (lib.qualifiedName)]);
60
+ });
61
+
62
+ lib.libraryDependencies.forEach ((LibraryDependencyMirror libDep) {
63
+ LibraryMirror target = libDep.targetLibrary;
64
+ if (! libDep.isExport) return ;
65
+ if (! seen.containsKey (target)) {
66
+ seen[target] = true ;
67
+ extractSymbols (target);
68
+ }
69
+ });
70
+ };
71
+
72
+ var lib = currentMirrorSystem ().findLibrary (new Symbol (libraryName));
73
+
74
+ extractSymbols (lib);
75
+ return names;
76
+ }
77
+
78
+ describe ('angular symbols' , () {
79
+ it ('should not export symbols that we do not know about' , () {
80
+ var names;
81
+ try { // Not impleneted in Dart VM 1.2
82
+ names = _getSymbolsFromLibrary ("angular" );
83
+ } finally {}
84
+
85
+ var ALLOWED_PREFIXS = [
86
+ "Ng" ,
87
+ "ng" ,
88
+ "Angular" ,
89
+ "_"
90
+ ];
91
+
92
+ var ALLOWED_NAMES = [
93
+ "di.FactoryFn" ,
94
+ "di.CreationStrategy" ,
95
+ "di.Injector" ,
96
+ "di.TypeFactory" ,
97
+ "di.Visibility" ,
98
+ "di.NoProviderError" ,
99
+ "di.CircularDependencyError" ,
100
+ "di.ObjectFactory" ,
101
+ "di.Module" ,
102
+ "angular.core.AnnotationMap" ,
103
+ "angular.core.LruCache" ,
104
+ "angular.core.ScopeStats" ,
105
+ "angular.core.ArrayFn" ,
106
+ "angular.core.Interpolation" ,
107
+ "angular.core.LongStackTrace" ,
108
+ "angular.core.Cache" ,
109
+ "angular.core.ExpressionVisitor" ,
110
+ "angular.core.ScopeEvent" ,
111
+ "angular.core.MapFn" ,
112
+ "angular.core.EvalFunction1" ,
113
+ "angular.core.MetadataExtractor" ,
114
+ "angular.core.ExceptionHandler" ,
115
+ "angular.core.ZoneOnTurn" ,
116
+ "angular.core.ZoneOnError" ,
117
+ "angular.core.ScopeDigestTTL" ,
118
+ "angular.core.EvalFunction0" ,
119
+ "angular.core.AnnotationsMap" ,
120
+ "angular.core.RootScope" ,
121
+ "angular.core.CacheStats" ,
122
+ "angular.core.ScopeLocals" ,
123
+ "angular.core.ScopeStreamSubscription" ,
124
+ "angular.core.Interpolate" ,
125
+ "angular.core.NOT_IMPLEMENTED" ,
126
+ "angular.core.Scope" ,
127
+ "angular.core.AttrFieldAnnotation" ,
128
+ "angular.core.UnboundedCache" ,
129
+ "angular.core.ScopeStream" ,
130
+ "angular.core.FilterMap" ,
131
+ "angular.core.AstParser" ,
132
+ "angular.watch_group.FunctionApply" ,
133
+ "angular.watch_group.WatchGroup" ,
134
+ "angular.watch_group.ContextReferenceAST" ,
135
+ "angular.watch_group.ConstantAST" ,
136
+ "angular.watch_group.Watch" ,
137
+ "angular.watch_group.ReactionFn" ,
138
+ "angular.watch_group.ChangeLog" ,
139
+ "angular.watch_group.FieldReadAST" ,
140
+ "angular.watch_group.PureFunctionAST" ,
141
+ "angular.watch_group.PrototypeMap" ,
142
+ "angular.watch_group.CollectionAST" ,
143
+ "angular.watch_group.MethodAST" ,
144
+ "angular.watch_group.AST" ,
145
+ "angular.watch_group.RootWatchGroup" ,
146
+ "angular.core.dom.AnimationResult" ,
147
+ "angular.core.dom.WalkingViewFactory" ,
148
+ "angular.core.dom.ResponseError" ,
149
+ "angular.core.dom.View" ,
150
+ "angular.core.dom.ElementBinder" ,
151
+ "angular.core.dom.NoOpAnimation" ,
152
+ "angular.core.dom.AttributeChanged" ,
153
+ "angular.core.dom.HttpBackend" ,
154
+ "angular.core.dom.HttpDefaults" ,
155
+ "angular.core.dom.TaggedElementBinder" ,
156
+ "angular.core.dom.LocationWrapper" ,
157
+ "angular.core.dom.Cookies" ,
158
+ "angular.core.dom.ElementBinderTreeRef" ,
159
+ "angular.core.dom.EventHandler" ,
160
+ "angular.core.dom.Response" ,
161
+ "angular.core.dom.HttpDefaultHeaders" ,
162
+ "angular.core.dom.Animation" ,
163
+ "angular.core.dom.ViewPort" ,
164
+ "angular.core.dom.TemplateLoader" ,
165
+ "angular.core.dom.RequestErrorInterceptor" ,
166
+ "angular.core.dom.TaggedTextBinder" ,
167
+ "angular.core.dom.Http" ,
168
+ "angular.core.dom.BoundViewFactory" ,
169
+ "angular.core.dom.ElementBinderFactory" ,
170
+ "angular.core.dom.DirectiveMap" ,
171
+ "angular.core.dom.BrowserCookies" ,
172
+ "angular.core.dom.HttpInterceptor" ,
173
+ "angular.core.dom.cloneElements" ,
174
+ "angular.core.dom.EventFunction" ,
175
+ "angular.core.dom.RequestInterceptor" ,
176
+ "angular.core.dom.DefaultTransformDataHttpInterceptor" ,
177
+ "angular.core.dom.HttpResponseConfig" ,
178
+ "angular.core.dom.ElementProbe" ,
179
+ "angular.core.dom.ApplyMapping" ,
180
+ "angular.core.dom.ViewCache" ,
181
+ "angular.core.dom.FieldMetadataExtractor" ,
182
+ "angular.core.dom.Compiler" ,
183
+ "angular.core.dom.HttpResponse" ,
184
+ "angular.core.dom.UrlRewriter" ,
185
+ "angular.core.dom.DirectiveRef" ,
186
+ "angular.core.dom.HttpInterceptors" ,
187
+ "angular.core.dom.forceNewDirectivesAndFilters" ,
188
+ "angular.core.dom.DirectiveSelectorFactory" ,
189
+ "angular.core.dom.ObserverChanged" ,
190
+ "angular.core.dom.TaggingViewFactory" ,
191
+ "angular.core.dom.NodeCursor" ,
192
+ "angular.core.dom.TemplateCache" ,
193
+ "angular.core.dom.ViewFactory" ,
194
+ "angular.core.dom.NullTreeSanitizer" ,
195
+ "angular.core.dom.NodeAttrs" ,
196
+ "angular.core.dom.ElementBinderTree" ,
197
+ "angular.core.dom.WalkingCompiler" ,
198
+ "angular.core.dom.TaggingCompiler" ,
199
+ "angular.core.dom.DirectiveSelector" ,
200
+ "angular.core.parser.BoundGetter" ,
201
+ "angular.core.parser.LocalsWrapper" ,
202
+ "angular.core.parser.Getter" ,
203
+ "angular.core.parser.Parser" ,
204
+ "angular.core.parser.ParserBackend" ,
205
+ "angular.core.parser.BoundSetter" ,
206
+ "angular.core.parser.Setter" ,
207
+ "angular.core.parser.syntax.LiteralObject" ,
208
+ "angular.core.parser.syntax.CallMember" ,
209
+ "angular.core.parser.syntax.Filter" ,
210
+ "angular.core.parser.syntax.defaultFilterMap" ,
211
+ "angular.core.parser.syntax.BoundExpression" ,
212
+ "angular.core.parser.syntax.AccessMember" ,
213
+ "angular.core.parser.syntax.Expression" ,
214
+ "angular.core.parser.syntax.AccessScope" ,
215
+ "angular.core.parser.syntax.Assign" ,
216
+ "angular.core.parser.syntax.AccessKeyed" ,
217
+ "angular.core.parser.syntax.CallScope" ,
218
+ "angular.core.parser.syntax.CallFunction" ,
219
+ "angular.core.parser.syntax.Conditional" ,
220
+ "angular.core.parser.syntax.Binary" ,
221
+ "angular.core.parser.syntax.Chain" ,
222
+ "angular.core.parser.syntax.Prefix" ,
223
+ "angular.core.parser.syntax.Literal" ,
224
+ "angular.core.parser.syntax.LiteralString" ,
225
+ "angular.core.parser.syntax.LiteralArray" ,
226
+ "angular.core.parser.syntax.LiteralPrimitive" ,
227
+ "angular.core.parser.syntax.Visitor" ,
228
+ "angular.core.parser.dynamic_parser.DynamicExpression" ,
229
+ "angular.core.parser.dynamic_parser.ClosureMap" ,
230
+ "angular.core.parser.dynamic_parser.DynamicParser" ,
231
+ "angular.core.parser.dynamic_parser.DynamicParserBackend" ,
232
+ "angular.core.parser.static_parser.StaticParserFunctions" ,
233
+ "angular.core.parser.static_parser.StaticExpression" ,
234
+ "angular.core.parser.static_parser.StaticParser" ,
235
+ "angular.core.parser.lexer.Scanner" ,
236
+ "angular.core.parser.lexer.OPERATORS" ,
237
+ "angular.core.parser.lexer.NumberToken" ,
238
+ "angular.core.parser.lexer.Token" ,
239
+ "angular.core.parser.lexer.IdentifierToken" ,
240
+ "angular.core.parser.lexer.StringToken" ,
241
+ "angular.core.parser.lexer.CharacterToken" ,
242
+ "angular.core.parser.lexer.Lexer" ,
243
+ "angular.core.parser.lexer.KEYWORDS" ,
244
+ "angular.core.parser.lexer.OperatorToken" ,
245
+ "angular.directive.ItemEval" ,
246
+ "angular.directive.OptionValueDirective" ,
247
+ "angular.directive.InputSelectDirective" ,
248
+ "angular.directive.InputTextLikeDirective" ,
249
+ "angular.directive.InputNumberLikeDirective" ,
250
+ "angular.directive.ContentEditableDirective" ,
251
+ "angular.directive.InputCheckboxDirective" ,
252
+ "angular.directive.InputRadioDirective" ,
253
+ "angular.filter.JsonFilter" ,
254
+ "angular.filter.Equals" ,
255
+ "angular.filter.Mapper" ,
256
+ "angular.filter.FilterFilter" ,
257
+ "angular.filter.NumberFilter" ,
258
+ "angular.filter.DateFilter" ,
259
+ "angular.filter.LowercaseFilter" ,
260
+ "angular.filter.UppercaseFilter" ,
261
+ "angular.filter.OrderByFilter" ,
262
+ "angular.filter.CurrencyFilter" ,
263
+ "angular.filter.LimitToFilter" ,
264
+ "angular.filter.Predicate" ,
265
+ "angular.routing.RouteInitializerFn" ,
266
+ "angular.routing.RouteProvider" ,
267
+ "angular.routing.RouteInitializer" ,
268
+ "angular.routing.RouteViewFactory" ,
269
+ "route.client.RouteHandle" ,
270
+ "route.client.RouteEnterEvent" ,
271
+ "route.client.RouteStartEvent" ,
272
+ "route.client.Router" ,
273
+ "route.client.RouteEvent" ,
274
+ "route.client.childRoute" ,
275
+ "route.client.RouteLeaveEventHandler" ,
276
+ "route.client.Route" ,
277
+ "route.client.RouteLeaveEvent" ,
278
+ "route.client.RoutePreEnterEventHandler" ,
279
+ "route.client.RoutePreEnterEvent" ,
280
+ "route.client.Routable" ,
281
+ "route.client.RouteEnterEventHandler" ,
282
+ "url_matcher.UrlMatcher" ,
283
+ "url_matcher.UrlMatch" ,
284
+ "dirty_checking_change_detector.FieldGetter" ,
285
+ "dirty_checking_change_detector.DirtyCheckingChangeDetector" ,
286
+ "dirty_checking_change_detector.DirtyCheckingRecord" ,
287
+ "dirty_checking_change_detector.ItemRecord" ,
288
+ "dirty_checking_change_detector.KeyValueRecord" ,
289
+ "dirty_checking_change_detector.DuplicateMap" ,
290
+ "dirty_checking_change_detector.GetterCache" ,
291
+ "dirty_checking_change_detector.DirtyCheckingChangeDetectorGroup"
292
+ ];
293
+
294
+ var _nameMap = {};
295
+ ALLOWED_NAMES .forEach ((x) => _nameMap[x] = true );
296
+
297
+ var assertSymbolNameIsOk = (List nameInfo) {
298
+ String name = nameInfo[0 ];
299
+ String libName = nameInfo[1 ];
300
+
301
+ if (ALLOWED_PREFIXS .any ((prefix) =>
302
+ name.startsWith (prefix))) return ;
303
+
304
+ var key = "$libName .$name " ;
305
+ if (_nameMap.containsKey (key)) {
306
+ _nameMap[key] = false ;
307
+ return ;
308
+ }
309
+
310
+ throw "Symbol $key is exported thru the angular library, but it shouldn't be" ;
311
+ };
312
+
313
+ names.forEach (assertSymbolNameIsOk);
314
+
315
+ // If there are keys that no longer need to be in the ALLOWED_NAMES list, complain.
316
+ _nameMap.forEach ((k,v) {
317
+ if (v) print ("angular_spec.dart: Unused ALLOWED_NAMES key $k " );
318
+ });
319
+ });
320
+ });
43
321
}
0 commit comments