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..8aafc5f65038fb0f83fd003f225548fdb5eb0e76 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 isClassReferencedFromMirrorSystem(ClassEntity element); |
+ |
+ /// 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 referencedFromMirrorSystem(Element element, [recursive = true]); |
+ bool isMemberReferencedFromMirrorSystem(MemberEntity 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 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,74 @@ class MirrorsDataImpl implements MirrorsData, MirrorsDataBuilder { |
return symbolsUsed.contains(name); |
} |
- bool retainMetadataOf(Element 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); |
+ @override |
+ bool retainMetadataOfParameter(ParameterElement element) { |
+ if (mustRetainMetadata) { |
+ hasRetainedMetadata = true; |
+ if (isParameterReferencedFromMirrorSystem(element)) { |
+ _retainMetadataOf(element); |
+ return true; |
+ } |
+ } |
+ return false; |
+ } |
+ |
+ @override |
+ bool retainMetadataOfMember(MemberElement element) { |
+ if (mustRetainMetadata) { |
+ hasRetainedMetadata = true; |
+ if (isMemberReferencedFromMirrorSystem(element)) { |
+ _retainMetadataOf(element); |
+ return true; |
+ } |
+ } |
+ return false; |
+ } |
+ |
+ @override |
+ bool retainMetadataOfClass(ClassElement element) { |
+ if (mustRetainMetadata) { |
+ hasRetainedMetadata = true; |
+ if (isClassReferencedFromMirrorSystem(element)) { |
+ _retainMetadataOf(element); |
+ return true; |
} |
- return true; |
} |
return false; |
} |
+ @override |
+ bool retainMetadataOfTypedef(TypedefElement element) { |
+ if (mustRetainMetadata) { |
+ hasRetainedMetadata = true; |
+ if (isTypedefReferencedFromMirrorSystem(element)) { |
+ _retainMetadataOf(element); |
+ return true; |
+ } |
+ } |
+ return false; |
+ } |
+ |
+ @override |
+ bool retainMetadataOfLibrary(LibraryElement element) { |
+ if (mustRetainMetadata) { |
+ hasRetainedMetadata = true; |
+ if (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 +328,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 +352,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 +420,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 +430,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) || |
- targetsUsed.contains(element) || |
- (enclosing != null && referencedFromMirrorSystem(enclosing)); |
+ classesInMirrorsUsedTargets.contains(element); |
+ } |
+ |
+ bool _typedefReferencedFromMirrorSystem(TypedefElement element) { |
+ return hasInsufficientMirrorsUsed || |
+ matchesMirrorsMetaTarget(element) || |
+ _typedefsInMirrorsUsedTargets.contains(element); |
+ } |
+ |
+ bool _libraryReferencedFromMirrorSystem(LibraryElement element) { |
+ return hasInsufficientMirrorsUsed || |
+ matchesMirrorsMetaTarget(element) || |
+ librariesInMirrorsUsedTargets.contains(element); |
} |
/** |
@@ -339,8 +509,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 +532,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 +552,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 +571,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 +588,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 +597,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 +620,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 +637,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 +656,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. |