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

Side by Side Diff: pkg/smoke/lib/static.dart

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

Powered by Google App Engine
This is Rietveld 408576698