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 /// Returns `true` if [cls] is declared in a private dart library. | 225 /// Returns `true` if [cls] is declared in a private dart library. |
176 bool isFromPrivateDartLibrary(ClassMirror cls) { | 226 bool isFromPrivateDartLibrary(ClassMirror cls) { |
177 if (isMixinApplication(cls)) cls = cls.mixin; | 227 if (isMixinApplication(cls)) cls = cls.mixin; |
178 var uri = cls.library.uri; | 228 var uri = getLibrary(cls).uri; |
179 return uri.scheme == 'dart' && uri.path.startsWith('_'); | 229 return uri.scheme == 'dart' && uri.path.startsWith('_'); |
180 } | 230 } |
181 | 231 |
182 /// Returns `true` if [mirror] reflects a mixin application. | 232 /// Returns `true` if [mirror] reflects a mixin application. |
183 bool isMixinApplication(Mirror mirror) { | 233 bool isMixinApplication(Mirror mirror) { |
184 return mirror is ClassMirror && mirror.mixin != mirror; | 234 return mirror is ClassMirror && mirror.mixin != mirror; |
185 } | 235 } |
186 | 236 |
187 /** | 237 /** |
188 * Returns the superclass of [cls] skipping unnamed mixin applications. | 238 * Returns the superclass of [cls] skipping unnamed mixin applications. |
189 * | 239 * |
190 * For instance, for all of the following definitions this method returns [:B:]. | 240 * For instance, for all of the following definitions this method returns [:B:]. |
191 * | 241 * |
192 * class A extends B {} | 242 * class A extends B {} |
193 * class A extends B with C1, C2 {} | 243 * class A extends B with C1, C2 {} |
194 * class A extends B implements D1, D2 {} | 244 * class A extends B implements D1, D2 {} |
195 * class A extends B with C1, C2 implements D1, D2 {} | 245 * class A extends B with C1, C2 implements D1, D2 {} |
196 * class A = B with C1, C2; | 246 * class A = B with C1, C2; |
197 * abstract class A = B with C1, C2 implements D1, D2; | 247 * abstract class A = B with C1, C2 implements D1, D2; |
198 */ | 248 */ |
199 ClassMirror getSuperclass(ClassMirror cls) { | 249 ClassSourceMirror getSuperclass(ClassSourceMirror cls) { |
200 ClassMirror superclass = cls.superclass; | 250 ClassSourceMirror superclass = cls.superclass; |
201 while (isMixinApplication(superclass) && superclass.isNameSynthetic) { | 251 while (isMixinApplication(superclass) && superclass.isNameSynthetic) { |
202 superclass = superclass.superclass; | 252 superclass = superclass.superclass; |
203 } | 253 } |
204 return superclass; | 254 return superclass; |
205 } | 255 } |
206 | 256 |
207 /** | 257 /** |
208 * Returns the mixins directly applied to [cls]. | 258 * Returns the mixins directly applied to [cls]. |
209 * | 259 * |
210 * For instance, for all of the following definitions this method returns | 260 * For instance, for all of the following definitions this method returns |
211 * [:C1, C2:]. | 261 * [:C1, C2:]. |
212 * | 262 * |
213 * class A extends B with C1, C2 {} | 263 * class A extends B with C1, C2 {} |
214 * class A extends B with C1, C2 implements D1, D2 {} | 264 * class A extends B with C1, C2 implements D1, D2 {} |
215 * class A = B with C1, C2; | 265 * class A = B with C1, C2; |
216 * abstract class A = B with C1, C2 implements D1, D2; | 266 * abstract class A = B with C1, C2 implements D1, D2; |
217 */ | 267 */ |
218 Iterable<ClassMirror> getAppliedMixins(ClassMirror cls) { | 268 Iterable<ClassSourceMirror> getAppliedMixins(ClassSourceMirror cls) { |
219 List<ClassMirror> mixins = <ClassMirror>[]; | 269 List<ClassSourceMirror> mixins = <ClassSourceMirror>[]; |
220 ClassMirror superclass = cls.superclass; | 270 ClassSourceMirror superclass = cls.superclass; |
221 while (isMixinApplication(superclass) && superclass.isNameSynthetic) { | 271 while (isMixinApplication(superclass) && superclass.isNameSynthetic) { |
222 mixins.add(superclass.mixin); | 272 mixins.add(superclass.mixin); |
223 superclass = superclass.superclass; | 273 superclass = superclass.superclass; |
224 } | 274 } |
225 if (mixins.length > 1) { | 275 if (mixins.length > 1) { |
226 mixins = new List<ClassMirror>.from(mixins.reversed); | 276 mixins = new List<ClassSourceMirror>.from(mixins.reversed); |
227 } | 277 } |
228 if (isMixinApplication(cls)) { | 278 if (isMixinApplication(cls)) { |
229 mixins.add(cls.mixin); | 279 mixins.add(cls.mixin); |
230 } | 280 } |
231 return mixins; | 281 return mixins; |
232 } | 282 } |
233 | 283 |
234 /** | 284 /** |
235 * Returns the superinterfaces directly and explicitly implemented by [cls]. | 285 * Returns the superinterfaces directly and explicitly implemented by [cls]. |
236 * | 286 * |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 * If [name] is of the form 'a.b.c', 'a' is looked up in the scope of | 357 * If [name] is of the form 'a.b.c', 'a' is looked up in the scope of |
308 * [declaration] and if unresolved 'a.b' is looked in the scope of | 358 * [declaration] and if unresolved 'a.b' is looked in the scope of |
309 * [declaration]. Each identifier of the remaining suffix, 'c' or 'b.c', is | 359 * [declaration]. Each identifier of the remaining suffix, 'c' or 'b.c', is |
310 * then looked up in the local scope of the previous result. | 360 * then looked up in the local scope of the previous result. |
311 * | 361 * |
312 * For instance, assumming that [:Iterable:] is imported into the scope of | 362 * For instance, assumming that [:Iterable:] is imported into the scope of |
313 * [declaration] via the prefix 'col', 'col.Iterable.E' finds the type | 363 * [declaration] via the prefix 'col', 'col.Iterable.E' finds the type |
314 * variable of [:Iterable:] and 'col.Iterable.contains.element' finds the | 364 * variable of [:Iterable:] and 'col.Iterable.contains.element' finds the |
315 * [:element:] parameter of the [:contains:] method on [:Iterable:]. | 365 * [:element:] parameter of the [:contains:] method on [:Iterable:]. |
316 */ | 366 */ |
317 DeclarationMirror lookupQualifiedInScope(DeclarationMirror declaration, | 367 DeclarationMirror lookupQualifiedInScope(DeclarationSourceMirror declaration, |
318 String name) { | 368 String name) { |
319 // TODO(11653): Support lookup of constructors using the [:new Foo:] | 369 // TODO(11653): Support lookup of constructors using the [:new Foo:] |
320 // syntax. | 370 // syntax. |
321 int offset = 1; | 371 int offset = 1; |
322 List<String> parts = name.split('.'); | 372 List<String> parts = name.split('.'); |
323 DeclarationMirror result = declaration.lookupInScope(parts[0]); | 373 DeclarationMirror result = declaration.lookupInScope(parts[0]); |
324 if (result == null && parts.length > 1) { | 374 if (result == null && parts.length > 1) { |
325 // Try lookup of `prefix.id`. | 375 // Try lookup of `prefix.id`. |
326 result = declaration.lookupInScope('${parts[0]}.${parts[1]}'); | 376 result = declaration.lookupInScope('${parts[0]}.${parts[1]}'); |
327 offset = 2; | 377 offset = 2; |
328 } | 378 } |
329 if (result == null) return null; | 379 if (result == null) return null; |
| 380 LibraryMirror library = getLibrary(result); |
330 while (result != null && offset < parts.length) { | 381 while (result != null && offset < parts.length) { |
331 result = _lookupLocal(result, parts[offset++]); | 382 result = _lookupLocal(result, symbolOf(parts[offset++], library)); |
332 } | 383 } |
333 return result; | 384 return result; |
334 } | 385 } |
335 | 386 |
336 DeclarationMirror _lookupLocal(Mirror mirror, String id) { | 387 DeclarationMirror _lookupLocal(Mirror mirror, Symbol id) { |
337 DeclarationMirror result; | 388 DeclarationMirror result; |
338 if (mirror is ContainerMirror) { | 389 if (mirror is LibraryMirror) { |
339 ContainerMirror containerMirror = mirror; | |
340 // Try member lookup. | 390 // Try member lookup. |
341 result = containerMirror.members[id]; | 391 result = mirror.declarations[id]; |
342 } | 392 } else if (mirror is ClassMirror) { |
343 if (result != null) return result; | 393 // Try member lookup. |
344 if (mirror is ClassMirror) { | 394 result = mirror.declarations[id]; |
345 ClassMirror classMirror = mirror; | 395 if (result != null) return result; |
346 // Try type variables. | 396 // Try type variables. |
347 result = classMirror.typeVariables.firstWhere( | 397 result = mirror.typeVariables.firstWhere( |
348 (TypeVariableMirror v) => v.simpleName == id, orElse: () => null); | 398 (TypeVariableMirror v) => v.simpleName == id, orElse: () => null); |
349 } else if (mirror is MethodMirror) { | 399 } else if (mirror is MethodMirror) { |
350 MethodMirror methodMirror = mirror; | 400 result = mirror.parameters.firstWhere( |
351 result = methodMirror.parameters.firstWhere( | |
352 (ParameterMirror p) => p.simpleName == id, orElse: () => null); | 401 (ParameterMirror p) => p.simpleName == id, orElse: () => null); |
353 } | 402 } |
354 return result; | 403 return result; |
355 | 404 |
356 } | 405 } |
OLD | NEW |