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

Side by Side Diff: lib/codegen/recorder.dart

Issue 1016913002: pkg/smoke: support latest analyzer version and formatted code (Closed) Base URL: https://github.com/dart-lang/smoke@master
Patch Set: updates Created 5 years, 9 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 unified diff | Download patch
« no previous file with comments | « lib/codegen/generator.dart ('k') | lib/mirrors.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
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. If [results] is not null, it will 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 /// be filled up with the members that match the query.
74 void runQuery(ClassElement type, QueryOptions options, 74 void runQuery(ClassElement type, QueryOptions options,
75 {bool includeAccessors: true, List results}) { 75 {bool includeAccessors: true, List results}) {
76 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.
77 var id = _typeFor(type); 77 var id = _typeFor(type);
78 var parent = type.supertype != null ? type.supertype.element : null; 78 var parent = type.supertype != null ? type.supertype.element : null;
79 if (options.includeInherited && parent != null && 79 if (options.includeInherited &&
80 parent != null &&
80 parent != options.includeUpTo) { 81 parent != options.includeUpTo) {
81 lookupParent(type); 82 lookupParent(type);
82 runQuery(parent, options, includeAccessors: includeAccessors); 83 runQuery(parent, options, includeAccessors: includeAccessors);
83 var parentId = _typeFor(parent); 84 var parentId = _typeFor(parent);
84 for (var m in type.mixins) { 85 for (var m in type.mixins) {
85 var mixinClass = m.element; 86 var mixinClass = m.element;
86 var mixinId = _mixins[parentId][mixinClass]; 87 var mixinId = _mixins[parentId][mixinClass];
87 _runQueryInternal( 88 _runQueryInternal(
88 mixinClass, mixinId, options, includeAccessors, results); 89 mixinClass, mixinId, options, includeAccessors, results);
89 parentId = mixinId; 90 parentId = mixinId;
90 } 91 }
91 } 92 }
92 _runQueryInternal(type, id, options, includeAccessors, results); 93 _runQueryInternal(type, id, options, includeAccessors, results);
93 } 94 }
94 95
95 /// Helper for [runQuery]. This runs the query only on a specific [type], 96 /// Helper for [runQuery]. This runs the query only on a specific [type],
96 /// which could be a class or a mixin labeled by [id]. 97 /// which could be a class or a mixin labeled by [id].
97 // TODO(sigmund): currently we materialize mixins in smoke/static.dart, 98 // TODO(sigmund): currently we materialize mixins in smoke/static.dart,
98 // we should consider to include the mixin declaration information directly, 99 // we should consider to include the mixin declaration information directly,
99 // and remove the duplication we have for mixins today. 100 // and remove the duplication we have for mixins today.
100 void _runQueryInternal(ClassElement type, TypeIdentifier id, 101 void _runQueryInternal(ClassElement type, TypeIdentifier id,
101 QueryOptions options, bool includeAccessors, List results) { 102 QueryOptions options, bool includeAccessors, List results) {
102
103 skipBecauseOfAnnotations(Element e) { 103 skipBecauseOfAnnotations(Element e) {
104 if (options.withAnnotations == null) return false; 104 if (options.withAnnotations == null) return false;
105 return !_matchesAnnotation(e.metadata, options.withAnnotations); 105 return !_matchesAnnotation(e.metadata, options.withAnnotations);
106 } 106 }
107 107
108 if (options.includeFields) { 108 if (options.includeFields) {
109 for (var f in type.fields) { 109 for (var f in type.fields) {
110 if (f.isStatic) continue; 110 if (f.isStatic) continue;
111 if (f.isSynthetic) continue; // exclude getters 111 if (f.isSynthetic) continue; // exclude getters
112 if (options.excludeFinal && f.isFinal) continue; 112 if (options.excludeFinal && f.isFinal) continue;
113 var name = f.displayName; 113 var name = f.displayName;
114 if (options.matches != null && !options.matches(name)) continue; 114 if (options.matches != null && !options.matches(name)) continue;
115 if (skipBecauseOfAnnotations(f)) continue; 115 if (skipBecauseOfAnnotations(f)) continue;
116 if (results != null) results.add(f); 116 if (results != null) results.add(f);
117 generator.addDeclaration(id, name, _typeFor(f.type.element), 117 generator.addDeclaration(id, name, _typeFor(f.type.element),
118 isField: true, isFinal: f.isFinal, 118 isField: true,
119 isFinal: f.isFinal,
119 annotations: _copyAnnotations(f)); 120 annotations: _copyAnnotations(f));
120 if (includeAccessors) _addAccessors(name, !f.isFinal); 121 if (includeAccessors) _addAccessors(name, !f.isFinal);
121 } 122 }
122 } 123 }
123 124
124 if (options.includeProperties) { 125 if (options.includeProperties) {
125 for (var a in type.accessors) { 126 for (var a in type.accessors) {
126 if (a is! PropertyAccessorElement) continue; 127 if (a is! PropertyAccessorElement) continue;
127 if (a.isStatic || !a.isGetter) continue; 128 if (a.isStatic || !a.isGetter) continue;
128 var v = a.variable; 129 var v = a.variable;
129 if (v is FieldElement && !v.isSynthetic) continue; // exclude fields 130 if (v is FieldElement && !v.isSynthetic) continue; // exclude fields
130 if (options.excludeFinal && v.isFinal) continue; 131 if (options.excludeFinal && v.isFinal) continue;
131 var name = v.displayName; 132 var name = v.displayName;
132 if (options.matches != null && !options.matches(name)) continue; 133 if (options.matches != null && !options.matches(name)) continue;
133 if (skipBecauseOfAnnotations(a)) continue; 134 if (skipBecauseOfAnnotations(a)) continue;
134 if (results != null) results.add(a); 135 if (results != null) results.add(a);
135 generator.addDeclaration(id, name, _typeFor(a.type.returnType.element), 136 generator.addDeclaration(id, name, _typeFor(a.type.returnType.element),
136 isProperty: true, isFinal: v.isFinal, 137 isProperty: true,
138 isFinal: v.isFinal,
137 annotations: _copyAnnotations(a)); 139 annotations: _copyAnnotations(a));
138 if (includeAccessors) _addAccessors(name, !v.isFinal); 140 if (includeAccessors) _addAccessors(name, !v.isFinal);
139 } 141 }
140 } 142 }
141 143
142 if (options.includeMethods) { 144 if (options.includeMethods) {
143 for (var m in type.methods) { 145 for (var m in type.methods) {
144 if (m.isStatic) continue; 146 if (m.isStatic) continue;
145 var name = m.displayName; 147 var name = m.displayName;
146 if (options.matches != null && !options.matches(name)) continue; 148 if (options.matches != null && !options.matches(name)) continue;
147 if (skipBecauseOfAnnotations(m)) continue; 149 if (skipBecauseOfAnnotations(m)) continue;
148 if (results != null) results.add(m); 150 if (results != null) results.add(m);
149 generator.addDeclaration(id, name, 151 generator.addDeclaration(
150 new TypeIdentifier('dart:core', 'Function'), isMethod: true, 152 id, name, new TypeIdentifier('dart:core', 'Function'),
151 annotations: _copyAnnotations(m)); 153 isMethod: true, annotations: _copyAnnotations(m));
152 if (includeAccessors) _addAccessors(name, false); 154 if (includeAccessors) _addAccessors(name, false);
153 } 155 }
154 } 156 }
155 } 157 }
156 158
157 /// Adds the declaration of [name] if it was found in [type]. If [recursive] 159 /// Adds the declaration of [name] if it was found in [type]. If [recursive]
158 /// is true, then we continue looking up [name] in the parent classes until we 160 /// is true, then we continue looking up [name] in the parent classes until we
159 /// find it or we reach [includeUpTo] or Object. Returns whether the 161 /// find it or we reach [includeUpTo] or Object. Returns whether the
160 /// declaration was found. When a declaration is found, add also a symbol, 162 /// declaration was found. When a declaration is found, add also a symbol,
161 /// getter, and setter if [includeAccessors] is true. 163 /// getter, and setter if [includeAccessors] is true.
162 bool lookupMember(ClassElement type, String name, {bool recursive: false, 164 bool lookupMember(ClassElement type, String name, {bool recursive: false,
163 bool includeAccessors: true, ClassElement includeUpTo}) => 165 bool includeAccessors: true, ClassElement includeUpTo}) =>
164 _lookupMemberInternal(type, _typeFor(type), name, recursive, 166 _lookupMemberInternal(
165 includeAccessors, includeUpTo); 167 type, _typeFor(type), name, recursive, includeAccessors, includeUpTo);
166 168
167 /// Helper for [lookupMember] that walks up the type hierarchy including mixin 169 /// Helper for [lookupMember] that walks up the type hierarchy including mixin
168 /// classes. 170 /// classes.
169 bool _lookupMemberInternal(ClassElement type, TypeIdentifier id, String name, 171 bool _lookupMemberInternal(ClassElement type, TypeIdentifier id, String name,
170 bool recursive, bool includeAccessors, ClassElement includeUpTo) { 172 bool recursive, bool includeAccessors, ClassElement includeUpTo) {
171 // Exclude members from [Object]. 173 // Exclude members from [Object].
172 if (type.type.isObject) return false; 174 if (type.type.isObject) return false;
173 generator.addEmptyDeclaration(id); 175 generator.addEmptyDeclaration(id);
174 for (var f in type.fields) { 176 for (var f in type.fields) {
175 if (f.displayName != name) continue; 177 if (f.displayName != name) continue;
176 if (f.isSynthetic) continue; // exclude getters 178 if (f.isSynthetic) continue; // exclude getters
177 generator.addDeclaration(id, name, 179 generator.addDeclaration(id, name, _typeFor(f.type.element),
178 _typeFor(f.type.element), isField: true, isFinal: f.isFinal, 180 isField: true,
179 isStatic: f.isStatic, annotations: _copyAnnotations(f)); 181 isFinal: f.isFinal,
182 isStatic: f.isStatic,
183 annotations: _copyAnnotations(f));
180 if (includeAccessors && !f.isStatic) _addAccessors(name, !f.isFinal); 184 if (includeAccessors && !f.isStatic) _addAccessors(name, !f.isFinal);
181 return true; 185 return true;
182 } 186 }
183 187
184 for (var a in type.accessors) { 188 for (var a in type.accessors) {
185 if (a is! PropertyAccessorElement) continue; 189 if (a is! PropertyAccessorElement) continue;
186 // TODO(sigmund): support setters without getters. 190 // TODO(sigmund): support setters without getters.
187 if (!a.isGetter) continue; 191 if (!a.isGetter) continue;
188 if (a.displayName != name) continue; 192 if (a.displayName != name) continue;
189 var v = a.variable; 193 var v = a.variable;
190 if (v is FieldElement && !v.isSynthetic) continue; // exclude fields 194 if (v is FieldElement && !v.isSynthetic) continue; // exclude fields
191 generator.addDeclaration(id, name, 195 generator.addDeclaration(id, name, _typeFor(a.type.returnType.element),
192 _typeFor(a.type.returnType.element), isProperty: true, 196 isProperty: true,
193 isFinal: v.isFinal, isStatic: a.isStatic, 197 isFinal: v.isFinal,
198 isStatic: a.isStatic,
194 annotations: _copyAnnotations(a)); 199 annotations: _copyAnnotations(a));
195 if (includeAccessors && !v.isStatic) _addAccessors(name, !v.isFinal); 200 if (includeAccessors && !v.isStatic) _addAccessors(name, !v.isFinal);
196 return true; 201 return true;
197 } 202 }
198 203
199 for (var m in type.methods) { 204 for (var m in type.methods) {
200 if (m.displayName != name) continue; 205 if (m.displayName != name) continue;
201 generator.addDeclaration(id, name, 206 generator.addDeclaration(
202 new TypeIdentifier('dart:core', 'Function'), isMethod: true, 207 id, name, new TypeIdentifier('dart:core', 'Function'),
203 isStatic: m.isStatic, annotations: _copyAnnotations(m)); 208 isMethod: true,
209 isStatic: m.isStatic,
210 annotations: _copyAnnotations(m));
204 if (includeAccessors) { 211 if (includeAccessors) {
205 if (m.isStatic) { 212 if (m.isStatic) {
206 generator.addStaticMethod(id, name); 213 generator.addStaticMethod(id, name);
207 generator.addSymbol(name); 214 generator.addSymbol(name);
208 } else { 215 } else {
209 _addAccessors(name, false); 216 _addAccessors(name, false);
210 } 217 }
211 } 218 }
212 return true; 219 return true;
213 } 220 }
214 221
215 if (recursive) { 222 if (recursive) {
216 lookupParent(type); 223 lookupParent(type);
217 var parent = type.supertype != null ? type.supertype.element : null; 224 var parent = type.supertype != null ? type.supertype.element : null;
218 if (parent == null || parent == includeUpTo) return false; 225 if (parent == null || parent == includeUpTo) return false;
219 var parentId = _typeFor(parent); 226 var parentId = _typeFor(parent);
220 for (var m in type.mixins) { 227 for (var m in type.mixins) {
221 var mixinClass = m.element; 228 var mixinClass = m.element;
222 var mixinId = _mixins[parentId][mixinClass]; 229 var mixinId = _mixins[parentId][mixinClass];
223 if (_lookupMemberInternal(mixinClass, mixinId, name, false, 230 if (_lookupMemberInternal(
224 includeAccessors, includeUpTo)) { 231 mixinClass, mixinId, name, false, includeAccessors, includeUpTo)) {
225 return true; 232 return true;
226 } 233 }
227 parentId = mixinId; 234 parentId = mixinId;
228 } 235 }
229 return _lookupMemberInternal(parent, parentId, name, true, 236 return _lookupMemberInternal(
230 includeAccessors, includeUpTo); 237 parent, parentId, name, true, includeAccessors, includeUpTo);
231 } 238 }
232 return false; 239 return false;
233 } 240 }
234 241
235 /// Add information so smoke can invoke the static method [type].[name]. 242 /// Add information so smoke can invoke the static method [type].[name].
236 void addStaticMethod(ClassElement type, String name) { 243 void addStaticMethod(ClassElement type, String name) {
237 generator.addStaticMethod(_typeFor(type), name); 244 generator.addStaticMethod(_typeFor(type), name);
238 } 245 }
239 246
240 /// Adds [name] as a symbol, a getter, and optionally a setter in [generator]. 247 /// Adds [name] as a symbol, a getter, and optionally a setter in [generator].
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
284 291
285 throw new UnsupportedError('unsupported annotation $annotation'); 292 throw new UnsupportedError('unsupported annotation $annotation');
286 } 293 }
287 294
288 /// Converts [expression] into a [ConstExpression]. 295 /// Converts [expression] into a [ConstExpression].
289 ConstExpression _convertExpression(Expression expression) { 296 ConstExpression _convertExpression(Expression expression) {
290 if (expression is StringLiteral) { 297 if (expression is StringLiteral) {
291 return new ConstExpression.string(expression.stringValue); 298 return new ConstExpression.string(expression.stringValue);
292 } 299 }
293 300
294 if (expression is BooleanLiteral || expression is DoubleLiteral || 301 if (expression is BooleanLiteral ||
295 expression is IntegerLiteral || expression is NullLiteral) { 302 expression is DoubleLiteral ||
303 expression is IntegerLiteral ||
304 expression is NullLiteral) {
296 return new CodeAsConstExpression("${(expression as dynamic).value}"); 305 return new CodeAsConstExpression("${(expression as dynamic).value}");
297 } 306 }
298 307
299 if (expression is Identifier) { 308 if (expression is Identifier) {
300 var element = expression.bestElement; 309 var element = expression.bestElement;
301 if (element == null || !element.isPublic) { 310 if (element == null || !element.isPublic) {
302 throw new UnsupportedError('private constants are not supported'); 311 throw new UnsupportedError('private constants are not supported');
303 } 312 }
304 313
305 var url = importUrlFor(element.library); 314 var url = importUrlFor(element.library);
(...skipping 15 matching lines...) Expand all
321 throw new UnimplementedError('expression convertion not implemented in ' 330 throw new UnimplementedError('expression convertion not implemented in '
322 'smoke.codegen.recorder (${expression.runtimeType} $expression)'); 331 'smoke.codegen.recorder (${expression.runtimeType} $expression)');
323 } 332 }
324 } 333 }
325 334
326 /// Returns whether [metadata] contains any annotation that is either equal to 335 /// Returns whether [metadata] contains any annotation that is either equal to
327 /// an annotation in [queryAnnotations] or whose type is a subclass of a type 336 /// an annotation in [queryAnnotations] or whose type is a subclass of a type
328 /// listed in [queryAnnotations]. This is equivalent to the check done in 337 /// listed in [queryAnnotations]. This is equivalent to the check done in
329 /// `src/common.dart#matchesAnnotation`, except that this is applied to 338 /// `src/common.dart#matchesAnnotation`, except that this is applied to
330 /// static metadata as it was provided by the analyzer. 339 /// static metadata as it was provided by the analyzer.
331 bool _matchesAnnotation(Iterable<ElementAnnotation> metadata, 340 bool _matchesAnnotation(
332 Iterable<Element> queryAnnotations) { 341 Iterable<ElementAnnotation> metadata, Iterable<Element> queryAnnotations) {
333 for (var meta in metadata) { 342 for (var meta in metadata) {
334 var element = meta.element; 343 var element = meta.element;
335 var exp; 344 var exp;
336 var type; 345 var type;
337 if (element is PropertyAccessorElement) { 346 if (element is PropertyAccessorElement) {
338 exp = element.variable; 347 exp = element.variable;
339 type = exp.evaluationResult.value.type; 348 type = exp.evaluationResult.value.type;
340 } else if (element is ConstructorElement) { 349 } else if (element is ConstructorElement) {
341 exp = element; 350 exp = element;
342 type = element.enclosingElement.type; 351 type = element.enclosingElement.type;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 388
380 /// If [withAnnotation] is not null, then it should be a list of types, so 389 /// If [withAnnotation] is not null, then it should be a list of types, so
381 /// only symbols that are annotated with instances of those types are 390 /// only symbols that are annotated with instances of those types are
382 /// included. 391 /// included.
383 final List<Element> withAnnotations; 392 final List<Element> withAnnotations;
384 393
385 /// If [matches] is not null, then only those fields, properties, or methods 394 /// If [matches] is not null, then only those fields, properties, or methods
386 /// that match will be included. 395 /// that match will be included.
387 final NameMatcher matches; 396 final NameMatcher matches;
388 397
389 const QueryOptions({ 398 const QueryOptions({this.includeFields: true, this.includeProperties: true,
390 this.includeFields: true, 399 this.includeInherited: true, this.includeUpTo: null,
391 this.includeProperties: true, 400 this.excludeFinal: false, this.includeMethods: false,
392 this.includeInherited: true, 401 this.withAnnotations: null, this.matches: null});
393 this.includeUpTo: null,
394 this.excludeFinal: false,
395 this.includeMethods: false,
396 this.withAnnotations: null,
397 this.matches: null});
398 } 402 }
399 403
400 /// Predicate that tells whether [name] should be included in query results. 404 /// Predicate that tells whether [name] should be included in query results.
401 typedef bool NameMatcher(String name); 405 typedef bool NameMatcher(String name);
OLDNEW
« no previous file with comments | « lib/codegen/generator.dart ('k') | lib/mirrors.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698