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 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 generator.addDeclaration(id, name, | 144 generator.addDeclaration(id, name, |
145 new TypeIdentifier('dart:core', 'Function'), isMethod: true, | 145 new TypeIdentifier('dart:core', 'Function'), isMethod: true, |
146 annotations: _copyAnnotations(m)); | 146 annotations: _copyAnnotations(m)); |
147 if (includeAccessors) _addAccessors(name, false); | 147 if (includeAccessors) _addAccessors(name, false); |
148 } | 148 } |
149 } | 149 } |
150 } | 150 } |
151 | 151 |
152 /// Adds the declaration of [name] if it was found in [type]. If [recursive] | 152 /// 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 | 153 /// is true, then we continue looking up [name] in the parent classes until we |
154 /// find it or we reach Object. Returns whether the declaration was found. | 154 /// find it or we reach [includeUpTo] or Object. Returns whether the |
155 /// When a declaration is found, add also a symbol, getter, and setter if | 155 /// declaration was found. When a declaration is found, add also a symbol, |
156 /// [includeAccessors] is true. | 156 /// getter, and setter if [includeAccessors] is true. |
157 bool lookupMember(ClassElement type, String name, {bool recursive: false, | 157 bool lookupMember(ClassElement type, String name, {bool recursive: false, |
158 bool includeAccessors: true}) => | 158 bool includeAccessors: true, ClassElement includeUpTo}) => |
159 _lookupMemberInternal(type, _typeFor(type), name, recursive, | 159 _lookupMemberInternal(type, _typeFor(type), name, recursive, |
160 includeAccessors); | 160 includeAccessors, includeUpTo); |
161 | 161 |
162 /// Helper for [lookupMember] that walks up the type hierarchy including mixin | 162 /// Helper for [lookupMember] that walks up the type hierarchy including mixin |
163 /// classes. | 163 /// classes. |
164 bool _lookupMemberInternal(ClassElement type, TypeIdentifier id, String name, | 164 bool _lookupMemberInternal(ClassElement type, TypeIdentifier id, String name, |
165 bool recursive, bool includeAccessors) { | 165 bool recursive, bool includeAccessors, ClassElement includeUpTo) { |
166 // Exclude members from [Object]. | 166 // Exclude members from [Object]. |
167 if (type.type.isObject) return false; | 167 if (type.type.isObject) return false; |
168 generator.addEmptyDeclaration(id); | 168 generator.addEmptyDeclaration(id); |
169 for (var f in type.fields) { | 169 for (var f in type.fields) { |
170 if (f.displayName != name) continue; | 170 if (f.displayName != name) continue; |
171 if (f.isSynthetic) continue; // exclude getters | 171 if (f.isSynthetic) continue; // exclude getters |
172 generator.addDeclaration(id, name, | 172 generator.addDeclaration(id, name, |
173 _typeFor(f.type.element), isField: true, isFinal: f.isFinal, | 173 _typeFor(f.type.element), isField: true, isFinal: f.isFinal, |
174 isStatic: f.isStatic, annotations: _copyAnnotations(f)); | 174 isStatic: f.isStatic, annotations: _copyAnnotations(f)); |
175 if (includeAccessors && !f.isStatic) _addAccessors(name, !f.isFinal); | 175 if (includeAccessors && !f.isStatic) _addAccessors(name, !f.isFinal); |
(...skipping 27 matching lines...) Expand all Loading... |
203 } else { | 203 } else { |
204 _addAccessors(name, false); | 204 _addAccessors(name, false); |
205 } | 205 } |
206 } | 206 } |
207 return true; | 207 return true; |
208 } | 208 } |
209 | 209 |
210 if (recursive) { | 210 if (recursive) { |
211 lookupParent(type); | 211 lookupParent(type); |
212 var parent = type.supertype != null ? type.supertype.element : null; | 212 var parent = type.supertype != null ? type.supertype.element : null; |
213 if (parent == null) return false; | 213 if (parent == null || parent == includeUpTo) return false; |
214 var parentId = _typeFor(parent); | 214 var parentId = _typeFor(parent); |
215 for (var m in type.mixins) { | 215 for (var m in type.mixins) { |
216 var mixinClass = m.element; | 216 var mixinClass = m.element; |
217 var mixinId = _mixins[parentId][mixinClass]; | 217 var mixinId = _mixins[parentId][mixinClass]; |
218 if (_lookupMemberInternal(mixinClass, mixinId, name, false, | 218 if (_lookupMemberInternal(mixinClass, mixinId, name, false, |
219 includeAccessors)) { | 219 includeAccessors, includeUpTo)) { |
220 return true; | 220 return true; |
221 } | 221 } |
222 parentId = mixinId; | 222 parentId = mixinId; |
223 } | 223 } |
224 return _lookupMemberInternal(parent, parentId, name, true, | 224 return _lookupMemberInternal(parent, parentId, name, true, |
225 includeAccessors); | 225 includeAccessors, includeUpTo); |
226 } | 226 } |
227 return false; | 227 return false; |
228 } | 228 } |
229 | 229 |
230 /// Add information so smoke can invoke the static method [type].[name]. | 230 /// Add information so smoke can invoke the static method [type].[name]. |
231 void addStaticMethod(ClassElement type, String name) { | 231 void addStaticMethod(ClassElement type, String name) { |
232 generator.addStaticMethod(_typeFor(type), name); | 232 generator.addStaticMethod(_typeFor(type), name); |
233 } | 233 } |
234 | 234 |
235 /// Adds [name] as a symbol, a getter, and optionally a setter in [generator]. | 235 /// Adds [name] as a symbol, a getter, and optionally a setter in [generator]. |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
387 this.includeInherited: true, | 387 this.includeInherited: true, |
388 this.includeUpTo: null, | 388 this.includeUpTo: null, |
389 this.excludeFinal: false, | 389 this.excludeFinal: false, |
390 this.includeMethods: false, | 390 this.includeMethods: false, |
391 this.withAnnotations: null, | 391 this.withAnnotations: null, |
392 this.matches: null}); | 392 this.matches: null}); |
393 } | 393 } |
394 | 394 |
395 /// Predicate that tells whether [name] should be included in query results. | 395 /// Predicate that tells whether [name] should be included in query results. |
396 typedef bool NameMatcher(String name); | 396 typedef bool NameMatcher(String name); |
OLD | NEW |