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

Unified Diff: observatory_pub_packages/smoke/static.dart

Issue 816693004: Add observatory_pub_packages snapshot to third_party (Closed) Base URL: http://dart.googlecode.com/svn/third_party/
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 side-by-side diff with in-line comments
Download patch
Index: observatory_pub_packages/smoke/static.dart
===================================================================
--- observatory_pub_packages/smoke/static.dart (revision 0)
+++ observatory_pub_packages/smoke/static.dart (working copy)
@@ -0,0 +1,292 @@
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Static implementation of smoke services using code-generated data.
+library smoke.static;
+
+import 'dart:math' as math;
+
+import 'package:logging/logging.dart';
+import 'package:smoke/smoke.dart';
+
+import 'src/common.dart';
+
+typedef T Getter<T>(object);
+typedef void Setter<T>(object, value);
+
+class StaticConfiguration {
+ /// Maps symbol to a function that reads that symbol of an object. For
+ /// instance, `#i: (o) => o.i`.
+ final Map<Symbol, Getter> getters;
+
+ /// Maps symbol to a function that updates that symbol of an object. For
+ /// instance, `#i: (o, v) { o.i = v; }`.
+ final Map<Symbol, Setter> setters;
+
+ /// Maps a type to its super class. For example, String: Object.
+ final Map<Type, Type> parents;
+
+ /// For each type, a map of declarations per symbol (property or method).
+ final Map<Type, Map<Symbol, Declaration>> declarations;
+
+ /// Static methods for each type.
+ // TODO(sigmund): should we add static getters & setters too?
+ final Map<Type, Map<Symbol, Function>> staticMethods;
+
+ /// A map from symbol to strings.
+ final Map<Symbol, String> names;
+
+ /// A map from strings to symbols (the reverse of [names]).
+ final Map<String, Symbol> _symbols = {};
+
+
+ /// Whether to check for missing declarations, otherwise, return default
+ /// values (for example a missing parent class can be treated as Object)
+ final bool checkedMode;
+
+ StaticConfiguration({
+ Map<Symbol, Getter> getters,
+ Map<Symbol, Setter> setters,
+ Map<Type, Type> parents,
+ Map<Type, Map<Symbol, Declaration>> declarations,
+ Map<Type, Map<Symbol, Function>> staticMethods,
+ Map<Symbol, String> names,
+ this.checkedMode: true})
+ : getters = getters != null ? getters : {},
+ setters = setters != null ? setters : {},
+ parents = parents != null ? parents : {},
+ declarations = declarations != null ? declarations : {},
+ staticMethods = staticMethods != null ? staticMethods : {},
+ names = names != null ? names : {} {
+ this.names.forEach((k, v) { _symbols[v] = k; });
+ }
+
+ void addAll(StaticConfiguration other) {
+ getters.addAll(other.getters);
+ setters.addAll(other.setters);
+ parents.addAll(other.parents);
+ _nestedAddAll(declarations, other.declarations);
+ _nestedAddAll(staticMethods, other.staticMethods);
+ names.addAll(other.names);
+ other.names.forEach((k, v) { _symbols[v] = k; });
+ }
+
+ static _nestedAddAll(Map a, Map b) {
+ for (var key in b.keys) {
+ a.putIfAbsent(key, () => {});
+ a[key].addAll(b[key]);
+ }
+ }
+}
+
+/// Set up the smoke package to use a static implementation based on the given
+/// [configuration].
+useGeneratedCode(StaticConfiguration configuration) {
+ configure(new GeneratedObjectAccessorService(configuration),
+ new GeneratedTypeInspectorService(configuration),
+ new GeneratedSymbolConverterService(configuration));
+}
+
+/// Implements [ObjectAccessorService] using a static configuration.
+class GeneratedObjectAccessorService implements ObjectAccessorService {
+ final StaticConfiguration _configuration;
+ Map<Symbol, Getter> get _getters => _configuration.getters;
+ Map<Symbol, Setter> get _setters => _configuration.setters;
+ Map<Type, Map<Symbol, Function>> get _staticMethods =>
+ _configuration.staticMethods;
+
+ GeneratedObjectAccessorService(this._configuration);
+
+ read(Object object, Symbol name) {
+ var getter = _getters[name];
+ if (getter == null) {
+ throw new MissingCodeException('getter "$name" in $object');
+ }
+ return getter(object);
+ }
+
+ void write(Object object, Symbol name, value) {
+ var setter = _setters[name];
+ if (setter == null) {
+ throw new MissingCodeException('setter "$name" in $object');
+ }
+ setter(object, value);
+ }
+
+ invoke(object, Symbol name, List args, {Map namedArgs, bool adjust: false}) {
+ var method;
+ if (object is Type && name != #toString) {
+ var classMethods = _staticMethods[object];
+ method = classMethods == null ? null : classMethods[name];
+ } else {
+ var getter = _getters[name];
+ method = getter == null ? null : getter(object);
+ }
+ if (method == null) {
+ throw new MissingCodeException('method "$name" in $object');
+ }
+ var tentativeError;
+ if (adjust) {
+ var min = minArgs(method);
+ if (min > SUPPORTED_ARGS) {
+ tentativeError = 'we tried to adjust the arguments for calling "$name"'
+ ', but we couldn\'t determine the exact number of arguments it '
+ 'expects (it is more than $SUPPORTED_ARGS).';
+ // The argument list might be correct, so we still invoke the function
+ // and let the user see the error.
+ args = adjustList(args, min, math.max(min, args.length));
+ } else {
+ var max = maxArgs(method);
+ args = adjustList(args, min, max >= 0 ? max : args.length);
+ }
+ }
+ if (namedArgs != null) {
+ throw new UnsupportedError(
+ 'smoke.static doesn\'t support namedArguments in invoke');
+ }
+ try {
+ return Function.apply(method, args);
+ } on NoSuchMethodError catch (e) {
+ // TODO(sigmund): consider whether this should just be in a logger or if
+ // we should wrap `e` as a new exception (what's the best way to let users
+ // know about this tentativeError?)
+ if (tentativeError != null) print(tentativeError);
+ rethrow;
+ }
+ }
+}
+
+/// Implements [TypeInspectorService] using a static configuration.
+class GeneratedTypeInspectorService implements TypeInspectorService {
+ final StaticConfiguration _configuration;
+
+ Map<Type, Type> get _parents => _configuration.parents;
+ Map<Type, Map<Symbol, Declaration>> get _declarations =>
+ _configuration.declarations;
+ bool get _checkedMode => _configuration.checkedMode;
+
+ GeneratedTypeInspectorService(this._configuration);
+
+ bool isSubclassOf(Type type, Type supertype) {
+ if (type == supertype || supertype == Object) return true;
+ while (type != Object) {
+ var parentType = _parents[type];
+ if (parentType == supertype) return true;
+ if (parentType == null) {
+ if (!_checkedMode) return false;
+ throw new MissingCodeException('superclass of "$type" ($parentType)');
+ }
+ type = parentType;
+ }
+ return false;
+ }
+
+ bool hasGetter(Type type, Symbol name) {
+ var decl = _findDeclaration(type, name);
+ // No need to check decl.isProperty because methods are also automatically
+ // considered getters (auto-closures).
+ return decl != null && !decl.isStatic;
+ }
+
+ bool hasSetter(Type type, Symbol name) {
+ var decl = _findDeclaration(type, name);
+ return decl != null && !decl.isMethod && !decl.isFinal && !decl.isStatic;
+ }
+
+ bool hasInstanceMethod(Type type, Symbol name) {
+ var decl = _findDeclaration(type, name);
+ return decl != null && decl.isMethod && !decl.isStatic;
+ }
+
+ bool hasStaticMethod(Type type, Symbol name) {
+ final map = _declarations[type];
+ if (map == null) {
+ if (!_checkedMode) return false;
+ throw new MissingCodeException('declarations for $type');
+ }
+ final decl = map[name];
+ return decl != null && decl.isMethod && decl.isStatic;
+ }
+
+ Declaration getDeclaration(Type type, Symbol name) {
+ var decl = _findDeclaration(type, name);
+ if (decl == null) {
+ if (!_checkedMode) return null;
+ throw new MissingCodeException('declaration for $type.$name');
+ }
+ return decl;
+ }
+
+ List<Declaration> query(Type type, QueryOptions options) {
+ var result = [];
+ if (options.includeInherited) {
+ var superclass = _parents[type];
+ if (superclass == null) {
+ if (_checkedMode) {
+ throw new MissingCodeException('superclass of "$type"');
+ }
+ } else if (superclass != options.includeUpTo) {
+ result = query(superclass, options);
+ }
+ }
+ var map = _declarations[type];
+ if (map == null) {
+ if (!_checkedMode) return result;
+ throw new MissingCodeException('declarations for $type');
+ }
+ for (var decl in map.values) {
+ if (!options.includeFields && decl.isField) continue;
+ if (!options.includeProperties && decl.isProperty) continue;
+ if (options.excludeFinal && decl.isFinal) continue;
+ if (!options.includeMethods && decl.isMethod) continue;
+ if (options.matches != null && !options.matches(decl.name)) continue;
+ if (options.withAnnotations != null &&
+ !matchesAnnotation(decl.annotations, options.withAnnotations)) {
+ continue;
+ }
+ result.add(decl);
+ }
+ return result;
+ }
+
+ Declaration _findDeclaration(Type type, Symbol name) {
+ while (type != Object) {
+ final declarations = _declarations[type];
+ if (declarations != null) {
+ final declaration = declarations[name];
+ if (declaration != null) return declaration;
+ }
+ var parentType = _parents[type];
+ if (parentType == null) {
+ if (!_checkedMode) return null;
+ throw new MissingCodeException('superclass of "$type"');
+ }
+ type = parentType;
+ }
+ return null;
+ }
+}
+
+/// Implements [SymbolConverterService] using a static configuration.
+class GeneratedSymbolConverterService implements SymbolConverterService {
+ final StaticConfiguration _configuration;
+ Map<Symbol, String> get _names => _configuration.names;
+ Map<String, Symbol> get _symbols => _configuration._symbols;
+
+ GeneratedSymbolConverterService(this._configuration);
+
+ String symbolToName(Symbol symbol) => _names[symbol];
+ Symbol nameToSymbol(String name) => _symbols[name];
+}
+
+
+/// Exception thrown when trynig to access something that should be there, but
+/// the code generator didn't include it.
+class MissingCodeException implements Exception {
+ final String description;
+ MissingCodeException(this.description);
+
+ String toString() => 'Missing $description. '
+ 'Code generation for the smoke package seems incomplete.';
+}
« no previous file with comments | « observatory_pub_packages/smoke/src/implementation.dart ('k') | observatory_pub_packages/smoke/static_debug.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698