| 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 /// Records accesses to Dart program declarations and generates code that will | 5 /// Records accesses to Dart program declarations and generates code that will |
| 6 /// allow to do the same accesses at runtime using `package:smoke/static.dart`. | 6 /// allow to do the same accesses at runtime using `package:smoke/static.dart`. |
| 7 /// Internally, this library relies on the `analyzer` to extract data from the | 7 /// Internally, this library relies on the `analyzer` to extract data from the |
| 8 /// program, and then uses [SmokeCodeGenerator] to produce the code needed by | 8 /// program, and then uses [SmokeCodeGenerator] to produce the code needed by |
| 9 /// the smoke system. | 9 /// the smoke system. |
| 10 /// | 10 /// |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 62 } | 62 } |
| 63 if (!baseType.type.isObject) generator.addParent(_typeFor(type), baseId); | 63 if (!baseType.type.isObject) generator.addParent(_typeFor(type), baseId); |
| 64 } | 64 } |
| 65 | 65 |
| 66 TypeIdentifier _typeFor(Element type) => new TypeIdentifier( | 66 TypeIdentifier _typeFor(Element type) => new TypeIdentifier( |
| 67 type.library == null ? 'dart:core' : importUrlFor(type.library), | 67 type.library == null ? 'dart:core' : importUrlFor(type.library), |
| 68 type.displayName); | 68 type.displayName); |
| 69 | 69 |
| 70 /// Adds any declaration and superclass information that is needed to answer a | 70 /// Adds any declaration and superclass information that is needed to answer a |
| 71 /// query on [type] that matches [options]. Also adds symbols, getters, and | 71 /// query on [type] that matches [options]. Also adds symbols, getters, and |
| 72 /// setters if [includeAccessors] is true. | 72 /// setters if [includeAccessors] is true. If [results] is not null, it will |
| 73 /// be filled up with the members that match the query. |
| 73 void runQuery(ClassElement type, QueryOptions options, | 74 void runQuery(ClassElement type, QueryOptions options, |
| 74 {bool includeAccessors: true}) { | 75 {bool includeAccessors: true, List results}) { |
| 75 if (type.type.isObject) return; // We don't include Object in query results. | 76 if (type.type.isObject) return; // We don't include Object in query results. |
| 76 var id = _typeFor(type); | 77 var id = _typeFor(type); |
| 77 var parent = type.supertype != null ? type.supertype.element : null; | 78 var parent = type.supertype != null ? type.supertype.element : null; |
| 78 if (options.includeInherited && parent != null && | 79 if (options.includeInherited && parent != null && |
| 79 parent != options.includeUpTo) { | 80 parent != options.includeUpTo) { |
| 80 lookupParent(type); | 81 lookupParent(type); |
| 81 runQuery(parent, options, includeAccessors: includeAccessors); | 82 runQuery(parent, options, includeAccessors: includeAccessors); |
| 82 var parentId = _typeFor(parent); | 83 var parentId = _typeFor(parent); |
| 83 for (var m in type.mixins) { | 84 for (var m in type.mixins) { |
| 84 var mixinClass = m.element; | 85 var mixinClass = m.element; |
| 85 var mixinId = _mixins[parentId][mixinClass]; | 86 var mixinId = _mixins[parentId][mixinClass]; |
| 86 _runQueryInternal(mixinClass, mixinId, options, includeAccessors); | 87 _runQueryInternal( |
| 88 mixinClass, mixinId, options, includeAccessors, results); |
| 87 parentId = mixinId; | 89 parentId = mixinId; |
| 88 } | 90 } |
| 89 } | 91 } |
| 90 _runQueryInternal(type, id, options, includeAccessors); | 92 _runQueryInternal(type, id, options, includeAccessors, results); |
| 91 } | 93 } |
| 92 | 94 |
| 93 /// Helper for [runQuery]. This runs the query only on a specific [type], | 95 /// Helper for [runQuery]. This runs the query only on a specific [type], |
| 94 /// which could be a class or a mixin labeled by [id]. | 96 /// which could be a class or a mixin labeled by [id]. |
| 95 // TODO(sigmund): currently we materialize mixins in smoke/static.dart, | 97 // TODO(sigmund): currently we materialize mixins in smoke/static.dart, |
| 96 // we should consider to include the mixin declaration information directly, | 98 // we should consider to include the mixin declaration information directly, |
| 97 // and remove the duplication we have for mixins today. | 99 // and remove the duplication we have for mixins today. |
| 98 void _runQueryInternal(ClassElement type, TypeIdentifier id, | 100 void _runQueryInternal(ClassElement type, TypeIdentifier id, |
| 99 QueryOptions options, bool includeAccessors) { | 101 QueryOptions options, bool includeAccessors, List results) { |
| 100 | 102 |
| 101 skipBecauseOfAnnotations(Element e) { | 103 skipBecauseOfAnnotations(Element e) { |
| 102 if (options.withAnnotations == null) return false; | 104 if (options.withAnnotations == null) return false; |
| 103 return !_matchesAnnotation(e.metadata, options.withAnnotations); | 105 return !_matchesAnnotation(e.metadata, options.withAnnotations); |
| 104 } | 106 } |
| 105 | 107 |
| 106 if (options.includeFields) { | 108 if (options.includeFields) { |
| 107 for (var f in type.fields) { | 109 for (var f in type.fields) { |
| 108 if (f.isStatic) continue; | 110 if (f.isStatic) continue; |
| 109 if (f.isSynthetic) continue; // exclude getters | 111 if (f.isSynthetic) continue; // exclude getters |
| 110 if (options.excludeFinal && f.isFinal) continue; | 112 if (options.excludeFinal && f.isFinal) continue; |
| 111 var name = f.displayName; | 113 var name = f.displayName; |
| 112 if (options.matches != null && !options.matches(name)) continue; | 114 if (options.matches != null && !options.matches(name)) continue; |
| 113 if (skipBecauseOfAnnotations(f)) continue; | 115 if (skipBecauseOfAnnotations(f)) continue; |
| 116 if (results != null) results.add(f); |
| 114 generator.addDeclaration(id, name, _typeFor(f.type.element), | 117 generator.addDeclaration(id, name, _typeFor(f.type.element), |
| 115 isField: true, isFinal: f.isFinal, | 118 isField: true, isFinal: f.isFinal, |
| 116 annotations: _copyAnnotations(f)); | 119 annotations: _copyAnnotations(f)); |
| 117 if (includeAccessors) _addAccessors(name, !f.isFinal); | 120 if (includeAccessors) _addAccessors(name, !f.isFinal); |
| 118 } | 121 } |
| 119 } | 122 } |
| 120 | 123 |
| 121 if (options.includeProperties) { | 124 if (options.includeProperties) { |
| 122 for (var a in type.accessors) { | 125 for (var a in type.accessors) { |
| 123 if (a is! PropertyAccessorElement) continue; | 126 if (a is! PropertyAccessorElement) continue; |
| 124 if (a.isStatic || !a.isGetter) continue; | 127 if (a.isStatic || !a.isGetter) continue; |
| 125 var v = a.variable; | 128 var v = a.variable; |
| 126 if (v is FieldElement && !v.isSynthetic) continue; // exclude fields | 129 if (v is FieldElement && !v.isSynthetic) continue; // exclude fields |
| 127 if (options.excludeFinal && v.isFinal) continue; | 130 if (options.excludeFinal && v.isFinal) continue; |
| 128 var name = v.displayName; | 131 var name = v.displayName; |
| 129 if (options.matches != null && !options.matches(name)) continue; | 132 if (options.matches != null && !options.matches(name)) continue; |
| 130 if (skipBecauseOfAnnotations(a)) continue; | 133 if (skipBecauseOfAnnotations(a)) continue; |
| 134 if (results != null) results.add(a); |
| 131 generator.addDeclaration(id, name, _typeFor(a.type.returnType.element), | 135 generator.addDeclaration(id, name, _typeFor(a.type.returnType.element), |
| 132 isProperty: true, isFinal: v.isFinal, | 136 isProperty: true, isFinal: v.isFinal, |
| 133 annotations: _copyAnnotations(a)); | 137 annotations: _copyAnnotations(a)); |
| 134 if (includeAccessors) _addAccessors(name, !v.isFinal); | 138 if (includeAccessors) _addAccessors(name, !v.isFinal); |
| 135 } | 139 } |
| 136 } | 140 } |
| 137 | 141 |
| 138 if (options.includeMethods) { | 142 if (options.includeMethods) { |
| 139 for (var m in type.methods) { | 143 for (var m in type.methods) { |
| 140 if (m.isStatic) continue; | 144 if (m.isStatic) continue; |
| 141 var name = m.displayName; | 145 var name = m.displayName; |
| 142 if (options.matches != null && !options.matches(name)) continue; | 146 if (options.matches != null && !options.matches(name)) continue; |
| 143 if (skipBecauseOfAnnotations(m)) continue; | 147 if (skipBecauseOfAnnotations(m)) continue; |
| 148 if (results != null) results.add(m); |
| 144 generator.addDeclaration(id, name, | 149 generator.addDeclaration(id, name, |
| 145 new TypeIdentifier('dart:core', 'Function'), isMethod: true, | 150 new TypeIdentifier('dart:core', 'Function'), isMethod: true, |
| 146 annotations: _copyAnnotations(m)); | 151 annotations: _copyAnnotations(m)); |
| 147 if (includeAccessors) _addAccessors(name, false); | 152 if (includeAccessors) _addAccessors(name, false); |
| 148 } | 153 } |
| 149 } | 154 } |
| 150 } | 155 } |
| 151 | 156 |
| 152 /// Adds the declaration of [name] if it was found in [type]. If [recursive] | 157 /// Adds the declaration of [name] if it was found in [type]. If [recursive] |
| 153 /// is true, then we continue looking up [name] in the parent classes until we | 158 /// is true, then we continue looking up [name] in the parent classes until we |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 387 this.includeInherited: true, | 392 this.includeInherited: true, |
| 388 this.includeUpTo: null, | 393 this.includeUpTo: null, |
| 389 this.excludeFinal: false, | 394 this.excludeFinal: false, |
| 390 this.includeMethods: false, | 395 this.includeMethods: false, |
| 391 this.withAnnotations: null, | 396 this.withAnnotations: null, |
| 392 this.matches: null}); | 397 this.matches: null}); |
| 393 } | 398 } |
| 394 | 399 |
| 395 /// Predicate that tells whether [name] should be included in query results. | 400 /// Predicate that tells whether [name] should be included in query results. |
| 396 typedef bool NameMatcher(String name); | 401 typedef bool NameMatcher(String name); |
| OLD | NEW |