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

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

Issue 169913004: Adding package:smoke. This CL includes the intial APIs, a mirror-based (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « pkg/smoke/lib/src/implementation.dart ('k') | pkg/smoke/pubspec.yaml » ('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 StaticConfiguration _configuration;
19 var _logger = new Logger('smoke.static');
20
21 class StaticConfiguration {
22 /// Maps symbol to a function that reads that symbol of an object. For
23 /// instance, `#i: (o) => o.i`.
24 final Map<Symbol, Getter> getters;
25
26 /// Maps symbol to a function that updates that symbol of an object. For
27 /// instance, `#i: (o, v) { o.i = v; }`.
28 final Map<Symbol, Setter> setters;
29
30 /// Maps a type to it's super class. For example, String: Object.
31 final Map<Type, Type> parents;
32
33 /// For each type, a map of declarations per symbol (property or method).
34 final Map<Type, Map<Symbol, Declaration>> declarations;
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 StaticConfiguration({
42 this.getters: const {}, this.setters: const {}, this.parents: const {},
43 this.declarations: const {}, this.names: const {}})
44 : this.symbols = {} {
45 names.forEach((k, v) { symbols[v] = k; });
46 }
47 }
48
49 /// Set up the smoke package to use a static implementation based on the given
50 /// [configuration].
51 useGeneratedCode(StaticConfiguration configuration) {
52 _configuration = configuration;
53 configure(new _GeneratedObjectAccessorService(),
54 new _GeneratedTypeInspectorService(),
55 new _GeneratedSymbolConverterService());
56 }
57
58 /// Implements [ObjectAccessorService] using a static configuration.
59 class _GeneratedObjectAccessorService implements ObjectAccessorService {
60 read(Object object, Symbol name) {
61 var getter = _configuration.getters[name];
62 if (getter == null) {
63 throw new MissingCodeException('getter "$name" in $object');
64 }
65 return getter(object);
66 }
67 void write(Object object, Symbol name, value) {
68 var setter = _configuration.setters[name];
69 if (setter == null) {
70 throw new MissingCodeException('setter "$name" in $object');
71 }
72 setter(object, value);
73 }
74
75 invoke(object, Symbol name, List args, {Map namedArgs, bool adjust: false}) {
76 var method;
77 if (object is Type) {
78 } else {
79 var getter = _configuration.getters[name];
80 method = getter == null ? null : getter(object);
81 }
82 if (method == null) {
83 throw new MissingCodeException('method "$name" in $object');
84 }
85 var tentativeError;
86 if (adjust) {
87 var min = minArgs(method);
88 if (min > SUPPORTED_ARGS) {
89 tentativeError = 'we tried to adjust the arguments for calling "$name"'
90 ', but we couldn\'t determine the exact number of arguments it '
91 'expects (it is more than $SUPPORTED_ARGS).';
92 // The argument list might be correct, so we still invoke the function
93 // and let the user see the error.
94 args = adjustList(args, min, math.max(min, args.length));
95 } else {
96 var max = maxArgs(method);
97 args = adjustList(args, min, max >= 0 ? max : args.length);
98 }
99 }
100 if (namedArgs != null) {
101 throw new UnsupportedError(
102 'smoke.static doesn\'t support namedArguments in invoke');
103 }
104 try {
105 return Function.apply(method, args);
106 } on NoSuchMethodError catch (e) {
107 if (tentativeError != null) print(tentativeError);
Jennifer Messerly 2014/02/20 23:24:37 +1, this is nice! one other thing this makes me t
Siggi Cherem (dart-lang) 2014/02/21 01:51:24 mmm, tricky. good question. I'm inclined for now t
Jennifer Messerly 2014/02/21 01:52:14 SGTM
108 rethrow;
109 }
110 }
111 }
112
113 /// Implements [TypeInspectorService] using a static configuration.
114 class _GeneratedTypeInspectorService implements TypeInspectorService {
115 bool hasGetter(Type type, Symbol name) {
116 var decl = _findDeclaration(type, name);
117 // No need to check decl.isProperty because methods are also automatically
118 // considered getters (auto-closures).
119 return decl != null && !decl.isStatic;
120 }
121
122 bool hasSetter(Type type, Symbol name) {
123 var decl = _findDeclaration(type, name);
124 return decl != null && !decl.isMethod && !decl.isFinal && !decl.isStatic;
125 }
126
127 bool hasInstanceMethod(Type type, Symbol name) {
128 var decl = _findDeclaration(type, name);
129 return decl != null && decl.isMethod && !decl.isStatic;
130 }
131
132 bool hasStaticMethod(Type type, Symbol name) {
133 final map = _configuration.declarations[type];
134 if (map == null) {
135 throw new MissingCodeException('declarations for $type');
136 }
137 final decl = map[name];
138 return decl != null && decl.isMethod && decl.isStatic;
139 }
140
141 Declaration getDeclaration(Type type, Symbol name) {
142 var decl = _findDeclaration(type, name);
143 if (decl == null) {
144 throw new MissingCodeException('declaration for $type.$name');
145 }
146 return decl;
147 }
148
149 List<Declaration> query(Type type, QueryOptions options) {
150 var result;
151 if (options.includeInherited) {
152 var superclass = _configuration.parents[type];
153 if (superclass == null) {
154 throw new MissingCodeException('superclass of "$type"');
155 }
156 result = (superclass == Object) ? [] : query(superclass, options);
157 } else {
158 result = [];
159 }
160 var map = _configuration.declarations[type];
161 if (map == null) {
162 throw new MissingCodeException('declarations for $type');
163 }
164 for (var decl in map.values) {
165 if (!options.includeProperties && decl.isProperty) continue;
166 if (options.excludeFinal && decl.isFinal) continue;
167 if (!options.includeMethods && decl.isMethod) continue;
168 if (options.withAnnotations != null &&
169 !matchesAnnotation(decl.annotations, options.withAnnotations)) {
170 continue;
171 }
172 result.add(decl);
173 }
174 return result;
175 }
176 }
177
178 /// Implements [SymbolConverterService] using a static configuration.
179 class _GeneratedSymbolConverterService implements SymbolConverterService {
180 String symbolToName(Symbol symbol) => _configuration.names[symbol];
181 Symbol nameToSymbol(String name) => _configuration.symbols[name];
182 }
183
184
185 /// Exception thrown when trynig to access something that should be there, but
186 /// the code generator didn't include it.
187 class MissingCodeException implements Exception {
188 final String description;
189 MissingCodeException(this.description);
190
191 String toString() => 'Missing $description. '
192 'Code generation for the smoke package seems incomplete.';
193 }
194
195 Declaration _findDeclaration(Type type, Symbol name) {
196 while (type != Object) {
197 final declarations = _configuration.declarations[type];
198 if (declarations != null) {
199 final declaration = declarations[name];
200 if (declaration != null) return declaration;
201 }
202 var parentType = _configuration.parents[type];
203 if (parentType == null) {
204 throw new MissingCodeException('superclass of "$type"');
205 }
206 type = parentType;
207 }
208 return null;
209 }
OLDNEW
« no previous file with comments | « pkg/smoke/lib/src/implementation.dart ('k') | pkg/smoke/pubspec.yaml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698