Chromium Code Reviews| Index: pkg/compiler/lib/src/js_backend/mirrors_data.dart |
| diff --git a/pkg/compiler/lib/src/js_backend/mirrors_data.dart b/pkg/compiler/lib/src/js_backend/mirrors_data.dart |
| index 97d348c83e88b5f16b1160af954e186c616482ec..ae9b3b57f44653f498c014c49ddeae7321ad206f 100644 |
| --- a/pkg/compiler/lib/src/js_backend/mirrors_data.dart |
| +++ b/pkg/compiler/lib/src/js_backend/mirrors_data.dart |
| @@ -8,7 +8,8 @@ import '../common_elements.dart'; |
| import '../compiler.dart'; |
| import '../constants/values.dart'; |
| import '../elements/elements.dart'; |
| -import '../elements/resolution_types.dart'; |
| +import '../elements/entities.dart'; |
| +import '../elements/types.dart'; |
| import '../options.dart'; |
| import '../world.dart'; |
| import '../universe/world_builder.dart'; |
| @@ -47,45 +48,90 @@ abstract class MirrorsData { |
| /// Set of symbols that the user has requested for reflection. |
| Iterable<String> get symbolsUsed; |
| - /// Set of elements that the user has requested for reflection. |
| - Iterable<Element> get targetsUsed; |
| + /// The members that the user has requested for reflection through the |
| + /// 'targets' property of a `MirrorsUsed` annotation. |
| + Iterable<MemberEntity> get membersInMirrorsUsedTargets; |
| + |
| + /// The classes that the user has requested for reflection through the |
| + /// 'targets' property of a `MirrorsUsed` annotation. |
| + Iterable<ClassEntity> get classesInMirrorsUsedTargets; |
| - /// Should [element] (a getter) that would normally not be generated due to |
| - /// treeshaking be retained for reflection? |
| - bool shouldRetainGetter(Element element); |
| + /// The libraries that the user has requested for reflection through the |
| + /// 'targets' property of a `MirrorsUsed` annotation. |
| + Iterable<LibraryEntity> get librariesInMirrorsUsedTargets; |
| - /// Should [element] (a setter) hat would normally not be generated due to |
| - /// treeshaking be retained for reflection? |
| - bool shouldRetainSetter(Element element); |
| + /// Should the getter for [element] that would normally not be generated due |
| + /// to tree-shaking be retained for reflection? |
| + bool shouldRetainGetter(FieldEntity element); |
| + |
| + /// Should the setter for [element] that would normally not be generated due |
| + /// to tree-shaking be retained for reflection? |
| + bool shouldRetainSetter(FieldEntity element); |
| /// Should [name] be retained for reflection? |
| bool shouldRetainName(String name); |
| - /// Returns true if this element is covered by a mirrorsUsed annotation. |
| + /// Returns `true` if the class [element] is covered by a `MirrorsUsed` |
| + /// annotation. |
| /// |
| /// Note that it might still be ok to tree shake the element away if no |
| /// reflection is used in the program (and thus [isTreeShakingDisabled] is |
| /// still false). Therefore _do not_ use this predicate to decide inclusion |
| /// in the tree, use [requiredByMirrorSystem] instead. |
| - bool referencedFromMirrorSystem(Element element, [recursive = true]); |
| + bool isClassReferencedFromMirrorSystem(ClassEntity element); |
| - /// Returns `true` if [element] can be accessed through reflection, that is, |
| - /// is in the set of elements covered by a `MirrorsUsed` annotation. |
| + /// Returns `true` if the member [element] is covered by a `MirrorsUsed` |
| + /// annotation. |
| + /// |
| + /// Note that it might still be ok to tree shake the element away if no |
| + /// reflection is used in the program (and thus [isTreeShakingDisabled] is |
| + /// still false). Therefore _do not_ use this predicate to decide inclusion |
| + /// in the tree, use [requiredByMirrorSystem] instead. |
| + bool isMemberReferencedFromMirrorSystem(MemberEntity element); |
| + |
| + /// Returns `true` if the library [element] is covered by a `MirrorsUsed` |
| + /// annotation. |
| + bool isLibraryReferencedFromMirrorSystem(LibraryEntity element); |
| + |
| + /// Returns `true` if the typedef [element] needs reflection information at |
| + /// runtime. |
| /// |
| /// This property is used to tag emitted elements with a marker which is |
| /// checked by the runtime system to throw an exception if an element is |
| /// accessed (invoked, get, set) that is not accessible for the reflective |
| /// system. |
| + bool isTypedefAccessibleByReflection(TypedefElement element); |
| + |
| + /// Returns `true` if the class [element] needs reflection information at |
| + /// runtime. |
| + /// |
| + /// This property is used to tag emitted elements with a marker which is |
| + /// checked by the runtime system to throw an exception if an element is |
| + /// accessed (invoked, get, set) that is not accessible for the reflective |
| + /// system. |
| + bool isClassAccessibleByReflection(ClassEntity element); |
| + |
| + /// Returns `true` if the member [element] needs reflection information at |
| + /// runtime. |
| + /// |
| + /// This property is used to tag emitted elements with a marker which is |
| + /// checked by the runtime system to throw an exception if an element is |
| + /// accessed (invoked, get, set) that is not accessible for the reflective |
| + /// system. |
| + bool isMemberAccessibleByReflection(MemberEntity element); |
| + |
| + // TODO(johnniwinther): Remove this. |
| + @deprecated |
| bool isAccessibleByReflection(Element element); |
| - bool retainMetadataOf(Element element); |
| + bool retainMetadataOfLibrary(LibraryEntity element); |
| + bool retainMetadataOfTypedef(TypedefElement element); |
| + bool retainMetadataOfClass(ClassEntity element); |
| + bool retainMetadataOfMember(MemberEntity element); |
| + bool retainMetadataOfParameter(ParameterElement element); |
| bool invokedReflectively(Element element); |
| - /// Returns `true` if this member element needs reflection information at |
| - /// runtime. |
| - bool isMemberAccessibleByReflection(MemberElement element); |
| - |
| /// Returns true if this element has to be enqueued due to |
| /// mirror usage. Might be a subset of [referencedFromMirrorSystem] if |
| /// normal tree shaking is still active ([isTreeShakingDisabled] is false). |
| @@ -144,11 +190,16 @@ class MirrorsDataImpl implements MirrorsData, MirrorsDataBuilder { |
| final Set<String> symbolsUsed = new Set<String>(); |
| /// Set of elements that the user has requested for reflection. |
| - final Set<Element> targetsUsed = new Set<Element>(); |
| + final Set<MemberEntity> membersInMirrorsUsedTargets = new Set<MemberEntity>(); |
| + final Set<ClassEntity> classesInMirrorsUsedTargets = new Set<ClassEntity>(); |
| + final Set<LibraryEntity> librariesInMirrorsUsedTargets = |
| + new Set<LibraryEntity>(); |
| + final Set<TypedefElement> _typedefsInMirrorsUsedTargets = |
| + new Set<TypedefElement>(); |
| /// List of annotations provided by user that indicate that the annotated |
| /// element must be retained. |
| - final Set<Element> metaTargetsUsed = new Set<Element>(); |
| + final Set<ClassEntity> metaTargetsUsed = new Set<ClassEntity>(); |
| // TODO(johnniwinther): Avoid the need for this. |
| final Compiler _compiler; |
| @@ -178,16 +229,12 @@ class MirrorsDataImpl implements MirrorsData, MirrorsDataBuilder { |
| } |
| } |
| - /// Should [element] (a getter) that would normally not be generated due to |
| - /// treeshaking be retained for reflection? |
| - bool shouldRetainGetter(Element element) { |
| - return isTreeShakingDisabled && isAccessibleByReflection(element); |
| + bool shouldRetainGetter(FieldElement element) { |
| + return isTreeShakingDisabled && isMemberAccessibleByReflection(element); |
| } |
| - /// Should [element] (a setter) hat would normally not be generated due to |
| - /// treeshaking be retained for reflection? |
| - bool shouldRetainSetter(Element element) { |
| - return isTreeShakingDisabled && isAccessibleByReflection(element); |
| + bool shouldRetainSetter(FieldElement element) { |
| + return isTreeShakingDisabled && isMemberAccessibleByReflection(element); |
| } |
| /// Should [name] be retained for reflection? |
| @@ -197,20 +244,64 @@ class MirrorsDataImpl implements MirrorsData, MirrorsDataBuilder { |
| return symbolsUsed.contains(name); |
| } |
| - bool retainMetadataOf(Element element) { |
| + @override |
| + bool retainMetadataOfParameter(ParameterElement element) { |
| if (mustRetainMetadata) hasRetainedMetadata = true; |
| - if (mustRetainMetadata && referencedFromMirrorSystem(element)) { |
| - for (MetadataAnnotation metadata in element.metadata) { |
| - metadata.ensureResolved(_compiler.resolution); |
| - ConstantValue constant = |
| - _constants.getConstantValueForMetadata(metadata); |
| - _constants.addCompileTimeConstantForEmission(constant); |
| - } |
| + if (mustRetainMetadata && isParameterReferencedFromMirrorSystem(element)) { |
| + _retainMetadataOf(element); |
| return true; |
| } |
| return false; |
| } |
| + @override |
| + bool retainMetadataOfMember(MemberElement element) { |
| + if (mustRetainMetadata) hasRetainedMetadata = true; |
| + if (mustRetainMetadata && isMemberReferencedFromMirrorSystem(element)) { |
|
Emily Fortuna
2017/04/04 18:27:13
any reason you don't write this as a nested loop l
Johnni Winther
2017/04/05 06:59:58
No _good_ reason. Changed.
|
| + _retainMetadataOf(element); |
| + return true; |
| + } |
| + return false; |
| + } |
| + |
| + @override |
| + bool retainMetadataOfClass(ClassElement element) { |
| + if (mustRetainMetadata) hasRetainedMetadata = true; |
| + if (mustRetainMetadata && isClassReferencedFromMirrorSystem(element)) { |
| + _retainMetadataOf(element); |
| + return true; |
| + } |
| + return false; |
| + } |
| + |
| + @override |
| + bool retainMetadataOfTypedef(TypedefElement element) { |
| + if (mustRetainMetadata) hasRetainedMetadata = true; |
| + if (mustRetainMetadata && isTypedefReferencedFromMirrorSystem(element)) { |
| + _retainMetadataOf(element); |
| + return true; |
| + } |
| + return false; |
| + } |
| + |
| + @override |
| + bool retainMetadataOfLibrary(LibraryElement element) { |
| + if (mustRetainMetadata) hasRetainedMetadata = true; |
| + if (mustRetainMetadata && isLibraryReferencedFromMirrorSystem(element)) { |
| + _retainMetadataOf(element); |
| + return true; |
| + } |
| + return false; |
| + } |
| + |
| + void _retainMetadataOf(Element element) { |
| + for (MetadataAnnotation metadata in element.metadata) { |
| + metadata.ensureResolved(_compiler.resolution); |
| + ConstantValue constant = _constants.getConstantValueForMetadata(metadata); |
| + _constants.addCompileTimeConstantForEmission(constant); |
| + } |
| + } |
| + |
| bool invokedReflectively(Element element) { |
| if (element.isParameter) { |
| ParameterElement parameter = element; |
| @@ -227,17 +318,17 @@ class MirrorsDataImpl implements MirrorsData, MirrorsDataBuilder { |
| return isAccessibleByReflection(element.declaration); |
| } |
| - /// Set of methods that are needed by reflection. Computed using |
| + /// Sets of elements that are needed by reflection. Computed using |
| /// [computeMembersNeededForReflection] on first use. |
| - Set<Element> _membersNeededForReflection = null; |
| - Iterable<Element> get membersNeededForReflection { |
| - assert(_membersNeededForReflection != null); |
| - return _membersNeededForReflection; |
| - } |
| + Set<ClassElement> _classesNeededForReflection; |
| + Set<TypedefElement> _typedefsNeededForReflection; |
| + Set<MemberElement> _membersNeededForReflection; |
| + Set<LocalFunctionElement> _closuresNeededForReflection; |
| /// Called by [MirrorUsageAnalyzerTask] after it has merged all @MirrorsUsed |
| /// annotations. The arguments corresponds to the unions of the corresponding |
| /// fields of the annotations. |
| + // TODO(johnniwinther): Change type of [metaTargets] to `Set<ClassEntity>`. |
| void registerMirrorUsage( |
| Set<String> symbols, Set<Element> targets, Set<Element> metaTargets) { |
| if (symbols == null && targets == null && metaTargets == null) { |
| @@ -251,28 +342,52 @@ class MirrorsDataImpl implements MirrorsData, MirrorsDataBuilder { |
| for (Element target in targets) { |
| if (target.isAbstractField) { |
| AbstractFieldElement field = target; |
| - targetsUsed.add(field.getter); |
| - targetsUsed.add(field.setter); |
| - } else { |
| - targetsUsed.add(target); |
| + if (field.getter != null) { |
| + membersInMirrorsUsedTargets.add(field.getter); |
| + } |
| + if (field.setter != null) { |
| + membersInMirrorsUsedTargets.add(field.setter); |
| + } |
| + } else if (target.isClass) { |
| + classesInMirrorsUsedTargets.add(target as ClassEntity); |
| + } else if (target.isTypedef) { |
| + _typedefsInMirrorsUsedTargets.add(target); |
| + } else if (target.isLibrary) { |
| + librariesInMirrorsUsedTargets.add(target as LibraryEntity); |
| + } else if (target != null) { |
| + membersInMirrorsUsedTargets.add(target as MemberEntity); |
| + } |
| + } |
| + } |
| + if (metaTargets != null) { |
| + for (var element in metaTargets) { |
| + if (element is ClassEntity) { |
| + metaTargetsUsed.add(element); |
| } |
| } |
| } |
| - if (metaTargets != null) metaTargetsUsed.addAll(metaTargets); |
| } |
| - /// Returns `true` if [element] can be accessed through reflection, that is, |
| - /// is in the set of elements covered by a `MirrorsUsed` annotation. |
| - /// |
| - /// This property is used to tag emitted elements with a marker which is |
| - /// checked by the runtime system to throw an exception if an element is |
| - /// accessed (invoked, get, set) that is not accessible for the reflective |
| - /// system. |
| + @override |
| + bool isClassAccessibleByReflection(ClassElement element) { |
| + return _classesNeededForReflection.contains(_getDartClass(element)); |
| + } |
| + |
| + @override |
| + bool isTypedefAccessibleByReflection(TypedefElement element) { |
| + return _typedefsNeededForReflection.contains(element); |
| + } |
| + |
| bool isAccessibleByReflection(Element element) { |
| - if (element.isClass) { |
| - element = _getDartClass(element); |
| + if (element.isLibrary) { |
| + return false; |
| + } else if (element.isClass) { |
| + return isClassAccessibleByReflection(element); |
| + } else if (element.isTypedef) { |
| + return isTypedefAccessibleByReflection(element); |
| + } else { |
| + return isMemberAccessibleByReflection(element); |
| } |
| - return membersNeededForReflection.contains(element); |
| } |
| ClassElement _getDartClass(ClassElement cls) { |
| @@ -295,10 +410,8 @@ class MirrorsDataImpl implements MirrorsData, MirrorsDataBuilder { |
| } |
| } |
| - /// Returns `true` if this member element needs reflection information at |
| - /// runtime. |
| bool isMemberAccessibleByReflection(MemberElement element) { |
| - return membersNeededForReflection.contains(element); |
| + return _membersNeededForReflection.contains(element); |
| } |
| /// Returns true if this element has to be enqueued due to |
| @@ -307,22 +420,69 @@ class MirrorsDataImpl implements MirrorsData, MirrorsDataBuilder { |
| bool requiredByMirrorSystem(Element element) { |
| return hasInsufficientMirrorsUsed && isTreeShakingDisabled || |
| matchesMirrorsMetaTarget(element) || |
| - targetsUsed.contains(element); |
| + classesInMirrorsUsedTargets.contains(element) || |
| + membersInMirrorsUsedTargets.contains(element) || |
| + librariesInMirrorsUsedTargets.contains(element) || |
| + _typedefsInMirrorsUsedTargets.contains(element); |
| } |
| - /// Returns true if this element is covered by a mirrorsUsed annotation. |
| - /// |
| - /// Note that it might still be ok to tree shake the element away if no |
| - /// reflection is used in the program (and thus [isTreeShakingDisabled] is |
| - /// still false). Therefore _do not_ use this predicate to decide inclusion |
| - /// in the tree, use [requiredByMirrorSystem] instead. |
| - bool referencedFromMirrorSystem(Element element, [recursive = true]) { |
| - Element enclosing = recursive ? element.enclosingElement : null; |
| + @override |
| + bool isLibraryReferencedFromMirrorSystem(LibraryElement element) { |
| + return _libraryReferencedFromMirrorSystem(element); |
| + } |
| + |
| + @override |
| + bool isMemberReferencedFromMirrorSystem(MemberElement element) { |
| + if (_memberReferencedFromMirrorSystem(element)) return true; |
| + if (element.enclosingClass != null) { |
| + return isClassReferencedFromMirrorSystem(element.enclosingClass); |
| + } else { |
| + return isLibraryReferencedFromMirrorSystem(element.library); |
| + } |
| + } |
| + @override |
| + bool isClassReferencedFromMirrorSystem(ClassElement element) { |
| + return _classReferencedFromMirrorSystem(element) || |
| + isLibraryReferencedFromMirrorSystem(element.library); |
| + } |
| + |
| + bool isParameterReferencedFromMirrorSystem(ParameterElement element) { |
| + return _parameterReferencedFromMirrorSystem(element) || |
| + isMemberReferencedFromMirrorSystem(element.memberContext); |
| + } |
| + |
| + bool isTypedefReferencedFromMirrorSystem(TypedefElement element) { |
| + return _typedefReferencedFromMirrorSystem(element) || |
| + isLibraryReferencedFromMirrorSystem(element.library); |
| + } |
| + |
| + bool _memberReferencedFromMirrorSystem(MemberElement element) { |
| + return hasInsufficientMirrorsUsed || |
| + matchesMirrorsMetaTarget(element) || |
| + membersInMirrorsUsedTargets.contains(element); |
| + } |
| + |
| + bool _parameterReferencedFromMirrorSystem(ParameterElement element) { |
| + return hasInsufficientMirrorsUsed || matchesMirrorsMetaTarget(element); |
| + } |
| + |
| + bool _classReferencedFromMirrorSystem(ClassElement element) { |
| + return hasInsufficientMirrorsUsed || |
| + matchesMirrorsMetaTarget(element) || |
| + classesInMirrorsUsedTargets.contains(element); |
| + } |
| + |
| + bool _typedefReferencedFromMirrorSystem(TypedefElement element) { |
| return hasInsufficientMirrorsUsed || |
| matchesMirrorsMetaTarget(element) || |
| - targetsUsed.contains(element) || |
| - (enclosing != null && referencedFromMirrorSystem(enclosing)); |
| + _typedefsInMirrorsUsedTargets.contains(element); |
| + } |
| + |
| + bool _libraryReferencedFromMirrorSystem(LibraryElement element) { |
| + return hasInsufficientMirrorsUsed || |
| + matchesMirrorsMetaTarget(element) || |
| + librariesInMirrorsUsedTargets.contains(element); |
| } |
| /** |
| @@ -339,8 +499,9 @@ class MirrorsDataImpl implements MirrorsData, MirrorsDataBuilder { |
| ConstantValue value = |
| _compiler.constants.getConstantValue(metadata.constant); |
| if (value == null) continue; |
| - ResolutionDartType type = value.getType(_commonElements); |
| - if (metaTargetsUsed.contains(type.element)) return true; |
| + DartType type = value.getType(_commonElements); |
| + if (type is InterfaceType && metaTargetsUsed.contains(type.element)) |
| + return true; |
| } |
| return false; |
| } |
| @@ -361,9 +522,18 @@ class MirrorsDataImpl implements MirrorsData, MirrorsDataBuilder { |
| ResolutionWorldBuilder worldBuilder, ClosedWorld closedWorld) { |
| if (_membersNeededForReflection != null) return; |
| if (closedWorld.commonElements.mirrorsLibrary == null) { |
| - _membersNeededForReflection = const ImmutableEmptySet<Element>(); |
| + _classesNeededForReflection = const ImmutableEmptySet<ClassElement>(); |
| + _typedefsNeededForReflection = const ImmutableEmptySet<TypedefElement>(); |
| + _membersNeededForReflection = const ImmutableEmptySet<MemberElement>(); |
| + _closuresNeededForReflection = |
| + const ImmutableEmptySet<LocalFunctionElement>(); |
| return; |
| } |
| + _classesNeededForReflection = new Set<ClassElement>(); |
| + _typedefsNeededForReflection = new Set<TypedefElement>(); |
| + _membersNeededForReflection = new Set<MemberElement>(); |
| + _closuresNeededForReflection = new Set<LocalFunctionElement>(); |
| + |
| // Compute a mapping from class to the closures it contains, so we |
| // can include the correct ones when including the class. |
| Map<ClassElement, List<LocalFunctionElement>> closureMap = |
| @@ -372,19 +542,18 @@ class MirrorsDataImpl implements MirrorsData, MirrorsDataBuilder { |
| closureMap.putIfAbsent(closure.enclosingClass, () => []).add(closure); |
| } |
| bool foundClosure = false; |
| - Set<Element> reflectableMembers = new Set<Element>(); |
| for (ClassElement cls in worldBuilder.directlyInstantiatedClasses) { |
| // Do not process internal classes. |
| if (cls.library.isInternalLibrary || cls.isInjected) continue; |
| - if (referencedFromMirrorSystem(cls)) { |
| + if (isClassReferencedFromMirrorSystem(cls)) { |
| Set<Name> memberNames = new Set<Name>(); |
| // 1) the class (should be resolved) |
| assert(invariant(cls, cls.isResolved)); |
| - reflectableMembers.add(cls); |
| + _classesNeededForReflection.add(cls); |
| // 2) its constructors (if resolved) |
| cls.constructors.forEach((ConstructorElement constructor) { |
| if (worldBuilder.isMemberUsed(constructor)) { |
| - reflectableMembers.add(constructor); |
| + _membersNeededForReflection.add(constructor); |
| } |
| }); |
| // 3) all members, including fields via getter/setters (if resolved) |
| @@ -392,11 +561,11 @@ class MirrorsDataImpl implements MirrorsData, MirrorsDataBuilder { |
| MemberElement element = member.element; |
| if (worldBuilder.isMemberUsed(element)) { |
| memberNames.add(member.name); |
| - reflectableMembers.add(element); |
| + _membersNeededForReflection.add(element); |
| element.nestedClosures |
| .forEach((SynthesizedCallMethodElementX callFunction) { |
| - reflectableMembers.add(callFunction); |
| - reflectableMembers.add(callFunction.closureClass); |
| + _membersNeededForReflection.add(callFunction); |
| + _classesNeededForReflection.add(callFunction.closureClass); |
| }); |
| } |
| }); |
| @@ -409,7 +578,7 @@ class MirrorsDataImpl implements MirrorsData, MirrorsDataBuilder { |
| // assert(invariant(member.element, |
| // worldBuilder.isMemberUsed(member.element))); |
| if (worldBuilder.isMemberUsed(member.element)) { |
| - reflectableMembers.add(member.element); |
| + _membersNeededForReflection.add(member.element); |
| } |
| } |
| }); |
| @@ -418,21 +587,21 @@ class MirrorsDataImpl implements MirrorsData, MirrorsDataBuilder { |
| // 5) all its closures |
| List<LocalFunctionElement> closures = closureMap[cls]; |
| if (closures != null) { |
| - reflectableMembers.addAll(closures); |
| + _closuresNeededForReflection.addAll(closures); |
| foundClosure = true; |
| } |
| } else { |
| // check members themselves |
| cls.constructors.forEach((ConstructorElement element) { |
| if (!worldBuilder.isMemberUsed(element)) return; |
| - if (referencedFromMirrorSystem(element, false)) { |
| - reflectableMembers.add(element); |
| + if (_memberReferencedFromMirrorSystem(element)) { |
| + _membersNeededForReflection.add(element); |
| } |
| }); |
| cls.forEachClassMember((Member member) { |
| if (!worldBuilder.isMemberUsed(member.element)) return; |
| - if (referencedFromMirrorSystem(member.element, false)) { |
| - reflectableMembers.add(member.element); |
| + if (_memberReferencedFromMirrorSystem(member.element)) { |
| + _membersNeededForReflection.add(member.element); |
| } |
| }); |
| // Also add in closures. Those might be reflectable is their enclosing |
| @@ -441,8 +610,8 @@ class MirrorsDataImpl implements MirrorsData, MirrorsDataBuilder { |
| if (closures != null) { |
| for (LocalFunctionElement closure in closures) { |
| MemberElement member = closure.memberContext; |
| - if (referencedFromMirrorSystem(member, false)) { |
| - reflectableMembers.add(closure); |
| + if (_memberReferencedFromMirrorSystem(member)) { |
| + _closuresNeededForReflection.add(closure); |
| foundClosure = true; |
| } |
| } |
| @@ -458,17 +627,17 @@ class MirrorsDataImpl implements MirrorsData, MirrorsDataBuilder { |
| if (element.isClass || element.isTypedef) return; |
| MemberElement member = element; |
| if (worldBuilder.isMemberUsed(member) && |
| - referencedFromMirrorSystem(member)) { |
| - reflectableMembers.add(member); |
| + isMemberReferencedFromMirrorSystem(member)) { |
| + _membersNeededForReflection.add(member); |
| } |
| }); |
| } |
| // And closures inside top-level elements that do not have a surrounding |
| // class. These will be in the [:null:] bucket of the [closureMap]. |
| if (closureMap.containsKey(null)) { |
| - for (Element closure in closureMap[null]) { |
| - if (referencedFromMirrorSystem(closure)) { |
| - reflectableMembers.add(closure); |
| + for (LocalFunctionElement closure in closureMap[null]) { |
| + if (isMemberReferencedFromMirrorSystem(closure.memberContext)) { |
| + _closuresNeededForReflection.add(closure); |
| foundClosure = true; |
| } |
| } |
| @@ -477,32 +646,40 @@ class MirrorsDataImpl implements MirrorsData, MirrorsDataBuilder { |
| // their superclasses are available for reflection manually. |
| if (foundClosure) { |
| ClassElement cls = _helpers.closureClass; |
| - reflectableMembers.add(cls); |
| + _classesNeededForReflection.add(cls); |
| } |
| Set<MethodElement> closurizedMembers = worldBuilder.closurizedMembers; |
| - if (closurizedMembers.any(reflectableMembers.contains)) { |
| + if (closurizedMembers.any(_membersNeededForReflection.contains)) { |
| ClassElement cls = _helpers.boundClosureClass; |
| - reflectableMembers.add(cls); |
| + _classesNeededForReflection.add(cls); |
| } |
| // Add typedefs. |
| - reflectableMembers |
| - .addAll(closedWorld.allTypedefs.where(referencedFromMirrorSystem)); |
| + _typedefsNeededForReflection.addAll( |
| + closedWorld.allTypedefs.where(isTypedefReferencedFromMirrorSystem)); |
| // Register all symbols of reflectable elements |
| - for (Element element in reflectableMembers) { |
| + for (ClassElement element in _classesNeededForReflection) { |
| + symbolsUsed.add(element.name); |
| + } |
| + for (TypedefElement element in _typedefsNeededForReflection) { |
| + symbolsUsed.add(element.name); |
| + } |
| + for (MemberElement element in _membersNeededForReflection) { |
| + symbolsUsed.add(element.name); |
| + } |
| + for (LocalFunctionElement element in _closuresNeededForReflection) { |
| symbolsUsed.add(element.name); |
| } |
| - _membersNeededForReflection = reflectableMembers; |
| } |
| // TODO(20791): compute closure classes after resolution and move this code to |
| // [computeMembersNeededForReflection]. |
| void maybeMarkClosureAsNeededForReflection( |
| ClosureClassElement globalizedElement, |
| - FunctionElement callFunction, |
| - FunctionElement function) { |
| - if (!_membersNeededForReflection.contains(function)) return; |
| + MethodElement callFunction, |
| + LocalFunctionElement function) { |
| + if (!_closuresNeededForReflection.contains(function)) return; |
| _membersNeededForReflection.add(callFunction); |
| - _membersNeededForReflection.add(globalizedElement); |
| + _classesNeededForReflection.add(globalizedElement); |
| } |
| /// Called when `const Symbol(name)` is seen. |