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 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 bool recursive, bool includeAccessors) { | 165 bool recursive, bool includeAccessors) { |
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) _addAccessors(name, !f.isFinal); | 175 if (includeAccessors && !f.isStatic) _addAccessors(name, !f.isFinal); |
176 return true; | 176 return true; |
177 } | 177 } |
178 | 178 |
179 for (var a in type.accessors) { | 179 for (var a in type.accessors) { |
180 if (a is! PropertyAccessorElement) continue; | 180 if (a is! PropertyAccessorElement) continue; |
181 // TODO(sigmund): support setters without getters. | 181 // TODO(sigmund): support setters without getters. |
182 if (!a.isGetter) continue; | 182 if (!a.isGetter) continue; |
183 if (a.displayName != name) continue; | 183 if (a.displayName != name) continue; |
184 var v = a.variable; | 184 var v = a.variable; |
185 if (v is FieldElement && !v.isSynthetic) continue; // exclude fields | 185 if (v is FieldElement && !v.isSynthetic) continue; // exclude fields |
186 generator.addDeclaration(id, name, | 186 generator.addDeclaration(id, name, |
187 _typeFor(a.type.returnType.element), isProperty: true, | 187 _typeFor(a.type.returnType.element), isProperty: true, |
188 isFinal: v.isFinal, isStatic: a.isStatic, | 188 isFinal: v.isFinal, isStatic: a.isStatic, |
189 annotations: _copyAnnotations(a)); | 189 annotations: _copyAnnotations(a)); |
190 if (includeAccessors) _addAccessors(name, !v.isFinal); | 190 if (includeAccessors && !v.isStatic) _addAccessors(name, !v.isFinal); |
191 return true; | 191 return true; |
192 } | 192 } |
193 | 193 |
194 for (var m in type.methods) { | 194 for (var m in type.methods) { |
195 if (m.displayName != name) continue; | 195 if (m.displayName != name) continue; |
196 generator.addDeclaration(id, name, | 196 generator.addDeclaration(id, name, |
197 new TypeIdentifier('dart:core', 'Function'), isMethod: true, | 197 new TypeIdentifier('dart:core', 'Function'), isMethod: true, |
198 isStatic: m.isStatic, annotations: _copyAnnotations(m)); | 198 isStatic: m.isStatic, annotations: _copyAnnotations(m)); |
199 if (includeAccessors) _addAccessors(name, false); | 199 if (includeAccessors) { |
| 200 if (m.isStatic) { |
| 201 generator.addStaticMethod(id, name); |
| 202 generator.addSymbol(name); |
| 203 } else { |
| 204 _addAccessors(name, false); |
| 205 } |
| 206 } |
200 return true; | 207 return true; |
201 } | 208 } |
202 | 209 |
203 if (recursive) { | 210 if (recursive) { |
204 lookupParent(type); | 211 lookupParent(type); |
205 var parent = type.supertype != null ? type.supertype.element : null; | 212 var parent = type.supertype != null ? type.supertype.element : null; |
206 if (parent == null) return false; | 213 if (parent == null) return false; |
207 var parentId = _typeFor(parent); | 214 var parentId = _typeFor(parent); |
208 for (var m in type.mixins) { | 215 for (var m in type.mixins) { |
209 var mixinClass = m.element; | 216 var mixinClass = m.element; |
210 var mixinId = _mixins[parentId][mixinClass]; | 217 var mixinId = _mixins[parentId][mixinClass]; |
211 if (_lookupMemberInternal(mixinClass, mixinId, name, false, | 218 if (_lookupMemberInternal(mixinClass, mixinId, name, false, |
212 includeAccessors)) { | 219 includeAccessors)) { |
213 return true; | 220 return true; |
214 } | 221 } |
215 parentId = mixinId; | 222 parentId = mixinId; |
216 } | 223 } |
217 return _lookupMemberInternal(parent, parentId, name, true, | 224 return _lookupMemberInternal(parent, parentId, name, true, |
218 includeAccessors); | 225 includeAccessors); |
219 } | 226 } |
220 return false; | 227 return false; |
221 } | 228 } |
222 | 229 |
| 230 /// Add information so smoke can invoke the static method [type].[name]. |
| 231 void addStaticMethod(ClassElement type, String name) { |
| 232 generator.addStaticMethod(_typeFor(type), name); |
| 233 } |
223 | 234 |
224 /// 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]. |
225 _addAccessors(String name, bool includeSetter) { | 236 _addAccessors(String name, bool includeSetter) { |
226 generator.addSymbol(name); | 237 generator.addSymbol(name); |
227 generator.addGetter(name); | 238 generator.addGetter(name); |
228 if (includeSetter) generator.addSetter(name); | 239 if (includeSetter) generator.addSetter(name); |
229 } | 240 } |
230 | 241 |
231 /// Copy metadata associated with the declaration of [target]. | 242 /// Copy metadata associated with the declaration of [target]. |
232 List<ConstExpression> _copyAnnotations(Element target) { | 243 List<ConstExpression> _copyAnnotations(Element target) { |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
376 this.includeInherited: true, | 387 this.includeInherited: true, |
377 this.includeUpTo: null, | 388 this.includeUpTo: null, |
378 this.excludeFinal: false, | 389 this.excludeFinal: false, |
379 this.includeMethods: false, | 390 this.includeMethods: false, |
380 this.withAnnotations: null, | 391 this.withAnnotations: null, |
381 this.matches: null}); | 392 this.matches: null}); |
382 } | 393 } |
383 | 394 |
384 /// Predicate that tells whether [name] should be included in query results. | 395 /// Predicate that tells whether [name] should be included in query results. |
385 typedef bool NameMatcher(String name); | 396 typedef bool NameMatcher(String name); |
OLD | NEW |