Search in sources :

Example 6 with MemberList

use of org.eclipse.n4js.ts.types.util.MemberList in project n4js by eclipse.

the class MissingApiMembersForTranspiler method create.

/**
 * Returns a tuple of collections used by transpiler to generate interface or class members.
 */
public static MissingApiMembersForTranspiler create(ContainerTypesHelper containerTypesHelper, ScriptApiTracker apiTracker, TClassifier type, ConcreteMembersOrderedForTranspiler cmoft, Script context) {
    MemberCollector collector = containerTypesHelper.fromContext(context);
    // IDE-1510 create missing API-methods here.
    MemberList<TMethod> missingApiMethods = new MemberList<>();
    if (type instanceof TClass) {
        List<TMethod> c = apiTracker.computeMissingApiMethods((TClass) type, context);
        missingApiMethods.addAll(c);
        List<VirtualApiTMethod> missingAPIfromInheritance = apiTracker.computeMethodDiff((TClass) type, collector, cmoft.ownedAndMixedInConcreteMembers, missingApiMethods);
        missingApiMethods.addAll(missingAPIfromInheritance);
    }
    if (type instanceof TInterface) {
        List<TMethod> c = apiTracker.computeMissingApiMethods((TInterface) type, context);
        missingApiMethods.addAll(c);
    }
    // IDE-1510 create missing API-fields here.
    List<AccessorTuple> missingApiAccessorTuples = new ArrayList<>();
    {
        List<AccessorTuple> computedMissingApiGetterSetter = apiTracker.computeMissingApiGetterSetter((TN4Classifier) type, cmoft.concreteAccessorTuples);
        List<AccessorTuple> computedMissingApiFields = apiTracker.computeMissingApiFields((TN4Classifier) type);
        // In case of field vs. getter the implementation should be free to choose the form.
        // So filter out all missing set/get pairs which are backed by a field (either concrete or inherited)
        List<AccessorTuple> filteredMissingApiGetterSetter = filterOutTuplesImplementedByField(computedMissingApiGetterSetter, cmoft.ownedAndMixedInConcreteMembers, cmoft.concreteInheritedMembers);
        // Some logic applies to missing fields which are backed by a getter/setter. The situation here is a
        // little bit more complex as the set/get must be processed as a pair and one could be missing or they stem
        // from different (super-)types.
        // *Beware* not side-effect free since we have to mix in virtual getter/setter into an existing but
        // incomplete accessor-pairs
        List<AccessorTuple> filteredMissingApiFields0 = filterMissingApiFieldsAndEnrichExistingTuples(computedMissingApiFields, cmoft.concreteAccessorTuples);
        List<AccessorTuple> filteredMissingApiFields = filterMissingApiFieldsImplementedBySuperGetSet(filteredMissingApiFields0, cmoft.concreteInheritedMembers);
        missingApiAccessorTuples.addAll(filteredMissingApiGetterSetter);
        missingApiAccessorTuples.addAll(filteredMissingApiFields);
    }
    MemberList<TField> fieldsOverridingAccessors = getFieldsOverridingAccessor(cmoft.ownedAndMixedInConcreteMembers, cmoft.concreteInheritedMembers);
    // compute the list of mixed in fields, which do not override any Accessor (handled separately)
    MemberList<TField> fieldsPurelyMixedInNotOverridingAccessor = new MemberList<>();
    fieldsPurelyMixedInNotOverridingAccessor.addAll(cmoft.ownedAndMixedInConcreteMembers.stream().filter(it -> it instanceof TField && // must stem from different type
    it.getContainingType() != type).map(it -> (TField) it).filter(// remove the ones overriding get/set
    it -> !fieldsOverridingAccessors.contains(it)).collect(Collectors.toList()));
    return new MissingApiMembersForTranspiler(missingApiMethods, missingApiAccessorTuples);
}
Also used : VirtualApiTMethod(org.eclipse.n4js.transpiler.utils.ScriptApiTracker.VirtualApiTMethod) TField(org.eclipse.n4js.ts.types.TField) TMember(org.eclipse.n4js.ts.types.TMember) Script(org.eclipse.n4js.n4JS.Script) TClass(org.eclipse.n4js.ts.types.TClass) TMethod(org.eclipse.n4js.ts.types.TMethod) AccessorTuple(org.eclipse.n4js.ts.types.util.AccessorTuple) Collectors(java.util.stream.Collectors) ArrayList(java.util.ArrayList) TSetter(org.eclipse.n4js.ts.types.TSetter) TGetter(org.eclipse.n4js.ts.types.TGetter) List(java.util.List) TN4Classifier(org.eclipse.n4js.ts.types.TN4Classifier) ContainerTypesHelper(org.eclipse.n4js.utils.ContainerTypesHelper) Stream(java.util.stream.Stream) TClassifier(org.eclipse.n4js.ts.types.TClassifier) TInterface(org.eclipse.n4js.ts.types.TInterface) MemberList(org.eclipse.n4js.ts.types.util.MemberList) Optional(java.util.Optional) MemberCollector(org.eclipse.n4js.utils.ContainerTypesHelper.MemberCollector) VirtualApiTMethod(org.eclipse.n4js.transpiler.utils.ScriptApiTracker.VirtualApiTMethod) TMethod(org.eclipse.n4js.ts.types.TMethod) TField(org.eclipse.n4js.ts.types.TField) MemberList(org.eclipse.n4js.ts.types.util.MemberList) TInterface(org.eclipse.n4js.ts.types.TInterface) TN4Classifier(org.eclipse.n4js.ts.types.TN4Classifier) VirtualApiTMethod(org.eclipse.n4js.transpiler.utils.ScriptApiTracker.VirtualApiTMethod) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) List(java.util.List) MemberList(org.eclipse.n4js.ts.types.util.MemberList) AccessorTuple(org.eclipse.n4js.ts.types.util.AccessorTuple) MemberCollector(org.eclipse.n4js.utils.ContainerTypesHelper.MemberCollector) TClass(org.eclipse.n4js.ts.types.TClass)

