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

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

Issue 204143002: Changes in smoke in preparation of polymer's codegen: (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 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 | Annotate | Revision Log
« no previous file with comments | « pkg/smoke/lib/codegen/generator.dart ('k') | pkg/smoke/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 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 }); 56 });
57 if (!baseType.type.isObject) generator.addParent(mixinId, baseId); 57 if (!baseType.type.isObject) generator.addParent(mixinId, baseId);
58 baseType = mixinType; 58 baseType = mixinType;
59 baseId = mixinId; 59 baseId = mixinId;
60 _mixins.putIfAbsent(mixinId, () => {}); 60 _mixins.putIfAbsent(mixinId, () => {});
61 } 61 }
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(ClassElement type) => 66 TypeIdentifier _typeFor(Element type) => new TypeIdentifier(
67 new TypeIdentifier(importUrlFor(type.library), type.displayName); 67 type.library == null ? 'dart:core' : importUrlFor(type.library),
68 type.displayName);
68 69
69 /// 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
70 /// query on [type] that matches [options]. 71 /// query on [type] that matches [options]. Also adds symbols, getters, and
71 void runQuery(ClassElement type, QueryOptions options) { 72 /// setters if [includeAccessors] is true.
73 void runQuery(ClassElement type, QueryOptions options,
74 {bool includeAccessors: true}) {
72 if (type.type.isObject) return; // We don't include Object in query results. 75 if (type.type.isObject) return; // We don't include Object in query results.
73 var id = _typeFor(type); 76 var id = _typeFor(type);
74 var parent = type.supertype != null ? type.supertype.element : null; 77 var parent = type.supertype != null ? type.supertype.element : null;
75 if (options.includeInherited && parent != null && 78 if (options.includeInherited && parent != null &&
76 parent != options.includeUpTo) { 79 parent != options.includeUpTo) {
77 lookupParent(type); 80 lookupParent(type);
78 runQuery(parent, options); 81 runQuery(parent, options, includeAccessors: includeAccessors);
79 var parentId = _typeFor(parent); 82 var parentId = _typeFor(parent);
80 for (var m in type.mixins) { 83 for (var m in type.mixins) {
81 var mixinClass = m.element; 84 var mixinClass = m.element;
82 var mixinId = _mixins[parentId][mixinClass]; 85 var mixinId = _mixins[parentId][mixinClass];
83 _runQueryInternal(mixinClass, mixinId, options); 86 _runQueryInternal(mixinClass, mixinId, options, includeAccessors);
84 parentId = mixinId; 87 parentId = mixinId;
85 } 88 }
86 } 89 }
87 _runQueryInternal(type, id, options); 90 _runQueryInternal(type, id, options, includeAccessors);
88 } 91 }
89 92
90 /// Helper for [runQuery]. This runs the query only on a specific [type], 93 /// Helper for [runQuery]. This runs the query only on a specific [type],
91 /// which could be a class or a mixin labeled by [id]. 94 /// which could be a class or a mixin labeled by [id].
92 // TODO(sigmund): currently we materialize mixins in smoke/static.dart, 95 // TODO(sigmund): currently we materialize mixins in smoke/static.dart,
93 // we should consider to include the mixin declaration information directly, 96 // we should consider to include the mixin declaration information directly,
94 // and remove the duplication we have for mixins today. 97 // and remove the duplication we have for mixins today.
95 void _runQueryInternal(ClassElement type, TypeIdentifier id, 98 void _runQueryInternal(ClassElement type, TypeIdentifier id,
96 QueryOptions options) { 99 QueryOptions options, bool includeAccessors) {
97 100
98 skipBecauseOfAnnotations(Element e) { 101 skipBecauseOfAnnotations(Element e) {
99 if (options.withAnnotations == null) return false; 102 if (options.withAnnotations == null) return false;
100 return !_matchesAnnotation(e.metadata, options.withAnnotations); 103 return !_matchesAnnotation(e.metadata, options.withAnnotations);
101 } 104 }
102 105
103 if (options.includeFields) { 106 if (options.includeFields) {
104 for (var f in type.fields) { 107 for (var f in type.fields) {
105 if (f.isStatic) continue; 108 if (f.isStatic) continue;
106 if (f.isSynthetic) continue; // exclude getters 109 if (f.isSynthetic) continue; // exclude getters
107 if (options.excludeFinal && f.isFinal) continue; 110 if (options.excludeFinal && f.isFinal) continue;
111 var name = f.displayName;
112 if (options.matches != null && !options.matches(name)) continue;
108 if (skipBecauseOfAnnotations(f)) continue; 113 if (skipBecauseOfAnnotations(f)) continue;
109 generator.addDeclaration(id, f.displayName, _typeFor(f.type.element), 114 generator.addDeclaration(id, name, _typeFor(f.type.element),
110 isField: true, isFinal: f.isFinal, 115 isField: true, isFinal: f.isFinal,
111 annotations: _copyAnnotations(f)); 116 annotations: _copyAnnotations(f));
117 if (includeAccessors) _addAccessors(name, !f.isFinal);
112 } 118 }
113 } 119 }
114 120
115 if (options.includeProperties) { 121 if (options.includeProperties) {
116 for (var a in type.accessors) { 122 for (var a in type.accessors) {
117 if (a is! PropertyAccessorElement) continue; 123 if (a is! PropertyAccessorElement) continue;
118 if (a.isStatic || !a.isGetter) continue; 124 if (a.isStatic || !a.isGetter) continue;
119 var v = a.variable; 125 var v = a.variable;
120 if (v is FieldElement && !v.isSynthetic) continue; // exclude fields 126 if (v is FieldElement && !v.isSynthetic) continue; // exclude fields
121 if (options.excludeFinal && v.isFinal) continue; 127 if (options.excludeFinal && v.isFinal) continue;
122 if (skipBecauseOfAnnotations(v)) continue; 128 var name = v.displayName;
123 generator.addDeclaration(id, v.displayName, _typeFor(v.type.element), 129 if (options.matches != null && !options.matches(name)) continue;
130 if (skipBecauseOfAnnotations(a)) continue;
131 generator.addDeclaration(id, name, _typeFor(a.type.returnType.element),
124 isProperty: true, isFinal: v.isFinal, 132 isProperty: true, isFinal: v.isFinal,
125 annotations: _copyAnnotations(a)); 133 annotations: _copyAnnotations(a));
134 if (includeAccessors) _addAccessors(name, !v.isFinal);
126 } 135 }
127 } 136 }
128 137
129 if (options.includeMethods) { 138 if (options.includeMethods) {
130 for (var m in type.methods) { 139 for (var m in type.methods) {
131 if (m.isStatic) continue; 140 if (m.isStatic) continue;
141 var name = m.displayName;
142 if (options.matches != null && !options.matches(name)) continue;
132 if (skipBecauseOfAnnotations(m)) continue; 143 if (skipBecauseOfAnnotations(m)) continue;
133 generator.addDeclaration(id, m.displayName, 144 generator.addDeclaration(id, name,
134 new TypeIdentifier('dart:core', 'Function'), isMethod: true, 145 new TypeIdentifier('dart:core', 'Function'), isMethod: true,
135 annotations: _copyAnnotations(m)); 146 annotations: _copyAnnotations(m));
147 if (includeAccessors) _addAccessors(name, false);
136 } 148 }
137 } 149 }
138 } 150 }
139 151
140 /// 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]
141 /// 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
142 /// find it or we reach Object. 154 /// find it or we reach Object. Returns whether the declaration was found.
143 void lookupMember(ClassElement type, String name, {bool recursive: false}) { 155 /// When a declaration is found, add also a symbol, getter, and setter if
144 _lookupMemberInternal(type, _typeFor(type), name, recursive); 156 /// [includeAccessors] is true.
145 } 157 bool lookupMember(ClassElement type, String name, {bool recursive: false,
158 bool includeAccessors: true}) =>
159 _lookupMemberInternal(type, _typeFor(type), name, recursive,
160 includeAccessors);
146 161
147 /// Helper for [lookupMember] that walks up the type hierarchy including mixin 162 /// Helper for [lookupMember] that walks up the type hierarchy including mixin
148 /// classes. 163 /// classes.
149 bool _lookupMemberInternal(ClassElement type, TypeIdentifier id, String name, 164 bool _lookupMemberInternal(ClassElement type, TypeIdentifier id, String name,
150 bool recursive) { 165 bool recursive, bool includeAccessors) {
151 // Exclude members from [Object]. 166 // Exclude members from [Object].
152 if (type.type.isObject) return false; 167 if (type.type.isObject) return false;
153 generator.addEmptyDeclaration(id); 168 generator.addEmptyDeclaration(id);
154 for (var f in type.fields) { 169 for (var f in type.fields) {
155 if (f.displayName != name) continue; 170 if (f.displayName != name) continue;
156 if (f.isSynthetic) continue; // exclude getters 171 if (f.isSynthetic) continue; // exclude getters
157 generator.addDeclaration(id, f.displayName, 172 generator.addDeclaration(id, name,
158 _typeFor(f.type.element), isField: true, isFinal: f.isFinal, 173 _typeFor(f.type.element), isField: true, isFinal: f.isFinal,
159 isStatic: f.isStatic, annotations: _copyAnnotations(f)); 174 isStatic: f.isStatic, annotations: _copyAnnotations(f));
175 if (includeAccessors) _addAccessors(name, !f.isFinal);
160 return true; 176 return true;
161 } 177 }
162 178
163 for (var a in type.accessors) { 179 for (var a in type.accessors) {
164 if (a is! PropertyAccessorElement) continue; 180 if (a is! PropertyAccessorElement) continue;
165 // TODO(sigmund): support setters without getters. 181 // TODO(sigmund): support setters without getters.
166 if (!a.isGetter) continue; 182 if (!a.isGetter) continue;
167 if (a.displayName != name) continue; 183 if (a.displayName != name) continue;
168 var v = a.variable; 184 var v = a.variable;
169 if (v is FieldElement && !v.isSynthetic) continue; // exclude fields 185 if (v is FieldElement && !v.isSynthetic) continue; // exclude fields
170 generator.addDeclaration(id, v.displayName, 186 generator.addDeclaration(id, name,
171 _typeFor(v.type.element), isProperty: true, isFinal: v.isFinal, 187 _typeFor(a.type.returnType.element), isProperty: true,
172 isStatic: v.isStatic, annotations: _copyAnnotations(a)); 188 isFinal: v.isFinal, isStatic: a.isStatic,
189 annotations: _copyAnnotations(a));
190 if (includeAccessors) _addAccessors(name, !v.isFinal);
173 return true; 191 return true;
174 } 192 }
175 193
176 for (var m in type.methods) { 194 for (var m in type.methods) {
177 if (m.displayName != name) continue; 195 if (m.displayName != name) continue;
178 generator.addDeclaration(id, m.displayName, 196 generator.addDeclaration(id, name,
179 new TypeIdentifier('dart:core', 'Function'), isMethod: true, 197 new TypeIdentifier('dart:core', 'Function'), isMethod: true,
180 isStatic: m.isStatic, annotations: _copyAnnotations(m)); 198 isStatic: m.isStatic, annotations: _copyAnnotations(m));
199 if (includeAccessors) _addAccessors(name, false);
181 return true; 200 return true;
182 } 201 }
183 202
184 if (recursive) { 203 if (recursive) {
185 lookupParent(type); 204 lookupParent(type);
186 var parent = type.supertype != null ? type.supertype.element : null; 205 var parent = type.supertype != null ? type.supertype.element : null;
187 if (parent == null) return false; 206 if (parent == null) return false;
188 var parentId = _typeFor(parent); 207 var parentId = _typeFor(parent);
189 for (var m in type.mixins) { 208 for (var m in type.mixins) {
190 var mixinClass = m.element; 209 var mixinClass = m.element;
191 var mixinId = _mixins[parentId][mixinClass]; 210 var mixinId = _mixins[parentId][mixinClass];
192 if (_lookupMemberInternal(mixinClass, mixinId, name, false)) { 211 if (_lookupMemberInternal(mixinClass, mixinId, name, false,
212 includeAccessors)) {
193 return true; 213 return true;
194 } 214 }
195 parentId = mixinId; 215 parentId = mixinId;
196 } 216 }
197 return _lookupMemberInternal(parent, parentId, name, true); 217 return _lookupMemberInternal(parent, parentId, name, true,
218 includeAccessors);
198 } 219 }
199 return false; 220 return false;
200 } 221 }
201 222
202 223
224 /// Adds [name] as a symbol, a getter, and optionally a setter in [generator].
225 _addAccessors(String name, bool includeSetter) {
226 generator.addSymbol(name);
227 generator.addGetter(name);
228 if (includeSetter) generator.addSetter(name);
229 }
230
203 /// Copy metadata associated with the declaration of [target]. 231 /// Copy metadata associated with the declaration of [target].
204 List<ConstExpression> _copyAnnotations(Element target) { 232 List<ConstExpression> _copyAnnotations(Element target) {
205 var node = target.node; 233 var node = target.node;
206 // [node] is the initialization expression, we walk up to get to the actual 234 // [node] is the initialization expression, we walk up to get to the actual
207 // member declaration where the metadata is attached to. 235 // member declaration where the metadata is attached to.
208 while (node is! ClassMember) node = node.parent; 236 while (node is! ClassMember) node = node.parent;
209 return node.metadata.map(_convertAnnotation).toList(); 237 return node.metadata.map(_convertAnnotation).toList();
210 } 238 }
211 239
212 /// Converts annotations into [ConstExpression]s supported by the codegen 240 /// Converts annotations into [ConstExpression]s supported by the codegen
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
331 final bool excludeFinal; 359 final bool excludeFinal;
332 360
333 /// Whether to include methods (default is false). 361 /// Whether to include methods (default is false).
334 final bool includeMethods; 362 final bool includeMethods;
335 363
336 /// If [withAnnotation] is not null, then it should be a list of types, so 364 /// If [withAnnotation] is not null, then it should be a list of types, so
337 /// only symbols that are annotated with instances of those types are 365 /// only symbols that are annotated with instances of those types are
338 /// included. 366 /// included.
339 final List<Element> withAnnotations; 367 final List<Element> withAnnotations;
340 368
369 /// If [matches] is not null, then only those fields, properties, or methods
370 /// that match will be included.
371 final NameMatcher matches;
372
341 const QueryOptions({ 373 const QueryOptions({
342 this.includeFields: true, 374 this.includeFields: true,
343 this.includeProperties: true, 375 this.includeProperties: true,
344 this.includeInherited: true, 376 this.includeInherited: true,
345 this.includeUpTo: null, 377 this.includeUpTo: null,
346 this.excludeFinal: false, 378 this.excludeFinal: false,
347 this.includeMethods: false, 379 this.includeMethods: false,
348 this.withAnnotations: null}); 380 this.withAnnotations: null,
381 this.matches: null});
349 } 382 }
383
384 /// Predicate that tells whether [name] should be included in query results.
385 typedef bool NameMatcher(String name);
OLDNEW
« no previous file with comments | « pkg/smoke/lib/codegen/generator.dart ('k') | pkg/smoke/lib/mirrors.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698