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

Unified Diff: packages/smoke/lib/codegen/recorder.dart

Issue 2989763002: Update charted to 0.4.8 and roll (Closed)
Patch Set: Removed Cutch from list of reviewers Created 3 years, 5 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « packages/smoke/lib/codegen/generator.dart ('k') | packages/smoke/lib/mirrors.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: packages/smoke/lib/codegen/recorder.dart
diff --git a/packages/smoke/lib/codegen/recorder.dart b/packages/smoke/lib/codegen/recorder.dart
deleted file mode 100644
index 8a9ebf1323891c1ebeb38e6ce9397d78e32a5352..0000000000000000000000000000000000000000
--- a/packages/smoke/lib/codegen/recorder.dart
+++ /dev/null
@@ -1,405 +0,0 @@
-// 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.
-
-/// Records accesses to Dart program declarations and generates code that will
-/// allow to do the same accesses at runtime using `package:smoke/static.dart`.
-/// Internally, this library relies on the `analyzer` to extract data from the
-/// program, and then uses [SmokeCodeGenerator] to produce the code needed by
-/// the smoke system.
-///
-/// This library only uses the analyzer to consume data previously produced by
-/// running the resolver. This library does not provide any hooks to integrate
-/// running the analyzer itself. See `package:code_transformers` to integrate
-/// the analyzer into pub transformers.
-library smoke.codegen.recorder;
-
-import 'package:analyzer/src/generated/element.dart';
-import 'package:analyzer/src/generated/ast.dart';
-import 'generator.dart';
-
-typedef String ImportUrlResolver(LibraryElement lib);
-
-/// A recorder that tracks how elements are accessed in order to generate code
-/// that replicates those accesses with the smoke runtime.
-class Recorder {
- /// Underlying code generator.
- SmokeCodeGenerator generator;
-
- /// Function that provides the import url for a library element. This may
- /// internally use the resolver to resolve the import url.
- ImportUrlResolver importUrlFor;
-
- Recorder(this.generator, this.importUrlFor);
-
- /// Stores mixins that have been recorded and associates a type identifier
- /// with them. Mixins don't have an associated identifier in the code, so we
- /// generate a unique identifier for them and use it throughout the code.
- Map<TypeIdentifier, Map<ClassElement, TypeIdentifier>> _mixins = {};
-
- /// Adds the superclass information of [type] (including intermediate mixins).
- /// This will not generate data for direct subtypes of Object, as that is
- /// considered redundant information.
- void lookupParent(ClassElement type) {
- var parent = type.supertype;
- var mixins = type.mixins;
- if (parent == null && mixins.isEmpty) return; // type is Object
- var baseType = parent.element;
- var baseId = _typeFor(baseType);
- if (mixins.isNotEmpty) {
- _mixins.putIfAbsent(baseId, () => {});
- for (var m in mixins) {
- var mixinType = m.element;
- var mixinId = _mixins[baseId].putIfAbsent(mixinType, () {
- var comment = '${baseId.name} & ${mixinType.name}';
- return generator.createMixinType(comment);
- });
- if (!baseType.type.isObject) generator.addParent(mixinId, baseId);
- baseType = mixinType;
- baseId = mixinId;
- _mixins.putIfAbsent(mixinId, () => {});
- }
- }
- if (!baseType.type.isObject) generator.addParent(_typeFor(type), baseId);
- }
-
- TypeIdentifier _typeFor(Element type) => new TypeIdentifier(
- type.library == null ? 'dart:core' : importUrlFor(type.library),
- type.displayName);
-
- /// Adds any declaration and superclass information that is needed to answer a
- /// query on [type] that matches [options]. Also adds symbols, getters, and
- /// setters if [includeAccessors] is true. If [results] is not null, it will
- /// be filled up with the members that match the query.
- void runQuery(ClassElement type, QueryOptions options,
- {bool includeAccessors: true, List results}) {
- if (type.type.isObject) return; // We don't include Object in query results.
- var id = _typeFor(type);
- var parent = type.supertype != null ? type.supertype.element : null;
- if (options.includeInherited &&
- parent != null &&
- parent != options.includeUpTo) {
- lookupParent(type);
- runQuery(parent, options, includeAccessors: includeAccessors);
- var parentId = _typeFor(parent);
- for (var m in type.mixins) {
- var mixinClass = m.element;
- var mixinId = _mixins[parentId][mixinClass];
- _runQueryInternal(
- mixinClass, mixinId, options, includeAccessors, results);
- parentId = mixinId;
- }
- }
- _runQueryInternal(type, id, options, includeAccessors, results);
- }
-
- /// Helper for [runQuery]. This runs the query only on a specific [type],
- /// which could be a class or a mixin labeled by [id].
- // TODO(sigmund): currently we materialize mixins in smoke/static.dart,
- // we should consider to include the mixin declaration information directly,
- // and remove the duplication we have for mixins today.
- void _runQueryInternal(ClassElement type, TypeIdentifier id,
- QueryOptions options, bool includeAccessors, List results) {
- skipBecauseOfAnnotations(Element e) {
- if (options.withAnnotations == null) return false;
- return !_matchesAnnotation(e.metadata, options.withAnnotations);
- }
-
- if (options.includeFields) {
- for (var f in type.fields) {
- if (f.isStatic) continue;
- if (f.isSynthetic) continue; // exclude getters
- if (options.excludeFinal && f.isFinal) continue;
- var name = f.displayName;
- if (options.matches != null && !options.matches(name)) continue;
- if (skipBecauseOfAnnotations(f)) continue;
- if (results != null) results.add(f);
- generator.addDeclaration(id, name, _typeFor(f.type.element),
- isField: true,
- isFinal: f.isFinal,
- annotations: _copyAnnotations(f));
- if (includeAccessors) _addAccessors(name, !f.isFinal);
- }
- }
-
- if (options.includeProperties) {
- for (var a in type.accessors) {
- if (a is! PropertyAccessorElement) continue;
- if (a.isStatic || !a.isGetter) continue;
- var v = a.variable;
- if (v is FieldElement && !v.isSynthetic) continue; // exclude fields
- if (options.excludeFinal && v.isFinal) continue;
- var name = v.displayName;
- if (options.matches != null && !options.matches(name)) continue;
- if (skipBecauseOfAnnotations(a)) continue;
- if (results != null) results.add(a);
- generator.addDeclaration(id, name, _typeFor(a.type.returnType.element),
- isProperty: true,
- isFinal: v.isFinal,
- annotations: _copyAnnotations(a));
- if (includeAccessors) _addAccessors(name, !v.isFinal);
- }
- }
-
- if (options.includeMethods) {
- for (var m in type.methods) {
- if (m.isStatic) continue;
- var name = m.displayName;
- if (options.matches != null && !options.matches(name)) continue;
- if (skipBecauseOfAnnotations(m)) continue;
- if (results != null) results.add(m);
- generator.addDeclaration(
- id, name, new TypeIdentifier('dart:core', 'Function'),
- isMethod: true, annotations: _copyAnnotations(m));
- if (includeAccessors) _addAccessors(name, false);
- }
- }
- }
-
- /// Adds the declaration of [name] if it was found in [type]. If [recursive]
- /// is true, then we continue looking up [name] in the parent classes until we
- /// find it or we reach [includeUpTo] or Object. Returns whether the
- /// declaration was found. When a declaration is found, add also a symbol,
- /// getter, and setter if [includeAccessors] is true.
- bool lookupMember(ClassElement type, String name, {bool recursive: false,
- bool includeAccessors: true, ClassElement includeUpTo}) =>
- _lookupMemberInternal(
- type, _typeFor(type), name, recursive, includeAccessors, includeUpTo);
-
- /// Helper for [lookupMember] that walks up the type hierarchy including mixin
- /// classes.
- bool _lookupMemberInternal(ClassElement type, TypeIdentifier id, String name,
- bool recursive, bool includeAccessors, ClassElement includeUpTo) {
- // Exclude members from [Object].
- if (type.type.isObject) return false;
- generator.addEmptyDeclaration(id);
- for (var f in type.fields) {
- if (f.displayName != name) continue;
- if (f.isSynthetic) continue; // exclude getters
- generator.addDeclaration(id, name, _typeFor(f.type.element),
- isField: true,
- isFinal: f.isFinal,
- isStatic: f.isStatic,
- annotations: _copyAnnotations(f));
- if (includeAccessors && !f.isStatic) _addAccessors(name, !f.isFinal);
- return true;
- }
-
- for (var a in type.accessors) {
- if (a is! PropertyAccessorElement) continue;
- // TODO(sigmund): support setters without getters.
- if (!a.isGetter) continue;
- if (a.displayName != name) continue;
- var v = a.variable;
- if (v is FieldElement && !v.isSynthetic) continue; // exclude fields
- generator.addDeclaration(id, name, _typeFor(a.type.returnType.element),
- isProperty: true,
- isFinal: v.isFinal,
- isStatic: a.isStatic,
- annotations: _copyAnnotations(a));
- if (includeAccessors && !v.isStatic) _addAccessors(name, !v.isFinal);
- return true;
- }
-
- for (var m in type.methods) {
- if (m.displayName != name) continue;
- generator.addDeclaration(
- id, name, new TypeIdentifier('dart:core', 'Function'),
- isMethod: true,
- isStatic: m.isStatic,
- annotations: _copyAnnotations(m));
- if (includeAccessors) {
- if (m.isStatic) {
- generator.addStaticMethod(id, name);
- generator.addSymbol(name);
- } else {
- _addAccessors(name, false);
- }
- }
- return true;
- }
-
- if (recursive) {
- lookupParent(type);
- var parent = type.supertype != null ? type.supertype.element : null;
- if (parent == null || parent == includeUpTo) return false;
- var parentId = _typeFor(parent);
- for (var m in type.mixins) {
- var mixinClass = m.element;
- var mixinId = _mixins[parentId][mixinClass];
- if (_lookupMemberInternal(
- mixinClass, mixinId, name, false, includeAccessors, includeUpTo)) {
- return true;
- }
- parentId = mixinId;
- }
- return _lookupMemberInternal(
- parent, parentId, name, true, includeAccessors, includeUpTo);
- }
- return false;
- }
-
- /// Add information so smoke can invoke the static method [type].[name].
- void addStaticMethod(ClassElement type, String name) {
- generator.addStaticMethod(_typeFor(type), name);
- }
-
- /// Adds [name] as a symbol, a getter, and optionally a setter in [generator].
- _addAccessors(String name, bool includeSetter) {
- generator.addSymbol(name);
- generator.addGetter(name);
- if (includeSetter) generator.addSetter(name);
- }
-
- /// Copy metadata associated with the declaration of [target].
- List<ConstExpression> _copyAnnotations(Element target) {
- var node = target.computeNode();
- // [node] is the initialization expression, we walk up to get to the actual
- // member declaration where the metadata is attached to.
- while (node is! ClassMember) node = node.parent;
- return node.metadata.map(_convertAnnotation).toList();
- }
-
- /// Converts annotations into [ConstExpression]s supported by the codegen
- /// library.
- ConstExpression _convertAnnotation(Annotation annotation) {
- var element = annotation.element;
- if (element is ConstructorElement) {
- if (!element.name.isEmpty) {
- throw new UnimplementedError(
- 'named constructors are not implemented in smoke.codegen.recorder');
- }
-
- var positionalArgs = [];
- var namedArgs = {};
- for (var arg in annotation.arguments.arguments) {
- if (arg is NamedExpression) {
- namedArgs[arg.name.label.name] = _convertExpression(arg.expression);
- } else {
- positionalArgs.add(_convertExpression(arg));
- }
- }
-
- return new ConstructorExpression(importUrlFor(element.library),
- element.enclosingElement.name, positionalArgs, namedArgs);
- }
-
- if (element is PropertyAccessorElement) {
- return new TopLevelIdentifier(
- importUrlFor(element.library), element.name);
- }
-
- throw new UnsupportedError('unsupported annotation $annotation');
- }
-
- /// Converts [expression] into a [ConstExpression].
- ConstExpression _convertExpression(Expression expression) {
- if (expression is StringLiteral) {
- return new ConstExpression.string(expression.stringValue);
- }
-
- if (expression is BooleanLiteral ||
- expression is DoubleLiteral ||
- expression is IntegerLiteral ||
- expression is NullLiteral) {
- return new CodeAsConstExpression("${(expression as dynamic).value}");
- }
-
- if (expression is Identifier) {
- var element = expression.bestElement;
- if (element == null || !element.isPublic) {
- throw new UnsupportedError('private constants are not supported');
- }
-
- var url = importUrlFor(element.library);
- if (element is ClassElement) {
- return new TopLevelIdentifier(url, element.name);
- }
-
- if (element is PropertyAccessorElement) {
- var variable = element.variable;
- if (variable is FieldElement) {
- var cls = variable.enclosingElement;
- return new TopLevelIdentifier(url, '${cls.name}.${variable.name}');
- } else if (variable is TopLevelVariableElement) {
- return new TopLevelIdentifier(url, variable.name);
- }
- }
- }
-
- throw new UnimplementedError('expression convertion not implemented in '
- 'smoke.codegen.recorder (${expression.runtimeType} $expression)');
- }
-}
-
-/// Returns whether [metadata] contains any annotation that is either equal to
-/// an annotation in [queryAnnotations] or whose type is a subclass of a type
-/// listed in [queryAnnotations]. This is equivalent to the check done in
-/// `src/common.dart#matchesAnnotation`, except that this is applied to
-/// static metadata as it was provided by the analyzer.
-bool _matchesAnnotation(
- Iterable<ElementAnnotation> metadata, Iterable<Element> queryAnnotations) {
- for (var meta in metadata) {
- var element = meta.element;
- var exp;
- var type;
- if (element is PropertyAccessorElement) {
- exp = element.variable;
- type = exp.evaluationResult.value.type;
- } else if (element is ConstructorElement) {
- exp = element;
- type = element.enclosingElement.type;
- } else {
- throw new UnimplementedError('Unsupported annotation: ${meta}');
- }
- for (var queryMeta in queryAnnotations) {
- if (exp == queryMeta) return true;
- if (queryMeta is ClassElement && type.isSubtypeOf(queryMeta.type)) {
- return true;
- }
- }
- }
- return false;
-}
-
-/// Options equivalent to `smoke.dart#QueryOptions`, except that type
-/// information and annotations are denoted by resolver's elements.
-class QueryOptions {
- /// Whether to include fields (default is true).
- final bool includeFields;
-
- /// Whether to include getters and setters (default is true). Note that to
- /// include fields you also need to enable [includeFields].
- final bool includeProperties;
-
- /// Whether to include symbols from the given type and its superclasses
- /// (except [Object]).
- final bool includeInherited;
-
- /// If [includeInherited], walk up the type hierarchy up to this type
- /// (defaults to [Object]).
- final ClassElement includeUpTo;
-
- /// Whether to include final fields and getter-only properties.
- final bool excludeFinal;
-
- /// Whether to include methods (default is false).
- final bool includeMethods;
-
- /// If [withAnnotation] is not null, then it should be a list of types, so
- /// only symbols that are annotated with instances of those types are
- /// included.
- final List<Element> withAnnotations;
-
- /// If [matches] is not null, then only those fields, properties, or methods
- /// that match will be included.
- final NameMatcher matches;
-
- const QueryOptions({this.includeFields: true, this.includeProperties: true,
- this.includeInherited: true, this.includeUpTo: null,
- this.excludeFinal: false, this.includeMethods: false,
- this.withAnnotations: null, this.matches: null});
-}
-
-/// Predicate that tells whether [name] should be included in query results.
-typedef bool NameMatcher(String name);
« no previous file with comments | « packages/smoke/lib/codegen/generator.dart ('k') | packages/smoke/lib/mirrors.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698