| 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 |