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

Side by Side Diff: packages/smoke/lib/static.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/src/implementation.dart ('k') | packages/smoke/lib/static_debug.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 /// Static implementation of smoke services using code-generated data.
6 library smoke.static;
7
8 import 'dart:math' as math;
9
10 import 'package:smoke/smoke.dart';
11
12 import 'src/common.dart';
13
14 typedef T Getter<T>(object);
15 typedef void Setter<T>(object, value);
16
17 class StaticConfiguration {
18 /// Maps symbol to a function that reads that symbol of an object. For
19 /// instance, `#i: (o) => o.i`.
20 final Map<Symbol, Getter> getters;
21
22 /// Maps symbol to a function that updates that symbol of an object. For
23 /// instance, `#i: (o, v) { o.i = v; }`.
24 final Map<Symbol, Setter> setters;
25
26 /// Maps a type to its super class. For example, String: Object.
27 final Map<Type, Type> parents;
28
29 /// For each type, a map of declarations per symbol (property or method).
30 final Map<Type, Map<Symbol, Declaration>> declarations;
31
32 /// Static methods for each type.
33 // TODO(sigmund): should we add static getters & setters too?
34 final Map<Type, Map<Symbol, Function>> staticMethods;
35
36 /// A map from symbol to strings.
37 final Map<Symbol, String> names;
38
39 /// A map from strings to symbols (the reverse of [names]).
40 final Map<String, Symbol> _symbols = {};
41
42 /// Whether to check for missing declarations, otherwise, return default
43 /// values (for example a missing parent class can be treated as Object)
44 final bool checkedMode;
45
46 StaticConfiguration({Map<Symbol, Getter> getters, Map<Symbol, Setter> setters,
47 Map<Type, Type> parents, Map<Type, Map<Symbol, Declaration>> declarations,
48 Map<Type, Map<Symbol, Function>> staticMethods, Map<Symbol, String> names,
49 this.checkedMode: true})
50 : getters = getters != null ? getters : {},
51 setters = setters != null ? setters : {},
52 parents = parents != null ? parents : {},
53 declarations = declarations != null ? declarations : {},
54 staticMethods = staticMethods != null ? staticMethods : {},
55 names = names != null ? names : {} {
56 this.names.forEach((k, v) {
57 _symbols[v] = k;
58 });
59 }
60
61 void addAll(StaticConfiguration other) {
62 getters.addAll(other.getters);
63 setters.addAll(other.setters);
64 parents.addAll(other.parents);
65 _nestedAddAll(declarations, other.declarations);
66 _nestedAddAll(staticMethods, other.staticMethods);
67 names.addAll(other.names);
68 other.names.forEach((k, v) {
69 _symbols[v] = k;
70 });
71 }
72
73 static _nestedAddAll(Map a, Map b) {
74 for (var key in b.keys) {
75 a.putIfAbsent(key, () => {});
76 a[key].addAll(b[key]);
77 }
78 }
79 }
80
81 /// Set up the smoke package to use a static implementation based on the given
82 /// [configuration].
83 useGeneratedCode(StaticConfiguration configuration) {
84 configure(new GeneratedObjectAccessorService(configuration),
85 new GeneratedTypeInspectorService(configuration),
86 new GeneratedSymbolConverterService(configuration));
87 }
88
89 /// Implements [ObjectAccessorService] using a static configuration.
90 class GeneratedObjectAccessorService implements ObjectAccessorService {
91 final StaticConfiguration _configuration;
92 Map<Symbol, Getter> get _getters => _configuration.getters;
93 Map<Symbol, Setter> get _setters => _configuration.setters;
94 Map<Type, Map<Symbol, Function>> get _staticMethods =>
95 _configuration.staticMethods;
96
97 GeneratedObjectAccessorService(this._configuration);
98
99 read(Object object, Symbol name) {
100 var getter = _getters[name];
101 if (getter == null) {
102 throw new MissingCodeException('getter "$name" in $object');
103 }
104 return getter(object);
105 }
106
107 void write(Object object, Symbol name, value) {
108 var setter = _setters[name];
109 if (setter == null) {
110 throw new MissingCodeException('setter "$name" in $object');
111 }
112 setter(object, value);
113 }
114
115 invoke(object, Symbol name, List args, {Map namedArgs, bool adjust: false}) {
116 var method;
117 if (object is Type && name != #toString) {
118 var classMethods = _staticMethods[object];
119 method = classMethods == null ? null : classMethods[name];
120 } else {
121 var getter = _getters[name];
122 method = getter == null ? null : getter(object);
123 }
124 if (method == null) {
125 throw new MissingCodeException('method "$name" in $object');
126 }
127 var tentativeError;
128 if (adjust) {
129 var min = minArgs(method);
130 if (min > SUPPORTED_ARGS) {
131 tentativeError = 'we tried to adjust the arguments for calling "$name"'
132 ', but we couldn\'t determine the exact number of arguments it '
133 'expects (it is more than $SUPPORTED_ARGS).';
134 // The argument list might be correct, so we still invoke the function
135 // and let the user see the error.
136 args = adjustList(args, min, math.max(min, args.length));
137 } else {
138 var max = maxArgs(method);
139 args = adjustList(args, min, max >= 0 ? max : args.length);
140 }
141 }
142 if (namedArgs != null) {
143 throw new UnsupportedError(
144 'smoke.static doesn\'t support namedArguments in invoke');
145 }
146 try {
147 return Function.apply(method, args);
148 } on NoSuchMethodError catch (_) {
149 // TODO(sigmund): consider whether this should just be in a logger or if
150 // we should wrap `e` as a new exception (what's the best way to let users
151 // know about this tentativeError?)
152 if (tentativeError != null) print(tentativeError);
153 rethrow;
154 }
155 }
156 }
157
158 /// Implements [TypeInspectorService] using a static configuration.
159 class GeneratedTypeInspectorService implements TypeInspectorService {
160 final StaticConfiguration _configuration;
161
162 Map<Type, Type> get _parents => _configuration.parents;
163 Map<Type, Map<Symbol, Declaration>> get _declarations =>
164 _configuration.declarations;
165 bool get _checkedMode => _configuration.checkedMode;
166
167 GeneratedTypeInspectorService(this._configuration);
168
169 bool isSubclassOf(Type type, Type supertype) {
170 if (type == supertype || supertype == Object) return true;
171 while (type != Object) {
172 var parentType = _parents[type];
173 if (parentType == supertype) return true;
174 if (parentType == null) {
175 if (!_checkedMode) return false;
176 throw new MissingCodeException('superclass of "$type" ($parentType)');
177 }
178 type = parentType;
179 }
180 return false;
181 }
182
183 bool hasGetter(Type type, Symbol name) {
184 var decl = _findDeclaration(type, name);
185 // No need to check decl.isProperty because methods are also automatically
186 // considered getters (auto-closures).
187 return decl != null && !decl.isStatic;
188 }
189
190 bool hasSetter(Type type, Symbol name) {
191 var decl = _findDeclaration(type, name);
192 return decl != null && !decl.isMethod && !decl.isFinal && !decl.isStatic;
193 }
194
195 bool hasInstanceMethod(Type type, Symbol name) {
196 var decl = _findDeclaration(type, name);
197 return decl != null && decl.isMethod && !decl.isStatic;
198 }
199
200 bool hasStaticMethod(Type type, Symbol name) {
201 final map = _declarations[type];
202 if (map == null) {
203 if (!_checkedMode) return false;
204 throw new MissingCodeException('declarations for $type');
205 }
206 final decl = map[name];
207 return decl != null && decl.isMethod && decl.isStatic;
208 }
209
210 Declaration getDeclaration(Type type, Symbol name) {
211 var decl = _findDeclaration(type, name);
212 if (decl == null) {
213 if (!_checkedMode) return null;
214 throw new MissingCodeException('declaration for $type.$name');
215 }
216 return decl;
217 }
218
219 List<Declaration> query(Type type, QueryOptions options) {
220 var result = [];
221 if (options.includeInherited) {
222 var superclass = _parents[type];
223 if (superclass == null) {
224 if (_checkedMode) {
225 throw new MissingCodeException('superclass of "$type"');
226 }
227 } else if (superclass != options.includeUpTo) {
228 result = query(superclass, options);
229 }
230 }
231 var map = _declarations[type];
232 if (map == null) {
233 if (!_checkedMode) return result;
234 throw new MissingCodeException('declarations for $type');
235 }
236 for (var decl in map.values) {
237 if (!options.includeFields && decl.isField) continue;
238 if (!options.includeProperties && decl.isProperty) continue;
239 if (options.excludeFinal && decl.isFinal) continue;
240 if (!options.includeMethods && decl.isMethod) continue;
241 if (options.matches != null && !options.matches(decl.name)) continue;
242 if (options.withAnnotations != null &&
243 !matchesAnnotation(decl.annotations, options.withAnnotations)) {
244 continue;
245 }
246 if (options.excludeOverriden) {
247 result.retainWhere((value) => decl.name != value.name);
248 }
249 result.add(decl);
250 }
251 return result;
252 }
253
254 Declaration _findDeclaration(Type type, Symbol name) {
255 while (type != Object) {
256 final declarations = _declarations[type];
257 if (declarations != null) {
258 final declaration = declarations[name];
259 if (declaration != null) return declaration;
260 }
261 var parentType = _parents[type];
262 if (parentType == null) {
263 if (!_checkedMode) return null;
264 throw new MissingCodeException('superclass of "$type"');
265 }
266 type = parentType;
267 }
268 return null;
269 }
270 }
271
272 /// Implements [SymbolConverterService] using a static configuration.
273 class GeneratedSymbolConverterService implements SymbolConverterService {
274 final StaticConfiguration _configuration;
275 Map<Symbol, String> get _names => _configuration.names;
276 Map<String, Symbol> get _symbols => _configuration._symbols;
277
278 GeneratedSymbolConverterService(this._configuration);
279
280 String symbolToName(Symbol symbol) => _names[symbol];
281 Symbol nameToSymbol(String name) => _symbols[name];
282 }
283
284 /// Exception thrown when trynig to access something that should be there, but
285 /// the code generator didn't include it.
286 class MissingCodeException implements Exception {
287 final String description;
288 MissingCodeException(this.description);
289
290 String toString() => 'Missing $description. '
291 'Code generation for the smoke package seems incomplete.';
292 }
OLDNEW
« no previous file with comments | « packages/smoke/lib/src/implementation.dart ('k') | packages/smoke/lib/static_debug.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698