Chromium Code Reviews| 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 |