Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(117)

Side by Side Diff: packages/smoke/lib/mirrors.dart

Issue 2989763002: Update charted to 0.4.8 and roll (Closed)
Patch Set: Removed Cutch from list of reviewers Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « packages/smoke/lib/codegen/recorder.dart ('k') | packages/smoke/lib/smoke.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 /// Implementation of the smoke services using mirrors.
6 library smoke.mirrors;
7
8 import 'dart:mirrors';
9 import 'package:smoke/smoke.dart';
10 import 'package:logging/logging.dart';
11 import 'src/common.dart';
12
13 /// Set up the smoke package to use a mirror-based implementation. To tune what
14 /// is preserved by `dart:mirrors`, use a @MirrorsUsed annotation and include
15 /// 'smoke.mirrors' in your override arguments.
16 useMirrors() {
17 configure(new ReflectiveObjectAccessorService(),
18 new ReflectiveTypeInspectorService(),
19 new ReflectiveSymbolConverterService());
20 }
21
22 var _logger = new Logger('smoke.mirrors');
23
24 /// Implements [ObjectAccessorService] using mirrors.
25 class ReflectiveObjectAccessorService implements ObjectAccessorService {
26 read(Object object, Symbol name) => reflect(object).getField(name).reflectee;
27
28 void write(Object object, Symbol name, value) {
29 reflect(object).setField(name, value);
30 }
31
32 invoke(receiver, Symbol methodName, List args,
33 {Map namedArgs, bool adjust: false}) {
34 var receiverMirror;
35 var method;
36 if (receiver is Type && methodName != #toString) {
37 receiverMirror = reflectType(receiver);
38 method = receiverMirror.declarations[methodName];
39 } else {
40 receiverMirror = reflect(receiver);
41 method = _findMethod(receiverMirror.type, methodName);
42 }
43 if (method != null && adjust) {
44 var required = 0;
45 var optional = 0;
46 for (var p in method.parameters) {
47 if (p.isOptional) {
48 if (!p.isNamed) optional++;
49 } else {
50 required++;
51 }
52 }
53 args = adjustList(args, required, required + optional);
54 }
55 return receiverMirror.invoke(methodName, args, namedArgs).reflectee;
56 }
57 }
58
59 /// Implements [TypeInspectorService] using mirrors.
60 class ReflectiveTypeInspectorService implements TypeInspectorService {
61 bool isSubclassOf(Type type, Type supertype) {
62 if (type == supertype || supertype == Object) return true;
63 // TODO(sigmund): change to mirror.isSubclassOf when it gets implemented in
64 // dart2js. (dartbug.com/12439)
65 var mirror = reflectClass(type);
66 var top = reflectClass(supertype);
67 while (mirror != _objectType) {
68 mirror = _safeSuperclass(mirror);
69 if (mirror == top) return true;
70 }
71 return false;
72 }
73
74 bool hasGetter(Type type, Symbol name) {
75 var mirror = reflectType(type);
76 if (mirror is! ClassMirror) return false;
77 while (mirror != _objectType) {
78 final members = mirror.declarations;
79 if (members.containsKey(name)) return true;
80 mirror = _safeSuperclass(mirror);
81 }
82 return false;
83 }
84
85 bool hasSetter(Type type, Symbol name) {
86 var mirror = reflectType(type);
87 if (mirror is! ClassMirror) return false;
88 var setterName = _setterName(name);
89 while (mirror != _objectType) {
90 final members = mirror.declarations;
91 var declaration = members[name];
92 if (declaration is VariableMirror && !declaration.isFinal) return true;
93 if (members.containsKey(setterName)) return true;
94 mirror = _safeSuperclass(mirror);
95 }
96 return false;
97 }
98
99 bool hasInstanceMethod(Type type, Symbol name) {
100 var mirror = reflectType(type);
101 if (mirror is! ClassMirror) return false;
102 while (mirror != _objectType) {
103 final m = mirror.declarations[name];
104 if (m is MethodMirror && m.isRegularMethod && !m.isStatic) return true;
105 mirror = _safeSuperclass(mirror);
106 }
107 return false;
108 }
109
110 bool hasStaticMethod(Type type, Symbol name) {
111 var mirror = reflectType(type);
112 if (mirror is! ClassMirror) return false;
113 final m = mirror.declarations[name];
114 return m is MethodMirror && m.isRegularMethod && m.isStatic;
115 }
116
117 Declaration getDeclaration(Type type, Symbol name) {
118 var mirror = reflectType(type);
119 if (mirror is! ClassMirror) return null;
120
121 var declaration;
122 while (mirror != _objectType) {
123 final members = mirror.declarations;
124 if (members.containsKey(name)) {
125 declaration = members[name];
126 break;
127 }
128 mirror = _safeSuperclass(mirror);
129 }
130 if (declaration == null) {
131 _logger.severe("declaration doesn't exists ($type.$name).");
132 return null;
133 }
134 return new _MirrorDeclaration(mirror, declaration);
135 }
136
137 List<Declaration> query(Type type, QueryOptions options) {
138 var mirror = reflectType(type);
139 if (mirror is! ClassMirror) return null;
140 return _query(mirror, options);
141 }
142
143 List<Declaration> _query(ClassMirror cls, QueryOptions options) {
144 final visitParent = options.includeInherited && cls.superclass != null &&
145 // TODO(sigmund): use _toType(cls.superclass) != options.includeUpTo
146 // when dartbug.com/16925 gets fixed (_toType fails in dart2js if
147 // applied to classes with type-arguments).
148 cls.superclass != reflectClass(options.includeUpTo);
149 var result = visitParent ? _query(cls.superclass, options) : [];
150 for (var member in cls.declarations.values) {
151 if (member is! VariableMirror && member is! MethodMirror) continue;
152 if (member.isStatic || member.isPrivate) continue;
153 var name = member.simpleName;
154 if (member is VariableMirror) {
155 if (!options.includeFields) continue;
156 if (options.excludeFinal && member.isFinal) continue;
157 }
158
159 // TODO(sigmund): what if we have a setter but no getter?
160 if (member is MethodMirror && member.isSetter) continue;
161 if (member is MethodMirror && member.isConstructor) continue;
162
163 if (member is MethodMirror && member.isGetter) {
164 if (!options.includeProperties) continue;
165 if (options.excludeFinal && !_hasSetter(cls, member)) continue;
166 }
167
168 if (member is MethodMirror && member.isRegularMethod) {
169 if (!options.includeMethods) continue;
170 }
171
172 if (options.matches != null && !options.matches(name)) continue;
173
174 var annotations = member.metadata.map((m) => m.reflectee).toList();
175 if (options.withAnnotations != null &&
176 !matchesAnnotation(annotations, options.withAnnotations)) {
177 continue;
178 }
179
180 var declaration = new _MirrorDeclaration(cls, member);
181
182 if (options.excludeOverriden) {
183 result.retainWhere((value) => declaration.name != value.name);
184 }
185
186 // TODO(sigmund): should we cache parts of this declaration so we don't
187 // compute them twice? For example, this chould be `new Declaration(name,
188 // type, ...)` and we could reuse what we computed above to implement the
189 // query filtering. Note, when I tried to eagerly compute everything, I
190 // run into trouble with type (`type = _toType(member.type)`), dart2js
191 // failed when the underlying types had type-arguments (see
192 // dartbug.com/16925).
193 result.add(declaration);
194 }
195
196 return result;
197 }
198 }
199
200 /// Implements [SymbolConverterService] using mirrors.
201 class ReflectiveSymbolConverterService implements SymbolConverterService {
202 String symbolToName(Symbol symbol) => MirrorSystem.getName(symbol);
203 Symbol nameToSymbol(String name) => new Symbol(name);
204 }
205
206 // TODO(jmesserly): workaround for:
207 // https://code.google.com/p/dart/issues/detail?id=10029
208 Symbol _setterName(Symbol getter) =>
209 new Symbol('${MirrorSystem.getName(getter)}=');
210
211 ClassMirror _safeSuperclass(ClassMirror type) {
212 try {
213 var t = type.superclass;
214 // TODO(sigmund): workaround for darbug.com/17779.
215 // Interceptor is leaked by dart2js. It has the same methods as Object
216 // (including noSuchMethod), and our code above assumes that it doesn't
217 // exist. Most queries exclude Object, so they should exclude Interceptor
218 // too. We don't check for t.simpleName == #Interceptor because depending on
219 // dart2js optimizations it may be #Interceptor or #num/Interceptor.
220 // Checking for a private library seems to reliably filter this out.
221 if (t != null && t.owner != null && t.owner.isPrivate) {
222 t = _objectType;
223 }
224 return t;
225 } on UnsupportedError catch (_) {
226 // Note: dart2js throws UnsupportedError when the type is not reflectable.
227 return _objectType;
228 }
229 }
230
231 MethodMirror _findMethod(ClassMirror type, Symbol name) {
232 do {
233 var member = type.declarations[name];
234 if (member is MethodMirror) return member;
235 type = type.superclass;
236 } while (type != null);
237 return null;
238 }
239
240 // When recursively looking for symbols up the type-hierarchy it's generally a
241 // good idea to stop at Object, since we know it doesn't have what we want.
242 // TODO(jmesserly): This is also a workaround for what appears to be a V8
243 // bug introduced between Chrome 31 and 32. After 32
244 // JsClassMirror.declarations on Object calls
245 // JsClassMirror.typeVariables, which tries to get the _jsConstructor's
246 // .prototype["<>"]. This ends up getting the "" property instead, maybe
247 // because "<>" doesn't exist, and gets ";" which then blows up because
248 // the code later on expects a List of ints.
249 final _objectType = reflectClass(Object);
250
251 bool _hasSetter(ClassMirror cls, MethodMirror getter) {
252 var mirror = cls.declarations[_setterName(getter.simpleName)];
253 return mirror is MethodMirror && mirror.isSetter;
254 }
255
256 Type _toType(TypeMirror t) {
257 // TODO(sigmund): this line can go away after dartbug.com/16962
258 if (t == _objectType) return Object;
259 if (t is ClassMirror) return t.reflectedType;
260 if (t == null || t.qualifiedName != #dynamic) {
261 _logger.warning('unknown type ($t).');
262 }
263 return dynamic;
264 }
265
266 class _MirrorDeclaration implements Declaration {
267 final ClassMirror _cls;
268 final _original;
269
270 _MirrorDeclaration(this._cls, DeclarationMirror this._original);
271
272 Symbol get name => _original.simpleName;
273
274 DeclarationKind get kind => isField ? FIELD : isProperty ? PROPERTY : METHOD;
275
276 bool get isField => _original is VariableMirror;
277
278 bool get isProperty =>
279 _original is MethodMirror && !_original.isRegularMethod;
280
281 bool get isMethod => !isField && !isProperty;
282
283 /// If this is a property, whether it's read only (final fields or properties
284 /// with no setter).
285 bool get isFinal => (_original is VariableMirror && _original.isFinal) ||
286 (_original is MethodMirror &&
287 _original.isGetter &&
288 !_hasSetter(_cls, _original));
289
290 /// If this is a property, it's declared type (including dynamic if it's not
291 /// declared). For methods, the returned type.
292 Type get type {
293 if (_original is MethodMirror && _original.isRegularMethod) {
294 return Function;
295 }
296 var typeMirror =
297 _original is VariableMirror ? _original.type : _original.returnType;
298 return _toType(typeMirror);
299 }
300
301 /// Whether this symbol is static.
302 bool get isStatic => _original.isStatic;
303
304 /// List of annotations in this declaration.
305 List get annotations => _original.metadata.map((a) => a.reflectee).toList();
306
307 int get hashCode => name.hashCode;
308 operator ==(other) => other is Declaration &&
309 name == other.name &&
310 kind == other.kind &&
311 isFinal == other.isFinal &&
312 type == other.type &&
313 isStatic == other.isStatic &&
314 compareLists(annotations, other.annotations);
315 String toString() => (new StringBuffer()
316 ..write('(mirror-based-declaration ')
317 ..write(name)
318 ..write(
319 isField ? ' (field) ' : (isProperty ? ' (property) ' : ' (method) '))
320 ..write(isFinal ? 'final ' : '')
321 ..write(isStatic ? 'static ' : '')
322 ..write(annotations)
323 ..write(')')).toString();
324 }
OLDNEW
« no previous file with comments | « packages/smoke/lib/codegen/recorder.dart ('k') | packages/smoke/lib/smoke.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698