Search in sources :

Example 6 with TInterface

use of org.eclipse.n4js.ts.types.TInterface in project n4js by eclipse.

the class ProjectCompareHelper method internalCompareApiImpl.

private ProjectCompareResult internalCompareApiImpl(ProjectComparisonEntry entry, int implIdx) {
    if (!entry.isElementEntry())
        // not an entry for an EObject element -> never report differences
        return ProjectCompareResult.equal();
    final int implCount = entry.getImplCount();
    if (implIdx < 0 || implIdx >= implCount)
        // implementation index out of range -> never report differences
        return ProjectCompareResult.equal();
    // compare implementation to API
    final EObject api = entry.getElementAPI();
    final EObject impl = entry.getElementImpl()[implIdx];
    // special case: no API
    if (api == null) {
        if (impl != null)
            return ProjectCompareResult.compliant();
        else
            return ProjectCompareResult.equal();
    }
    // special case: no impl
    if (impl == null) {
        // note: we know api!=null because of above check
        return ProjectCompareResult.error("missing implementation");
    }
    // accessibility-based compare:
    if (api instanceof TMember && impl instanceof TMember) {
        // order important: check for member before type!
        if (AccessModifiers.less((TMember) impl, (TMember) api))
            return ProjectCompareResult.error("reduced visibility");
    } else if (api instanceof Type && impl instanceof Type) {
        final MemberAccessModifier apiAcc = AccessModifiers.toMemberModifier((Type) api);
        final MemberAccessModifier implAcc = AccessModifiers.toMemberModifier((Type) impl);
        if (AccessModifiers.less(implAcc, apiAcc))
            return ProjectCompareResult.error("reduced visibility");
    }
    ImplToApiReplacementProvider typeReplacementProvider = new ImplToApiReplacementProvider(entry.getRoot());
    // subtype-based compare:
    if (api instanceof TMember && impl instanceof TMember) {
        final TMember apiMember = (TMember) api;
        final TMember implMember = (TMember) impl;
        if (apiMember instanceof TField) {
            boolean bAPIProvidesInitializer = PROVIDES_INITIALZER.hasAnnotation(apiMember);
            if (bAPIProvidesInitializer && !hasInitializer(impl)) {
                if (bAPIProvidesInitializer) {
                    return ProjectCompareResult.error("no initializer in implementation but @" + PROVIDES_INITIALZER.name + " in API");
                } else {
                    return ProjectCompareResult.error("initializer in implementation but no @" + PROVIDES_INITIALZER.name + " in API)");
                }
            }
        } else {
            // Method or accessor
            boolean bAPIProvidesDefImpl = PROVIDES_DEFAULT_IMPLEMENTATION.hasAnnotation(apiMember);
            if ((bAPIProvidesDefImpl != hasBody(impl)) && apiMember.eContainer() instanceof TInterface) {
                if (bAPIProvidesDefImpl) {
                    return ProjectCompareResult.error("no body in implementation but @" + PROVIDES_DEFAULT_IMPLEMENTATION.name + " in API");
                } else {
                    return ProjectCompareResult.error("body in implementation but no @" + PROVIDES_DEFAULT_IMPLEMENTATION.name + " in API");
                }
            }
        }
        final TypeRef context = TypeUtils.createTypeRef((Type) api.eContainer());
        final TypeRef typeApi = typeSystem.tau(apiMember, context);
        final TypeRef typeImpl = typeSystem.tau(implMember, context);
        final RuleEnvironment G = RuleEnvironmentExtensions.newRuleEnvironment(api);
        RuleEnvironmentExtensions.setTypeReplacement(G, typeReplacementProvider);
        final Result<Boolean> implSubtypeApi = typeSystem.subtype(G, typeImpl, typeApi);
        final Result<Boolean> apiSubtypeImpl = typeSystem.subtype(G, typeApi, typeImpl);
        final boolean isImplSubtypeApi = !implSubtypeApi.failed();
        final boolean isApiSubtypeImpl = !apiSubtypeImpl.failed();
        final boolean isEqualType = isImplSubtypeApi && isApiSubtypeImpl;
        if (!isEqualType) {
            if (isImplSubtypeApi)
                // not equal but at least compliant
                return ProjectCompareResult.compliant();
            else {
                final String msg = implSubtypeApi.getRuleFailedException().getLocalizedMessage();
                // not even compliant
                return ProjectCompareResult.error(msg);
            }
        }
        if (isSpecialCaseOfHiddenMethodDiff(api, impl)) {
            // not equal but at least compliant
            return ProjectCompareResult.compliant();
        }
        // all fine
        return ProjectCompareResult.equal();
    }
    // classifier compare
    if (api instanceof TClassifier && impl instanceof TClassifier) {
        TClassifier apiClassifier = (TClassifier) api;
        TClassifier implClassifier = (TClassifier) impl;
        EList<TypeVariable> apiTypeVars = apiClassifier.getTypeVars();
        EList<TypeVariable> implTypeVars = implClassifier.getTypeVars();
        // check for number of type variables
        if (apiTypeVars.size() != implTypeVars.size()) {
            return ProjectCompareResult.error("the number of type variables doesn't match");
        }
        final RuleEnvironment ruleEnvironment = RuleEnvironmentExtensions.newRuleEnvironment(api);
        RuleEnvironmentExtensions.setTypeReplacement(ruleEnvironment, typeReplacementProvider);
        // check for upper bound compatibility
        for (int i = 0; i < apiTypeVars.size(); i++) {
            TypeVariable apiTypeVar = apiTypeVars.get(i);
            TypeVariable implTypeVar = implTypeVars.get(i);
            TypeRef apiDeclaredUpperBound = apiTypeVar.getDeclaredUpperBound();
            TypeRef implDeclaredUpperBound = implTypeVar.getDeclaredUpperBound();
            if ((apiDeclaredUpperBound != null) != (implDeclaredUpperBound != null) || (apiDeclaredUpperBound != null && implDeclaredUpperBound != null && !typeSystem.equaltypeSucceeded(ruleEnvironment, apiDeclaredUpperBound, implDeclaredUpperBound))) {
                return ProjectCompareResult.error(String.format("the upper bound of type variable %s isn't compatible with the API", implTypeVar.getName()));
            }
        }
        return ProjectCompareResult.equal();
    }
    // text-based compare:
    // always compare with API
    final String textApi = entry.getTextAPI();
    final String textImpl = entry.getTextImpl(implIdx);
    final boolean isEqual = textApi != null ? textApi.equals(textImpl) : textImpl == null;
    if (!isEqual)
        return ProjectCompareResult.error(textImpl + " is not equal to " + textApi);
    return ProjectCompareResult.equal();
}
Also used : TClassifier(org.eclipse.n4js.ts.types.TClassifier) TField(org.eclipse.n4js.ts.types.TField) TInterface(org.eclipse.n4js.ts.types.TInterface) TypeRef(org.eclipse.n4js.ts.typeRefs.TypeRef) MemberAccessModifier(org.eclipse.n4js.ts.types.MemberAccessModifier) ContainerType(org.eclipse.n4js.ts.types.ContainerType) Type(org.eclipse.n4js.ts.types.Type) TypeVariable(org.eclipse.n4js.ts.types.TypeVariable) EObject(org.eclipse.emf.ecore.EObject) RuleEnvironment(org.eclipse.xsemantics.runtime.RuleEnvironment) TMember(org.eclipse.n4js.ts.types.TMember)

