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

Side by Side Diff: reflectable/lib/src/transformer_implementation.dart

Issue 1289933004: Implements support for reflection on parameters. (Closed) Base URL: https://github.com/dart-lang/reflectable.git@master
Patch Set: Created 5 years, 4 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
OLDNEW
1 // (c) 2015, the Dart Team. All rights reserved. Use of this 1 // (c) 2015, the Dart Team. All rights reserved. Use of this
2 // source code is governed by a BSD-style license that can be found in 2 // source code is governed by a BSD-style license that can be found in
3 // the LICENSE file. 3 // the LICENSE file.
4 4
5 library reflectable.src.transformer_implementation; 5 library reflectable.src.transformer_implementation;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:convert'; 8 import 'dart:convert';
9 import 'dart:io'; 9 import 'dart:io';
10 import 'package:analyzer/src/generated/ast.dart'; 10 import 'package:analyzer/src/generated/ast.dart';
11 import 'package:analyzer/src/generated/constant.dart'; 11 import 'package:analyzer/src/generated/constant.dart';
12 import 'package:analyzer/src/generated/element.dart'; 12 import 'package:analyzer/src/generated/element.dart';
13 import 'package:analyzer/src/generated/utilities_dart.dart';
13 import 'package:barback/barback.dart'; 14 import 'package:barback/barback.dart';
14 import 'package:code_transformers/resolver.dart'; 15 import 'package:code_transformers/resolver.dart';
15 import 'element_capability.dart' as ec; 16 import 'element_capability.dart' as ec;
16 import 'encoding_constants.dart' as constants; 17 import 'encoding_constants.dart' as constants;
17 import "reflectable_class_constants.dart" as reflectable_class_constants; 18 import "reflectable_class_constants.dart" as reflectable_class_constants;
18 import 'source_manager.dart'; 19 import 'source_manager.dart';
19 import 'transformer_errors.dart' as errors; 20 import 'transformer_errors.dart' as errors;
20 21
21 class ReflectionWorld { 22 class ReflectionWorld {
22 final List<_ReflectorDomain> reflectors = new List<_ReflectorDomain>(); 23 final List<_ReflectorDomain> reflectors = new List<_ReflectorDomain>();
(...skipping 24 matching lines...) Expand all
47 })); 48 }));
48 } 49 }
49 } 50 }
50 51
51 /// Similar to a `Set<T>` but also keeps track of the index of the first 52 /// Similar to a `Set<T>` but also keeps track of the index of the first
52 /// insertion of each item. 53 /// insertion of each item.
53 class Enumerator<T> { 54 class Enumerator<T> {
54 final Map<T, int> _map = new Map<T, int>(); 55 final Map<T, int> _map = new Map<T, int>();
55 int _count = 0; 56 int _count = 0;
56 57
58 bool _contains(T t) => _map.containsKey(t);
floitsch 2015/08/13 17:33:36 I don't think it's worth having this redirection j
eernst 2015/08/14 12:05:34 The reason why I created the abstraction is that i
59
57 get length => _count; 60 get length => _count;
58 61
59 /// Tries to insert [t]. If it was already there return false, else insert it 62 /// Tries to insert [t]. If it was already there return false, else insert it
60 /// and return true. 63 /// and return true.
61 bool add(T t) { 64 bool add(T t) {
62 if (_map.containsKey(t)) return false; 65 if (_contains(t)) return false;
63 _map[t] = _count; 66 _map[t] = _count;
64 ++_count; 67 ++_count;
65 return true; 68 return true;
66 } 69 }
67 70
68 /// Returns the index of a given item. 71 /// Returns the index of a given item.
69 int indexOf(T t) { 72 int indexOf(T t) {
70 return _map[t]; 73 return _map[t];
71 } 74 }
72 75
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 119
117 List<String> parameterNames = type.parameters 120 List<String> parameterNames = type.parameters
118 .map((ParameterElement parameter) => parameter.name) 121 .map((ParameterElement parameter) => parameter.name)
119 .toList(); 122 .toList();
120 123
121 List<String> NamedParameterNames = type.namedParameterTypes.keys.toList(); 124 List<String> NamedParameterNames = type.namedParameterTypes.keys.toList();
122 125
123 String positionals = new Iterable.generate( 126 String positionals = new Iterable.generate(
124 requiredPositionalCount, (int i) => parameterNames[i]).join(", "); 127 requiredPositionalCount, (int i) => parameterNames[i]).join(", ");
125 128
126 String optionalsWithDefaults = new Iterable.generate( 129 String optionalsWithDefaults =
127 optionalPositionalCount, (int i) { 130 new Iterable.generate(optionalPositionalCount, (int i) {
128 String defaultValueCode = 131 String defaultValueCode =
129 constructor.parameters[requiredPositionalCount + i].defaultValueCode; 132 constructor.parameters[requiredPositionalCount + i].defaultValueCode;
130 String defaultValueString = 133 String defaultValueString =
131 defaultValueCode == null ? "" : " = $defaultValueCode"; 134 defaultValueCode == null ? "" : " = $defaultValueCode";
132 return "${parameterNames[i + requiredPositionalCount]}" 135 return "${parameterNames[i + requiredPositionalCount]}"
133 "$defaultValueString"; 136 "$defaultValueString";
134 }).join(", "); 137 }).join(", ");
135 138
136 String namedWithDefaults = new Iterable.generate(NamedParameterNames.length, 139 String namedWithDefaults =
137 (int i) { 140 new Iterable.generate(NamedParameterNames.length, (int i) {
138 // TODO(#8) future: Recreate default values. 141 // TODO(#8) future: Recreate default values.
139 // TODO(#8) implement: Until that is done, recognize 142 // TODO(#8) implement: Until that is done, recognize
140 // unhandled cases, and emit error/warning. 143 // unhandled cases, and emit error/warning.
141 String defaultValueCode = 144 String defaultValueCode =
142 constructor.parameters[requiredPositionalCount + i].defaultValueCode; 145 constructor.parameters[requiredPositionalCount + i].defaultValueCode;
143 String defaultValueString = 146 String defaultValueString =
144 defaultValueCode == null ? "" : ": $defaultValueCode"; 147 defaultValueCode == null ? "" : ": $defaultValueCode";
145 return "${NamedParameterNames[i]}$defaultValueString"; 148 return "${NamedParameterNames[i]}$defaultValueString";
146 }).join(", "); 149 }).join(", ");
147 150
(...skipping 28 matching lines...) Expand all
176 String _constConstructionCode(_ImportCollector importCollector) { 179 String _constConstructionCode(_ImportCollector importCollector) {
177 String prefix = importCollector._getPrefix(_reflector.library); 180 String prefix = importCollector._getPrefix(_reflector.library);
178 return "const $prefix.${_reflector.name}()"; 181 return "const $prefix.${_reflector.name}()";
179 } 182 }
180 183
181 String _generateCode(Resolver resolver, _ImportCollector importCollector, 184 String _generateCode(Resolver resolver, _ImportCollector importCollector,
182 TransformLogger logger, AssetId dataId) { 185 TransformLogger logger, AssetId dataId) {
183 Enumerator<ClassElement> classes = new Enumerator<ClassElement>(); 186 Enumerator<ClassElement> classes = new Enumerator<ClassElement>();
184 Enumerator<ExecutableElement> members = new Enumerator<ExecutableElement>(); 187 Enumerator<ExecutableElement> members = new Enumerator<ExecutableElement>();
185 Enumerator<FieldElement> fields = new Enumerator<FieldElement>(); 188 Enumerator<FieldElement> fields = new Enumerator<FieldElement>();
189 Enumerator<ParameterElement> parameters =
190 new Enumerator<ParameterElement>();
186 Set<String> instanceGetterNames = new Set<String>(); 191 Set<String> instanceGetterNames = new Set<String>();
187 Set<String> instanceSetterNames = new Set<String>(); 192 Set<String> instanceSetterNames = new Set<String>();
188 193
189 // Fill in [classes], [members], [fields], [instanceGetterNames], 194 // Fill in [classes], [members], [fields], [parameters],
190 // and [instanceSetterNames]. 195 // [instanceGetterNames], and [instanceSetterNames].
191 for (_ClassDomain classDomain in _annotatedClasses) { 196 for (_ClassDomain classDomain in _annotatedClasses) {
192 // Gather all annotated classes. 197 // Gather all annotated classes.
193 classes.add(classDomain._classElement); 198 classes.add(classDomain._classElement);
194 199
195 // Gather the behavioral interface into [members]. Note that 200 // Gather the behavioral interface into [members]. Note that
196 // this includes implicitly generated getters and setters, but 201 // this includes implicitly generated getters and setters, but
197 // omits fields. Also note that this does not match the 202 // omits fields. Also note that this does not match the
198 // semantics of the `declarations` method in a [ClassMirror]. 203 // semantics of the `declarations` method in a [ClassMirror].
199 classDomain._declarations.forEach(members.add); 204 classDomain._declarations.forEach(members.add);
200 205
201 // Add the behavioral interface from this class (redundantly) and 206 // Add the behavioral interface from this class (redundantly) and
202 // all superclasses (which matters) to [members], such that it 207 // all superclasses (which matters) to [members], such that it
203 // contains both the behavioral parts for the target class and its 208 // contains both the behavioral parts for the target class and its
204 // superclasses, and the program structure oriented parts for the 209 // superclasses, and the program structure oriented parts for the
205 // target class (omitting those from its superclasses). 210 // target class (omitting those from its superclasses).
206 classDomain._instanceMembers.forEach(members.add); 211 classDomain._instanceMembers.forEach(members.add);
207 212
213 // Add all the formal parameters (as a single, global set) which
214 // are declared by any of the methods in `classDomain._declarations`.
215 classDomain._declaredParameters.forEach(parameters.add);
216
208 // Gather the fields declared in the target class (not inherited 217 // Gather the fields declared in the target class (not inherited
209 // ones) in [fields], i.e., the elements missing from [members] 218 // ones) in [fields], i.e., the elements missing from [members]
210 // at this point, in order to support `declarations` in a 219 // at this point, in order to support `declarations` in a
211 // [ClassMirror]. 220 // [ClassMirror].
212 classDomain._declaredFields.forEach(fields.add); 221 classDomain._declaredFields.forEach(fields.add);
213 222
214 // Gather all getters and setters based on [instanceMembers], including 223 // Gather all getters and setters based on [instanceMembers], including
215 // both explicitly declared ones, implicitly generated ones for fields, 224 // both explicitly declared ones, implicitly generated ones for fields,
216 // and the implicitly generated ones that correspond to method tear-offs. 225 // and the implicitly generated ones that correspond to method tear-offs.
217 classDomain._instanceMembers.forEach((ExecutableElement instanceMember) { 226 classDomain._instanceMembers.forEach((ExecutableElement instanceMember) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 String name = setterName.substring(0, setterName.length - 1); 279 String name = setterName.substring(0, setterName.length - 1);
271 String className = classElement.name; 280 String className = classElement.name;
272 String prefix = importCollector._getPrefix(classElement.library); 281 String prefix = importCollector._getPrefix(classElement.library);
273 return 'r"$setterName": (value) => $prefix.$className.$name = value'; 282 return 'r"$setterName": (value) => $prefix.$className.$name = value';
274 } 283 }
275 284
276 // Compute `includedClasses`, i.e., the set of classes which are 285 // Compute `includedClasses`, i.e., the set of classes which are
277 // annotated, or the upwards-closed completion of that set. 286 // annotated, or the upwards-closed completion of that set.
278 Set<_ClassDomain> includedClasses = new Set<_ClassDomain>(); 287 Set<_ClassDomain> includedClasses = new Set<_ClassDomain>();
279 includedClasses.addAll(_annotatedClasses); 288 includedClasses.addAll(_annotatedClasses);
289 if (_capabilities._impliesParameterTypes) {
290 parameters.items.forEach((ParameterElement parameterElement) {
291 Element parameterType = parameterElement.type.element;
292 if (parameterType is ClassElement) {
293 includedClasses.add(_createClassDomain(parameterType, this));
294 classes.add(parameterType);
295 }
296 });
297 }
280 if (_capabilities._impliesUpwardsClosure) { 298 if (_capabilities._impliesUpwardsClosure) {
281 Set<_ClassDomain> workingSetOfClasses = includedClasses; 299 Set<_ClassDomain> workingSetOfClasses = includedClasses;
282 while (true) { 300 while (true) {
283 // Invariant for `workingSetOfClasses`: Every class from 301 // Invariant for `workingSetOfClasses`: Every class from
284 // `includedClasses` for which it is possible that its superclass 302 // `includedClasses` for which it is possible that its superclass
285 // is not yet in `includedClasses` must be a member of 303 // is not yet in `includedClasses` must be a member of
286 // `workingSetOfClasses`. 304 // `workingSetOfClasses`.
287 Set<_ClassDomain> additionalClasses = new Set<_ClassDomain>(); 305 Set<_ClassDomain> additionalClasses = new Set<_ClassDomain>();
288 workingSetOfClasses.forEach((_ClassDomain workingClass) { 306 workingSetOfClasses.forEach((_ClassDomain workingClass) {
289 InterfaceType workingSuperType = workingClass._classElement.supertype; 307 InterfaceType workingSuperType = workingClass._classElement.supertype;
(...skipping 12 matching lines...) Expand all
302 includedClasses.addAll(additionalClasses); 320 includedClasses.addAll(additionalClasses);
303 additionalClasses.forEach((_ClassDomain classDomain) { 321 additionalClasses.forEach((_ClassDomain classDomain) {
304 classes.add(classDomain._classElement); 322 classes.add(classDomain._classElement);
305 }); 323 });
306 workingSetOfClasses = additionalClasses; 324 workingSetOfClasses = additionalClasses;
307 } 325 }
308 } 326 }
309 327
310 // Generate the class mirrors. 328 // Generate the class mirrors.
311 int classIndex = 0; 329 int classIndex = 0;
312 String classMirrorsCode = _formatAsList(includedClasses 330 String classMirrorsCode =
313 .map((_ClassDomain classDomain) { 331 _formatAsList(includedClasses.map((_ClassDomain classDomain) {
314
315 // Fields go first in [memberMirrors], so they will get the 332 // Fields go first in [memberMirrors], so they will get the
316 // same index as in [fields]. 333 // same index as in [fields].
317 Iterable<int> fieldsIndices = classDomain._declaredFields 334 Iterable<int> fieldsIndices =
318 .map((FieldElement element) { 335 classDomain._declaredFields.map((FieldElement element) {
319 return fields.indexOf(element); 336 return fields.indexOf(element);
320 }); 337 });
321 338
322 int fieldsLength = fields.length; 339 int fieldsLength = fields.length;
323 340
324 // All the elements in the behavioral interface go after the 341 // All the elements in the behavioral interface go after the
325 // fields in [memberMirrors], so they must get an offset of 342 // fields in [memberMirrors], so they must get an offset of
326 // `fields.length` on the index. 343 // `fields.length` on the index.
327 Iterable<int> methodsIndices = classDomain._declarations 344 Iterable<int> methodsIndices = classDomain._declarations
328 .where(_executableIsntImplicitGetterOrSetter) 345 .where(_executableIsntImplicitGetterOrSetter)
329 .map((ExecutableElement element) { 346 .map((ExecutableElement element) {
330 // TODO(eernst) implement: The "magic" default constructor in `Object` 347 // TODO(eernst) implement: The "magic" default constructor in `Object`
331 // (the one that ultimately allocates the memory for _every_ new object) 348 // (the one that ultimately allocates the memory for _every_ new object)
332 // has no index, which creates the need to catch a `null` here. 349 // has no index, which creates the need to catch a `null` here.
333 // Search for "magic" to find other occurrences of the same issue. 350 // Search for "magic" to find other occurrences of the same issue.
334 // For now, we provide the index -1 for this declaration, because 351 // For now, we provide the index -1 for this declaration, because
335 // it is not yet supported. Need to find the correct solution, though! 352 // it is not yet supported. Need to find the correct solution, though!
336 int index = members.indexOf(element); 353 int index = members.indexOf(element);
337 return index == null ? -1 : index + fieldsLength; 354 return index == null ? -1 : index + fieldsLength;
338 }); 355 });
339 356
340 List<int> declarationsIndices = <int>[] 357 List<int> declarationsIndices = <int>[]
341 ..addAll(fieldsIndices) 358 ..addAll(fieldsIndices)
342 ..addAll(methodsIndices); 359 ..addAll(methodsIndices);
343 String declarationsCode = _formatAsList(declarationsIndices); 360 String declarationsCode = _formatAsList(declarationsIndices);
344 361
345 // All instance members belong to the behavioral interface, so they 362 // All instance members belong to the behavioral interface, so they
346 // also get an offset of `fields.length`. 363 // also get an offset of `fields.length`.
347 String instanceMembersCode = _formatAsList(classDomain._instanceMembers 364 String instanceMembersCode = _formatAsList(
348 .map((ExecutableElement element) { 365 classDomain._instanceMembers.map((ExecutableElement element) {
349 // TODO(eernst) implement: The "magic" default constructor has 366 // TODO(eernst) implement: The "magic" default constructor has
350 // index: -1; adjust this when support for it has been implemented. 367 // index: -1; adjust this when support for it has been implemented.
351 int index = members.indexOf(element); 368 int index = members.indexOf(element);
352 return index == null ? -1 : index + fieldsLength; 369 return index == null ? -1 : index + fieldsLength;
353 })); 370 }));
354 371
355 InterfaceType superType = classDomain._classElement.supertype; 372 InterfaceType superType = classDomain._classElement.supertype;
356 ClassElement superclass = superType == null ? null : superType.element; 373 ClassElement superclass = superType == null ? null : superType.element;
357 String superclassIndex; 374 String superclassIndex;
358 if (superclass == null) { 375 if (superclass == null) {
359 superclassIndex = null; 376 superclassIndex = null;
360 } else { 377 } else {
361 int index = classes.indexOf(superclass); 378 int index = classes.indexOf(superclass);
362 if (index == null) { 379 if (index == null) {
363 // There is a superclass, but we have no capability for it. 380 // There is a superclass, but we have no capability for it.
364 index = -1; 381 index = -1;
365 } 382 }
366 superclassIndex = "$index"; 383 superclassIndex = "$index";
367 } 384 }
368 385
369 String constructorsCode; 386 String constructorsCode;
370 387
371 if (classDomain._classElement.isAbstract) { 388 if (classDomain._classElement.isAbstract) {
372 constructorsCode = '{}'; 389 constructorsCode = '{}';
373 } else { 390 } else {
374 constructorsCode = _formatAsMap(classDomain._constructors 391 constructorsCode = _formatAsMap(
375 .map((ConstructorElement constructor) { 392 classDomain._constructors.map((ConstructorElement constructor) {
376 String code = _constructorCode(constructor, importCollector); 393 String code = _constructorCode(constructor, importCollector);
377 return 'r"${constructor.name}": $code'; 394 return 'r"${constructor.name}": $code';
378 })); 395 }));
379 } 396 }
380 397
381 String classMetadataCode; 398 String classMetadataCode;
382 if (_capabilities._supportsMetadata) { 399 if (_capabilities._supportsMetadata) {
383 classMetadataCode = _extractMetadataCode(classDomain._classElement, 400 classMetadataCode = _extractMetadataCode(classDomain._classElement,
384 resolver, importCollector, logger, dataId); 401 resolver, importCollector, logger, dataId);
385 } else { 402 } else {
386 classMetadataCode = "null"; 403 classMetadataCode = "null";
387 } 404 }
388 405
389 String staticGettersCode = _formatAsMap([ 406 String staticGettersCode = _formatAsMap([
390 classDomain._declaredMethods 407 classDomain._declaredMethods
391 .where((ExecutableElement element) => element.isStatic), 408 .where((ExecutableElement element) => element.isStatic),
392 classDomain._declaredAndImplicitAccessors.where( 409 classDomain._declaredAndImplicitAccessors.where(
393 (PropertyAccessorElement element) => 410 (PropertyAccessorElement element) =>
394 element.isStatic && element.isGetter) 411 element.isStatic && element.isGetter)
395 ].expand((x) => x).map((ExecutableElement element) => 412 ].expand((x) => x).map((ExecutableElement element) =>
396 staticGettingClosure(classDomain._classElement, element.name))); 413 staticGettingClosure(classDomain._classElement, element.name)));
397 String staticSettersCode = _formatAsMap( 414 String staticSettersCode = _formatAsMap(classDomain
398 classDomain._declaredAndImplicitAccessors 415 ._declaredAndImplicitAccessors
399 .where((PropertyAccessorElement element) => 416 .where((PropertyAccessorElement element) =>
400 element.isStatic && element.isSetter) 417 element.isStatic && element.isSetter)
401 .map((PropertyAccessorElement element) => _staticSettingClosure( 418 .map((PropertyAccessorElement element) =>
402 classDomain._classElement, element.name))); 419 _staticSettingClosure(classDomain._classElement, element.name)));
403 String result = 'new r.ClassMirrorImpl(r"${classDomain._simpleName}", ' 420 String result = 'new r.ClassMirrorImpl(r"${classDomain._simpleName}", '
404 'r"${classDomain._qualifiedName}", $classIndex, ' 421 'r"${classDomain._qualifiedName}", $classIndex, '
405 '${_constConstructionCode(importCollector)}, ' 422 '${_constConstructionCode(importCollector)}, '
406 '$declarationsCode, $instanceMembersCode, $superclassIndex, ' 423 '$declarationsCode, $instanceMembersCode, $superclassIndex, '
407 '$staticGettersCode, $staticSettersCode, $constructorsCode, ' 424 '$staticGettersCode, $staticSettersCode, $constructorsCode, '
408 '$classMetadataCode)'; 425 '$classMetadataCode)';
409 classIndex++; 426 classIndex++;
410 return result; 427 return result;
411 })); 428 }));
412 429
413 String gettersCode = _formatAsMap(instanceGetterNames.map(gettingClosure)); 430 String gettersCode = _formatAsMap(instanceGetterNames.map(gettingClosure));
414 String settersCode = _formatAsMap(instanceSetterNames.map(settingClosure)); 431 String settersCode = _formatAsMap(instanceSetterNames.map(settingClosure));
415 432
416 Iterable<String> methodsList = members.items 433 Iterable<String> methodsList =
417 .map((ExecutableElement element) { 434 members.items.map((ExecutableElement element) {
418 int descriptor = _declarationDescriptor(element); 435 int descriptor = _declarationDescriptor(element);
419 int ownerIndex = classes.indexOf(element.enclosingElement); 436 int ownerIndex = classes.indexOf(element.enclosingElement);
437 List<int> parameterIndices =
438 element.parameters.map((ParameterElement parameterElement) {
439 return parameters.indexOf(parameterElement);
440 });
441 String parameterIndicesCode = _formatAsList(parameterIndices);
420 String metadataCode; 442 String metadataCode;
421 if (_capabilities._supportsMetadata) { 443 if (_capabilities._supportsMetadata) {
422 metadataCode = _extractMetadataCode( 444 metadataCode = _extractMetadataCode(
423 element, resolver, importCollector, logger, dataId); 445 element, resolver, importCollector, logger, dataId);
424 } else { 446 } else {
425 metadataCode = null; 447 metadataCode = null;
426 } 448 }
427 return 'new r.MethodMirrorImpl(r"${element.name}", $descriptor, ' 449 return 'new r.MethodMirrorImpl(r"${element.name}", $descriptor, '
428 '$ownerIndex, ${_constConstructionCode(importCollector)}, ' 450 '$ownerIndex, $parameterIndicesCode, '
429 '$metadataCode)'; 451 '${_constConstructionCode(importCollector)}, $metadataCode)';
430 }); 452 });
431 453
432 Iterable<String> fieldsList = fields.items.map((FieldElement element) { 454 Iterable<String> fieldsList = fields.items.map((FieldElement element) {
433 int descriptor = _fieldDescriptor(element); 455 int descriptor = _fieldDescriptor(element);
434 int ownerIndex = classes.indexOf(element.enclosingElement); 456 int ownerIndex = classes.indexOf(element.enclosingElement);
435 String metadataCode; 457 String metadataCode;
436 if (_capabilities._supportsMetadata) { 458 if (_capabilities._supportsMetadata) {
437 metadataCode = _extractMetadataCode( 459 metadataCode = _extractMetadataCode(
438 element, resolver, importCollector, logger, dataId); 460 element, resolver, importCollector, logger, dataId);
439 } else { 461 } else {
440 metadataCode = null; 462 metadataCode = null;
441 } 463 }
442 return 'new r.VariableMirrorImpl("${element.name}", $descriptor, ' 464 return 'new r.VariableMirrorImpl("${element.name}", $descriptor, '
443 '$ownerIndex, ${_constConstructionCode(importCollector)}, ' 465 '$ownerIndex, ${_constConstructionCode(importCollector)}, '
444 '$metadataCode)'; 466 '$metadataCode)';
445 }); 467 });
446 468
447 List<String> membersList = <String>[] 469 List<String> membersList = <String>[]
448 ..addAll(fieldsList) 470 ..addAll(fieldsList)
449 ..addAll(methodsList); 471 ..addAll(methodsList);
450 String membersCode = _formatAsList(membersList); 472 String membersCode = _formatAsList(membersList);
451 473
452 String typesCode = _formatAsList(classes.items 474 String typesCode =
453 .map((ClassElement classElement) { 475 _formatAsList(classes.items.map((ClassElement classElement) {
454 String prefix = importCollector._getPrefix(classElement.library); 476 String prefix = importCollector._getPrefix(classElement.library);
455 return "$prefix.${classElement.name}"; 477 return "$prefix.${classElement.name}";
456 })); 478 }));
457 479
458 return "new r.ReflectorData($classMirrorsCode, $membersCode, $typesCode, " 480 Iterable<String> parametersList =
459 "$gettersCode, $settersCode)"; 481 parameters.items.map((ParameterElement element) {
482 int descriptor = _parameterDescriptor(element);
483 int ownerIndex = members.indexOf(element.enclosingElement);
484 int classMirrorIndex = classes._contains(element.type.element)
485 ? classes.indexOf(element.type.element)
486 : -1;
487 String metadataCode;
488 if (_capabilities._supportsMetadata) {
489 metadataCode = _extractMetadataCode(
490 element, resolver, importCollector, logger, dataId);
491 } else {
492 metadataCode = null;
493 }
494 // TODO(eernst) implement: Detect and, if possible, handle the case
495 // where it is incorrect to move element.defaultValueCode out of its
496 // original scope. If we cannot solve the problem we should issue
497 // a warning (it's worse than `new UndefinedClass()`, because it
498 // might "work" with a different semantics at runtime, rather than just
499 // failing if ever executed).
500 return 'new r.ParameterMirrorImpl(r"${element.name}", $descriptor, '
501 '$ownerIndex, ${_constConstructionCode(importCollector)}, '
502 '$metadataCode, ${element.defaultValueCode}, $classMirrorIndex)';
503 });
504 String parameterMirrorsCode = _formatAsList(parametersList);
505
506 return "new r.ReflectorData($classMirrorsCode, $membersCode, "
507 "$parameterMirrorsCode, $typesCode, $gettersCode, $settersCode)";
460 } 508 }
461 } 509 }
462 510
463 /// Information about reflectability for a given class. 511 /// Information about reflectability for a given class.
464 class _ClassDomain { 512 class _ClassDomain {
465 /// Element describing the target class. 513 /// Element describing the target class.
466 final ClassElement _classElement; 514 final ClassElement _classElement;
467 515
468 /// Fields declared by [classElement] and included for reflection support, 516 /// Fields declared by [classElement] and included for reflection support,
469 /// according to the reflector described by the [reflectorDomain]; 517 /// according to the reflector described by the [reflectorDomain];
470 /// obtained by filtering `classElement.fields`. 518 /// obtained by filtering `classElement.fields`.
471 final Iterable<FieldElement> _declaredFields; 519 final Iterable<FieldElement> _declaredFields;
472 520
473 /// Methods which are declared by [classElement] and included for 521 /// Methods which are declared by [classElement] and included for
474 /// reflection support, according to the reflector described by 522 /// reflection support, according to the reflector described by
475 /// [reflectorDomain]; obtained by filtering `classElement.methods`. 523 /// [reflectorDomain]; obtained by filtering `classElement.methods`.
476 final Iterable<MethodElement> _declaredMethods; 524 final Iterable<MethodElement> _declaredMethods;
477 525
526 /// Formal parameters declared by one of the [_declaredMethods].
527 final Iterable<ParameterElement> _declaredParameters;
528
478 /// Getters and setters possessed by [classElement] and included for 529 /// Getters and setters possessed by [classElement] and included for
479 /// reflection support, according to the reflector described by 530 /// reflection support, according to the reflector described by
480 /// [reflectorDomain]; obtained by filtering `classElement.accessors`. 531 /// [reflectorDomain]; obtained by filtering `classElement.accessors`.
481 /// Note that it includes declared as well as synthetic accessors, 532 /// Note that it includes declared as well as synthetic accessors,
482 /// implicitly created as getters/setters for fields. 533 /// implicitly created as getters/setters for fields.
483 final Iterable<PropertyAccessorElement> _declaredAndImplicitAccessors; 534 final Iterable<PropertyAccessorElement> _declaredAndImplicitAccessors;
484 535
485 /// Constructors declared by [classElement] and included for reflection 536 /// Constructors declared by [classElement] and included for reflection
486 /// support, according to the reflector described by [reflectorDomain]; 537 /// support, according to the reflector described by [reflectorDomain];
487 /// obtained by filtering `classElement.constructors`. 538 /// obtained by filtering `classElement.constructors`.
488 final Iterable<ConstructorElement> _constructors; 539 final Iterable<ConstructorElement> _constructors;
489 540
490 /// The reflector domain that holds [this] object as one of its 541 /// The reflector domain that holds [this] object as one of its
491 /// class domains. 542 /// class domains.
492 final _ReflectorDomain _reflectorDomain; 543 final _ReflectorDomain _reflectorDomain;
493 544
494 _ClassDomain(this._classElement, this._declaredFields, this._declaredMethods, 545 _ClassDomain(
495 this._declaredAndImplicitAccessors, this._constructors, 546 this._classElement,
547 this._declaredFields,
548 this._declaredMethods,
549 this._declaredParameters,
550 this._declaredAndImplicitAccessors,
551 this._constructors,
496 this._reflectorDomain); 552 this._reflectorDomain);
497 553
498 String get _simpleName => _classElement.name; 554 String get _simpleName => _classElement.name;
499 String get _qualifiedName { 555 String get _qualifiedName {
500 return "${_classElement.library.name}.${_classElement.name}"; 556 return "${_classElement.library.name}.${_classElement.name}";
501 } 557 }
502 558
503 /// Returns the declared methods, accessors and constructors in 559 /// Returns the declared methods, accessors and constructors in
504 /// [classElement]. Note that this includes synthetic getters and 560 /// [classElement]. Note that this includes synthetic getters and
505 /// setters, and omits fields; in other words, it provides the 561 /// setters, and omits fields; in other words, it provides the
506 /// behavioral point of view on the class. Also note that this is not 562 /// behavioral point of view on the class. Also note that this is not
507 /// the same semantics as that of `declarations` in [ClassMirror]. 563 /// the same semantics as that of `declarations` in [ClassMirror].
508 Iterable<ExecutableElement> get _declarations { 564 Iterable<ExecutableElement> get _declarations {
509 // TODO(sigurdm) feature: Include type variables (if we keep them). 565 // TODO(sigurdm) feature: Include type variables (if we keep them).
510 return [ 566 return [_declaredMethods, _declaredAndImplicitAccessors, _constructors]
511 _declaredMethods, 567 .expand((x) => x);
512 _declaredAndImplicitAccessors,
513 _constructors
514 ].expand((x) => x);
515 } 568 }
516 569
517 /// Finds all instance members by going through the class hierarchy. 570 /// Finds all instance members by going through the class hierarchy.
518 Iterable<ExecutableElement> get _instanceMembers { 571 Iterable<ExecutableElement> get _instanceMembers {
519 Map<String, ExecutableElement> helper(ClassElement classElement) { 572 Map<String, ExecutableElement> helper(ClassElement classElement) {
520 if (_reflectorDomain._instanceMemberCache[classElement] != null) { 573 if (_reflectorDomain._instanceMemberCache[classElement] != null) {
521 return _reflectorDomain._instanceMemberCache[classElement]; 574 return _reflectorDomain._instanceMemberCache[classElement];
522 } 575 }
523 Map<String, ExecutableElement> result = 576 Map<String, ExecutableElement> result =
524 new Map<String, ExecutableElement>(); 577 new Map<String, ExecutableElement>();
525 578
526 void addIfCapable(ExecutableElement member) { 579 void addIfCapable(ExecutableElement member) {
527 // If [member] is a synthetic accessor created from a field, search for 580 // If [member] is a synthetic accessor created from a field, search for
528 // the metadata on the original field. 581 // the metadata on the original field.
529 List<ElementAnnotation> metadata = (member is PropertyAccessorElement && 582 List<ElementAnnotation> metadata = (member is PropertyAccessorElement &&
530 member.isSynthetic) ? member.variable.metadata : member.metadata; 583 member.isSynthetic) ? member.variable.metadata : member.metadata;
531 if (_reflectorDomain._capabilities.supportsInstanceInvoke( 584 if (_reflectorDomain._capabilities
532 member.name, metadata)) { 585 .supportsInstanceInvoke(member.name, metadata)) {
533 result[member.name] = member; 586 result[member.name] = member;
534 } 587 }
535 } 588 }
536 if (classElement.supertype != null) { 589 if (classElement.supertype != null) {
537 helper(classElement.supertype.element) 590 helper(classElement.supertype.element)
538 .forEach((String name, ExecutableElement member) { 591 .forEach((String name, ExecutableElement member) {
539 addIfCapable(member); 592 addIfCapable(member);
540 }); 593 });
541 } 594 }
542 for (InterfaceType mixin in classElement.mixins) { 595 for (InterfaceType mixin in classElement.mixins) {
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
737 } 790 }
738 791
739 // Returns [true] iff these [Capabilities] specify reflection support where 792 // Returns [true] iff these [Capabilities] specify reflection support where
740 // the set of included classes must be upwards closed, i.e., extra classes 793 // the set of included classes must be upwards closed, i.e., extra classes
741 // must be added beyond the ones that are directly included as reflectable 794 // must be added beyond the ones that are directly included as reflectable
742 // because we must support operations like `superclass`. 795 // because we must support operations like `superclass`.
743 bool get _impliesUpwardsClosure { 796 bool get _impliesUpwardsClosure {
744 return _capabilities.any((ec.ReflectCapability capability) => 797 return _capabilities.any((ec.ReflectCapability capability) =>
745 capability == ec.typeRelationsCapability); 798 capability == ec.typeRelationsCapability);
746 } 799 }
800
801 bool get _impliesParameterTypes {
802 bool haveDeclarations =
803 _capabilities.any((ec.ReflectCapability capability) {
804 return capability == ec.declarationsCapability;
805 });
806 if (!haveDeclarations) return false;
807 return _capabilities.any((ec.ReflectCapability capability) {
808 return capability is ec.TypeCapability ||
809 capability is ec.TypingCapability;
810 });
811 }
747 } 812 }
748 813
749 /// Collects the libraries that needs to be imported, and gives each library 814 /// Collects the libraries that needs to be imported, and gives each library
750 /// a unique prefix. 815 /// a unique prefix.
751 class _ImportCollector { 816 class _ImportCollector {
752 Map<LibraryElement, String> _mapping = new Map<LibraryElement, String>(); 817 Map<LibraryElement, String> _mapping = new Map<LibraryElement, String>();
753 int _count = 0; 818 int _count = 0;
754 819
755 /// Returns the prefix associated with [library]. 820 /// Returns the prefix associated with [library].
756 String _getPrefix(LibraryElement library) { 821 String _getPrefix(LibraryElement library) {
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
982 } 1047 }
983 ClassElement reflector = 1048 ClassElement reflector =
984 value.fields["(super)"].fields["reflector"].type.element; 1049 value.fields["(super)"].fields["reflector"].type.element;
985 if (reflector == null || 1050 if (reflector == null ||
986 reflector.type.element.supertype.element != 1051 reflector.type.element.supertype.element !=
987 reflectableClass) { 1052 reflectableClass) {
988 String found = 1053 String found =
989 reflector == null ? "" : " Found ${reflector.name}"; 1054 reflector == null ? "" : " Found ${reflector.name}";
990 _warn( 1055 _warn(
991 "The reflector must be a direct subclass of Reflectable." + 1056 "The reflector must be a direct subclass of Reflectable." +
992 found, import); 1057 found,
1058 import);
993 continue; 1059 continue;
994 } 1060 }
995 globalPatterns 1061 globalPatterns
996 .putIfAbsent( 1062 .putIfAbsent(
997 new RegExp(pattern), () => new List<ClassElement>()) 1063 new RegExp(pattern), () => new List<ClassElement>())
998 .add(reflector); 1064 .add(reflector);
999 } 1065 }
1000 } else if (metadatum.element == 1066 } else if (metadatum.element ==
1001 globalQuantifyMetaCapabilityConstructor) { 1067 globalQuantifyMetaCapabilityConstructor) {
1002 EvaluationResultImpl evaluation = metadatum.evaluationResult; 1068 EvaluationResultImpl evaluation = metadatum.evaluationResult;
1003 if (evaluation != null && evaluation.value != null) { 1069 if (evaluation != null && evaluation.value != null) {
1004 DartObjectImpl value = evaluation.value; 1070 DartObjectImpl value = evaluation.value;
1005 Object metadataFieldValue = value.fields["metadataType"].value; 1071 Object metadataFieldValue = value.fields["metadataType"].value;
1006 if (metadataFieldValue == null || 1072 if (metadataFieldValue == null ||
1007 value.fields["metadataType"].type.element != typeClass) { 1073 value.fields["metadataType"].type.element != typeClass) {
1008 // TODO(sigurdm) implement: Create a span for the annotation. 1074 // TODO(sigurdm) implement: Create a span for the annotation.
1009 _warn("The metadata must be a Type. " 1075 _warn(
1076 "The metadata must be a Type. "
1010 "Found ${value.fields["metadataType"].type.element.name}", 1077 "Found ${value.fields["metadataType"].type.element.name}",
1011 import); 1078 import);
1012 continue; 1079 continue;
1013 } 1080 }
1014 ClassElement reflector = 1081 ClassElement reflector =
1015 value.fields["(super)"].fields["reflector"].type.element; 1082 value.fields["(super)"].fields["reflector"].type.element;
1016 if (reflector == null || 1083 if (reflector == null ||
1017 reflector.type.element.supertype.element != 1084 reflector.type.element.supertype.element !=
1018 reflectableClass) { 1085 reflectableClass) {
1019 String found = 1086 String found =
1020 reflector == null ? "" : " Found ${reflector.name}"; 1087 reflector == null ? "" : " Found ${reflector.name}";
1021 _warn( 1088 _warn(
1022 "The reflector must be a direct subclass of Reflectable." + 1089 "The reflector must be a direct subclass of Reflectable." +
1023 found, import); 1090 found,
1091 import);
1024 continue; 1092 continue;
1025 } 1093 }
1026 globalMetadata 1094 globalMetadata
1027 .putIfAbsent( 1095 .putIfAbsent(
1028 metadataFieldValue, () => new List<ClassElement>()) 1096 metadataFieldValue, () => new List<ClassElement>())
1029 .add(reflector); 1097 .add(reflector);
1030 } 1098 }
1031 } 1099 }
1032 } 1100 }
1033 } 1101 }
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1094 // Add the class if it is annotated by a reflector. 1162 // Add the class if it is annotated by a reflector.
1095 ClassElement reflector = 1163 ClassElement reflector =
1096 _getReflectableAnnotation(metadatum, focusClass); 1164 _getReflectableAnnotation(metadatum, focusClass);
1097 if (reflector != null) { 1165 if (reflector != null) {
1098 addClassDomain(type, reflector); 1166 addClassDomain(type, reflector);
1099 } 1167 }
1100 } 1168 }
1101 // Add the class to the domain of all reflectors associated with a 1169 // Add the class to the domain of all reflectors associated with a
1102 // pattern, via GlobalQuantifyCapability, that matches the qualified 1170 // pattern, via GlobalQuantifyCapability, that matches the qualified
1103 // name of the class. 1171 // name of the class.
1104 globalPatterns 1172 globalPatterns.forEach(
1105 .forEach((RegExp pattern, List<ClassElement> reflectors) { 1173 (RegExp pattern, List<ClassElement> reflectors) {
1106 String qualifiedName = "${type.library.name}.${type.name}"; 1174 String qualifiedName = "${type.library.name}.${type.name}";
1107 if (pattern.hasMatch(qualifiedName)) { 1175 if (pattern.hasMatch(qualifiedName)) {
1108 for (ClassElement reflector in reflectors) { 1176 for (ClassElement reflector in reflectors) {
1109 addClassDomain(type, reflector); 1177 addClassDomain(type, reflector);
1110 } 1178 }
1111 } 1179 }
1112 }); 1180 });
1113 } 1181 }
1114 } 1182 }
1115 } 1183 }
(...skipping 13 matching lines...) Expand all
1129 LibraryElement annotatedLibrary = classData._classElement.library; 1197 LibraryElement annotatedLibrary = classData._classElement.library;
1130 if (metadataLibrary != annotatedLibrary) { 1198 if (metadataLibrary != annotatedLibrary) {
1131 domain._missingImports.add(annotatedLibrary); 1199 domain._missingImports.add(annotatedLibrary);
1132 } 1200 }
1133 } 1201 }
1134 } 1202 }
1135 1203
1136 ImportElement _findLastImport(LibraryElement library) { 1204 ImportElement _findLastImport(LibraryElement library) {
1137 if (library.imports.isNotEmpty) { 1205 if (library.imports.isNotEmpty) {
1138 ImportElement importElement = library.imports.lastWhere( 1206 ImportElement importElement = library.imports.lastWhere(
1139 (importElement) => importElement.node != null, orElse: () => null); 1207 (importElement) => importElement.node != null,
1208 orElse: () => null);
1140 if (importElement != null) { 1209 if (importElement != null) {
1141 // Found an import element with a node (i.e., a non-synthetic one). 1210 // Found an import element with a node (i.e., a non-synthetic one).
1142 return importElement; 1211 return importElement;
1143 } else { 1212 } else {
1144 // No non-synthetic imports. 1213 // No non-synthetic imports.
1145 return null; 1214 return null;
1146 } 1215 }
1147 } 1216 }
1148 // library.imports.isEmpty 1217 // library.imports.isEmpty
1149 return null; 1218 return null;
1150 } 1219 }
1151 1220
1152 ExportElement _findFirstExport(LibraryElement library) { 1221 ExportElement _findFirstExport(LibraryElement library) {
1153 if (library.exports.isNotEmpty) { 1222 if (library.exports.isNotEmpty) {
1154 ExportElement exportElement = library.exports.firstWhere( 1223 ExportElement exportElement = library.exports.firstWhere(
1155 (exportElement) => exportElement.node != null, orElse: () => null); 1224 (exportElement) => exportElement.node != null,
1225 orElse: () => null);
1156 if (exportElement != null) { 1226 if (exportElement != null) {
1157 // Found an export element with a node (i.e., a non-synthetic one) 1227 // Found an export element with a node (i.e., a non-synthetic one)
1158 return exportElement; 1228 return exportElement;
1159 } else { 1229 } else {
1160 // No non-synthetic exports. 1230 // No non-synthetic exports.
1161 return null; 1231 return null;
1162 } 1232 }
1163 } 1233 }
1164 // library.exports.isEmpty 1234 // library.exports.isEmpty
1165 return null; 1235 return null;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1211 1281
1212 DartObjectImpl constant = evaluated.value; 1282 DartObjectImpl constant = evaluated.value;
1213 1283
1214 ParameterizedType dartType = constant.type; 1284 ParameterizedType dartType = constant.type;
1215 // We insist that the type must be a class, and we insist that it must 1285 // We insist that the type must be a class, and we insist that it must
1216 // be in the given `capabilityLibrary` (because we could never know 1286 // be in the given `capabilityLibrary` (because we could never know
1217 // how to interpret the meaning of a user-written capability class, so 1287 // how to interpret the meaning of a user-written capability class, so
1218 // users cannot write their own capability classes). 1288 // users cannot write their own capability classes).
1219 if (dartType.element is! ClassElement) { 1289 if (dartType.element is! ClassElement) {
1220 if (dartType.element.source != null) { 1290 if (dartType.element.source != null) {
1221 _logger.error(errors.applyTemplate(errors.SUPER_ARGUMENT_NON_CLASS, { 1291 _logger.error(
1222 "type": dartType.displayName 1292 errors.applyTemplate(errors.SUPER_ARGUMENT_NON_CLASS,
1223 }), span: _resolver.getSourceSpan(dartType.element)); 1293 {"type": dartType.displayName}),
1294 span: _resolver.getSourceSpan(dartType.element));
1224 } else { 1295 } else {
1225 _logger.error(errors.applyTemplate( 1296 _logger.error(errors.applyTemplate(
1226 errors.SUPER_ARGUMENT_NON_CLASS, {"type": dartType.displayName})); 1297 errors.SUPER_ARGUMENT_NON_CLASS, {"type": dartType.displayName}));
1227 } 1298 }
1228 } 1299 }
1229 ClassElement classElement = dartType.element; 1300 ClassElement classElement = dartType.element;
1230 if (classElement.library != capabilityLibrary) { 1301 if (classElement.library != capabilityLibrary) {
1231 _logger.error(errors.applyTemplate(errors.SUPER_ARGUMENT_WRONG_LIBRARY, { 1302 _logger.error(
1232 "library": capabilityLibrary, 1303 errors.applyTemplate(errors.SUPER_ARGUMENT_WRONG_LIBRARY,
1233 "element": classElement 1304 {"library": capabilityLibrary, "element": classElement}),
1234 }), span: _resolver.getSourceSpan(classElement)); 1305 span: _resolver.getSourceSpan(classElement));
1235 } 1306 }
1236 1307
1237 /// Extracts the namePattern String from an instance of a subclass of 1308 /// Extracts the namePattern String from an instance of a subclass of
1238 /// NamePatternCapability. 1309 /// NamePatternCapability.
1239 String extractNamePattern(DartObjectImpl constant) { 1310 String extractNamePattern(DartObjectImpl constant) {
1240 if (constant.fields == null || 1311 if (constant.fields == null ||
1241 constant.fields["(super)"] == null || 1312 constant.fields["(super)"] == null ||
1242 constant.fields["(super)"].fields["namePattern"] == null || 1313 constant.fields["(super)"].fields["namePattern"] == null ||
1243 constant.fields["(super)"].fields["namePattern"].stringValue == 1314 constant.fields["(super)"].fields["namePattern"].stringValue ==
1244 null) { 1315 null) {
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
1427 '\nimport "$reflectWorldUri" show initializeReflectable;'); 1498 '\nimport "$reflectWorldUri" show initializeReflectable;');
1428 1499
1429 // TODO(eernst) implement: This won't work if main is not declared 1500 // TODO(eernst) implement: This won't work if main is not declared
1430 // in `mainLibrary`. 1501 // in `mainLibrary`.
1431 if (mainLibrary.entryPoint == null) { 1502 if (mainLibrary.entryPoint == null) {
1432 _logger.warning("Could not find a main method in $entryPoint. Skipping."); 1503 _logger.warning("Could not find a main method in $entryPoint. Skipping.");
1433 return source; 1504 return source;
1434 } 1505 }
1435 sourceManager.insert(mainLibrary.entryPoint.nameOffset, "_"); 1506 sourceManager.insert(mainLibrary.entryPoint.nameOffset, "_");
1436 String args = (mainLibrary.entryPoint.parameters.length == 0) ? "" : "args"; 1507 String args = (mainLibrary.entryPoint.parameters.length == 0) ? "" : "args";
1437 sourceManager.insert(source.length, """ 1508 sourceManager.insert(
1509 source.length,
1510 """
1438 main($args) { 1511 main($args) {
1439 initializeReflectable(); 1512 initializeReflectable();
1440 return _main($args); 1513 return _main($args);
1441 }"""); 1514 }""");
1442 return sourceManager.source; 1515 return sourceManager.source;
1443 } 1516 }
1444 1517
1445 /// Performs the transformation which eliminates all imports of 1518 /// Performs the transformation which eliminates all imports of
1446 /// `package:reflectable/reflectable.dart` and instead provides a set of 1519 /// `package:reflectable/reflectable.dart` and instead provides a set of
1447 /// statically generated mirror classes. 1520 /// statically generated mirror classes.
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1514 /// which case we can drop this class and use that method. 1587 /// which case we can drop this class and use that method.
1515 class _AggregateTransformWrapper implements Transform { 1588 class _AggregateTransformWrapper implements Transform {
1516 final AggregateTransform _aggregateTransform; 1589 final AggregateTransform _aggregateTransform;
1517 final Asset primaryInput; 1590 final Asset primaryInput;
1518 _AggregateTransformWrapper(this._aggregateTransform, this.primaryInput); 1591 _AggregateTransformWrapper(this._aggregateTransform, this.primaryInput);
1519 TransformLogger get logger => _aggregateTransform.logger; 1592 TransformLogger get logger => _aggregateTransform.logger;
1520 Future<Asset> getInput(AssetId id) => _aggregateTransform.getInput(id); 1593 Future<Asset> getInput(AssetId id) => _aggregateTransform.getInput(id);
1521 Future<String> readInputAsString(AssetId id, {Encoding encoding}) { 1594 Future<String> readInputAsString(AssetId id, {Encoding encoding}) {
1522 return _aggregateTransform.readInputAsString(id, encoding: encoding); 1595 return _aggregateTransform.readInputAsString(id, encoding: encoding);
1523 } 1596 }
1597
1524 Stream<List<int>> readInput(AssetId id) => _aggregateTransform.readInput(id); 1598 Stream<List<int>> readInput(AssetId id) => _aggregateTransform.readInput(id);
1525 Future<bool> hasInput(AssetId id) => _aggregateTransform.hasInput(id); 1599 Future<bool> hasInput(AssetId id) => _aggregateTransform.hasInput(id);
1526 void addOutput(Asset output) => _aggregateTransform.addOutput(output); 1600 void addOutput(Asset output) => _aggregateTransform.addOutput(output);
1527 void consumePrimary() => _aggregateTransform.consumePrimary(primaryInput.id); 1601 void consumePrimary() => _aggregateTransform.consumePrimary(primaryInput.id);
1528 } 1602 }
1529 1603
1530 bool _accessorIsntImplicitGetterOrSetter(PropertyAccessorElement accessor) { 1604 bool _accessorIsntImplicitGetterOrSetter(PropertyAccessorElement accessor) {
1531 return !accessor.isSynthetic || (!accessor.isGetter && !accessor.isSetter); 1605 return !accessor.isSynthetic || (!accessor.isGetter && !accessor.isSetter);
1532 } 1606 }
1533 1607
1534 bool _executableIsntImplicitGetterOrSetter(ExecutableElement executable) { 1608 bool _executableIsntImplicitGetterOrSetter(ExecutableElement executable) {
1535 return executable is! PropertyAccessorElement || 1609 return executable is! PropertyAccessorElement ||
1536 _accessorIsntImplicitGetterOrSetter(executable); 1610 _accessorIsntImplicitGetterOrSetter(executable);
1537 } 1611 }
1538 1612
1539 /// Returns an integer encoding of the kind and attributes of the given 1613 /// Returns an integer encoding of the kind and attributes of the given
1540 /// field. 1614 /// field.
1541 int _fieldDescriptor(FieldElement element) { 1615 int _fieldDescriptor(FieldElement element) {
1542 int result = constants.field; 1616 int result = constants.field;
1543 if (element.isPrivate) result |= constants.privateAttribute; 1617 if (element.isPrivate) result |= constants.privateAttribute;
1544 if (element.isSynthetic) result |= constants.syntheticAttribute; 1618 if (element.isSynthetic) result |= constants.syntheticAttribute;
1545 if (element.isConst) result |= constants.constAttribute; 1619 if (element.isConst) result |= constants.constAttribute;
1546 if (element.isFinal) result |= constants.finalAttribute; 1620 if (element.isFinal) result |= constants.finalAttribute;
1547 if (element.isStatic) result |= constants.staticAttribute; 1621 if (element.isStatic) result |= constants.staticAttribute;
1548 return result; 1622 return result;
1549 } 1623 }
1550 1624
1551 /// Returns an integer encoding of the kind and attributes of the given 1625 /// Returns an integer encoding of the kind and attributes of the given
1626 /// parameter.
1627 int _parameterDescriptor(ParameterElement element) {
1628 int result = constants.parameter;
1629 if (element.isPrivate) result |= constants.privateAttribute;
1630 if (element.isSynthetic) result |= constants.syntheticAttribute;
1631 if (element.isConst) result |= constants.constAttribute;
1632 if (element.isFinal) result |= constants.finalAttribute;
1633 if (element.defaultValueCode != null) {
1634 result |= constants.hasDefaultValueAttribute;
1635 }
1636 if (element.parameterKind.isOptional) {
1637 result |= constants.optionalAttribute;
1638 }
1639 if (element.parameterKind == ParameterKind.NAMED) {
1640 result |= constants.namedAttribute;
1641 }
1642 if (element.type.isDynamic) {
1643 result |= constants.dynamicAttribute;
1644 }
1645 Element elementType = element.type.element;
1646 if (elementType is ClassElement) {
1647 result |= constants.classTypeAttribute;
1648 }
1649 return result;
1650 }
1651
1652 /// Returns an integer encoding of the kind and attributes of the given
1552 /// method/constructor/getter/setter. 1653 /// method/constructor/getter/setter.
1553 int _declarationDescriptor(ExecutableElement element) { 1654 int _declarationDescriptor(ExecutableElement element) {
1554 int result; 1655 int result;
1555 if (element is PropertyAccessorElement) { 1656 if (element is PropertyAccessorElement) {
1556 result = element.isGetter ? constants.getter : constants.setter; 1657 result = element.isGetter ? constants.getter : constants.setter;
1557 } else if (element is ConstructorElement) { 1658 } else if (element is ConstructorElement) {
1558 if (element.isFactory) { 1659 if (element.isFactory) {
1559 result = constants.factoryConstructor; 1660 result = constants.factoryConstructor;
1560 } else { 1661 } else {
1561 result = constants.generativeConstructor; 1662 result = constants.generativeConstructor;
(...skipping 19 matching lines...) Expand all
1581 : "${element.enclosingElement.name}.${element.name}"; 1682 : "${element.enclosingElement.name}.${element.name}";
1582 } 1683 }
1583 return element.name; 1684 return element.name;
1584 } 1685 }
1585 1686
1586 String _formatAsList(Iterable parts) => "[${parts.join(", ")}]"; 1687 String _formatAsList(Iterable parts) => "[${parts.join(", ")}]";
1587 1688
1588 String _formatAsMap(Iterable parts) => "{${parts.join(", ")}}"; 1689 String _formatAsMap(Iterable parts) => "{${parts.join(", ")}}";
1589 1690
1590 /// Returns code that will reproduce the given constant expression. 1691 /// Returns code that will reproduce the given constant expression.
1591 String _extractConstantCode(Expression expression, 1692 String _extractConstantCode(
1592 LibraryElement originatingLibrary, Resolver resolver, 1693 Expression expression,
1694 LibraryElement originatingLibrary,
1695 Resolver resolver,
1593 _ImportCollector importCollector) { 1696 _ImportCollector importCollector) {
1594 if (expression is ListLiteral) { 1697 if (expression is ListLiteral) {
1595 List<String> elements = expression.elements.map((Expression subExpression) { 1698 List<String> elements = expression.elements.map((Expression subExpression) {
1596 return _extractConstantCode( 1699 return _extractConstantCode(
1597 subExpression, originatingLibrary, resolver, importCollector); 1700 subExpression, originatingLibrary, resolver, importCollector);
1598 }); 1701 });
1599 // TODO(sigurdm) feature: Type arguments. 1702 // TODO(sigurdm) feature: Type arguments.
1600 return "const ${_formatAsList(elements)}"; 1703 return "const ${_formatAsList(elements)}";
1601 } else if (expression is MapLiteral) { 1704 } else if (expression is MapLiteral) {
1602 List<String> elements = expression.entries.map((MapLiteralEntry entry) { 1705 List<String> elements = expression.entries.map((MapLiteralEntry entry) {
1603 String key = _extractConstantCode( 1706 String key = _extractConstantCode(
1604 entry.key, originatingLibrary, resolver, importCollector); 1707 entry.key, originatingLibrary, resolver, importCollector);
1605 String value = _extractConstantCode( 1708 String value = _extractConstantCode(
1606 entry.value, originatingLibrary, resolver, importCollector); 1709 entry.value, originatingLibrary, resolver, importCollector);
1607 return "$key: $value"; 1710 return "$key: $value";
1608 }); 1711 });
1609 // TODO(sigurdm) feature: Type arguments. 1712 // TODO(sigurdm) feature: Type arguments.
1610 return "const ${_formatAsMap(elements)}"; 1713 return "const ${_formatAsMap(elements)}";
1611 } else if (expression is InstanceCreationExpression) { 1714 } else if (expression is InstanceCreationExpression) {
1612 String constructor = expression.constructorName.toSource(); 1715 String constructor = expression.constructorName.toSource();
1613 LibraryElement libraryOfConstructor = expression.staticElement.library; 1716 LibraryElement libraryOfConstructor = expression.staticElement.library;
1614 importCollector._addLibrary(libraryOfConstructor); 1717 importCollector._addLibrary(libraryOfConstructor);
1615 String prefix = 1718 String prefix =
1616 importCollector._getPrefix(expression.staticElement.library); 1719 importCollector._getPrefix(expression.staticElement.library);
1617 // TODO(sigurdm) implement: Named arguments. 1720 // TODO(sigurdm) implement: Named arguments.
1618 String arguments = expression.argumentList.arguments 1721 String arguments =
1619 .map((Expression argument) { 1722 expression.argumentList.arguments.map((Expression argument) {
1620 return _extractConstantCode( 1723 return _extractConstantCode(
1621 argument, originatingLibrary, resolver, importCollector); 1724 argument, originatingLibrary, resolver, importCollector);
1622 }).join(", "); 1725 }).join(", ");
1623 // TODO(sigurdm) feature: Type arguments. 1726 // TODO(sigurdm) feature: Type arguments.
1624 return "const $prefix.$constructor($arguments)"; 1727 return "const $prefix.$constructor($arguments)";
1625 } else if (expression is Identifier) { 1728 } else if (expression is Identifier) {
1626 Element element = expression.staticElement; 1729 Element element = expression.staticElement;
1627 importCollector._addLibrary(element.library); 1730 importCollector._addLibrary(element.library);
1628 String prefix = importCollector._getPrefix(element.library); 1731 String prefix = importCollector._getPrefix(element.library);
1629 Element enclosingElement = element.enclosingElement; 1732 Element enclosingElement = element.enclosingElement;
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
1753 span: resolver.getSourceSpan(element)); 1856 span: resolver.getSourceSpan(element));
1754 continue; 1857 continue;
1755 } 1858 }
1756 importCollector._addLibrary(library); 1859 importCollector._addLibrary(library);
1757 String prefix = importCollector._getPrefix(library); 1860 String prefix = importCollector._getPrefix(library);
1758 if (annotationNode.arguments != null) { 1861 if (annotationNode.arguments != null) {
1759 // A const constructor. 1862 // A const constructor.
1760 String constructor = (annotationNode.constructorName == null) 1863 String constructor = (annotationNode.constructorName == null)
1761 ? annotationNode.name 1864 ? annotationNode.name
1762 : "${annotationNode.name}.${annotationNode.constructorName}"; 1865 : "${annotationNode.name}.${annotationNode.constructorName}";
1763 String arguments = annotationNode.arguments.arguments 1866 String arguments =
1764 .map((Expression argument) { 1867 annotationNode.arguments.arguments.map((Expression argument) {
1765 return _extractConstantCode( 1868 return _extractConstantCode(
1766 argument, element.library, resolver, importCollector); 1869 argument, element.library, resolver, importCollector);
1767 }).join(", "); 1870 }).join(", ");
1768 metadataParts.add("const $prefix.$constructor($arguments)"); 1871 metadataParts.add("const $prefix.$constructor($arguments)");
1769 } else { 1872 } else {
1770 // A field reference. 1873 // A field reference.
1771 metadataParts.add("$prefix.${annotationNode.name}"); 1874 metadataParts.add("$prefix.${annotationNode.name}");
1772 } 1875 }
1773 } 1876 }
1774 1877
1775 return _formatAsList(metadataParts); 1878 return _formatAsList(metadataParts);
1776 } 1879 }
1777 1880
1778 Iterable<FieldElement> _declaredFields( 1881 Iterable<FieldElement> _extractDeclaredFields(
1779 ClassElement classElement, _Capabilities capabilities) { 1882 ClassElement classElement, _Capabilities capabilities) {
1780 return classElement.fields.where((FieldElement field) { 1883 return classElement.fields.where((FieldElement field) {
1781 Function capabilityChecker = field.isStatic 1884 Function capabilityChecker = field.isStatic
1782 ? capabilities.supportsStaticInvoke 1885 ? capabilities.supportsStaticInvoke
1783 : capabilities.supportsInstanceInvoke; 1886 : capabilities.supportsInstanceInvoke;
1784 return !field.isSynthetic && capabilityChecker(field.name, field.metadata); 1887 return !field.isSynthetic && capabilityChecker(field.name, field.metadata);
1785 }); 1888 });
1786 } 1889 }
1787 1890
1788 Iterable<MethodElement> _declaredMethods( 1891 Iterable<MethodElement> _extractDeclaredMethods(
1789 ClassElement classElement, _Capabilities capabilities) { 1892 ClassElement classElement, _Capabilities capabilities) {
1790 return classElement.methods.where((MethodElement method) { 1893 return classElement.methods.where((MethodElement method) {
1791 Function capabilityChecker = method.isStatic 1894 Function capabilityChecker = method.isStatic
1792 ? capabilities.supportsStaticInvoke 1895 ? capabilities.supportsStaticInvoke
1793 : capabilities.supportsInstanceInvoke; 1896 : capabilities.supportsInstanceInvoke;
1794 return capabilityChecker(method.name, method.metadata); 1897 return capabilityChecker(method.name, method.metadata);
1795 }); 1898 });
1796 } 1899 }
1797 1900
1901 Iterable<ParameterElement> _extractDeclaredParameters(
1902 Iterable<MethodElement> declaredMethods) {
1903 List<ParameterElement> result = <ParameterElement>[];
1904 for (MethodElement declaredMethod in declaredMethods) {
1905 result.addAll(declaredMethod.parameters);
1906 }
1907 return result;
1908 }
1909
1798 /// Returns the [PropertyAccessorElement]s which are the accessors 1910 /// Returns the [PropertyAccessorElement]s which are the accessors
1799 /// of the given [classElement], including both the declared ones 1911 /// of the given [classElement], including both the declared ones
1800 /// and the implicitly generated ones corresponding to fields. This 1912 /// and the implicitly generated ones corresponding to fields. This
1801 /// is the set of accessors that corresponds to the behavioral interface 1913 /// is the set of accessors that corresponds to the behavioral interface
1802 /// of the corresponding instances, as opposed to the source code oriented 1914 /// of the corresponding instances, as opposed to the source code oriented
1803 /// interface, e.g., `declarations`. But the latter can be computed from 1915 /// interface, e.g., `declarations`. But the latter can be computed from
1804 /// here, by filtering out the accessors whose `isSynthetic` is true 1916 /// here, by filtering out the accessors whose `isSynthetic` is true
1805 /// and adding the fields. 1917 /// and adding the fields.
1806 Iterable<PropertyAccessorElement> _declaredAndImplicitAccessors( 1918 Iterable<PropertyAccessorElement> _declaredAndImplicitAccessors(
1807 ClassElement classElement, _Capabilities capabilities) { 1919 ClassElement classElement, _Capabilities capabilities) {
1808 return classElement.accessors.where((PropertyAccessorElement accessor) { 1920 return classElement.accessors.where((PropertyAccessorElement accessor) {
1809 Function capabilityChecker = accessor.isStatic 1921 Function capabilityChecker = accessor.isStatic
1810 ? capabilities.supportsStaticInvoke 1922 ? capabilities.supportsStaticInvoke
1811 : capabilities.supportsInstanceInvoke; 1923 : capabilities.supportsInstanceInvoke;
1812 return capabilityChecker(accessor.name, accessor.metadata); 1924 return capabilityChecker(accessor.name, accessor.metadata);
1813 }); 1925 });
1814 } 1926 }
1815 1927
1816 Iterable<ConstructorElement> _declaredConstructors( 1928 Iterable<ConstructorElement> _declaredConstructors(
1817 ClassElement classElement, _Capabilities capabilities) { 1929 ClassElement classElement, _Capabilities capabilities) {
1818 return classElement.constructors.where((ConstructorElement constructor) { 1930 return classElement.constructors.where((ConstructorElement constructor) {
1819 return capabilities.supportsNewInstance( 1931 return capabilities.supportsNewInstance(
1820 constructor.name, constructor.metadata); 1932 constructor.name, constructor.metadata);
1821 }); 1933 });
1822 } 1934 }
1823 1935
1824 _ClassDomain _createClassDomain(ClassElement type, _ReflectorDomain domain) { 1936 _ClassDomain _createClassDomain(ClassElement type, _ReflectorDomain domain) {
1825 List<FieldElement> declaredFieldsOfClass = 1937 List<FieldElement> declaredFieldsOfClass =
1826 _declaredFields(type, domain._capabilities).toList(); 1938 _extractDeclaredFields(type, domain._capabilities).toList();
1827 List<MethodElement> declaredMethodsOfClass = 1939 List<MethodElement> declaredMethodsOfClass =
1828 _declaredMethods(type, domain._capabilities).toList(); 1940 _extractDeclaredMethods(type, domain._capabilities).toList();
1941 List<ParameterElement> declaredParametersOfClass =
1942 _extractDeclaredParameters(declaredMethodsOfClass);
1829 List<PropertyAccessorElement> declaredAndImplicitAccessorsOfClass = 1943 List<PropertyAccessorElement> declaredAndImplicitAccessorsOfClass =
1830 _declaredAndImplicitAccessors(type, domain._capabilities).toList(); 1944 _declaredAndImplicitAccessors(type, domain._capabilities).toList();
1831 List<ConstructorElement> declaredConstructorsOfClass = 1945 List<ConstructorElement> declaredConstructorsOfClass =
1832 _declaredConstructors(type, domain._capabilities).toList(); 1946 _declaredConstructors(type, domain._capabilities).toList();
1833 return new _ClassDomain(type, declaredFieldsOfClass, declaredMethodsOfClass, 1947 return new _ClassDomain(
1834 declaredAndImplicitAccessorsOfClass, declaredConstructorsOfClass, domain); 1948 type,
1835 } 1949 declaredFieldsOfClass,
1950 declaredMethodsOfClass,
1951 declaredParametersOfClass,
1952 declaredAndImplicitAccessorsOfClass,
1953 declaredConstructorsOfClass,
1954 domain);
1955 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698