OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 library initialize.mirror_loader; | 4 library initialize.mirror_loader; |
5 | 5 |
6 import 'dart:collection' show Queue; | 6 import 'dart:collection' show Queue; |
7 import 'dart:mirrors'; | 7 import 'dart:mirrors'; |
8 import 'package:path/path.dart' as path; | 8 import 'package:path/path.dart' as path; |
9 import 'package:initialize/initialize.dart'; | 9 import 'package:initialize/initialize.dart'; |
10 | 10 |
11 final _root = currentMirrorSystem().isolate.rootLibrary; | 11 final LibraryMirror _root = currentMirrorSystem().isolate.rootLibrary; |
12 final _libs = currentMirrorSystem().libraries; | 12 final Map<Uri, LibraryMirror> _libs = currentMirrorSystem().libraries; |
13 | 13 |
14 Queue<Function> loadInitializers( | 14 Queue<Function> loadInitializers( |
15 {List<Type> typeFilter, InitializerFilter customFilter, Uri from}) { | 15 {List<Type> typeFilter, InitializerFilter customFilter, Uri from}) { |
16 return new InitializationCrawler(typeFilter, customFilter, from: from).run(); | 16 return new InitializationCrawler(typeFilter, customFilter, from: from).run(); |
17 } | 17 } |
18 | 18 |
19 // Crawls a library and all its dependencies for `Initializer` annotations using | 19 // Crawls a library and all its dependencies for `Initializer` annotations using |
20 // mirrors | 20 // mirrors |
21 class InitializationCrawler { | 21 class InitializationCrawler { |
22 // Set of all visited annotations, keys are the declarations that were | 22 // Set of all visited annotations, keys are the declarations that were |
23 // annotated, values are the annotations that have been processed. | 23 // annotated, values are the annotations that have been processed. |
24 static final _annotationsFound = | 24 static final _annotationsFound = |
25 new Map<DeclarationMirror, Set<InstanceMirror>>(); | 25 new Map<DeclarationMirror, Set<InstanceMirror>>(); |
26 | 26 |
27 // If non-null, then only these annotations should be processed. | 27 // If non-null, then only these annotations should be processed. |
28 final List<Type> typeFilter; | 28 final List<Type> typeFilter; |
29 | 29 |
30 // If non-null, then only annotations which return true when passed to this | 30 // If non-null, then only annotations which return true when passed to this |
31 // function will be processed. | 31 // function will be processed. |
32 final InitializerFilter customFilter; | 32 final InitializerFilter customFilter; |
33 | 33 |
34 /// The library to start crawling from. | 34 /// The library to start crawling from. |
35 final LibraryMirror _rootLibrary; | 35 final LibraryMirror _rootLibrary; |
36 | 36 |
37 /// Note: The [from] argument is only supported in the mirror_loader.dart. It | 37 /// Note: The [from] argument is only supported in the mirror_loader.dart. It |
38 /// is not supported statically. | 38 /// is not supported statically. |
39 InitializationCrawler(this.typeFilter, this.customFilter, {Uri from}) | 39 InitializationCrawler(this.typeFilter, this.customFilter, {Uri from}) |
40 : _rootLibrary = from == null | 40 : _rootLibrary = from == null ? _root : _libs[from] { |
41 ? _root | |
42 : _libs[from] { | |
43 if (_rootLibrary == null) throw 'Unable to find library at $from.'; | 41 if (_rootLibrary == null) throw 'Unable to find library at $from.'; |
44 } | 42 } |
45 | 43 |
46 // The primary function in this class, invoke it to crawl and collect all the | 44 // The primary function in this class, invoke it to crawl and collect all the |
47 // annotations into a queue of init functions. | 45 // annotations into a queue of init functions. |
48 Queue<Function> run() { | 46 Queue<Function> run() { |
49 var librariesSeen = new Set<LibraryMirror>(); | 47 var librariesSeen = new Set<LibraryMirror>(); |
50 var queue = new Queue<Function>(); | 48 var queue = new Queue<Function>(); |
51 | 49 |
52 _readLibraryDeclarations(_rootLibrary, librariesSeen, queue); | 50 _readLibraryDeclarations(_rootLibrary, librariesSeen, queue); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 } | 115 } |
118 } | 116 } |
119 } | 117 } |
120 | 118 |
121 return queue; | 119 return queue; |
122 } | 120 } |
123 | 121 |
124 Iterable<DeclarationMirror> _sortedDeclarationsWithMetadata( | 122 Iterable<DeclarationMirror> _sortedDeclarationsWithMetadata( |
125 LibraryMirror lib) { | 123 LibraryMirror lib) { |
126 return new List() | 124 return new List() |
127 ..addAll(_sortDeclarations(lib, lib.declarations.values | 125 ..addAll(_sortDeclarations( |
128 .where((d) => d is MethodMirror && d.metadata.isNotEmpty))) | 126 lib, |
129 ..addAll(_sortDeclarations(lib, lib.declarations.values | 127 lib.declarations.values |
130 .where((d) => d is ClassMirror && d.metadata.isNotEmpty))); | 128 .where((d) => d is MethodMirror && d.metadata.isNotEmpty))) |
| 129 ..addAll(_sortDeclarations( |
| 130 lib, |
| 131 lib.declarations.values |
| 132 .where((d) => d is ClassMirror && d.metadata.isNotEmpty))); |
131 } | 133 } |
132 | 134 |
133 List<DeclarationMirror> _sortDeclarations( | 135 List<DeclarationMirror> _sortDeclarations( |
134 LibraryMirror sourceLib, Iterable<DeclarationMirror> declarations) { | 136 LibraryMirror sourceLib, Iterable<DeclarationMirror> declarations) { |
135 var declarationList = declarations.toList(); | 137 var declarationList = declarations.toList(); |
136 declarationList.sort((DeclarationMirror a, DeclarationMirror b) { | 138 declarationList.sort((DeclarationMirror a, DeclarationMirror b) { |
137 // If in the same file, compare by line. | 139 // If in the same file, compare by line. |
138 var aSourceUri = a.location.sourceUri; | 140 var aSourceUri = a.location.sourceUri; |
139 var bSourceUri = b.location.sourceUri; | 141 var bSourceUri = b.location.sourceUri; |
140 if (aSourceUri == bSourceUri) { | 142 if (aSourceUri == bSourceUri) { |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 | 197 |
196 var annotatedValue; | 198 var annotatedValue; |
197 if (declaration is ClassMirror) { | 199 if (declaration is ClassMirror) { |
198 annotatedValue = declaration.reflectedType; | 200 annotatedValue = declaration.reflectedType; |
199 } else if (declaration is MethodMirror) { | 201 } else if (declaration is MethodMirror) { |
200 if (declaration.owner is! LibraryMirror) { | 202 if (declaration.owner is! LibraryMirror) { |
201 // TODO(jakemac): Support static class methods. | 203 // TODO(jakemac): Support static class methods. |
202 throw _TOP_LEVEL_FUNCTIONS_ONLY; | 204 throw _TOP_LEVEL_FUNCTIONS_ONLY; |
203 } | 205 } |
204 annotatedValue = (declaration.owner as ObjectMirror) | 206 annotatedValue = (declaration.owner as ObjectMirror) |
205 .getField(declaration.simpleName).reflectee; | 207 .getField(declaration.simpleName) |
| 208 .reflectee; |
206 } else if (declaration is LibraryMirror) { | 209 } else if (declaration is LibraryMirror) { |
207 var package; | 210 var package; |
208 var filePath; | 211 var filePath; |
209 Uri uri = declaration.uri; | 212 Uri uri = declaration.uri; |
210 // Convert to a package style uri if possible. | 213 // Convert to a package style uri if possible. |
211 if (_isHttpStylePackageUrl(uri)) { | 214 if (_isHttpStylePackageUrl(uri)) { |
212 uri = _packageUriFor(uri); | 215 uri = _packageUriFor(uri); |
213 } | 216 } |
214 if (uri.scheme == 'file' || uri.scheme.startsWith('http')) { | 217 if (uri.scheme == 'file' || uri.scheme.startsWith('http')) { |
215 filePath = path.url.relative(uri.path, | 218 filePath = path.url.relative(uri.path, |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
248 return true; | 251 return true; |
249 } | 252 } |
250 } | 253 } |
251 | 254 |
252 final _TOP_LEVEL_FUNCTIONS_ONLY = new UnsupportedError( | 255 final _TOP_LEVEL_FUNCTIONS_ONLY = new UnsupportedError( |
253 'Only top level methods are supported for initializers'); | 256 'Only top level methods are supported for initializers'); |
254 | 257 |
255 final _UNSUPPORTED_DECLARATION = new UnsupportedError( | 258 final _UNSUPPORTED_DECLARATION = new UnsupportedError( |
256 'Initializers are only supported on libraries, classes, and top level ' | 259 'Initializers are only supported on libraries, classes, and top level ' |
257 'methods'); | 260 'methods'); |
OLD | NEW |