OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 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. |
| 4 |
| 5 /// An implementation of dart:mirrors that checks if everything accessed through |
| 6 /// reflection has been declared via the @MirrorUsed API. |
| 7 /// |
| 8 /// Usage: |
| 9 /// |
| 10 /// * Import `package:checked_mirrors/checked_mirrors.dart` instead of |
| 11 /// `dart:mirrors`. |
| 12 /// |
| 13 /// * Move the @[MirrorsUsed] annotations to a top-level const symbol named |
| 14 /// `checked_mirrors_workaround_for_10360`. This step is needed temporarily |
| 15 /// until issue [10360](http://dartbug.com/10360) is fixed. |
| 16 /// |
| 17 /// * Add a transformer section to your pubspec to include a phase that will |
| 18 /// remove the checks from this library when you deploy your application: |
| 19 /// |
| 20 /// transformers: |
| 21 /// - checked_mirrors |
| 22 |
| 23 library checked_mirrors; |
| 24 |
| 25 // Except for top-level APIs, expose everything else. |
| 26 export "dart:mirrors" hide currentMirrorSystem, reflect, reflectClass, |
| 27 reflectType, MirrorSystem; |
| 28 |
| 29 import 'dart:async'; |
| 30 import "dart:collection" show ListMixin; |
| 31 import 'dart:isolate'; |
| 32 import "dart:mirrors" as mirrors; |
| 33 import "dart:mirrors" hide currentMirrorSystem, reflect, reflectClass, |
| 34 reflectType, MirrorSystem; |
| 35 |
| 36 import 'src/checker.dart'; |
| 37 |
| 38 /// An expando to store existing wrappers, since some APIs are expected to |
| 39 /// return the same instance (at least according to the mirror tests). |
| 40 Expando _wrappers = new Expando(); |
| 41 |
| 42 /// Returns a wrapper for [original], an object from the base mirror system. We |
| 43 /// internally try to store the wrapper in an expando to ensure we use the same |
| 44 /// wrapper whenever it's possible. |
| 45 _wrap(original) { |
| 46 if (original == null) return null; |
| 47 var value = _wrappers[original]; |
| 48 if (value != null) return value; |
| 49 value = _createWrapper(original); |
| 50 _wrappers[original] = value; |
| 51 return value; |
| 52 } |
| 53 |
| 54 /// Creates a wrapper for [original] assuming one doesn't exist already. The |
| 55 /// wrapper will be a corresponding object in this library, for instance |
| 56 /// _ClosureMirror for ClosureMirror. This function also wraps maps and lists |
| 57 /// whose values are mirror system objects. |
| 58 _createWrapper(original) { |
| 59 // Note: the order below is important to guarnatee we create the most precise |
| 60 // wrapper for a given type (e.g. FunctionTypeMirror is a ClassMirror too). |
| 61 |
| 62 if (original is Map) return new _MapWrapper(original); |
| 63 if (original is List) return new _ListWrapper(original); |
| 64 if (original is FunctionTypeMirror) return new _FunctionTypeMirror(original); |
| 65 if (original is ClassMirror) return new _ClassMirror(original); |
| 66 |
| 67 if (original is ClosureMirror) return new _ClosureMirror(original); |
| 68 if (original is InstanceMirror) return new _InstanceMirror(original); |
| 69 if (original is LibraryMirror) return new _LibraryMirror(original); |
| 70 if (original is ObjectMirror) return new _ObjectMirror(original); |
| 71 |
| 72 if (original is ParameterMirror) return new _ParameterMirror(original); |
| 73 if (original is VariableMirror) return new _VariableMirror(original); |
| 74 |
| 75 if (original is TypeVariableMirror) return new _TypeVariableMirror(original); |
| 76 if (original is IsolateMirror) return new _IsolateMirror(original); |
| 77 if (original is MethodMirror) return new _MethodMirror(original); |
| 78 if (original is mirrors.MirrorSystem) return new MirrorSystem(original); |
| 79 if (original is TypedefMirror) return new _TypedefMirror(original); |
| 80 |
| 81 if (original is TypeMirror) return new _TypeMirror(original); |
| 82 if (original is DeclarationMirror) return new _DeclarationMirror(original); |
| 83 throw "Unknown mirror type: ${original.runtimeType}"; |
| 84 } |
| 85 |
| 86 MirrorSystem _current = _wrap(mirrors.currentMirrorSystem()); |
| 87 MirrorSystem currentMirrorSystem() => _current; |
| 88 InstanceMirror reflect(Object reflectee) => _wrap(mirrors.reflect(reflectee)); |
| 89 ClassMirror reflectClass(Type key) => _wrap(mirrors.reflectClass(key)); |
| 90 TypeMirror reflectType(Type key) => _wrap(mirrors.reflectType(key)); |
| 91 |
| 92 class _Mirror { |
| 93 dynamic _original; |
| 94 _Mirror(this._original); |
| 95 |
| 96 toString() => _original.toString(); |
| 97 } |
| 98 |
| 99 // We use the original name for this class because it exposes static methods |
| 100 // that could be used externally. |
| 101 // TODO(sigmund): technically the top-level symbols exposed here could be used |
| 102 // too, like #LibraryMirror. Maybe we need to override the names of all these |
| 103 // symbols? |
| 104 class MirrorSystem extends _Mirror with mirrors.MirrorSystem { |
| 105 MirrorSystem(original) : super(original); |
| 106 |
| 107 Map<Uri, LibraryMirror> get libraries => _wrap(_original.libraries); |
| 108 |
| 109 IsolateMirror get isolate => _wrap(_original.isolate); |
| 110 |
| 111 TypeMirror get dynamicType => _wrap(_original.dynamicType); |
| 112 |
| 113 TypeMirror get voidType => _wrap(_original.voidType); |
| 114 |
| 115 static String getName(Symbol symbol) { |
| 116 checker.useSymbol(symbol); |
| 117 return mirrors.MirrorSystem.getName(symbol); |
| 118 } |
| 119 |
| 120 static Symbol getSymbol(String name, [LibraryMirror library]) { |
| 121 if (library == null) { |
| 122 var symbol = mirrors.MirrorSystem.getSymbol(name); |
| 123 checker.useSymbol(symbol); |
| 124 return symbol; |
| 125 } |
| 126 if (library is! _LibraryMirror) { |
| 127 throw new ArgumentError("$library is not a LibraryMirror"); |
| 128 } |
| 129 _LibraryMirror lib = library; // type-check |
| 130 var symbol = mirrors.MirrorSystem.getSymbol(name, lib._original); |
| 131 checker.useSymbol(symbol); |
| 132 return symbol; |
| 133 } |
| 134 } |
| 135 |
| 136 class _IsolateMirror extends _Mirror implements mirrors.IsolateMirror { |
| 137 _IsolateMirror(original) : super(original); |
| 138 |
| 139 String get debugName => _original.debugName; |
| 140 bool get isCurrent => _original.isCurrent; |
| 141 LibraryMirror get rootLibrary => _wrap(_original.rootLibrary); |
| 142 bool operator == (other) { |
| 143 if (other == null || other is! _IsolateMirror) return false; |
| 144 return _original == other._original; |
| 145 } |
| 146 int get hashCode => _original.hashCode; |
| 147 } |
| 148 |
| 149 abstract class _DeclarationMirrorMixin implements mirrors.DeclarationMirror { |
| 150 get _original; |
| 151 Symbol get simpleName => _original.simpleName; |
| 152 Symbol get qualifiedName => _original.qualifiedName; |
| 153 DeclarationMirror get owner => _wrap(_original.owner); |
| 154 bool get isPrivate => _original.isPrivate; |
| 155 bool get isTopLevel => _original.isTopLevel; |
| 156 SourceLocation get location => _original.location; |
| 157 List<InstanceMirror> get metadata => _wrap(_original.metadata); |
| 158 } |
| 159 |
| 160 class _DeclarationMirror extends _Mirror with _DeclarationMirrorMixin |
| 161 implements mirrors.DeclarationMirror { |
| 162 _DeclarationMirror(original) : super(original); |
| 163 get _original => super._original; // to get rid of static warnings |
| 164 |
| 165 } |
| 166 |
| 167 abstract class _ObjectMirrorMixin implements mirrors.ObjectMirror { |
| 168 get _original; |
| 169 |
| 170 InstanceMirror invoke(Symbol memberName, |
| 171 List positionalArguments, |
| 172 [Map<Symbol,dynamic> namedArguments]) => |
| 173 _wrap(_original.invoke(memberName, positionalArguments, namedArguments)); |
| 174 |
| 175 InstanceMirror getField(Symbol fieldName) { |
| 176 checker.access(_original, fieldName); |
| 177 return _wrap(_original.getField(fieldName)); |
| 178 } |
| 179 |
| 180 InstanceMirror setField(Symbol fieldName, Object value) { |
| 181 checker.access(_original, fieldName); |
| 182 return _wrap(_original.setField(fieldName, value)); |
| 183 } |
| 184 } |
| 185 |
| 186 class _ObjectMirror extends _Mirror with _ObjectMirrorMixin |
| 187 implements mirrors.ObjectMirror { |
| 188 _ObjectMirror(original) : super(original); |
| 189 get _original => super._original; // to get rid of static warnings |
| 190 } |
| 191 |
| 192 class _InstanceMirror extends _ObjectMirror implements mirrors.InstanceMirror { |
| 193 _InstanceMirror(original) : super(original); |
| 194 |
| 195 ClassMirror get type => _wrap(_original.type); |
| 196 bool get hasReflectee => _original.hasReflectee; |
| 197 get reflectee => _original.reflectee; |
| 198 bool operator == (other) { |
| 199 if (other == null || other is! _InstanceMirror) return false; |
| 200 return _original == other._original; |
| 201 } |
| 202 int get hashCode => _original.hashCode; |
| 203 |
| 204 delegate(Invocation invocation) => _original.delegate(invocation); |
| 205 Function operator [](Symbol name) { |
| 206 print('warning: this cannot be debugged: InstanceMirror.operator[]'); |
| 207 // TODO(sigmund): we'd like to wrap the result inside the function, but we |
| 208 // don't have a way to dynamically take arguments. |
| 209 return _original[name]; |
| 210 } |
| 211 } |
| 212 |
| 213 class _ClosureMirror extends _InstanceMirror implements mirrors.ClosureMirror { |
| 214 _ClosureMirror(original) : super(original); |
| 215 |
| 216 MethodMirror get function => _wrap(_original.function); |
| 217 InstanceMirror apply(List positionalArguments, |
| 218 [Map<Symbol, dynamic> namedArguments]) => |
| 219 _wrap(_original.apply(positionalArguments, namedArguments)); |
| 220 InstanceMirror findInContext(Symbol name, {ifAbsent: null}) => |
| 221 _wrap(_original.findInContext(name, ifAbsent: ifAbsent)); |
| 222 } |
| 223 |
| 224 class _LibraryMirror extends _DeclarationMirror with _ObjectMirrorMixin |
| 225 implements mirrors.LibraryMirror { |
| 226 _LibraryMirror(original) : super(original); |
| 227 get _original => super._original; // to get rid of static warnings |
| 228 |
| 229 Uri get uri => _original.uri; |
| 230 Map<Symbol, DeclarationMirror> get declarations => |
| 231 _wrap(_original.declarations); |
| 232 |
| 233 Map<Symbol, MethodMirror> get topLevelMembers => |
| 234 _wrap(_original.topLevelMembers); |
| 235 |
| 236 bool operator == (other) { |
| 237 if (other == null || other is! _LibraryMirror) return false; |
| 238 return _original == other._original; |
| 239 } |
| 240 int get hashCode => _original.hashCode; |
| 241 |
| 242 Function operator [](Symbol name) { |
| 243 print('warning: this cannot be debugged: LibraryMirror.operator[]'); |
| 244 // TODO(sigmund): we'd like to wrap the result inside the function, but we |
| 245 // don't have a way to dynamically take arguments. |
| 246 return _original[name]; |
| 247 } |
| 248 } |
| 249 |
| 250 class _TypeMirror extends _DeclarationMirror implements mirrors.TypeMirror { |
| 251 _TypeMirror(original) : super(original); |
| 252 |
| 253 List<TypeVariableMirror> get typeVariables => |
| 254 _wrap(_original.typeVariables); |
| 255 List<TypeMirror> get typeArguments => |
| 256 _wrap(_original.typeArguments); |
| 257 bool get isOriginalDeclaration => _original.isOriginalDeclaration; |
| 258 TypeMirror get originalDeclaration => |
| 259 _wrap(_original.originalDeclaration); |
| 260 |
| 261 bool operator == (other) { |
| 262 if (other == null || other is! _TypeMirror) return false; |
| 263 return _original == other._original; |
| 264 } |
| 265 int get hashCode => _original.hashCode; |
| 266 } |
| 267 |
| 268 class _ClassMirror extends _TypeMirror with _ObjectMirrorMixin |
| 269 implements ClassMirror { |
| 270 _ClassMirror(original) : super(original); |
| 271 |
| 272 bool get hasReflectedType => _original.hasReflectedType; |
| 273 Type get reflectedType => _original.reflectedType; |
| 274 ClassMirror get superclass => _wrap(_original.superclass); |
| 275 List<ClassMirror> get superinterfaces => |
| 276 _wrap(_original.superinterfaces); |
| 277 |
| 278 Map<Symbol, DeclarationMirror> get declarations => |
| 279 _wrap(_original.declarations); |
| 280 Map<Symbol, MethodMirror> get instanceMembers => |
| 281 _wrap(_original.instanceMembers); |
| 282 Map<Symbol, MethodMirror> get staticMembers => |
| 283 _wrap(_original.staticMembers); |
| 284 ClassMirror get mixin => _wrap(_original.mixin); |
| 285 InstanceMirror newInstance(Symbol constructorName, |
| 286 List positionalArguments, |
| 287 [Map<Symbol,dynamic> namedArguments]) => |
| 288 _wrap(_original.newInstance(constructorName, |
| 289 positionalArguments, namedArguments)); |
| 290 |
| 291 bool operator == (other) { |
| 292 if (other == null || other is! _ClassMirror) return false; |
| 293 return _original == other._original; |
| 294 } |
| 295 int get hashCode => _original.hashCode; |
| 296 |
| 297 Function operator [](Symbol name) { |
| 298 print('warning: this cannot be debugged: ClassMirror.operator[]'); |
| 299 // TODO(sigmund): we'd like to wrap the result inside the function, but we |
| 300 // don't have a way to dynamically take arguments. |
| 301 return _original[name]; |
| 302 } |
| 303 } |
| 304 |
| 305 class _FunctionTypeMirror extends _ClassMirror implements FunctionTypeMirror { |
| 306 _FunctionTypeMirror(original) : super(original); |
| 307 get _original => super._original; // to get rid of static warnings |
| 308 |
| 309 TypeMirror get returnType => _wrap(_original.returnType); |
| 310 List<ParameterMirror> get parameters => |
| 311 _wrap(_original.parameters); |
| 312 MethodMirror get callMethod => _wrap(_original.callMethod); |
| 313 } |
| 314 |
| 315 class _TypeVariableMirror extends _TypeMirror implements TypeVariableMirror { |
| 316 _TypeVariableMirror(original) : super(original); |
| 317 |
| 318 TypeMirror get upperBound => _wrap(_original.upperBound); |
| 319 bool get isStatic => _original.isStatic; |
| 320 bool operator == (other) { |
| 321 if (other == null || other is! _TypeVariableMirror) return false; |
| 322 return _original == other._original; |
| 323 } |
| 324 int get hashCode => _original.hashCode; |
| 325 } |
| 326 |
| 327 class _TypedefMirror extends _TypeMirror implements TypedefMirror { |
| 328 _TypedefMirror(original) : super(original); |
| 329 |
| 330 FunctionTypeMirror get referent => _wrap(_original.referent); |
| 331 } |
| 332 |
| 333 class _MethodMirror extends _DeclarationMirror implements MethodMirror { |
| 334 _MethodMirror(original) : super(original); |
| 335 |
| 336 TypeMirror get returnType => _wrap(_original.returnType); |
| 337 String get source => _original.source; |
| 338 List<ParameterMirror> get parameters => |
| 339 _wrap(_original.parameters); |
| 340 bool get isStatic => _original.isStatic; |
| 341 bool get isAbstract => _original.isAbstract; |
| 342 bool get isSynthetic => _original.isSynthetic; |
| 343 bool get isRegularMethod => _original.isRegularMethod; |
| 344 bool get isOperator => _original.isOperator; |
| 345 bool get isGetter => _original.isGetter; |
| 346 bool get isSetter => _original.isSetter; |
| 347 bool get isConstructor => _original.isConstructor; |
| 348 Symbol get constructorName => _original.constructorName; |
| 349 bool get isConstConstructor => _original.isConstConstructor; |
| 350 bool get isGenerativeConstructor => _original.isGenerativeConstructor; |
| 351 bool get isRedirectingConstructor => _original.isRedirectingConstructor; |
| 352 bool get isFactoryConstructor => _original.isFactoryConstructor; |
| 353 bool operator == (other) { |
| 354 if (other == null || other is! _MethodMirror) return false; |
| 355 return _original == other._original; |
| 356 } |
| 357 int get hashCode => _original.hashCode; |
| 358 } |
| 359 |
| 360 class _VariableMirror extends _DeclarationMirror implements VariableMirror { |
| 361 _VariableMirror(original) : super(original); |
| 362 TypeMirror get type => _wrap(_original.type); |
| 363 bool get isStatic => _original.isStatic; |
| 364 bool get isFinal => _original.isFinal; |
| 365 bool get isConst => _original.isConst; |
| 366 bool operator == (other) { |
| 367 if (other == null || other is! _VariableMirror) return false; |
| 368 return _original == other._original; |
| 369 } |
| 370 int get hashCode => _original.hashCode; |
| 371 } |
| 372 |
| 373 class _ParameterMirror extends _VariableMirror implements ParameterMirror { |
| 374 _ParameterMirror(original) : super(original); |
| 375 TypeMirror get type => _wrap(_original.type); |
| 376 bool get isOptional => _original.isOptional; |
| 377 bool get isNamed => _original.isNamed; |
| 378 bool get hasDefaultValue => _original.hasDefaultValue; |
| 379 InstanceMirror get defaultValue => _original.defaultValue; |
| 380 } |
| 381 |
| 382 /// Wraps a map that contains mirror values |
| 383 class _MapWrapper<K, V extends _Mirror> implements Map<K, V> { |
| 384 Map<K, V> _original; |
| 385 _MapWrapper(Map<K, V> original) : _original = original; |
| 386 |
| 387 V operator [](Object key) => _wrap(_original[key]); |
| 388 |
| 389 void operator []=(K key, V value) { |
| 390 _original[key] = value._original; |
| 391 } |
| 392 |
| 393 void addAll(Map<K, V> other) { |
| 394 other.forEach((key, value) { _original[key] = value; }); |
| 395 } |
| 396 |
| 397 bool containsValue(Object value) => |
| 398 _original.containsValue(value != null && (value as dynamic)._original); |
| 399 |
| 400 V putIfAbsent(K key, V ifAbsent()) => |
| 401 _original.putIfAbsent(key, () => ifAbsent()._original); |
| 402 |
| 403 // Every other method is just delegated to the original |
| 404 |
| 405 Iterable<V> get values => _original.values.map(_wrap); |
| 406 |
| 407 void clear() => _original.clear(); |
| 408 |
| 409 bool containsKey(Object key) => _original.containsKey(key); |
| 410 |
| 411 void forEach(void f(K key, V value)) { |
| 412 _original.forEach(f); |
| 413 } |
| 414 |
| 415 bool get isEmpty => _original.isEmpty; |
| 416 |
| 417 bool get isNotEmpty => _original.isNotEmpty; |
| 418 |
| 419 Iterable<K> get keys => _original.keys; |
| 420 |
| 421 int get length => _original.length; |
| 422 |
| 423 V remove(Object key) => _original.remove(key); |
| 424 } |
| 425 |
| 426 /// Wraps a list of mirror values |
| 427 class _ListWrapper<E extends _Mirror> extends Object with ListMixin<E> { |
| 428 List _original; |
| 429 |
| 430 _ListWrapper(this._original); |
| 431 |
| 432 E operator [](int index) => _wrap(_original[index]); |
| 433 |
| 434 void operator []=(int index, E value) { |
| 435 _original[index] = value._original; |
| 436 } |
| 437 |
| 438 int get length => _original.length; |
| 439 |
| 440 void set length(int newLength) { |
| 441 _original.length = newLength; |
| 442 } |
| 443 } |
OLD | NEW |