Example 7 with MemberList

use of org.eclipse.n4js.ts.types.util.MemberList in project n4js by eclipse.

the class N4JSMemberRedefinitionValidator method constraints_69_Implementation.

/**
 * Constraints 69: Implementation of Interface Members
 *
 * This method doesn't add issues for missing override annotations but adds the missing-annotation-members to the
 * given collection.
 */
private void constraints_69_Implementation(MemberMatrix mm, Collection<TMember> membersMissingOverrideAnnotation) {
    String missingAccessor = null;
    List<TMember> missingAccessors = new MemberList<>();
    List<TMember> conflictingMembers = new MemberList<>();
    TClassifier currentClassifier = getCurrentClassifier();
    // avoid multiple errors on a single element (but not on
    Set<TMember> ownedErroneousMembers = null;
    for (TMember m : mm.implemented()) {
        if (mm.isConsumed(m)) {
            // m is mixed in, so it exits and we do not need other tests
            continue;
        }
        boolean bExistCompatibleMember = false;
        boolean bExistCompatibleGetter = false;
        boolean bExistCompatibleSetter = false;
        for (SourceAwareIterator iter = mm.ownedConsumedInheritedImplemented(); iter.hasNext(); ) {
            TMember m_ = iter.next();
            if (ownedErroneousMembers != null && !iter.isOwnedMember()) {
                // we found problems with owned members, we do not need more error messages.
                break;
            }
            // short cut and avoid multiple errors for single member
            if (m_ == m || ownedErroneousMembers != null && ownedErroneousMembers.contains(m_)) {
                if (iter.isInheritedMember()) {
                    // consumed by super class and then inherited
                    bExistCompatibleMember = true;
                }
                // we do not break since we want to find possible consumption problems
                continue;
            }
            // 1. m must be accessible and
            // 2.a & 2.b: m_ must be implementation-compatible to m
            OverrideCompatibilityResult compatibility = checkAccessibilityAndOverrideCompatibility(RedefinitionType.implemented, m_, m, !iter.isActualMember(), mm);
            if (compatibility == OverrideCompatibilityResult.ACCESSOR_PAIR) {
                continue;
            } else if (compatibility == OverrideCompatibilityResult.ERROR) {
                if (iter.isOwnedMember()) {
                    // do not skip other errors for owned members, usually accessor pairs
                    if (ownedErroneousMembers == null) {
                        ownedErroneousMembers = new HashSet<>();
                    }
                    ownedErroneousMembers.add(m_);
                } else if (iter.isActualMember()) {
                    // error message already
                    return;
                } else {
                    break;
                }
            } else if (iter.isActualMember()) {
                // mark found implementor
                if (m.isField()) {
                    if (m_.isGetter()) {
                        bExistCompatibleGetter = true;
                    } else if (m_.isSetter()) {
                        bExistCompatibleSetter = true;
                    } else {
                        bExistCompatibleMember = true;
                    }
                } else {
                    bExistCompatibleMember = true;
                }
                // 1 & 2 declared overridden
                if (!m_.isDeclaredOverride() && m_.getContainingType() == currentClassifier) {
                    membersMissingOverrideAnnotation.add(m_);
                }
            }
        }
        if (bExistCompatibleGetter != bExistCompatibleSetter) {
            missingAccessor = bExistCompatibleGetter ? "setter" : "getter";
            missingAccessors.add(m);
        } else if (!bExistCompatibleMember && !(bExistCompatibleGetter && bExistCompatibleSetter)) {
            conflictingMembers.add(m);
        }
    }
    if (ownedErroneousMembers != null) {
        // avoid consequential errors
        return;
    }
    if (!conflictingMembers.isEmpty()) {
        messageConflictingMixins(conflictingMembers);
    } else if (!missingAccessors.isEmpty()) {
        messageMissingAccessor(missingAccessor, missingAccessors);
    }
}
Also used : TClassifier(org.eclipse.n4js.ts.types.TClassifier) MemberList(org.eclipse.n4js.ts.types.util.MemberList) SourceAwareIterator(org.eclipse.n4js.validation.validators.utils.MemberMatrix.SourceAwareIterator) TMember(org.eclipse.n4js.ts.types.TMember) HashSet(java.util.HashSet)

