Search in sources :

Example 11 with TClassifier

use of org.eclipse.n4js.ts.types.TClassifier 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 12 with TClassifier

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

the class VisibilityAwareCtorScope method wrapFilteredDescription.

@Override
protected IEObjectDescriptionWithError wrapFilteredDescription(IEObjectDescription originalDescr) {
    EObject proxyOrInstance = originalDescr.getEObjectOrProxy();
    // The cast to TClassifier always works (see the method isAccepted below).
    TClassifier ctorClassifier = (TClassifier) proxyOrInstance;
    return new InvisibleCtorDescription(originalDescr, ctorClassifier);
}
Also used : TClassifier(org.eclipse.n4js.ts.types.TClassifier) EObject(org.eclipse.emf.ecore.EObject)

Example 13 with TClassifier

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

the class N4JSScopingConsumableMethodsDiagnosis method diagnose.

@Override
DiagnosticMessage diagnose(QualifiedName name, ParameterizedPropertyAccessExpression propertyAccess) {
    // determine containing member declaration and classifier definition
    N4MemberDeclaration containingMemberDeclaration = EcoreUtil2.getContainerOfType(propertyAccess, N4MemberDeclaration.class);
    N4ClassifierDefinition classifierDefinition = EcoreUtil2.getContainerOfType(containingMemberDeclaration, N4ClassifierDefinition.class);
    // if ancestors present and non-static context (no super in static context)
    if (containingMemberDeclaration != null && !containingMemberDeclaration.isStatic() && classifierDefinition != null) {
        // Get candidate methods
        MemberList<TMember>.MemberIterable<TMethod> methods = containerTypesHelper.fromContext(propertyAccess).membersOfImplementedInterfacesForConsumption((TClassifier) classifierDefinition.getDefinedType()).methods();
        boolean hasMethod = methods.stream().filter(// Filter for non-static non-abstract methods
        m -> !m.isHasNoBody() && !m.isStatic()).anyMatch(m -> m.getName().equals(name.toString()));
        if (hasMethod) {
            return createMessage(IssueCodes.CLF_CANNOT_REFER_TO_DEFAULT_METHOD_WITH_SUPER, IssueCodes.getMessageForCLF_CANNOT_REFER_TO_DEFAULT_METHOD_WITH_SUPER());
        }
    }
    return null;
}
Also used : TClassifier(org.eclipse.n4js.ts.types.TClassifier) QualifiedName(org.eclipse.xtext.naming.QualifiedName) IssueCodes(org.eclipse.n4js.validation.IssueCodes) Inject(com.google.inject.Inject) TMember(org.eclipse.n4js.ts.types.TMember) TMethod(org.eclipse.n4js.ts.types.TMethod) DiagnosticMessage(org.eclipse.xtext.diagnostics.DiagnosticMessage) ContainerTypesHelper(org.eclipse.n4js.utils.ContainerTypesHelper) TClassifier(org.eclipse.n4js.ts.types.TClassifier) ParameterizedPropertyAccessExpression(org.eclipse.n4js.n4JS.ParameterizedPropertyAccessExpression) N4MemberDeclaration(org.eclipse.n4js.n4JS.N4MemberDeclaration) EcoreUtil2(org.eclipse.xtext.EcoreUtil2) MemberList(org.eclipse.n4js.ts.types.util.MemberList) N4ClassifierDefinition(org.eclipse.n4js.n4JS.N4ClassifierDefinition) TMethod(org.eclipse.n4js.ts.types.TMethod) MemberList(org.eclipse.n4js.ts.types.util.MemberList) N4ClassifierDefinition(org.eclipse.n4js.n4JS.N4ClassifierDefinition) N4MemberDeclaration(org.eclipse.n4js.n4JS.N4MemberDeclaration)

Example 14 with TClassifier

use of org.eclipse.n4js.ts.types.TClassifier 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 15 with TClassifier

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

the class PrimitiveTypeImpl method setAutoboxedType.

/**
 * <!-- begin-user-doc -->
 * <!-- end-user-doc -->
 * @generated
 */
public void setAutoboxedType(TClassifier newAutoboxedType) {
    TClassifier oldAutoboxedType = autoboxedType;
    autoboxedType = newAutoboxedType;
    if (eNotificationRequired())
        eNotify(new ENotificationImpl(this, Notification.SET, TypesPackage.PRIMITIVE_TYPE__AUTOBOXED_TYPE, oldAutoboxedType, autoboxedType));
}
Also used : TClassifier(org.eclipse.n4js.ts.types.TClassifier) ENotificationImpl(org.eclipse.emf.ecore.impl.ENotificationImpl)

Aggregations

TClassifier (org.eclipse.n4js.ts.types.TClassifier)29 TMember (org.eclipse.n4js.ts.types.TMember)12 ParameterizedTypeRef (org.eclipse.n4js.ts.typeRefs.ParameterizedTypeRef)11 EObject (org.eclipse.emf.ecore.EObject)10 Type (org.eclipse.n4js.ts.types.Type)10 TypeRef (org.eclipse.n4js.ts.typeRefs.TypeRef)9 TClass (org.eclipse.n4js.ts.types.TClass)8 ContainerType (org.eclipse.n4js.ts.types.ContainerType)7 TMethod (org.eclipse.n4js.ts.types.TMethod)7 BaseTypeRef (org.eclipse.n4js.ts.typeRefs.BaseTypeRef)6 BoundThisTypeRef (org.eclipse.n4js.ts.typeRefs.BoundThisTypeRef)6 ComposedTypeRef (org.eclipse.n4js.ts.typeRefs.ComposedTypeRef)6 ExistentialTypeRef (org.eclipse.n4js.ts.typeRefs.ExistentialTypeRef)6 FunctionTypeRef (org.eclipse.n4js.ts.typeRefs.FunctionTypeRef)6 StructuralTypeRef (org.eclipse.n4js.ts.typeRefs.StructuralTypeRef)6 ThisTypeRef (org.eclipse.n4js.ts.typeRefs.ThisTypeRef)6 TypeTypeRef (org.eclipse.n4js.ts.typeRefs.TypeTypeRef)6 TInterface (org.eclipse.n4js.ts.types.TInterface)6 RuleEnvironment (org.eclipse.xsemantics.runtime.RuleEnvironment)6 ArrayList (java.util.ArrayList)5