Example 7 with TInterface

use of org.eclipse.n4js.ts.types.TInterface in project n4js by eclipse.

the class AccessModifiers method fixed.

/**
 * Returns either the declared access modifier, or a correct fixed version. E.g., members of interfaces must never
 * be declared private, thus such a modifier is corrected to project. Note that
 * {@link TMemberWithAccessModifier#getMemberAccessModifier()} may calculate the modifier if it is undefined, but
 * does not "fix" a wrongly declared modifier.
 */
public static MemberAccessModifier fixed(TMember m) {
    MemberAccessModifier modifier = m.getMemberAccessModifier();
    Type containingType = m.getContainingType();
    if (containingType instanceof TInterface) {
        // correspongingMAM will be one of {PRIVATE PROJECT PUBLIC_INTERNAL PUBLIC} - with PROJECT as default.
        MemberAccessModifier correspondingTypesMAM = toMemberModifier(containingType);
        if (correspondingTypesMAM == MemberAccessModifier.PRIVATE && containingType instanceof TInterface) {
            correspondingTypesMAM = MemberAccessModifier.PROJECT;
        }
    }
    return modifier;
}
Also used : Type(org.eclipse.n4js.ts.types.Type) TInterface(org.eclipse.n4js.ts.types.TInterface) MemberAccessModifier(org.eclipse.n4js.ts.types.MemberAccessModifier)

Example 8 with TInterface