Example 8 with MemberList

use of org.eclipse.n4js.ts.types.util.MemberList in project n4js by eclipse.

the class N4JSMemberRedefinitionValidator method checkMemberRedefinitions.

/**
 * Checks constraints defined in chapter 5.4. Redefinition of Members.
 */
@Check
public void checkMemberRedefinitions(N4ClassifierDefinition n4ClassifierDefinition) {
    if (!(n4ClassifierDefinition.getDefinedType() instanceof TClassifier)) {
        // wrongly parsed
        return;
    }
    TClassifier tClassifier = (TClassifier) n4ClassifierDefinition.getDefinedType();
    getContext().put(TClassifier.class, tClassifier);
    RuleEnvironment g = RuleEnvironmentExtensions.newRuleEnvironment(tClassifier);
    getContext().put(RuleEnvironment.class, g);
    // the context for type variables
    ParameterizedTypeRef classTypeRef = TypeUtils.createTypeRef(tClassifier);
    getContext().put(TYPE_VAR_CONTEXT, classTypeRef);
    MemberCube memberCube = createMemberValidationList();
    final boolean isClass = tClassifier instanceof TClass;
    final Map<ParameterizedTypeRef, MemberList<TMember>> nonAccessibleAbstractMembersBySuperTypeRef = new HashMap<>();
    for (Entry<NameStaticPair, MemberMatrix> entry : memberCube.entrySet()) {
        MemberMatrix mm = entry.getValue();
        // Set to collect all owned members that are lacking an override annotation.
        Collection<TMember> membersMissingOverrideAnnotation = new HashSet<>();
        if (isClass) {
            constraints_67_MemberOverride_checkEntry(mm, membersMissingOverrideAnnotation);
        }
        if (mm.hasImplemented()) {
            // first mix in
            if (holdConstraints_68_Consumption(mm)) {
                // then check if everything is implemented
                constraints_69_Implementation(mm, membersMissingOverrideAnnotation);
            }
        }
        constraints_60_InheritedConsumedCovariantSpecConstructor(tClassifier, mm);
        constraints_66_NonOverride(mm);
        constraints_42_45_46_AbstractMember(mm, nonAccessibleAbstractMembersBySuperTypeRef);
        unusedGenericTypeVariable(mm);
        checkUnpairedAccessorConsumption(mm, n4ClassifierDefinition);
        checkUnpairedAccessorFilling(mm, n4ClassifierDefinition);
        messageMissingOverrideAnnotation(mm, membersMissingOverrideAnnotation);
    }
    final boolean foundImpossibleExtendsImplements = !nonAccessibleAbstractMembersBySuperTypeRef.isEmpty();
    if (foundImpossibleExtendsImplements) {
        messageImpossibleExtendsImplements(n4ClassifierDefinition, nonAccessibleAbstractMembersBySuperTypeRef);
    }
    if (!foundImpossibleExtendsImplements) {
        // avoid consequential errors
        constraints_41_AbstractClass(tClassifier, memberCube);
    }
}
Also used : TClassifier(org.eclipse.n4js.ts.types.TClassifier) NameStaticPair(org.eclipse.n4js.ts.types.util.NameStaticPair) MemberList(org.eclipse.n4js.ts.types.util.MemberList) HashMap(java.util.HashMap) MemberMatrix(org.eclipse.n4js.validation.validators.utils.MemberMatrix) ParameterizedTypeRef(org.eclipse.n4js.ts.typeRefs.ParameterizedTypeRef) MemberCube(org.eclipse.n4js.validation.validators.utils.MemberCube) RuleEnvironment(org.eclipse.xsemantics.runtime.RuleEnvironment) TMember(org.eclipse.n4js.ts.types.TMember) TClass(org.eclipse.n4js.ts.types.TClass) HashSet(java.util.HashSet) Check(org.eclipse.xtext.validation.Check)

