| 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.
|
|
|