OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 /// Implementation of the smoke services using mirrors. | 5 /// Implementation of the smoke services using mirrors. |
6 library smoke.mirrors; | 6 library smoke.mirrors; |
7 | 7 |
8 import 'dart:mirrors'; | 8 import 'dart:mirrors'; |
9 import 'package:smoke/smoke.dart'; | 9 import 'package:smoke/smoke.dart'; |
10 import 'package:logging/logging.dart'; | 10 import 'package:logging/logging.dart'; |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 | 138 |
139 List<Declaration> _query(ClassMirror cls, QueryOptions options) { | 139 List<Declaration> _query(ClassMirror cls, QueryOptions options) { |
140 var result = (!options.includeInherited || cls.superclass == _objectType) | 140 var result = (!options.includeInherited || cls.superclass == _objectType) |
141 ? [] : _query(cls.superclass, options); | 141 ? [] : _query(cls.superclass, options); |
142 for (var member in cls.declarations.values) { | 142 for (var member in cls.declarations.values) { |
143 if (member is! VariableMirror && member is! MethodMirror) continue; | 143 if (member is! VariableMirror && member is! MethodMirror) continue; |
144 if (member.isStatic || member.isPrivate) continue; | 144 if (member.isStatic || member.isPrivate) continue; |
145 var name = member.simpleName; | 145 var name = member.simpleName; |
146 bool isMethod = false; | 146 bool isMethod = false; |
147 if (member is VariableMirror) { | 147 if (member is VariableMirror) { |
148 if (!options.includeProperties) continue; | 148 if (!options.includeFields) continue; |
149 if (options.excludeFinal && member.isFinal) continue; | 149 if (options.excludeFinal && member.isFinal) continue; |
150 } | 150 } |
151 | 151 |
152 // TODO(sigmund): what if we have a setter but no getter? | 152 // TODO(sigmund): what if we have a setter but no getter? |
153 if (member is MethodMirror && member.isSetter) continue; | 153 if (member is MethodMirror && member.isSetter) continue; |
154 if (member is MethodMirror && member.isConstructor) continue; | 154 if (member is MethodMirror && member.isConstructor) continue; |
155 | 155 |
156 if (member is MethodMirror && member.isGetter) { | 156 if (member is MethodMirror && member.isGetter) { |
157 if (!options.includeProperties) continue; | 157 if (!options.includeProperties) continue; |
158 if (options.excludeFinal && !_hasSetter(cls, member)) continue; | 158 if (options.excludeFinal && !_hasSetter(cls, member)) continue; |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
241 } | 241 } |
242 | 242 |
243 class _MirrorDeclaration implements Declaration { | 243 class _MirrorDeclaration implements Declaration { |
244 final ClassMirror _cls; | 244 final ClassMirror _cls; |
245 final _original; | 245 final _original; |
246 | 246 |
247 _MirrorDeclaration(this._cls, DeclarationMirror this._original); | 247 _MirrorDeclaration(this._cls, DeclarationMirror this._original); |
248 | 248 |
249 Symbol get name => _original.simpleName; | 249 Symbol get name => _original.simpleName; |
250 | 250 |
251 /// Whether the symbol is a property (either this or [isMethod] is true). | 251 DeclarationKind get kind => isField ? FIELD : isProperty ? PROPERTY : METHOD; |
252 bool get isProperty => _original is VariableMirror || | |
253 (_original is MethodMirror && !_original.isRegularMethod); | |
254 | 252 |
255 /// Whether the symbol is a method (either this or [isProperty] is true) | 253 bool get isField => _original is VariableMirror; |
256 bool get isMethod => !isProperty; | 254 |
| 255 bool get isProperty => |
| 256 _original is MethodMirror && !_original.isRegularMethod; |
| 257 |
| 258 bool get isMethod => !isField && !isProperty; |
257 | 259 |
258 /// If this is a property, whether it's read only (final fields or properties | 260 /// If this is a property, whether it's read only (final fields or properties |
259 /// with no setter). | 261 /// with no setter). |
260 bool get isFinal => | 262 bool get isFinal => |
261 (_original is VariableMirror && _original.isFinal) || | 263 (_original is VariableMirror && _original.isFinal) || |
262 (_original is MethodMirror && _original.isGetter && | 264 (_original is MethodMirror && _original.isGetter && |
263 !_hasSetter(_cls, _original)); | 265 !_hasSetter(_cls, _original)); |
264 | 266 |
265 /// If this is a property, it's declared type (including dynamic if it's not | 267 /// If this is a property, it's declared type (including dynamic if it's not |
266 /// declared). For methods, the returned type. | 268 /// declared). For methods, the returned type. |
267 Type get type { | 269 Type get type { |
268 if (_original is MethodMirror && _original.isRegularMethod) { | 270 if (_original is MethodMirror && _original.isRegularMethod) { |
269 return Function; | 271 return Function; |
270 } | 272 } |
271 var typeMirror = _original is VariableMirror ? _original.type | 273 var typeMirror = _original is VariableMirror ? _original.type |
272 : _original.returnType; | 274 : _original.returnType; |
273 return _toType(typeMirror); | 275 return _toType(typeMirror); |
274 } | 276 } |
275 | 277 |
276 /// Whether this symbol is static. | 278 /// Whether this symbol is static. |
277 bool get isStatic => _original.isStatic; | 279 bool get isStatic => _original.isStatic; |
278 | 280 |
279 /// List of annotations in this declaration. | 281 /// List of annotations in this declaration. |
280 List get annotations => _original.metadata.map((a) => a.reflectee).toList(); | 282 List get annotations => _original.metadata.map((a) => a.reflectee).toList(); |
281 | 283 |
282 String toString() { | 284 String toString() { |
283 return (new StringBuffer() | 285 return (new StringBuffer() |
284 ..write('[declaration ') | 286 ..write('[declaration ') |
285 ..write(name) | 287 ..write(name) |
286 ..write(isProperty ? ' (property) ' : ' (method) ') | 288 ..write(isField ? ' (field) ' |
| 289 : (isProperty ? ' (property) ' : ' (method) ')) |
287 ..write(isFinal ? 'final ' : '') | 290 ..write(isFinal ? 'final ' : '') |
288 ..write(isStatic ? 'static ' : '') | 291 ..write(isStatic ? 'static ' : '') |
289 ..write(annotations) | 292 ..write(annotations) |
290 ..write(']')).toString(); | 293 ..write(']')).toString(); |
291 } | 294 } |
292 } | 295 } |
293 | 296 |
294 class _MethodClosure extends Function { | 297 class _MethodClosure extends Function { |
295 final receiver; | 298 final receiver; |
296 final Symbol methodName; | 299 final Symbol methodName; |
297 | 300 |
298 _MethodClosure(this.receiver, this.methodName); | 301 _MethodClosure(this.receiver, this.methodName); |
299 | 302 |
300 // Technically we could just use noSuchMethod to implement [call], but we | 303 // Technically we could just use noSuchMethod to implement [call], but we |
301 // don't for 3 reasons: | 304 // don't for 3 reasons: |
302 // * noSuchMethod makes the code a lot bigger. | 305 // * noSuchMethod makes the code a lot bigger. |
303 // * even with noSuchMethod, an analyzer bug requires to declare [call] (see | 306 // * even with noSuchMethod, an analyzer bug requires to declare [call] (see |
304 // dartbug.com/16078). | 307 // dartbug.com/16078). |
305 // * having [call] also allows `is` checks to work for functions of 0 | 308 // * having [call] also allows `is` checks to work for functions of 0 |
306 // through 3 arguments. We depend on this in | 309 // through 3 arguments. We depend on this in |
307 // `polymer_expressions/lib/eval.dart` to check whether a function is a | 310 // `polymer_expressions/lib/eval.dart` to check whether a function is a |
308 // filter (takes a single argument). (Note that it's possible to include | 311 // filter (takes a single argument). (Note that it's possible to include |
309 // both [call] and [noSuchMethod], which would make instance-of checks | 312 // both [call] and [noSuchMethod], which would make instance-of checks |
310 // work with the signature of [call], but will allow invoking the function | 313 // work with the signature of [call], but will allow invoking the function |
311 // using [noSuchMethod]. | 314 // using [noSuchMethod]. |
312 call([a, b, c]) => invoke(receiver, methodName, [a, b, c], adjust: true); | 315 call([a, b, c]) => invoke(receiver, methodName, [a, b, c], adjust: true); |
313 } | 316 } |
OLD | NEW |