Example 9 with MemberList

use of org.eclipse.n4js.ts.types.util.MemberList in project n4js by eclipse.

the class N4JSMemberRedefinitionValidator method holdConstraints_68_Consumption.

/**
 * Constraints 68: Consumption of Interface Members
 *
 * Returns false if an error occurred which is not solvable in current classifier (i.e., incompatible meta types).
 */
private boolean holdConstraints_68_Consumption(MemberMatrix mm) {
    TClassifier currentType = getCurrentClassifier();
    MemberList<TMember> consumedMembers = new MemberList<>(2);
    for (TMember m : mm.implemented()) {
        boolean consume = true;
        for (SourceAwareIterator iter = mm.allMembers(); iter.hasNext(); ) {
            TMember m_ = iter.next();
            if (m_ == m && iter.isInterfaceMember()) {
                // again. Thus, we only consume if both members stem from interfaces
                continue;
            }
            // 1. meta type
            if ((m.isMethod() && !m_.isMethod()) || (!m.isMethod() && !(m_.isAccessor() || m_.isField()))) {
                if (iter.isInterfaceMember()) {
                    messageIncompatibleMembersToImplement(mm.implemented());
                    return false;
                } else if (iter.isInheritedMember()) {
                    messageIncompatibleInheritedMembersToImplement(m_, mm.implemented());
                    return false;
                } else {
                    return true;
                }
            }
            // 2 (abstract/owned), 3 (visibility) and 4 (type):
            boolean accessorPair = TypeUtils.isAccessorPair(m, m_);
            if (!accessorPair) {
                // 2. not abstract or owned
                if ((!m_.isAbstract() || m_.getContainingType() == currentType)) {
                    consume = false;
                    break;
                }
                // 3. access modifier
                if (AccessModifiers.less(m, m_)) {
                    consume = false;
                    break;
                }
                // 4. type
                if (!m_.isSetter()) {
                    if (!isSubType(m, m_)) {
                        consume = false;
                        break;
                    }
                }
                if (m_.isSetter() || m_.isField()) {
                    if (!isSubType(m_, m)) {
                        consume = false;
                        break;
                    }
                }
            }
        }
        if (consume) {
            if (!consumedMembers.contains(m)) {
                // in case an interface is (indirectly) redundantly implemented
                consumedMembers.add(m);
            }
        }
    }
    mm.markConsumed(consumedMembers);
    return true;
}
Also used : TClassifier(org.eclipse.n4js.ts.types.TClassifier) MemberList(org.eclipse.n4js.ts.types.util.MemberList) SourceAwareIterator(org.eclipse.n4js.validation.validators.utils.MemberMatrix.SourceAwareIterator) TMember(org.eclipse.n4js.ts.types.TMember)

Aggregations

MemberList (org.eclipse.n4js.ts.types.util.MemberList)9 TMember (org.eclipse.n4js.ts.types.TMember)8 TClassifier (org.eclipse.n4js.ts.types.TClassifier)7 TClass (org.eclipse.n4js.ts.types.TClass)5 HashSet (java.util.HashSet)4 TInterface (org.eclipse.n4js.ts.types.TInterface)4 ArrayList (java.util.ArrayList)3 HashMap (java.util.HashMap)3 List (java.util.List)3 Collectors (java.util.stream.Collectors)3 Script (org.eclipse.n4js.n4JS.Script)3 ParameterizedTypeRef (org.eclipse.n4js.ts.typeRefs.ParameterizedTypeRef)3 TField (org.eclipse.n4js.ts.types.TField)3 TGetter (org.eclipse.n4js.ts.types.TGetter)3 TMethod (org.eclipse.n4js.ts.types.TMethod)3 TSetter (org.eclipse.n4js.ts.types.TSetter)3 AccessorTuple (org.eclipse.n4js.ts.types.util.AccessorTuple)3 NameStaticPair (org.eclipse.n4js.ts.types.util.NameStaticPair)3 ContainerTypesHelper (org.eclipse.n4js.utils.ContainerTypesHelper)3 MemberCollector (org.eclipse.n4js.utils.ContainerTypesHelper.MemberCollector)3