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

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: Merging with code from Sigurd, caused several adjustments 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 'package:path/path.dart' as path; 16 import 'package:path/path.dart' as path;
16 import 'element_capability.dart' as ec; 17 import 'element_capability.dart' as ec;
17 import 'encoding_constants.dart' as constants; 18 import 'encoding_constants.dart' as constants;
18 import "reflectable_class_constants.dart" as reflectable_class_constants; 19 import "reflectable_class_constants.dart" as reflectable_class_constants;
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);
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 metadataCode = _capabilities._supportsMetadata ? "<Object>[]" : "null";
489 // TODO(eernst) implement: Detect and, if possible, handle the case
490 // where it is incorrect to move element.defaultValueCode out of its
491 // original scope. If we cannot solve the problem we should issue
492 // a warning (it's worse than `new UndefinedClass()`, because it
493 // might "work" with a different semantics at runtime, rather than just
494 // failing if ever executed).
495 return 'new r.ParameterMirrorImpl(r"${element.name}", $descriptor, '
496 '$ownerIndex, ${_constConstructionCode(importCollector)}, '
497 '$metadataCode, ${element.defaultValueCode}, $classMirrorIndex)';
498 });
499 String parameterMirrorsCode = _formatAsList(parametersList);
500
501 return "new r.ReflectorData($classMirrorsCode, $membersCode, "
502 "$parameterMirrorsCode, $typesCode, $gettersCode, $settersCode)";
460 } 503 }
461 } 504 }
462 505
463 /// Information about reflectability for a given class. 506 /// Information about reflectability for a given class.
464 class _ClassDomain { 507 class _ClassDomain {
465 /// Element describing the target class. 508 /// Element describing the target class.
466 final ClassElement _classElement; 509 final ClassElement _classElement;
467 510
468 /// Fields declared by [classElement] and included for reflection support, 511 /// Fields declared by [classElement] and included for reflection support,
469 /// according to the reflector described by the [reflectorDomain]; 512 /// according to the reflector described by the [reflectorDomain];
470 /// obtained by filtering `classElement.fields`. 513 /// obtained by filtering `classElement.fields`.
471 final Iterable<FieldElement> _declaredFields; 514 final Iterable<FieldElement> _declaredFields;
472 515
473 /// Methods which are declared by [classElement] and included for 516 /// Methods which are declared by [classElement] and included for
474 /// reflection support, according to the reflector described by 517 /// reflection support, according to the reflector described by
475 /// [reflectorDomain]; obtained by filtering `classElement.methods`. 518 /// [reflectorDomain]; obtained by filtering `classElement.methods`.
476 final Iterable<MethodElement> _declaredMethods; 519 final Iterable<MethodElement> _declaredMethods;
477 520
521 /// Formal parameters declared by one of the [_declaredMethods].
522 final Iterable<ParameterElement> _declaredParameters;
523
478 /// Getters and setters possessed by [classElement] and included for 524 /// Getters and setters possessed by [classElement] and included for
479 /// reflection support, according to the reflector described by 525 /// reflection support, according to the reflector described by
480 /// [reflectorDomain]; obtained by filtering `classElement.accessors`. 526 /// [reflectorDomain]; obtained by filtering `classElement.accessors`.
481 /// Note that it includes declared as well as synthetic accessors, 527 /// Note that it includes declared as well as synthetic accessors,
482 /// implicitly created as getters/setters for fields. 528 /// implicitly created as getters/setters for fields.
483 final Iterable<PropertyAccessorElement> _declaredAndImplicitAccessors; 529 final Iterable<PropertyAccessorElement> _declaredAndImplicitAccessors;
484 530
485 /// Constructors declared by [classElement] and included for reflection 531 /// Constructors declared by [classElement] and included for reflection
486 /// support, according to the reflector described by [reflectorDomain]; 532 /// support, according to the reflector described by [reflectorDomain];
487 /// obtained by filtering `classElement.constructors`. 533 /// obtained by filtering `classElement.constructors`.
488 final Iterable<ConstructorElement> _constructors; 534 final Iterable<ConstructorElement> _constructors;
489 535
490 /// The reflector domain that holds [this] object as one of its 536 /// The reflector domain that holds [this] object as one of its
491 /// class domains. 537 /// class domains.
492 final _ReflectorDomain _reflectorDomain; 538 final _ReflectorDomain _reflectorDomain;
493 539
494 _ClassDomain(this._classElement, this._declaredFields, this._declaredMethods, 540 _ClassDomain(
495 this._declaredAndImplicitAccessors, this._constructors, 541 this._classElement,
542 this._declaredFields,
543 this._declaredMethods,
544 this._declaredParameters,
545 this._declaredAndImplicitAccessors,
546 this._constructors,
496 this._reflectorDomain); 547 this._reflectorDomain);
497 548
498 String get _simpleName => _classElement.name; 549 String get _simpleName => _classElement.name;
499 String get _qualifiedName { 550 String get _qualifiedName {
500 return "${_classElement.library.name}.${_classElement.name}"; 551 return "${_classElement.library.name}.${_classElement.name}";
501 } 552 }
502 553
503 /// Returns the declared methods, accessors and constructors in 554 /// Returns the declared methods, accessors and constructors in
504 /// [classElement]. Note that this includes synthetic getters and 555 /// [classElement]. Note that this includes synthetic getters and
505 /// setters, and omits fields; in other words, it provides the 556 /// setters, and omits fields; in other words, it provides the
506 /// behavioral point of view on the class. Also note that this is not 557 /// behavioral point of view on the class. Also note that this is not
507 /// the same semantics as that of `declarations` in [ClassMirror]. 558 /// the same semantics as that of `declarations` in [ClassMirror].
508 Iterable<ExecutableElement> get _declarations { 559 Iterable<ExecutableElement> get _declarations {
509 // TODO(sigurdm) feature: Include type variables (if we keep them). 560 // TODO(sigurdm) feature: Include type variables (if we keep them).
510 return [ 561 return [_declaredMethods, _declaredAndImplicitAccessors, _constructors]
511 _declaredMethods, 562 .expand((x) => x);
512 _declaredAndImplicitAccessors,
513 _constructors
514 ].expand((x) => x);
515 } 563 }
516 564
517 /// Finds all instance members by going through the class hierarchy. 565 /// Finds all instance members by going through the class hierarchy.
518 Iterable<ExecutableElement> get _instanceMembers { 566 Iterable<ExecutableElement> get _instanceMembers {
519 Map<String, ExecutableElement> helper(ClassElement classElement) { 567 Map<String, ExecutableElement> helper(ClassElement classElement) {
520 if (_reflectorDomain._instanceMemberCache[classElement] != null) { 568 if (_reflectorDomain._instanceMemberCache[classElement] != null) {
521 return _reflectorDomain._instanceMemberCache[classElement]; 569 return _reflectorDomain._instanceMemberCache[classElement];
522 } 570 }
523 Map<String, ExecutableElement> result = 571 Map<String, ExecutableElement> result =
524 new Map<String, ExecutableElement>(); 572 new Map<String, ExecutableElement>();
525 573
526 void addIfCapable(ExecutableElement member) { 574 void addIfCapable(ExecutableElement member) {
575 if (member.isPrivate) return;
527 // If [member] is a synthetic accessor created from a field, search for 576 // If [member] is a synthetic accessor created from a field, search for
528 // the metadata on the original field. 577 // the metadata on the original field.
529 List<ElementAnnotation> metadata = (member is PropertyAccessorElement && 578 List<ElementAnnotation> metadata = (member is PropertyAccessorElement &&
530 member.isSynthetic) ? member.variable.metadata : member.metadata; 579 member.isSynthetic) ? member.variable.metadata : member.metadata;
531 if (_reflectorDomain._capabilities.supportsInstanceInvoke( 580 if (_reflectorDomain._capabilities
532 member.name, metadata)) { 581 .supportsInstanceInvoke(member.name, metadata)) {
533 result[member.name] = member; 582 result[member.name] = member;
534 } 583 }
535 } 584 }
536 if (classElement.supertype != null) { 585 if (classElement.supertype != null) {
537 helper(classElement.supertype.element) 586 helper(classElement.supertype.element)
538 .forEach((String name, ExecutableElement member) { 587 .forEach((String name, ExecutableElement member) {
539 addIfCapable(member); 588 addIfCapable(member);
540 }); 589 });
541 } 590 }
542 for (InterfaceType mixin in classElement.mixins) { 591 for (InterfaceType mixin in classElement.mixins) {
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
737 } 786 }
738 787
739 // Returns [true] iff these [Capabilities] specify reflection support where 788 // Returns [true] iff these [Capabilities] specify reflection support where
740 // the set of included classes must be upwards closed, i.e., extra classes 789 // 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 790 // must be added beyond the ones that are directly included as reflectable
742 // because we must support operations like `superclass`. 791 // because we must support operations like `superclass`.
743 bool get _impliesUpwardsClosure { 792 bool get _impliesUpwardsClosure {
744 return _capabilities.any((ec.ReflectCapability capability) => 793 return _capabilities.any((ec.ReflectCapability capability) =>
745 capability == ec.typeRelationsCapability); 794 capability == ec.typeRelationsCapability);
746 } 795 }
796
797 bool get _impliesParameterTypes {
798 bool haveDeclarations =
799 _capabilities.any((ec.ReflectCapability capability) {
800 return capability == ec.declarationsCapability;
801 });
802 if (!haveDeclarations) return false;
803 return _capabilities.any((ec.ReflectCapability capability) {
804 return capability is ec.TypeCapability ||
805 capability is ec.TypingCapability;
806 });
807 }
747 } 808 }
748 809
749 /// Collects the libraries that needs to be imported, and gives each library 810 /// Collects the libraries that needs to be imported, and gives each library
750 /// a unique prefix. 811 /// a unique prefix.
751 class _ImportCollector { 812 class _ImportCollector {
752 Map<LibraryElement, String> _mapping = new Map<LibraryElement, String>(); 813 Map<LibraryElement, String> _mapping = new Map<LibraryElement, String>();
753 int _count = 0; 814 int _count = 0;
754 815
755 /// Returns the prefix associated with [library]. 816 /// Returns the prefix associated with [library].
756 String _getPrefix(LibraryElement library) { 817 String _getPrefix(LibraryElement library) {
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
982 } 1043 }
983 ClassElement reflector = 1044 ClassElement reflector =
984 value.fields["(super)"].fields["reflector"].type.element; 1045 value.fields["(super)"].fields["reflector"].type.element;
985 if (reflector == null || 1046 if (reflector == null ||
986 reflector.type.element.supertype.element != 1047 reflector.type.element.supertype.element !=
987 reflectableClass) { 1048 reflectableClass) {
988 String found = 1049 String found =
989 reflector == null ? "" : " Found ${reflector.name}"; 1050 reflector == null ? "" : " Found ${reflector.name}";
990 _warn( 1051 _warn(
991 "The reflector must be a direct subclass of Reflectable." + 1052 "The reflector must be a direct subclass of Reflectable." +
992 found, import); 1053 found,
1054 import);
993 continue; 1055 continue;
994 } 1056 }
995 globalPatterns 1057 globalPatterns
996 .putIfAbsent( 1058 .putIfAbsent(
997 new RegExp(pattern), () => new List<ClassElement>()) 1059 new RegExp(pattern), () => new List<ClassElement>())
998 .add(reflector); 1060 .add(reflector);
999 } 1061 }
1000 } else if (metadatum.element == 1062 } else if (metadatum.element ==
1001 globalQuantifyMetaCapabilityConstructor) { 1063 globalQuantifyMetaCapabilityConstructor) {
1002 EvaluationResultImpl evaluation = metadatum.evaluationResult; 1064 EvaluationResultImpl evaluation = metadatum.evaluationResult;
1003 if (evaluation != null && evaluation.value != null) { 1065 if (evaluation != null && evaluation.value != null) {
1004 DartObjectImpl value = evaluation.value; 1066 DartObjectImpl value = evaluation.value;
1005 Object metadataFieldValue = value.fields["metadataType"].value; 1067 Object metadataFieldValue = value.fields["metadataType"].value;
1006 if (metadataFieldValue == null || 1068 if (metadataFieldValue == null ||
1007 value.fields["metadataType"].type.element != typeClass) { 1069 value.fields["metadataType"].type.element != typeClass) {
1008 // TODO(sigurdm) implement: Create a span for the annotation. 1070 // TODO(sigurdm) implement: Create a span for the annotation.
1009 _warn("The metadata must be a Type. " 1071 _warn(
1072 "The metadata must be a Type. "
1010 "Found ${value.fields["metadataType"].type.element.name}", 1073 "Found ${value.fields["metadataType"].type.element.name}",
1011 import); 1074 import);
1012 continue; 1075 continue;
1013 } 1076 }
1014 ClassElement reflector = 1077 ClassElement reflector =
1015 value.fields["(super)"].fields["reflector"].type.element; 1078 value.fields["(super)"].fields["reflector"].type.element;
1016 if (reflector == null || 1079 if (reflector == null ||
1017 reflector.type.element.supertype.element != 1080 reflector.type.element.supertype.element !=
1018 reflectableClass) { 1081 reflectableClass) {
1019 String found = 1082 String found =
1020 reflector == null ? "" : " Found ${reflector.name}"; 1083 reflector == null ? "" : " Found ${reflector.name}";
1021 _warn( 1084 _warn(
1022 "The reflector must be a direct subclass of Reflectable." + 1085 "The reflector must be a direct subclass of Reflectable." +
1023 found, import); 1086 found,
1087 import);
1024 continue; 1088 continue;
1025 } 1089 }
1026 globalMetadata 1090 globalMetadata
1027 .putIfAbsent( 1091 .putIfAbsent(
1028 metadataFieldValue, () => new List<ClassElement>()) 1092 metadataFieldValue, () => new List<ClassElement>())
1029 .add(reflector); 1093 .add(reflector);
1030 } 1094 }
1031 } 1095 }
1032 } 1096 }
1033 } 1097 }
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1094 // Add the class if it is annotated by a reflector. 1158 // Add the class if it is annotated by a reflector.
1095 ClassElement reflector = 1159 ClassElement reflector =
1096 _getReflectableAnnotation(metadatum, focusClass); 1160 _getReflectableAnnotation(metadatum, focusClass);
1097 if (reflector != null) { 1161 if (reflector != null) {
1098 addClassDomain(type, reflector); 1162 addClassDomain(type, reflector);
1099 } 1163 }
1100 } 1164 }
1101 // Add the class to the domain of all reflectors associated with a 1165 // Add the class to the domain of all reflectors associated with a
1102 // pattern, via GlobalQuantifyCapability, that matches the qualified 1166 // pattern, via GlobalQuantifyCapability, that matches the qualified
1103 // name of the class. 1167 // name of the class.
1104 globalPatterns 1168 globalPatterns.forEach(
1105 .forEach((RegExp pattern, List<ClassElement> reflectors) { 1169 (RegExp pattern, List<ClassElement> reflectors) {
1106 String qualifiedName = "${type.library.name}.${type.name}"; 1170 String qualifiedName = "${type.library.name}.${type.name}";
1107 if (pattern.hasMatch(qualifiedName)) { 1171 if (pattern.hasMatch(qualifiedName)) {
1108 for (ClassElement reflector in reflectors) { 1172 for (ClassElement reflector in reflectors) {
1109 addClassDomain(type, reflector); 1173 addClassDomain(type, reflector);
1110 } 1174 }
1111 } 1175 }
1112 }); 1176 });
1113 } 1177 }
1114 } 1178 }
1115 } 1179 }
(...skipping 10 matching lines...) Expand all
1126 void _collectMissingImports(_ReflectorDomain domain) { 1190 void _collectMissingImports(_ReflectorDomain domain) {
1127 LibraryElement metadataLibrary = domain._reflector.library; 1191 LibraryElement metadataLibrary = domain._reflector.library;
1128 for (_ClassDomain classData in domain._annotatedClasses) { 1192 for (_ClassDomain classData in domain._annotatedClasses) {
1129 LibraryElement annotatedLibrary = classData._classElement.library; 1193 LibraryElement annotatedLibrary = classData._classElement.library;
1130 if (metadataLibrary != annotatedLibrary) { 1194 if (metadataLibrary != annotatedLibrary) {
1131 domain._missingImports.add(annotatedLibrary); 1195 domain._missingImports.add(annotatedLibrary);
1132 } 1196 }
1133 } 1197 }
1134 } 1198 }
1135 1199
1136 ImportElement _findLastImport(LibraryElement library) {
1137 if (library.imports.isNotEmpty) {
1138 ImportElement importElement = library.imports.lastWhere(
1139 (importElement) => importElement.node != null, orElse: () => null);
1140 if (importElement != null) {
1141 // Found an import element with a node (i.e., a non-synthetic one).
1142 return importElement;
1143 } else {
1144 // No non-synthetic imports.
1145 return null;
1146 }
1147 }
1148 // library.imports.isEmpty
1149 return null;
1150 }
1151
1152 ExportElement _findFirstExport(LibraryElement library) {
1153 if (library.exports.isNotEmpty) {
1154 ExportElement exportElement = library.exports.firstWhere(
1155 (exportElement) => exportElement.node != null, orElse: () => null);
1156 if (exportElement != null) {
1157 // Found an export element with a node (i.e., a non-synthetic one)
1158 return exportElement;
1159 } else {
1160 // No non-synthetic exports.
1161 return null;
1162 }
1163 }
1164 // library.exports.isEmpty
1165 return null;
1166 }
1167
1168 /// Find a suitable index for insertion of additional import directives
1169 /// into [targetLibrary].
1170 int _newImportIndex(LibraryElement targetLibrary) {
1171 // Index in [source] where the new import directive is inserted, we
1172 // use 0 as the default placement (at the front of the file), but
1173 // make a heroic attempt to find a better placement first.
1174 int index = 0;
1175 ImportElement importElement = _findLastImport(targetLibrary);
1176 if (importElement != null) {
1177 index = importElement.node.end;
1178 } else {
1179 // No non-synthetic import directives present.
1180 ExportElement exportElement = _findFirstExport(targetLibrary);
1181 if (exportElement != null) {
1182 // Put the new import before the exports
1183 index = exportElement.node.offset;
1184 } else {
1185 // No non-synthetic import nor export directives present.
1186 CompilationUnit compilationUnitNode =
1187 targetLibrary.definingCompilationUnit.node;
1188 LibraryDirective libraryDirective = compilationUnitNode.directives
1189 .firstWhere((directive) => directive is LibraryDirective,
1190 orElse: () => null);
1191 if (libraryDirective != null) {
1192 // Put the new import after the library name directive.
1193 index = libraryDirective.end;
1194 } else {
1195 // No library directive either, keep index == 0.
1196 }
1197 }
1198 }
1199 return index;
1200 }
1201
1202 /// Returns the [ReflectCapability] denoted by the given [initializer]. 1200 /// Returns the [ReflectCapability] denoted by the given [initializer].
1203 ec.ReflectCapability _capabilityOfExpression(LibraryElement capabilityLibrary, 1201 ec.ReflectCapability _capabilityOfExpression(LibraryElement capabilityLibrary,
1204 Expression expression, LibraryElement containingLibrary) { 1202 Expression expression, LibraryElement containingLibrary) {
1205 EvaluationResult evaluated = 1203 EvaluationResult evaluated =
1206 _resolver.evaluateConstant(containingLibrary, expression); 1204 _resolver.evaluateConstant(containingLibrary, expression);
1207 1205
1208 if (!evaluated.isValid) { 1206 if (!evaluated.isValid) {
1209 _logger.error("Invalid constant $expression in capability-list."); 1207 _logger.error("Invalid constant $expression in capability-list.");
1210 } 1208 }
1211 1209
1212 DartObjectImpl constant = evaluated.value; 1210 DartObjectImpl constant = evaluated.value;
1213 1211
1214 ParameterizedType dartType = constant.type; 1212 ParameterizedType dartType = constant.type;
1215 // We insist that the type must be a class, and we insist that it must 1213 // 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 1214 // be in the given `capabilityLibrary` (because we could never know
1217 // how to interpret the meaning of a user-written capability class, so 1215 // how to interpret the meaning of a user-written capability class, so
1218 // users cannot write their own capability classes). 1216 // users cannot write their own capability classes).
1219 if (dartType.element is! ClassElement) { 1217 if (dartType.element is! ClassElement) {
1220 if (dartType.element.source != null) { 1218 if (dartType.element.source != null) {
1221 _logger.error(errors.applyTemplate(errors.SUPER_ARGUMENT_NON_CLASS, { 1219 _logger.error(
1222 "type": dartType.displayName 1220 errors.applyTemplate(errors.SUPER_ARGUMENT_NON_CLASS,
1223 }), span: _resolver.getSourceSpan(dartType.element)); 1221 {"type": dartType.displayName}),
1222 span: _resolver.getSourceSpan(dartType.element));
1224 } else { 1223 } else {
1225 _logger.error(errors.applyTemplate( 1224 _logger.error(errors.applyTemplate(
1226 errors.SUPER_ARGUMENT_NON_CLASS, {"type": dartType.displayName})); 1225 errors.SUPER_ARGUMENT_NON_CLASS, {"type": dartType.displayName}));
1227 } 1226 }
1228 } 1227 }
1229 ClassElement classElement = dartType.element; 1228 ClassElement classElement = dartType.element;
1230 if (classElement.library != capabilityLibrary) { 1229 if (classElement.library != capabilityLibrary) {
1231 _logger.error(errors.applyTemplate(errors.SUPER_ARGUMENT_WRONG_LIBRARY, { 1230 _logger.error(
1232 "library": capabilityLibrary, 1231 errors.applyTemplate(errors.SUPER_ARGUMENT_WRONG_LIBRARY,
1233 "element": classElement 1232 {"library": capabilityLibrary, "element": classElement}),
1234 }), span: _resolver.getSourceSpan(classElement)); 1233 span: _resolver.getSourceSpan(classElement));
1235 } 1234 }
1236 1235
1237 /// Extracts the namePattern String from an instance of a subclass of 1236 /// Extracts the namePattern String from an instance of a subclass of
1238 /// NamePatternCapability. 1237 /// NamePatternCapability.
1239 String extractNamePattern(DartObjectImpl constant) { 1238 String extractNamePattern(DartObjectImpl constant) {
1240 if (constant.fields == null || 1239 if (constant.fields == null ||
1241 constant.fields["(super)"] == null || 1240 constant.fields["(super)"] == null ||
1242 constant.fields["(super)"].fields["namePattern"] == null || 1241 constant.fields["(super)"].fields["namePattern"] == null ||
1243 constant.fields["(super)"].fields["namePattern"].stringValue == 1242 constant.fields["(super)"].fields["namePattern"].stringValue ==
1244 null) { 1243 null) {
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
1393 List<String> imports = new List<String>(); 1392 List<String> imports = new List<String>();
1394 world.importCollector._libraries.forEach((LibraryElement library) { 1393 world.importCollector._libraries.forEach((LibraryElement library) {
1395 Uri uri = _resolver.getImportUri(library, from: generatedId); 1394 Uri uri = _resolver.getImportUri(library, from: generatedId);
1396 String prefix = world.importCollector._getPrefix(library); 1395 String prefix = world.importCollector._getPrefix(library);
1397 imports.add("import '$uri' as $prefix;"); 1396 imports.add("import '$uri' as $prefix;");
1398 }); 1397 });
1399 imports.sort(); 1398 imports.sort();
1400 1399
1401 String args = 1400 String args =
1402 (entryPointLibrary.entryPoint.parameters.length == 0) ? "" : "args"; 1401 (entryPointLibrary.entryPoint.parameters.length == 0) ? "" : "args";
1403 StringBuffer buffer = new StringBuffer();
1404 return """ 1402 return """
1405 // This file has been generated by the reflectable package. 1403 // This file has been generated by the reflectable package.
1406 // https://github.com/dart-lang/reflectable. 1404 // https://github.com/dart-lang/reflectable.
1407 1405
1408 library reflectable_generated_main_library; 1406 library reflectable_generated_main_library;
1409 1407
1410 import "dart:core"; 1408 import "dart:core";
1411 import "$originalEntryPointFilename" as original show main; 1409 import "$originalEntryPointFilename" as original show main;
1412 ${imports.join('\n')} 1410 ${imports.join('\n')}
1413 1411
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
1514 /// which case we can drop this class and use that method. 1512 /// which case we can drop this class and use that method.
1515 class _AggregateTransformWrapper implements Transform { 1513 class _AggregateTransformWrapper implements Transform {
1516 final AggregateTransform _aggregateTransform; 1514 final AggregateTransform _aggregateTransform;
1517 final Asset primaryInput; 1515 final Asset primaryInput;
1518 _AggregateTransformWrapper(this._aggregateTransform, this.primaryInput); 1516 _AggregateTransformWrapper(this._aggregateTransform, this.primaryInput);
1519 TransformLogger get logger => _aggregateTransform.logger; 1517 TransformLogger get logger => _aggregateTransform.logger;
1520 Future<Asset> getInput(AssetId id) => _aggregateTransform.getInput(id); 1518 Future<Asset> getInput(AssetId id) => _aggregateTransform.getInput(id);
1521 Future<String> readInputAsString(AssetId id, {Encoding encoding}) { 1519 Future<String> readInputAsString(AssetId id, {Encoding encoding}) {
1522 return _aggregateTransform.readInputAsString(id, encoding: encoding); 1520 return _aggregateTransform.readInputAsString(id, encoding: encoding);
1523 } 1521 }
1522
1524 Stream<List<int>> readInput(AssetId id) => _aggregateTransform.readInput(id); 1523 Stream<List<int>> readInput(AssetId id) => _aggregateTransform.readInput(id);
1525 Future<bool> hasInput(AssetId id) => _aggregateTransform.hasInput(id); 1524 Future<bool> hasInput(AssetId id) => _aggregateTransform.hasInput(id);
1526 void addOutput(Asset output) => _aggregateTransform.addOutput(output); 1525 void addOutput(Asset output) => _aggregateTransform.addOutput(output);
1527 void consumePrimary() => _aggregateTransform.consumePrimary(primaryInput.id); 1526 void consumePrimary() => _aggregateTransform.consumePrimary(primaryInput.id);
1528 } 1527 }
1529 1528
1530 bool _accessorIsntImplicitGetterOrSetter(PropertyAccessorElement accessor) { 1529 bool _accessorIsntImplicitGetterOrSetter(PropertyAccessorElement accessor) {
1531 return !accessor.isSynthetic || (!accessor.isGetter && !accessor.isSetter); 1530 return !accessor.isSynthetic || (!accessor.isGetter && !accessor.isSetter);
1532 } 1531 }
1533 1532
1534 bool _executableIsntImplicitGetterOrSetter(ExecutableElement executable) { 1533 bool _executableIsntImplicitGetterOrSetter(ExecutableElement executable) {
1535 return executable is! PropertyAccessorElement || 1534 return executable is! PropertyAccessorElement ||
1536 _accessorIsntImplicitGetterOrSetter(executable); 1535 _accessorIsntImplicitGetterOrSetter(executable);
1537 } 1536 }
1538 1537
1539 /// Returns an integer encoding of the kind and attributes of the given 1538 /// Returns an integer encoding of the kind and attributes of the given
1540 /// field. 1539 /// field.
1541 int _fieldDescriptor(FieldElement element) { 1540 int _fieldDescriptor(FieldElement element) {
1542 int result = constants.field; 1541 int result = constants.field;
1543 if (element.isPrivate) result |= constants.privateAttribute; 1542 if (element.isPrivate) result |= constants.privateAttribute;
1544 if (element.isSynthetic) result |= constants.syntheticAttribute; 1543 if (element.isSynthetic) result |= constants.syntheticAttribute;
1545 if (element.isConst) result |= constants.constAttribute; 1544 if (element.isConst) result |= constants.constAttribute;
1546 if (element.isFinal) result |= constants.finalAttribute; 1545 if (element.isFinal) result |= constants.finalAttribute;
1547 if (element.isStatic) result |= constants.staticAttribute; 1546 if (element.isStatic) result |= constants.staticAttribute;
1548 return result; 1547 return result;
1549 } 1548 }
1550 1549
1551 /// Returns an integer encoding of the kind and attributes of the given 1550 /// Returns an integer encoding of the kind and attributes of the given
1551 /// parameter.
1552 int _parameterDescriptor(ParameterElement element) {
1553 int result = constants.parameter;
1554 if (element.isPrivate) result |= constants.privateAttribute;
1555 if (element.isSynthetic) result |= constants.syntheticAttribute;
1556 if (element.isConst) result |= constants.constAttribute;
1557 if (element.isFinal) result |= constants.finalAttribute;
1558 if (element.defaultValueCode != null) {
1559 result |= constants.hasDefaultValueAttribute;
1560 }
1561 if (element.parameterKind.isOptional) {
1562 result |= constants.optionalAttribute;
1563 }
1564 if (element.parameterKind == ParameterKind.NAMED) {
1565 result |= constants.namedAttribute;
1566 }
1567 if (element.type.isDynamic) {
1568 result |= constants.dynamicAttribute;
1569 }
1570 Element elementType = element.type.element;
1571 if (elementType is ClassElement) {
1572 result |= constants.classTypeAttribute;
1573 }
1574 return result;
1575 }
1576
1577 /// Returns an integer encoding of the kind and attributes of the given
1552 /// method/constructor/getter/setter. 1578 /// method/constructor/getter/setter.
1553 int _declarationDescriptor(ExecutableElement element) { 1579 int _declarationDescriptor(ExecutableElement element) {
1554 int result; 1580 int result;
1555 if (element is PropertyAccessorElement) { 1581 if (element is PropertyAccessorElement) {
1556 result = element.isGetter ? constants.getter : constants.setter; 1582 result = element.isGetter ? constants.getter : constants.setter;
1557 } else if (element is ConstructorElement) { 1583 } else if (element is ConstructorElement) {
1558 if (element.isFactory) { 1584 if (element.isFactory) {
1559 result = constants.factoryConstructor; 1585 result = constants.factoryConstructor;
1560 } else { 1586 } else {
1561 result = constants.generativeConstructor; 1587 result = constants.generativeConstructor;
(...skipping 19 matching lines...) Expand all
1581 : "${element.enclosingElement.name}.${element.name}"; 1607 : "${element.enclosingElement.name}.${element.name}";
1582 } 1608 }
1583 return element.name; 1609 return element.name;
1584 } 1610 }
1585 1611
1586 String _formatAsList(Iterable parts) => "[${parts.join(", ")}]"; 1612 String _formatAsList(Iterable parts) => "[${parts.join(", ")}]";
1587 1613
1588 String _formatAsMap(Iterable parts) => "{${parts.join(", ")}}"; 1614 String _formatAsMap(Iterable parts) => "{${parts.join(", ")}}";
1589 1615
1590 /// Returns code that will reproduce the given constant expression. 1616 /// Returns code that will reproduce the given constant expression.
1591 String _extractConstantCode(Expression expression, 1617 String _extractConstantCode(
1592 LibraryElement originatingLibrary, Resolver resolver, 1618 Expression expression,
1619 LibraryElement originatingLibrary,
1620 Resolver resolver,
1593 _ImportCollector importCollector) { 1621 _ImportCollector importCollector) {
1594 if (expression is ListLiteral) { 1622 if (expression is ListLiteral) {
1595 List<String> elements = expression.elements.map((Expression subExpression) { 1623 List<String> elements = expression.elements.map((Expression subExpression) {
1596 return _extractConstantCode( 1624 return _extractConstantCode(
1597 subExpression, originatingLibrary, resolver, importCollector); 1625 subExpression, originatingLibrary, resolver, importCollector);
1598 }); 1626 });
1599 // TODO(sigurdm) feature: Type arguments. 1627 // TODO(sigurdm) feature: Type arguments.
1600 return "const ${_formatAsList(elements)}"; 1628 return "const ${_formatAsList(elements)}";
1601 } else if (expression is MapLiteral) { 1629 } else if (expression is MapLiteral) {
1602 List<String> elements = expression.entries.map((MapLiteralEntry entry) { 1630 List<String> elements = expression.entries.map((MapLiteralEntry entry) {
1603 String key = _extractConstantCode( 1631 String key = _extractConstantCode(
1604 entry.key, originatingLibrary, resolver, importCollector); 1632 entry.key, originatingLibrary, resolver, importCollector);
1605 String value = _extractConstantCode( 1633 String value = _extractConstantCode(
1606 entry.value, originatingLibrary, resolver, importCollector); 1634 entry.value, originatingLibrary, resolver, importCollector);
1607 return "$key: $value"; 1635 return "$key: $value";
1608 }); 1636 });
1609 // TODO(sigurdm) feature: Type arguments. 1637 // TODO(sigurdm) feature: Type arguments.
1610 return "const ${_formatAsMap(elements)}"; 1638 return "const ${_formatAsMap(elements)}";
1611 } else if (expression is InstanceCreationExpression) { 1639 } else if (expression is InstanceCreationExpression) {
1612 String constructor = expression.constructorName.toSource(); 1640 String constructor = expression.constructorName.toSource();
1613 LibraryElement libraryOfConstructor = expression.staticElement.library; 1641 LibraryElement libraryOfConstructor = expression.staticElement.library;
1614 importCollector._addLibrary(libraryOfConstructor); 1642 importCollector._addLibrary(libraryOfConstructor);
1615 String prefix = 1643 String prefix =
1616 importCollector._getPrefix(expression.staticElement.library); 1644 importCollector._getPrefix(expression.staticElement.library);
1617 // TODO(sigurdm) implement: Named arguments. 1645 // TODO(sigurdm) implement: Named arguments.
1618 String arguments = expression.argumentList.arguments 1646 String arguments =
1619 .map((Expression argument) { 1647 expression.argumentList.arguments.map((Expression argument) {
1620 return _extractConstantCode( 1648 return _extractConstantCode(
1621 argument, originatingLibrary, resolver, importCollector); 1649 argument, originatingLibrary, resolver, importCollector);
1622 }).join(", "); 1650 }).join(", ");
1623 // TODO(sigurdm) feature: Type arguments. 1651 // TODO(sigurdm) feature: Type arguments.
1624 return "const $prefix.$constructor($arguments)"; 1652 return "const $prefix.$constructor($arguments)";
1625 } else if (expression is Identifier) { 1653 } else if (expression is Identifier) {
1626 Element element = expression.staticElement; 1654 Element element = expression.staticElement;
1627 importCollector._addLibrary(element.library); 1655 importCollector._addLibrary(element.library);
1628 String prefix = importCollector._getPrefix(element.library); 1656 String prefix = importCollector._getPrefix(element.library);
1629 Element enclosingElement = element.enclosingElement; 1657 Element enclosingElement = element.enclosingElement;
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
1753 span: resolver.getSourceSpan(element)); 1781 span: resolver.getSourceSpan(element));
1754 continue; 1782 continue;
1755 } 1783 }
1756 importCollector._addLibrary(library); 1784 importCollector._addLibrary(library);
1757 String prefix = importCollector._getPrefix(library); 1785 String prefix = importCollector._getPrefix(library);
1758 if (annotationNode.arguments != null) { 1786 if (annotationNode.arguments != null) {
1759 // A const constructor. 1787 // A const constructor.
1760 String constructor = (annotationNode.constructorName == null) 1788 String constructor = (annotationNode.constructorName == null)
1761 ? annotationNode.name 1789 ? annotationNode.name
1762 : "${annotationNode.name}.${annotationNode.constructorName}"; 1790 : "${annotationNode.name}.${annotationNode.constructorName}";
1763 String arguments = annotationNode.arguments.arguments 1791 String arguments =
1764 .map((Expression argument) { 1792 annotationNode.arguments.arguments.map((Expression argument) {
1765 return _extractConstantCode( 1793 return _extractConstantCode(
1766 argument, element.library, resolver, importCollector); 1794 argument, element.library, resolver, importCollector);
1767 }).join(", "); 1795 }).join(", ");
1768 metadataParts.add("const $prefix.$constructor($arguments)"); 1796 metadataParts.add("const $prefix.$constructor($arguments)");
1769 } else { 1797 } else {
1770 // A field reference. 1798 // A field reference.
1771 metadataParts.add("$prefix.${annotationNode.name}"); 1799 metadataParts.add("$prefix.${annotationNode.name}");
1772 } 1800 }
1773 } 1801 }
1774 1802
1775 return _formatAsList(metadataParts); 1803 return _formatAsList(metadataParts);
1776 } 1804 }
1777 1805
1778 Iterable<FieldElement> _declaredFields( 1806 Iterable<FieldElement> _extractDeclaredFields(
1779 ClassElement classElement, _Capabilities capabilities) { 1807 ClassElement classElement, _Capabilities capabilities) {
1780 return classElement.fields.where((FieldElement field) { 1808 return classElement.fields.where((FieldElement field) {
1809 if (field.isPrivate) return false;
1781 Function capabilityChecker = field.isStatic 1810 Function capabilityChecker = field.isStatic
1782 ? capabilities.supportsStaticInvoke 1811 ? capabilities.supportsStaticInvoke
1783 : capabilities.supportsInstanceInvoke; 1812 : capabilities.supportsInstanceInvoke;
1784 return !field.isSynthetic && capabilityChecker(field.name, field.metadata); 1813 return !field.isSynthetic && capabilityChecker(field.name, field.metadata);
1785 }); 1814 });
1786 } 1815 }
1787 1816
1788 Iterable<MethodElement> _declaredMethods( 1817 Iterable<MethodElement> _extractDeclaredMethods(
1789 ClassElement classElement, _Capabilities capabilities) { 1818 ClassElement classElement, _Capabilities capabilities) {
1790 return classElement.methods.where((MethodElement method) { 1819 return classElement.methods.where((MethodElement method) {
1820 if (method.isPrivate) return false;
1791 Function capabilityChecker = method.isStatic 1821 Function capabilityChecker = method.isStatic
1792 ? capabilities.supportsStaticInvoke 1822 ? capabilities.supportsStaticInvoke
1793 : capabilities.supportsInstanceInvoke; 1823 : capabilities.supportsInstanceInvoke;
1794 return capabilityChecker(method.name, method.metadata); 1824 return capabilityChecker(method.name, method.metadata);
1795 }); 1825 });
1796 } 1826 }
1797 1827
1828 Iterable<ParameterElement> _extractDeclaredParameters(
1829 Iterable<MethodElement> declaredMethods) {
1830 List<ParameterElement> result = <ParameterElement>[];
1831 for (MethodElement declaredMethod in declaredMethods) {
1832 result.addAll(declaredMethod.parameters);
1833 }
1834 return result;
1835 }
1836
1798 /// Returns the [PropertyAccessorElement]s which are the accessors 1837 /// Returns the [PropertyAccessorElement]s which are the accessors
1799 /// of the given [classElement], including both the declared ones 1838 /// of the given [classElement], including both the declared ones
1800 /// and the implicitly generated ones corresponding to fields. This 1839 /// and the implicitly generated ones corresponding to fields. This
1801 /// is the set of accessors that corresponds to the behavioral interface 1840 /// is the set of accessors that corresponds to the behavioral interface
1802 /// of the corresponding instances, as opposed to the source code oriented 1841 /// of the corresponding instances, as opposed to the source code oriented
1803 /// interface, e.g., `declarations`. But the latter can be computed from 1842 /// interface, e.g., `declarations`. But the latter can be computed from
1804 /// here, by filtering out the accessors whose `isSynthetic` is true 1843 /// here, by filtering out the accessors whose `isSynthetic` is true
1805 /// and adding the fields. 1844 /// and adding the fields.
1806 Iterable<PropertyAccessorElement> _declaredAndImplicitAccessors( 1845 Iterable<PropertyAccessorElement> _declaredAndImplicitAccessors(
1807 ClassElement classElement, _Capabilities capabilities) { 1846 ClassElement classElement, _Capabilities capabilities) {
1808 return classElement.accessors.where((PropertyAccessorElement accessor) { 1847 return classElement.accessors.where((PropertyAccessorElement accessor) {
1848 if (accessor.isPrivate) return false;
1809 Function capabilityChecker = accessor.isStatic 1849 Function capabilityChecker = accessor.isStatic
1810 ? capabilities.supportsStaticInvoke 1850 ? capabilities.supportsStaticInvoke
1811 : capabilities.supportsInstanceInvoke; 1851 : capabilities.supportsInstanceInvoke;
1812 return capabilityChecker(accessor.name, accessor.metadata); 1852 return capabilityChecker(accessor.name, accessor.metadata);
1813 }); 1853 });
1814 } 1854 }
1815 1855
1816 Iterable<ConstructorElement> _declaredConstructors( 1856 Iterable<ConstructorElement> _declaredConstructors(
1817 ClassElement classElement, _Capabilities capabilities) { 1857 ClassElement classElement, _Capabilities capabilities) {
1818 return classElement.constructors.where((ConstructorElement constructor) { 1858 return classElement.constructors.where((ConstructorElement constructor) {
1859 if (constructor.isPrivate) return false;
1819 return capabilities.supportsNewInstance( 1860 return capabilities.supportsNewInstance(
1820 constructor.name, constructor.metadata); 1861 constructor.name, constructor.metadata);
1821 }); 1862 });
1822 } 1863 }
1823 1864
1824 _ClassDomain _createClassDomain(ClassElement type, _ReflectorDomain domain) { 1865 _ClassDomain _createClassDomain(ClassElement type, _ReflectorDomain domain) {
1825 List<FieldElement> declaredFieldsOfClass = 1866 List<FieldElement> declaredFieldsOfClass =
1826 _declaredFields(type, domain._capabilities).toList(); 1867 _extractDeclaredFields(type, domain._capabilities).toList();
1827 List<MethodElement> declaredMethodsOfClass = 1868 List<MethodElement> declaredMethodsOfClass =
1828 _declaredMethods(type, domain._capabilities).toList(); 1869 _extractDeclaredMethods(type, domain._capabilities).toList();
1870 List<ParameterElement> declaredParametersOfClass =
1871 _extractDeclaredParameters(declaredMethodsOfClass);
1829 List<PropertyAccessorElement> declaredAndImplicitAccessorsOfClass = 1872 List<PropertyAccessorElement> declaredAndImplicitAccessorsOfClass =
1830 _declaredAndImplicitAccessors(type, domain._capabilities).toList(); 1873 _declaredAndImplicitAccessors(type, domain._capabilities).toList();
1831 List<ConstructorElement> declaredConstructorsOfClass = 1874 List<ConstructorElement> declaredConstructorsOfClass =
1832 _declaredConstructors(type, domain._capabilities).toList(); 1875 _declaredConstructors(type, domain._capabilities).toList();
1833 return new _ClassDomain(type, declaredFieldsOfClass, declaredMethodsOfClass, 1876 return new _ClassDomain(
1834 declaredAndImplicitAccessorsOfClass, declaredConstructorsOfClass, domain); 1877 type,
1835 } 1878 declaredFieldsOfClass,
1879 declaredMethodsOfClass,
1880 declaredParametersOfClass,
1881 declaredAndImplicitAccessorsOfClass,
1882 declaredConstructorsOfClass,
1883 domain);
1884 }
OLDNEW
« no previous file with comments | « reflectable/lib/src/reflectable_implementation.dart ('k') | reflectable/test/mock_tests/check_literal_transform_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698