use of org.eclipse.n4js.ts.types.TInterface in project n4js by eclipse.

the class AllSuperTypeRefsCollector method doProcess.

@Override
protected void doProcess(ContainerType<?> containerType) {
    if (containerType instanceof TClass) {
        TClass casted = (TClass) containerType;
        ParameterizedTypeRef superType = casted.getSuperClassRef();
        result.addAll(casted.getImplementedInterfaceRefs());
        if (superType != null) {
            result.add(superType);
        }
    } else if (containerType instanceof TInterface) {
        TInterface casted = (TInterface) containerType;
        result.addAll(casted.getSuperInterfaceRefs());
    } else if (containerType instanceof TObjectPrototype) {
        TObjectPrototype casted = (TObjectPrototype) containerType;
        ParameterizedTypeRef superType = casted.getSuperType();
        if (superType != null) {
            result.add(superType);
        }
    } else if (containerType instanceof PrimitiveType) {
        PrimitiveType assignmentCompatible = ((PrimitiveType) containerType).getAssignmentCompatible();
        if (assignmentCompatible != null) {
            ParameterizedTypeRef typeRef = TypeRefsFactory.eINSTANCE.createParameterizedTypeRef();
            typeRef.setDeclaredType(assignmentCompatible);
            result.add(typeRef);
        }
    }
}
Also used : ParameterizedTypeRef(org.eclipse.n4js.ts.typeRefs.ParameterizedTypeRef) TInterface(org.eclipse.n4js.ts.types.TInterface) TObjectPrototype(org.eclipse.n4js.ts.types.TObjectPrototype) PrimitiveType(org.eclipse.n4js.ts.types.PrimitiveType) TClass(org.eclipse.n4js.ts.types.TClass)

Example 9 with TInterface

use of org.eclipse.n4js.ts.types.TInterface in project n4js by eclipse.

the class TMethodImpl method getMemberAccessModifier.

/**
 * <!-- begin-user-doc -->
 * <!-- end-user-doc -->
 * @generated
 */
public MemberAccessModifier getMemberAccessModifier() {
    MemberAccessModifier _declaredMemberAccessModifier = this.getDeclaredMemberAccessModifier();
    boolean _tripleEquals = (_declaredMemberAccessModifier == MemberAccessModifier.UNDEFINED);
    if (_tripleEquals) {
        final EObject parent = this.eContainer();
        if ((parent instanceof TInterface)) {
            final MemberAccessModifier modifierDerivedFromType = AccessModifiers.toMemberModifier(((Type) parent).getTypeAccessModifier());
            if ((modifierDerivedFromType != MemberAccessModifier.PRIVATE)) {
                return modifierDerivedFromType;
            }
        }
        return MemberAccessModifier.PROJECT;
    }
    return this.getDeclaredMemberAccessModifier();
}
Also used : TInterface(org.eclipse.n4js.ts.types.TInterface) EObject(org.eclipse.emf.ecore.EObject) MemberAccessModifier(org.eclipse.n4js.ts.types.MemberAccessModifier)

Example 10 with TInterface

use of org.eclipse.n4js.ts.types.TInterface 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)

Aggregations

TInterface (org.eclipse.n4js.ts.types.TInterface)16 ParameterizedTypeRef (org.eclipse.n4js.ts.typeRefs.ParameterizedTypeRef)9 Type (org.eclipse.n4js.ts.types.Type)8 EObject (org.eclipse.emf.ecore.EObject)7 TClass (org.eclipse.n4js.ts.types.TClass)7 TClassifier (org.eclipse.n4js.ts.types.TClassifier)6 TField (org.eclipse.n4js.ts.types.TField)5 ArrayList (java.util.ArrayList)4 List (java.util.List)4 Collectors (java.util.stream.Collectors)4 Stream (java.util.stream.Stream)4 PrimitiveType (org.eclipse.n4js.ts.types.PrimitiveType)4 TGetter (org.eclipse.n4js.ts.types.TGetter)4 TMember (org.eclipse.n4js.ts.types.TMember)4 TSetter (org.eclipse.n4js.ts.types.TSetter)4 AccessorTuple (org.eclipse.n4js.ts.types.util.AccessorTuple)4 MemberList (org.eclipse.n4js.ts.types.util.MemberList)4 HashSet (java.util.HashSet)3 Optional (java.util.Optional)3 N4InterfaceDeclaration (org.eclipse.n4js.n4JS.N4InterfaceDeclaration)3