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 /// Static implementation of smoke services using code-generated data. | 5 /// Static implementation of smoke services using code-generated data. |
6 library smoke.static; | 6 library smoke.static; |
7 | 7 |
8 import 'dart:math' as math; | 8 import 'dart:math' as math; |
9 | 9 |
10 import 'package:logging/logging.dart'; | 10 import 'package:logging/logging.dart'; |
(...skipping 19 matching lines...) Expand all Loading... |
30 /// For each type, a map of declarations per symbol (property or method). | 30 /// For each type, a map of declarations per symbol (property or method). |
31 final Map<Type, Map<Symbol, Declaration>> declarations; | 31 final Map<Type, Map<Symbol, Declaration>> declarations; |
32 | 32 |
33 /// Static methods for each type. | 33 /// Static methods for each type. |
34 // TODO(sigmund): should we add static getters & setters too? | 34 // TODO(sigmund): should we add static getters & setters too? |
35 final Map<Type, Map<Symbol, Function>> staticMethods; | 35 final Map<Type, Map<Symbol, Function>> staticMethods; |
36 | 36 |
37 /// A map from symbol to strings. | 37 /// A map from symbol to strings. |
38 final Map<Symbol, String> names; | 38 final Map<Symbol, String> names; |
39 | 39 |
| 40 /// A map from strings to symbols (the reverse of [names]). |
| 41 final Map<String, Symbol> _symbols = {}; |
| 42 |
| 43 |
40 /// Whether to check for missing declarations, otherwise, return default | 44 /// Whether to check for missing declarations, otherwise, return default |
41 /// values (for example a missing parent class can be treated as Object) | 45 /// values (for example a missing parent class can be treated as Object) |
42 final bool checkedMode; | 46 final bool checkedMode; |
43 | 47 |
44 StaticConfiguration({ | 48 StaticConfiguration({ |
45 this.getters: const {}, this.setters: const {}, this.parents: const {}, | 49 Map<Symbol, Getter> getters, |
46 this.declarations: const {}, this.staticMethods: const {}, | 50 Map<Symbol, Setter> setters, |
47 this.names: const {}, this.checkedMode: true}); | 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 } |
48 } | 81 } |
49 | 82 |
50 /// Set up the smoke package to use a static implementation based on the given | 83 /// Set up the smoke package to use a static implementation based on the given |
51 /// [configuration]. | 84 /// [configuration]. |
52 useGeneratedCode(StaticConfiguration configuration) { | 85 useGeneratedCode(StaticConfiguration configuration) { |
53 configure(new GeneratedObjectAccessorService(configuration), | 86 configure(new GeneratedObjectAccessorService(configuration), |
54 new GeneratedTypeInspectorService(configuration), | 87 new GeneratedTypeInspectorService(configuration), |
55 new GeneratedSymbolConverterService(configuration)); | 88 new GeneratedSymbolConverterService(configuration)); |
56 } | 89 } |
57 | 90 |
58 /// Implements [ObjectAccessorService] using a static configuration. | 91 /// Implements [ObjectAccessorService] using a static configuration. |
59 class GeneratedObjectAccessorService implements ObjectAccessorService { | 92 class GeneratedObjectAccessorService implements ObjectAccessorService { |
60 final Map<Symbol, Getter> _getters; | 93 final StaticConfiguration _configuration; |
61 final Map<Symbol, Setter> _setters; | 94 Map<Symbol, Getter> get _getters => _configuration.getters; |
62 final Map<Type, Map<Symbol, Function>> _staticMethods; | 95 Map<Symbol, Setter> get _setters => _configuration.setters; |
| 96 Map<Type, Map<Symbol, Function>> get _staticMethods => |
| 97 _configuration.staticMethods; |
63 | 98 |
64 GeneratedObjectAccessorService(StaticConfiguration configuration) | 99 GeneratedObjectAccessorService(this._configuration); |
65 : _getters = configuration.getters, | |
66 _setters = configuration.setters, | |
67 _staticMethods = configuration.staticMethods; | |
68 | 100 |
69 read(Object object, Symbol name) { | 101 read(Object object, Symbol name) { |
70 var getter = _getters[name]; | 102 var getter = _getters[name]; |
71 if (getter == null) { | 103 if (getter == null) { |
72 throw new MissingCodeException('getter "$name" in $object'); | 104 throw new MissingCodeException('getter "$name" in $object'); |
73 } | 105 } |
74 return getter(object); | 106 return getter(object); |
75 } | 107 } |
76 | 108 |
77 void write(Object object, Symbol name, value) { | 109 void write(Object object, Symbol name, value) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
120 // we should wrap `e` as a new exception (what's the best way to let users | 152 // we should wrap `e` as a new exception (what's the best way to let users |
121 // know about this tentativeError?) | 153 // know about this tentativeError?) |
122 if (tentativeError != null) print(tentativeError); | 154 if (tentativeError != null) print(tentativeError); |
123 rethrow; | 155 rethrow; |
124 } | 156 } |
125 } | 157 } |
126 } | 158 } |
127 | 159 |
128 /// Implements [TypeInspectorService] using a static configuration. | 160 /// Implements [TypeInspectorService] using a static configuration. |
129 class GeneratedTypeInspectorService implements TypeInspectorService { | 161 class GeneratedTypeInspectorService implements TypeInspectorService { |
130 final Map<Type, Type> _parents; | 162 final StaticConfiguration _configuration; |
131 final Map<Type, Map<Symbol, Declaration>> _declarations; | |
132 final bool _checkedMode; | |
133 | 163 |
134 GeneratedTypeInspectorService(StaticConfiguration configuration) | 164 Map<Type, Type> get _parents => _configuration.parents; |
135 : _parents = configuration.parents, | 165 Map<Type, Map<Symbol, Declaration>> get _declarations => |
136 _declarations = configuration.declarations, | 166 _configuration.declarations; |
137 _checkedMode = configuration.checkedMode; | 167 bool get _checkedMode => _configuration.checkedMode; |
| 168 |
| 169 GeneratedTypeInspectorService(this._configuration); |
| 170 |
138 bool isSubclassOf(Type type, Type supertype) { | 171 bool isSubclassOf(Type type, Type supertype) { |
139 if (type == supertype || supertype == Object) return true; | 172 if (type == supertype || supertype == Object) return true; |
140 while (type != Object) { | 173 while (type != Object) { |
141 var parentType = _parents[type]; | 174 var parentType = _parents[type]; |
142 if (parentType == supertype) return true; | 175 if (parentType == supertype) return true; |
143 if (parentType == null) { | 176 if (parentType == null) { |
144 if (!_checkedMode) return false; | 177 if (!_checkedMode) return false; |
145 throw new MissingCodeException('superclass of "$type" ($parentType)'); | 178 throw new MissingCodeException('superclass of "$type" ($parentType)'); |
146 } | 179 } |
147 type = parentType; | 180 type = parentType; |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 throw new MissingCodeException('superclass of "$type"'); | 263 throw new MissingCodeException('superclass of "$type"'); |
231 } | 264 } |
232 type = parentType; | 265 type = parentType; |
233 } | 266 } |
234 return null; | 267 return null; |
235 } | 268 } |
236 } | 269 } |
237 | 270 |
238 /// Implements [SymbolConverterService] using a static configuration. | 271 /// Implements [SymbolConverterService] using a static configuration. |
239 class GeneratedSymbolConverterService implements SymbolConverterService { | 272 class GeneratedSymbolConverterService implements SymbolConverterService { |
240 Map<Symbol, String> _names; | 273 final StaticConfiguration _configuration; |
| 274 Map<Symbol, String> get _names => _configuration.names; |
| 275 Map<String, Symbol> get _symbols => _configuration._symbols; |
241 | 276 |
242 /// A map from strings to symbols (the reverse of [names]). | 277 GeneratedSymbolConverterService(this._configuration); |
243 final Map<String, Symbol> _symbols; | |
244 | |
245 GeneratedSymbolConverterService(StaticConfiguration configuration) | |
246 : _names = configuration.names, | |
247 _symbols = {} { | |
248 _names.forEach((k, v) { _symbols[v] = k; }); | |
249 } | |
250 | 278 |
251 String symbolToName(Symbol symbol) => _names[symbol]; | 279 String symbolToName(Symbol symbol) => _names[symbol]; |
252 Symbol nameToSymbol(String name) => _symbols[name]; | 280 Symbol nameToSymbol(String name) => _symbols[name]; |
253 } | 281 } |
254 | 282 |
255 | 283 |
256 /// Exception thrown when trynig to access something that should be there, but | 284 /// Exception thrown when trynig to access something that should be there, but |
257 /// the code generator didn't include it. | 285 /// the code generator didn't include it. |
258 class MissingCodeException implements Exception { | 286 class MissingCodeException implements Exception { |
259 final String description; | 287 final String description; |
260 MissingCodeException(this.description); | 288 MissingCodeException(this.description); |
261 | 289 |
262 String toString() => 'Missing $description. ' | 290 String toString() => 'Missing $description. ' |
263 'Code generation for the smoke package seems incomplete.'; | 291 'Code generation for the smoke package seems incomplete.'; |
264 } | 292 } |
OLD | NEW |