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