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'; |
11 import 'package:smoke/smoke.dart'; | 11 import 'package:smoke/smoke.dart'; |
12 | 12 |
13 import 'src/common.dart'; | 13 import 'src/common.dart'; |
14 | 14 |
15 typedef T Getter<T>(object); | 15 typedef T Getter<T>(object); |
16 typedef void Setter<T>(object, value); | 16 typedef void Setter<T>(object, value); |
17 | 17 |
18 class StaticConfiguration { | 18 class StaticConfiguration { |
19 /// Maps symbol to a function that reads that symbol of an object. For | 19 /// Maps symbol to a function that reads that symbol of an object. For |
20 /// instance, `#i: (o) => o.i`. | 20 /// instance, `#i: (o) => o.i`. |
21 final Map<Symbol, Getter> getters; | 21 final Map<Symbol, Getter> getters; |
22 | 22 |
23 /// Maps symbol to a function that updates that symbol of an object. For | 23 /// Maps symbol to a function that updates that symbol of an object. For |
24 /// instance, `#i: (o, v) { o.i = v; }`. | 24 /// instance, `#i: (o, v) { o.i = v; }`. |
25 final Map<Symbol, Setter> setters; | 25 final Map<Symbol, Setter> setters; |
26 | 26 |
27 /// Maps a type to it's super class. For example, String: Object. | 27 /// Maps a type to its super class. For example, String: Object. |
28 final Map<Type, Type> parents; | 28 final Map<Type, Type> parents; |
29 | 29 |
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. |
| 34 // TODO(sigmund): should we add static getters & setters too? |
| 35 final Map<Type, Map<Symbol, Function>> staticMethods; |
| 36 |
33 /// A map from symbol to strings. | 37 /// A map from symbol to strings. |
34 final Map<Symbol, String> names; | 38 final Map<Symbol, String> names; |
35 | 39 |
36 /// Whether to check for missing declarations, otherwise, return default | 40 /// Whether to check for missing declarations, otherwise, return default |
37 /// values (for example a missing parent class can be treated as Object) | 41 /// values (for example a missing parent class can be treated as Object) |
38 final bool checkedMode; | 42 final bool checkedMode; |
39 | 43 |
40 StaticConfiguration({ | 44 StaticConfiguration({ |
41 this.getters: const {}, this.setters: const {}, this.parents: const {}, | 45 this.getters: const {}, this.setters: const {}, this.parents: const {}, |
42 this.declarations: const {}, this.names: const {}, | 46 this.declarations: const {}, this.staticMethods: const {}, |
43 this.checkedMode: true}); | 47 this.names: const {}, this.checkedMode: true}); |
44 } | 48 } |
45 | 49 |
46 /// Set up the smoke package to use a static implementation based on the given | 50 /// Set up the smoke package to use a static implementation based on the given |
47 /// [configuration]. | 51 /// [configuration]. |
48 useGeneratedCode(StaticConfiguration configuration) { | 52 useGeneratedCode(StaticConfiguration configuration) { |
49 configure(new GeneratedObjectAccessorService(configuration), | 53 configure(new GeneratedObjectAccessorService(configuration), |
50 new GeneratedTypeInspectorService(configuration), | 54 new GeneratedTypeInspectorService(configuration), |
51 new GeneratedSymbolConverterService(configuration)); | 55 new GeneratedSymbolConverterService(configuration)); |
52 } | 56 } |
53 | 57 |
54 /// Implements [ObjectAccessorService] using a static configuration. | 58 /// Implements [ObjectAccessorService] using a static configuration. |
55 class GeneratedObjectAccessorService implements ObjectAccessorService { | 59 class GeneratedObjectAccessorService implements ObjectAccessorService { |
56 final Map<Symbol, Getter> _getters; | 60 final Map<Symbol, Getter> _getters; |
57 final Map<Symbol, Setter> _setters; | 61 final Map<Symbol, Setter> _setters; |
| 62 final Map<Type, Map<Symbol, Function>> _staticMethods; |
58 | 63 |
59 GeneratedObjectAccessorService(StaticConfiguration configuration) | 64 GeneratedObjectAccessorService(StaticConfiguration configuration) |
60 : _getters = configuration.getters, | 65 : _getters = configuration.getters, |
61 _setters = configuration.setters; | 66 _setters = configuration.setters, |
| 67 _staticMethods = configuration.staticMethods; |
62 | 68 |
63 read(Object object, Symbol name) { | 69 read(Object object, Symbol name) { |
64 var getter = _getters[name]; | 70 var getter = _getters[name]; |
65 if (getter == null) { | 71 if (getter == null) { |
66 throw new MissingCodeException('getter "$name" in $object'); | 72 throw new MissingCodeException('getter "$name" in $object'); |
67 } | 73 } |
68 return getter(object); | 74 return getter(object); |
69 } | 75 } |
| 76 |
70 void write(Object object, Symbol name, value) { | 77 void write(Object object, Symbol name, value) { |
71 var setter = _setters[name]; | 78 var setter = _setters[name]; |
72 if (setter == null) { | 79 if (setter == null) { |
73 throw new MissingCodeException('setter "$name" in $object'); | 80 throw new MissingCodeException('setter "$name" in $object'); |
74 } | 81 } |
75 setter(object, value); | 82 setter(object, value); |
76 } | 83 } |
77 | 84 |
78 invoke(object, Symbol name, List args, {Map namedArgs, bool adjust: false}) { | 85 invoke(object, Symbol name, List args, {Map namedArgs, bool adjust: false}) { |
79 var method; | 86 var method; |
80 if (object is Type) { | 87 if (object is Type) { |
| 88 var classMethods = _staticMethods[object]; |
| 89 method = classMethods == null ? null : classMethods[name]; |
81 } else { | 90 } else { |
82 var getter = _getters[name]; | 91 var getter = _getters[name]; |
83 method = getter == null ? null : getter(object); | 92 method = getter == null ? null : getter(object); |
84 } | 93 } |
85 if (method == null) { | 94 if (method == null) { |
86 throw new MissingCodeException('method "$name" in $object'); | 95 throw new MissingCodeException('method "$name" in $object'); |
87 } | 96 } |
88 var tentativeError; | 97 var tentativeError; |
89 if (adjust) { | 98 if (adjust) { |
90 var min = minArgs(method); | 99 var min = minArgs(method); |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 | 255 |
247 /// Exception thrown when trynig to access something that should be there, but | 256 /// Exception thrown when trynig to access something that should be there, but |
248 /// the code generator didn't include it. | 257 /// the code generator didn't include it. |
249 class MissingCodeException implements Exception { | 258 class MissingCodeException implements Exception { |
250 final String description; | 259 final String description; |
251 MissingCodeException(this.description); | 260 MissingCodeException(this.description); |
252 | 261 |
253 String toString() => 'Missing $description. ' | 262 String toString() => 'Missing $description. ' |
254 'Code generation for the smoke package seems incomplete.'; | 263 'Code generation for the smoke package seems incomplete.'; |
255 } | 264 } |
OLD | NEW |