OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 | 4 |
5 library mirrors_util; | 5 library mirrors_util; |
6 | 6 |
7 import 'dart:collection' show Queue, IterableBase; | 7 import 'dart:collection' show Queue, IterableBase; |
8 | 8 |
9 // TODO(rnystrom): Use "package:" URL (#4968). | 9 import 'source_mirrors.dart'; |
10 import 'mirrors.dart'; | |
11 | 10 |
12 //------------------------------------------------------------------------------ | 11 //------------------------------------------------------------------------------ |
13 // Utility functions for using the Mirror API | 12 // Utility functions for using the Mirror API |
14 //------------------------------------------------------------------------------ | 13 //------------------------------------------------------------------------------ |
15 | 14 |
15 String nameOf(DeclarationMirror mirror) => | |
16 MirrorSystem.getName(mirror.simpleName); | |
17 | |
18 String qualifiedNameOf(DeclarationMirror mirror) => | |
19 MirrorSystem.getName(mirror.qualifiedName); | |
20 | |
21 // TODO(johnniwinther): Handle private names. | |
22 Symbol symbolOf(String name, LibraryMirror library) => new Symbol(name); | |
16 | 23 |
17 /** | 24 /** |
18 * Return the display name for [mirror]. | 25 * Return the display name for [mirror]. |
19 * | 26 * |
20 * The display name is the normal representation of the entity name. In most | 27 * The display name is the normal representation of the entity name. In most |
21 * cases the display name is the simple name, but for a setter 'foo=' the | 28 * cases the display name is the simple name, but for a setter 'foo=' the |
22 * display name is simply 'foo' and for the unary minus operator the display | 29 * display name is simply 'foo' and for the unary minus operator the display |
23 * name is 'operator -'. For 'dart:' libraries the display name is the URI and | 30 * name is 'operator -'. For 'dart:' libraries the display name is the URI and |
24 * not the library name, for instance 'dart:core' instead of 'dart.core'. | 31 * not the library name, for instance 'dart:core' instead of 'dart.core'. |
25 * | 32 * |
26 * The display name is not unique. | 33 * The display name is not unique. |
27 */ | 34 */ |
28 String displayName(DeclarationMirror mirror) { | 35 String displayName(DeclarationMirror mirror) { |
29 if (mirror is LibraryMirror) { | 36 if (mirror is LibraryMirror) { |
30 LibraryMirror library = mirror; | 37 LibraryMirror library = mirror; |
31 if (library.uri.scheme == 'dart') { | 38 if (library.uri.scheme == 'dart') { |
32 return library.uri.toString(); | 39 return library.uri.toString(); |
33 } | 40 } |
34 } else if (mirror is MethodMirror) { | 41 } else if (mirror is MethodMirror) { |
35 MethodMirror methodMirror = mirror; | 42 String simpleName = nameOf(mirror); |
36 String simpleName = methodMirror.simpleName; | 43 if (mirror.isSetter) { |
37 if (methodMirror.isSetter) { | |
38 // Remove trailing '='. | 44 // Remove trailing '='. |
39 return simpleName.substring(0, simpleName.length-1); | 45 return simpleName.substring(0, simpleName.length-1); |
40 } else if (methodMirror.isOperator) { | 46 } else if (mirror.isOperator) { |
41 return 'operator ${operatorName(methodMirror)}'; | 47 return 'operator ${operatorName(mirror)}'; |
42 } else if (methodMirror.isConstructor) { | 48 } else if (mirror.isConstructor) { |
43 String className = displayName(methodMirror.owner); | 49 String className = displayName(mirror.owner); |
44 if (simpleName == '') { | 50 if (simpleName == '') { |
45 return className; | 51 return className; |
46 } else { | 52 } else { |
47 return '$className.$simpleName'; | 53 return '$className.$simpleName'; |
48 } | 54 } |
49 } | 55 } |
50 } | 56 } |
51 return mirror.simpleName; | 57 return MirrorSystem.getName(mirror.simpleName); |
52 } | 58 } |
53 | 59 |
54 /** | 60 /** |
55 * Returns the operator name if [methodMirror] is an operator method, | 61 * Returns the operator name if [methodMirror] is an operator method, |
56 * for instance [:'<':] for [:operator <:] and [:'-':] for the unary minus | 62 * for instance [:'<':] for [:operator <:] and [:'-':] for the unary minus |
57 * operator. Return [:null:] if [methodMirror] is not an operator method. | 63 * operator. Return [:null:] if [methodMirror] is not an operator method. |
58 */ | 64 */ |
59 String operatorName(MethodMirror methodMirror) { | 65 String operatorName(MethodMirror methodMirror) { |
60 String simpleName = methodMirror.simpleName; | |
61 if (methodMirror.isOperator) { | 66 if (methodMirror.isOperator) { |
62 if (simpleName == Mirror.UNARY_MINUS) { | 67 if (methodMirror.simpleName == const Symbol('unary-')) { |
63 return '-'; | 68 return '-'; |
64 } else { | 69 } else { |
65 return simpleName; | 70 return nameOf(methodMirror); |
66 } | 71 } |
67 } | 72 } |
68 return null; | 73 return null; |
69 } | 74 } |
70 | 75 |
71 /** | 76 /** |
72 * Returns an iterable over the type declarations directly inheriting from | 77 * Returns an iterable over the type declarations directly inheriting from |
73 * the declaration of this type. | 78 * the declaration of [type] within [mirrors]. |
74 */ | 79 */ |
75 Iterable<ClassMirror> computeSubdeclarations(ClassMirror type) { | 80 Iterable<ClassMirror> computeSubdeclarations(MirrorSystem mirrors, |
81 ClassMirror type) { | |
76 type = type.originalDeclaration; | 82 type = type.originalDeclaration; |
77 var subtypes = <ClassMirror>[]; | 83 var subtypes = <ClassMirror>[]; |
78 type.mirrors.libraries.forEach((_, library) { | 84 mirrors.libraries.forEach((_, library) { |
79 for (ClassMirror otherType in library.classes.values) { | 85 library.declarations.values |
86 .where((mirror) => mirror is ClassMirror) | |
87 .forEach((ClassMirror otherType) { | |
80 var superClass = otherType.superclass; | 88 var superClass = otherType.superclass; |
81 if (superClass != null) { | 89 if (superClass != null) { |
82 superClass = superClass.originalDeclaration; | 90 superClass = superClass.originalDeclaration; |
83 if (type.library == superClass.library) { | 91 if (superClass == type) { |
84 if (superClass == type) { | 92 subtypes.add(otherType); |
85 subtypes.add(otherType); | |
86 } | |
87 } | 93 } |
88 } | 94 } |
89 final superInterfaces = otherType.superinterfaces; | 95 final superInterfaces = otherType.superinterfaces; |
90 for (ClassMirror superInterface in superInterfaces) { | 96 for (ClassMirror superInterface in superInterfaces) { |
91 superInterface = superInterface.originalDeclaration; | 97 superInterface = superInterface.originalDeclaration; |
92 if (type.library == superInterface.library) { | 98 if (superInterface == type) { |
93 if (superInterface == type) { | 99 subtypes.add(otherType); |
94 subtypes.add(otherType); | |
95 } | |
96 } | 100 } |
97 } | 101 } |
98 } | 102 }); |
99 }); | 103 }); |
100 return subtypes; | 104 return subtypes; |
101 } | 105 } |
102 | 106 |
103 LibraryMirror findLibrary(MemberMirror member) { | |
104 DeclarationMirror owner = member.owner; | |
105 if (owner is LibraryMirror) { | |
106 return owner; | |
107 } else if (owner is TypeMirror) { | |
108 TypeMirror mirror = owner; | |
109 return mirror.library; | |
110 } | |
111 throw new Exception('Unexpected owner: ${owner}'); | |
112 } | |
113 | |
114 class HierarchyIterable extends IterableBase<ClassMirror> { | 107 class HierarchyIterable extends IterableBase<ClassMirror> { |
115 final bool includeType; | 108 final bool includeType; |
116 final ClassMirror type; | 109 final ClassMirror type; |
117 | 110 |
118 HierarchyIterable(this.type, {bool includeType}) | 111 HierarchyIterable(this.type, {bool includeType}) |
119 : this.includeType = includeType; | 112 : this.includeType = includeType; |
120 | 113 |
121 Iterator<ClassMirror> get iterator => | 114 Iterator<ClassMirror> get iterator => |
122 new HierarchyIterator(type, includeType: includeType); | 115 new HierarchyIterator(type, includeType: includeType); |
123 } | 116 } |
(...skipping 15 matching lines...) Expand all Loading... | |
139 HierarchyIterator(ClassMirror type, {bool includeType}) { | 132 HierarchyIterator(ClassMirror type, {bool includeType}) { |
140 if (includeType) { | 133 if (includeType) { |
141 queue.add(type); | 134 queue.add(type); |
142 } else { | 135 } else { |
143 push(type); | 136 push(type); |
144 } | 137 } |
145 } | 138 } |
146 | 139 |
147 ClassMirror push(ClassMirror type) { | 140 ClassMirror push(ClassMirror type) { |
148 if (type.superclass != null) { | 141 if (type.superclass != null) { |
149 if (type.superclass.isObject) { | 142 if (isObject(type.superclass)) { |
150 object = type.superclass; | 143 object = type.superclass; |
151 } else { | 144 } else { |
152 queue.addFirst(type.superclass); | 145 queue.addFirst(type.superclass); |
153 } | 146 } |
154 } | 147 } |
155 queue.addAll(type.superinterfaces); | 148 queue.addAll(type.superinterfaces); |
156 return type; | 149 return type; |
157 } | 150 } |
158 | 151 |
159 ClassMirror get current => _current; | 152 ClassMirror get current => _current; |
160 | 153 |
161 bool moveNext() { | 154 bool moveNext() { |
162 _current = null; | 155 _current = null; |
163 if (queue.isEmpty) { | 156 if (queue.isEmpty) { |
164 if (object == null) return false; | 157 if (object == null) return false; |
165 _current = object; | 158 _current = object; |
166 object = null; | 159 object = null; |
167 return true; | 160 return true; |
168 } else { | 161 } else { |
169 _current = push(queue.removeFirst()); | 162 _current = push(queue.removeFirst()); |
170 return true; | 163 return true; |
171 } | 164 } |
172 } | 165 } |
173 } | 166 } |
174 | 167 |
168 LibraryMirror getLibrary(DeclarationMirror declaration) { | |
169 while (declaration != null && declaration is! LibraryMirror) { | |
170 declaration = declaration.owner; | |
171 } | |
172 return declaration; | |
173 } | |
174 | |
175 Iterable<DeclarationMirror> membersOf( | |
176 Map<Symbol, DeclarationMirror> declarations) { | |
177 return declarations.values.where( | |
178 (mirror) => mirror is MethodMirror || mirror is VariableMirror); | |
179 } | |
180 | |
181 Iterable<TypeMirror> classesOf( | |
182 Map<Symbol, DeclarationMirror> declarations) { | |
183 return declarations.values.where((mirror) => mirror is ClassMirror); | |
184 } | |
185 | |
186 Iterable<TypeMirror> typesOf( | |
187 Map<Symbol, DeclarationMirror> declarations) { | |
188 return declarations.values.where((mirror) => mirror is TypeMirror); | |
189 } | |
190 | |
191 Iterable<MethodMirror> methodsOf( | |
192 Map<Symbol, DeclarationMirror> declarations) { | |
193 return declarations.values.where( | |
194 (mirror) => mirror is MethodMirror && mirror.isRegularMethod); | |
195 } | |
196 | |
197 Iterable<MethodMirror> constructorsOf( | |
198 Map<Symbol, DeclarationMirror> declarations) { | |
199 return declarations.values.where( | |
200 (mirror) => mirror is MethodMirror && mirror.isConstructor); | |
201 } | |
202 | |
203 Iterable<MethodMirror> settersOf( | |
204 Map<Symbol, DeclarationMirror> declarations) { | |
205 return declarations.values.where( | |
206 (mirror) => mirror is MethodMirror && mirror.isSetter); | |
207 } | |
208 | |
209 Iterable<MethodMirror> gettersOf( | |
210 Map<Symbol, DeclarationMirror> declarations) { | |
211 return declarations.values.where( | |
212 (mirror) => mirror is MethodMirror && mirror.isGetter); | |
213 } | |
214 | |
215 Iterable<VariableMirror> variablesOf( | |
216 Map<Symbol, DeclarationMirror> declarations) { | |
217 return declarations.values.where((mirror) => mirror is VariableMirror); | |
218 } | |
219 | |
220 | |
221 | |
222 bool isObject(TypeMirror mirror) => | |
223 mirror is ClassMirror && mirror.superclass == null; | |
224 | |
175 bool isMixinApplication(Mirror mirror) { | 225 bool isMixinApplication(Mirror mirror) { |
176 return mirror is ClassMirror && mirror.mixin != mirror; | 226 return mirror is ClassMirror && mirror.mixin != mirror; |
177 } | 227 } |
178 | 228 |
179 /** | 229 /** |
180 * Returns the superclass of [cls] skipping unnamed mixin applications. | 230 * Returns the superclass of [cls] skipping unnamed mixin applications. |
181 * | 231 * |
182 * For instance, for all of the following definitions this method returns [:B:]. | 232 * For instance, for all of the following definitions this method returns [:B:]. |
183 * | 233 * |
184 * class A extends B {} | 234 * class A extends B {} |
185 * class A extends B with C1, C2 {} | 235 * class A extends B with C1, C2 {} |
186 * class A extends B implements D1, D2 {} | 236 * class A extends B implements D1, D2 {} |
187 * class A extends B with C1, C2 implements D1, D2 {} | 237 * class A extends B with C1, C2 implements D1, D2 {} |
188 * class A = B with C1, C2; | 238 * class A = B with C1, C2; |
189 * abstract class A = B with C1, C2 implements D1, D2; | 239 * abstract class A = B with C1, C2 implements D1, D2; |
190 */ | 240 */ |
191 ClassMirror getSuperclass(ClassMirror cls) { | 241 ClassSourceMirror getSuperclass(ClassSourceMirror cls) { |
192 ClassMirror superclass = cls.superclass; | 242 ClassSourceMirror superclass = cls.superclass; |
193 while (isMixinApplication(superclass) && superclass.isNameSynthetic) { | 243 while (isMixinApplication(superclass) && superclass.isNameSynthetic) { |
194 superclass = superclass.superclass; | 244 superclass = superclass.superclass; |
195 } | 245 } |
196 return superclass; | 246 return superclass; |
197 } | 247 } |
198 | 248 |
199 /** | 249 /** |
200 * Returns the mixins directly applied to [cls]. | 250 * Returns the mixins directly applied to [cls]. |
201 * | 251 * |
202 * For instance, for all of the following definitions this method returns | 252 * For instance, for all of the following definitions this method returns |
203 * [:C1, C2:]. | 253 * [:C1, C2:]. |
204 * | 254 * |
205 * class A extends B with C1, C2 {} | 255 * class A extends B with C1, C2 {} |
206 * class A extends B with C1, C2 implements D1, D2 {} | 256 * class A extends B with C1, C2 implements D1, D2 {} |
207 * class A = B with C1, C2; | 257 * class A = B with C1, C2; |
208 * abstract class A = B with C1, C2 implements D1, D2; | 258 * abstract class A = B with C1, C2 implements D1, D2; |
209 */ | 259 */ |
210 Iterable<ClassMirror> getAppliedMixins(ClassMirror cls) { | 260 Iterable<ClassSourceMirror> getAppliedMixins(ClassSourceMirror cls) { |
211 List<ClassMirror> mixins = <ClassMirror>[]; | 261 List<ClassSourceMirror> mixins = <ClassSourceMirror>[]; |
212 ClassMirror superclass = cls.superclass; | 262 ClassSourceMirror superclass = cls.superclass; |
213 while (isMixinApplication(superclass) && superclass.isNameSynthetic) { | 263 while (isMixinApplication(superclass) && superclass.isNameSynthetic) { |
214 mixins.add(superclass.mixin); | 264 mixins.add(superclass.mixin); |
215 superclass = superclass.superclass; | 265 superclass = superclass.superclass; |
216 } | 266 } |
217 if (mixins.length > 1) { | 267 if (mixins.length > 1) { |
218 mixins = new List<ClassMirror>.from(mixins.reversed); | 268 mixins = new List<ClassSourceMirror>.from(mixins.reversed); |
219 } | 269 } |
220 if (isMixinApplication(cls)) { | 270 if (isMixinApplication(cls)) { |
221 mixins.add(cls.mixin); | 271 mixins.add(cls.mixin); |
222 } | 272 } |
223 return mixins; | 273 return mixins; |
224 } | 274 } |
225 | 275 |
226 /** | 276 /** |
227 * Returns the superinterfaces directly and explicitly implemented by [cls]. | 277 * Returns the superinterfaces directly and explicitly implemented by [cls]. |
228 * | 278 * |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
299 * If [name] is of the form 'a.b.c', 'a' is looked up in the scope of | 349 * If [name] is of the form 'a.b.c', 'a' is looked up in the scope of |
300 * [declaration] and if unresolved 'a.b' is looked in the scope of | 350 * [declaration] and if unresolved 'a.b' is looked in the scope of |
301 * [declaration]. Each identifier of the remaining suffix, 'c' or 'b.c', is | 351 * [declaration]. Each identifier of the remaining suffix, 'c' or 'b.c', is |
302 * then looked up in the local scope of the previous result. | 352 * then looked up in the local scope of the previous result. |
303 * | 353 * |
304 * For instance, assumming that [:Iterable:] is imported into the scope of | 354 * For instance, assumming that [:Iterable:] is imported into the scope of |
305 * [declaration] via the prefix 'col', 'col.Iterable.E' finds the type | 355 * [declaration] via the prefix 'col', 'col.Iterable.E' finds the type |
306 * variable of [:Iterable:] and 'col.Iterable.contains.element' finds the | 356 * variable of [:Iterable:] and 'col.Iterable.contains.element' finds the |
307 * [:element:] parameter of the [:contains:] method on [:Iterable:]. | 357 * [:element:] parameter of the [:contains:] method on [:Iterable:]. |
308 */ | 358 */ |
309 DeclarationMirror lookupQualifiedInScope(DeclarationMirror declaration, | 359 DeclarationMirror lookupQualifiedInScope(DeclarationSourceMirror declaration, |
310 String name) { | 360 String name) { |
311 // TODO(11653): Support lookup of constructors using the [:new Foo:] | 361 // TODO(11653): Support lookup of constructors using the [:new Foo:] |
312 // syntax. | 362 // syntax. |
313 int offset = 1; | 363 int offset = 1; |
314 List<String> parts = name.split('.'); | 364 List<String> parts = name.split('.'); |
315 DeclarationMirror result = declaration.lookupInScope(parts[0]); | 365 DeclarationMirror result = declaration.lookupInScope(parts[0]); |
316 if (result == null && parts.length > 1) { | 366 if (result == null && parts.length > 1) { |
317 // Try lookup of `prefix.id`. | 367 // Try lookup of `prefix.id`. |
318 result = declaration.lookupInScope('${parts[0]}.${parts[1]}'); | 368 result = declaration.lookupInScope('${parts[0]}.${parts[1]}'); |
319 offset = 2; | 369 offset = 2; |
320 } | 370 } |
321 if (result == null) return null; | 371 if (result == null) return null; |
372 LibraryMirror library = getLibrary(result); | |
322 while (result != null && offset < parts.length) { | 373 while (result != null && offset < parts.length) { |
323 result = _lookupLocal(result, parts[offset++]); | 374 result = _lookupLocal(result, symbolOf(parts[offset++], library)); |
324 } | 375 } |
325 return result; | 376 return result; |
326 } | 377 } |
327 | 378 |
328 DeclarationMirror _lookupLocal(Mirror mirror, String id) { | 379 DeclarationMirror _lookupLocal(Mirror mirror, Symbol id) { |
329 DeclarationMirror result; | 380 DeclarationMirror result; |
330 if (mirror is ContainerMirror) { | 381 if (mirror is LibraryMirror) { |
331 ContainerMirror containerMirror = mirror; | |
332 // Try member lookup. | 382 // Try member lookup. |
333 result = containerMirror.members[id]; | 383 result = mirror.declarations[id]; |
floitsch
2014/01/28 19:21:53
You are already returning from the middle of the s
| |
334 } | 384 } else if (mirror is ClassMirror) { |
335 if (result != null) return result; | 385 // Try member lookup. |
336 if (mirror is ClassMirror) { | 386 result = mirror.declarations[id]; |
337 ClassMirror classMirror = mirror; | 387 if (result != null) return result; |
338 // Try type variables. | 388 // Try type variables. |
339 result = classMirror.typeVariables.firstWhere( | 389 result = mirror.typeVariables.firstWhere( |
340 (TypeVariableMirror v) => v.simpleName == id, orElse: () => null); | 390 (TypeVariableMirror v) => v.simpleName == id, orElse: () => null); |
341 } else if (mirror is MethodMirror) { | 391 } else if (mirror is MethodMirror) { |
342 MethodMirror methodMirror = mirror; | 392 result = mirror.parameters.firstWhere( |
343 result = methodMirror.parameters.firstWhere( | |
344 (ParameterMirror p) => p.simpleName == id, orElse: () => null); | 393 (ParameterMirror p) => p.simpleName == id, orElse: () => null); |
345 } | 394 } |
346 return result; | 395 return result; |
347 | 396 |
348 } | 397 } |
OLD | NEW |