Search in sources :

Example 1 with IResolvedOperation

use of org.eclipse.xtext.xbase.typesystem.override.IResolvedOperation in project xtext-xtend by eclipse.

the class XtendReentrantTypeResolver method getReturnTypeOfOverriddenOperation.

@Override
protected LightweightTypeReference getReturnTypeOfOverriddenOperation(JvmOperation operation, ResolvedTypes resolvedTypes, IFeatureScopeSession session) {
    if (operation.getVisibility() == JvmVisibility.PRIVATE)
        return null;
    if (InferredTypeIndicator.isInferred(operation.getReturnType())) {
        LightweightTypeReference declaringType = resolvedTypes.getActualType(operation.getDeclaringType());
        if (declaringType == null) {
            throw new IllegalStateException("Cannot determine declaring type of operation: " + operation);
        }
        BottomResolvedOperation resolvedOperation = new BottomResolvedOperation(operation, declaringType, overrideTester);
        List<IResolvedOperation> overriddenMethods = resolvedOperation.getOverriddenAndImplementedMethods();
        if (overriddenMethods.isEmpty())
            return null;
        IResolvedOperation overriddenMethod = overriddenMethods.get(0);
        JvmOperation declaration = overriddenMethod.getDeclaration();
        XExpression inferredFrom = getInferredFrom(declaration.getReturnType());
        // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=439535
        if (inferredFrom != null && (inferredFrom == getInferredFrom(operation.getReturnType()) || isHandled(inferredFrom))) {
            return null;
        }
        LightweightTypeReference result = overriddenMethod.getResolvedReturnType();
        return result;
    }
    return null;
}
Also used : JvmOperation(org.eclipse.xtext.common.types.JvmOperation) LightweightTypeReference(org.eclipse.xtext.xbase.typesystem.references.LightweightTypeReference) XExpression(org.eclipse.xtext.xbase.XExpression) BottomResolvedOperation(org.eclipse.xtext.xbase.typesystem.override.BottomResolvedOperation) IResolvedOperation(org.eclipse.xtext.xbase.typesystem.override.IResolvedOperation)

Example 2 with IResolvedOperation

use of org.eclipse.xtext.xbase.typesystem.override.IResolvedOperation in project xtext-xtend by eclipse.

the class XtendValidator method doCheckFunctionOverrides.

protected void doCheckFunctionOverrides(EObject sourceElement, IResolvedOperation resolved, List<IResolvedOperation> allInherited) {
    boolean overrideProblems = false;
    List<IResolvedOperation> exceptionMismatch = null;
    for (IResolvedOperation inherited : allInherited) {
        if (inherited.getOverrideCheckResult().hasProblems()) {
            overrideProblems = true;
            EnumSet<OverrideCheckDetails> details = inherited.getOverrideCheckResult().getDetails();
            if (details.contains(OverrideCheckDetails.IS_FINAL)) {
                error("Attempt to override final method " + inherited.getSimpleSignature(), sourceElement, nameFeature(sourceElement), OVERRIDDEN_FINAL);
            } else if (details.contains(OverrideCheckDetails.REDUCED_VISIBILITY)) {
                error("Cannot reduce the visibility of the overridden method " + inherited.getSimpleSignature(), sourceElement, nameFeature(sourceElement), OVERRIDE_REDUCES_VISIBILITY);
            } else if (details.contains(OverrideCheckDetails.EXCEPTION_MISMATCH)) {
                if (exceptionMismatch == null)
                    exceptionMismatch = Lists.newArrayListWithCapacity(allInherited.size());
                exceptionMismatch.add(inherited);
            } else if (details.contains(OverrideCheckDetails.RETURN_MISMATCH)) {
                error("The return type is incompatible with " + inherited.getSimpleSignature(), sourceElement, returnTypeFeature(sourceElement), INCOMPATIBLE_RETURN_TYPE);
            } else if (details.contains(OverrideCheckDetails.SYNCHRONIZED_MISMATCH)) {
                warning("The overridden method is synchronized, the current one is not synchronized.", sourceElement, nameFeature(sourceElement), MISSING_SYNCHRONIZED);
            }
        }
    }
    if (exceptionMismatch != null) {
        createExceptionMismatchError(resolved, sourceElement, exceptionMismatch);
    }
    if (sourceElement instanceof XtendFunction) {
        XtendFunction function = (XtendFunction) sourceElement;
        if (!overrideProblems && !function.isOverride() && !function.isStatic()) {
            error("The method " + resolved.getSimpleSignature() + " of type " + getDeclaratorName(resolved) + " must use override keyword since it actually overrides a supertype method.", function, XTEND_FUNCTION__NAME, MISSING_OVERRIDE);
        }
        if (!overrideProblems && function.isOverride() && function.isStatic()) {
            for (IResolvedOperation inherited : allInherited) {
                error("The method " + resolved.getSimpleSignature() + " of type " + getDeclaratorName(resolved) + " shadows the method " + resolved.getSimpleSignature() + " of type " + getDeclaratorName(inherited) + ", but does not override it.", function, XTEND_FUNCTION__NAME, function.getModifiers().indexOf("override"), OBSOLETE_OVERRIDE);
            }
        }
        if (function.isOverride()) {
            for (XAnnotation anno : function.getAnnotations()) {
                if (anno != null && anno.getAnnotationType() != null && Override.class.getName().equals(anno.getAnnotationType().getIdentifier())) {
                    warning("Superfluous @Override annotation", anno, null, OBSOLETE_ANNOTATION_OVERRIDE);
                }
            }
        }
    }
}
Also used : XtendFunction(org.eclipse.xtend.core.xtend.XtendFunction) XAnnotation(org.eclipse.xtext.xbase.annotations.xAnnotations.XAnnotation) IResolvedOperation(org.eclipse.xtext.xbase.typesystem.override.IResolvedOperation) OverrideCheckDetails(org.eclipse.xtext.xbase.typesystem.override.IOverrideCheckResult.OverrideCheckDetails)

Example 3 with IResolvedOperation

use of org.eclipse.xtext.xbase.typesystem.override.IResolvedOperation in project xtext-xtend by eclipse.

the class XtendValidator method doCheckOverriddenMethods.

protected void doCheckOverriddenMethods(XtendTypeDeclaration xtendType, JvmGenericType inferredType, ResolvedFeatures resolvedFeatures, Set<EObject> flaggedOperations) {
    List<IResolvedOperation> operationsMissingImplementation = null;
    boolean doCheckAbstract = !inferredType.isAbstract();
    if (doCheckAbstract) {
        operationsMissingImplementation = Lists.newArrayList();
    }
    IVisibilityHelper visibilityHelper = new ContextualVisibilityHelper(this.visibilityHelper, resolvedFeatures.getType());
    boolean flaggedType = false;
    for (IResolvedOperation operation : resolvedFeatures.getAllOperations()) {
        JvmDeclaredType operationDeclaringType = operation.getDeclaration().getDeclaringType();
        if (operationDeclaringType != inferredType) {
            if (operationsMissingImplementation != null && operation.getDeclaration().isAbstract()) {
                operationsMissingImplementation.add(operation);
            }
            if (visibilityHelper.isVisible(operation.getDeclaration())) {
                String erasureSignature = operation.getResolvedErasureSignature();
                List<IResolvedOperation> declaredOperationsWithSameErasure = resolvedFeatures.getDeclaredOperations(erasureSignature);
                for (IResolvedOperation localOperation : declaredOperationsWithSameErasure) {
                    if (!localOperation.isOverridingOrImplementing(operation.getDeclaration()).isOverridingOrImplementing()) {
                        EObject source = findPrimarySourceElement(localOperation);
                        if (flaggedOperations.add(source)) {
                            if (operation.getDeclaration().isStatic() && !localOperation.getDeclaration().isStatic()) {
                                error("The instance method " + localOperation.getSimpleSignature() + " cannot override the static method " + operation.getSimpleSignature() + " of type " + getDeclaratorName(operation.getDeclaration()) + ".", source, nameFeature(source), DUPLICATE_METHOD);
                            } else {
                                error("Name clash: The method " + localOperation.getSimpleSignature() + " of type " + inferredType.getSimpleName() + " has the same erasure as " + // due to name transformations in JVM model inference
                                operation.getSimpleSignature() + " of type " + getDeclaratorName(operation.getDeclaration()) + " but does not override it.", source, nameFeature(source), DUPLICATE_METHOD);
                            }
                        }
                    }
                }
                if (operation instanceof ConflictingDefaultOperation && contributesToConflict(inferredType, (ConflictingDefaultOperation) operation) && !flaggedType) {
                    IResolvedOperation conflictingOperation = ((ConflictingDefaultOperation) operation).getConflictingOperations().get(0);
                    // Include the declaring class in the issue code in order to give better quick fixes
                    String[] uris = new String[] { getDeclaratorName(operation.getDeclaration()) + "|" + EcoreUtil.getURI(operation.getDeclaration()).toString(), getDeclaratorName(conflictingOperation.getDeclaration()) + "|" + EcoreUtil.getURI(conflictingOperation.getDeclaration()).toString() };
                    if (!operation.getDeclaration().isAbstract() && !conflictingOperation.getDeclaration().isAbstract()) {
                        error("The type " + inferredType.getSimpleName() + " inherits multiple implementations of the method " + conflictingOperation.getSimpleSignature() + " from " + getDeclaratorName(conflictingOperation.getDeclaration()) + " and " + getDeclaratorName(operation.getDeclaration()) + ".", xtendType, XtendPackage.Literals.XTEND_TYPE_DECLARATION__NAME, CONFLICTING_DEFAULT_METHODS, uris);
                    } else {
                        // At least one of the operations is non-abstract
                        IResolvedOperation abstractOp, nonabstractOp;
                        if (operation.getDeclaration().isAbstract()) {
                            abstractOp = operation;
                            nonabstractOp = conflictingOperation;
                        } else {
                            abstractOp = conflictingOperation;
                            nonabstractOp = operation;
                        }
                        error("The non-abstract method " + nonabstractOp.getSimpleSignature() + " inherited from " + getDeclaratorName(nonabstractOp.getDeclaration()) + " conflicts with the method " + abstractOp.getSimpleSignature() + " inherited from " + getDeclaratorName(abstractOp.getDeclaration()) + ".", xtendType, XtendPackage.Literals.XTEND_TYPE_DECLARATION__NAME, CONFLICTING_DEFAULT_METHODS, uris);
                    }
                    flaggedType = true;
                }
            }
        }
    }
    if (operationsMissingImplementation != null && !operationsMissingImplementation.isEmpty() && !flaggedType) {
        reportMissingImplementations(xtendType, inferredType, operationsMissingImplementation);
    }
}
Also used : ConflictingDefaultOperation(org.eclipse.xtext.xbase.typesystem.override.ConflictingDefaultOperation) ContextualVisibilityHelper(org.eclipse.xtext.xbase.typesystem.util.ContextualVisibilityHelper) EObject(org.eclipse.emf.ecore.EObject) JvmDeclaredType(org.eclipse.xtext.common.types.JvmDeclaredType) IVisibilityHelper(org.eclipse.xtext.xbase.typesystem.util.IVisibilityHelper) RichString(org.eclipse.xtend.core.xtend.RichString) IResolvedOperation(org.eclipse.xtext.xbase.typesystem.override.IResolvedOperation)

Example 4 with IResolvedOperation

use of org.eclipse.xtext.xbase.typesystem.override.IResolvedOperation in project xtext-xtend by eclipse.

the class XtendValidator method contributesToConflict.

/**
 * Determine whether the given type contributes to the conflict caused by the given default interface implementation.
 */
private boolean contributesToConflict(JvmGenericType rootType, ConflictingDefaultOperation conflictingDefaultOperation) {
    Set<JvmDeclaredType> involvedInterfaces = Sets.newHashSet();
    involvedInterfaces.add(conflictingDefaultOperation.getDeclaration().getDeclaringType());
    for (IResolvedOperation conflictingOperation : conflictingDefaultOperation.getConflictingOperations()) {
        involvedInterfaces.add(conflictingOperation.getDeclaration().getDeclaringType());
    }
    RecursionGuard<JvmDeclaredType> recursionGuard = new RecursionGuard<JvmDeclaredType>();
    if (rootType.isInterface()) {
        int contributingCount = 0;
        for (JvmTypeReference typeRef : rootType.getExtendedInterfaces()) {
            JvmType rawType = typeRef.getType();
            if (rawType instanceof JvmDeclaredType && contributesToConflict((JvmDeclaredType) rawType, involvedInterfaces, recursionGuard)) {
                contributingCount++;
            }
        }
        return contributingCount >= 2;
    } else {
        return contributesToConflict(rootType, involvedInterfaces, recursionGuard);
    }
}
Also used : JvmTypeReference(org.eclipse.xtext.common.types.JvmTypeReference) JvmDeclaredType(org.eclipse.xtext.common.types.JvmDeclaredType) RecursionGuard(org.eclipse.xtext.xbase.typesystem.util.RecursionGuard) JvmType(org.eclipse.xtext.common.types.JvmType) IResolvedOperation(org.eclipse.xtext.xbase.typesystem.override.IResolvedOperation)

Example 5 with IResolvedOperation

use of org.eclipse.xtext.xbase.typesystem.override.IResolvedOperation in project xtext-xtend by eclipse.

the class XtendValidator method reportMissingImplementations.

protected void reportMissingImplementations(XtendTypeDeclaration xtendClass, JvmGenericType inferredType, List<IResolvedOperation> operationsMissingImplementation) {
    StringBuilder errorMsg = new StringBuilder();
    String name = xtendClass.getName();
    boolean needsNewLine = operationsMissingImplementation.size() > 1;
    if (xtendClass.isAnonymous()) {
        JvmTypeReference superType = Iterables.getLast(inferredType.getSuperTypes());
        errorMsg.append("The anonymous subclass of ").append(superType.getSimpleName());
        errorMsg.append(" does not implement ");
    } else {
        errorMsg.append("The class ").append(name);
        errorMsg.append(" must be defined abstract because it does not implement ");
    }
    if (needsNewLine) {
        errorMsg.append("its inherited abstract methods ");
    }
    IResolvedOperation operation;
    for (int i = 0; i < operationsMissingImplementation.size() && i < 3; ++i) {
        operation = operationsMissingImplementation.get(i);
        if (needsNewLine)
            errorMsg.append("\n- ");
        errorMsg.append(operation.getSimpleSignature());
    }
    int numUnshownOperations = operationsMissingImplementation.size() - 3;
    if (numUnshownOperations > 0)
        errorMsg.append("\nand " + numUnshownOperations + " more.");
    List<String> uris = transform(operationsMissingImplementation, new Function<IResolvedOperation, String>() {

        @Override
        public String apply(IResolvedOperation from) {
            return EcoreUtil.getURI(from.getDeclaration()).toString();
        }
    });
    if (xtendClass.isAnonymous()) {
        error(errorMsg.toString(), xtendClass, ANONYMOUS_CLASS__CONSTRUCTOR_CALL, ANONYMOUS_CLASS_MISSING_MEMBERS, toArray(uris, String.class));
    } else {
        error(errorMsg.toString(), xtendClass, XTEND_TYPE_DECLARATION__NAME, CLASS_MUST_BE_ABSTRACT, toArray(uris, String.class));
    }
}
Also used : ToStringBuilder(org.eclipse.xtext.xbase.lib.util.ToStringBuilder) JvmTypeReference(org.eclipse.xtext.common.types.JvmTypeReference) RichString(org.eclipse.xtend.core.xtend.RichString) IResolvedOperation(org.eclipse.xtext.xbase.typesystem.override.IResolvedOperation)

Aggregations

IResolvedOperation (org.eclipse.xtext.xbase.typesystem.override.IResolvedOperation)10 LightweightTypeReference (org.eclipse.xtext.xbase.typesystem.references.LightweightTypeReference)4 JvmDeclaredType (org.eclipse.xtext.common.types.JvmDeclaredType)3 RichString (org.eclipse.xtend.core.xtend.RichString)2 JvmType (org.eclipse.xtext.common.types.JvmType)2 JvmTypeReference (org.eclipse.xtext.common.types.JvmTypeReference)2 ToStringBuilder (org.eclipse.xtext.xbase.lib.util.ToStringBuilder)2 BottomResolvedOperation (org.eclipse.xtext.xbase.typesystem.override.BottomResolvedOperation)2 IResolvedConstructor (org.eclipse.xtext.xbase.typesystem.override.IResolvedConstructor)2 List (java.util.List)1 Consumer (java.util.function.Consumer)1 Matcher (java.util.regex.Matcher)1 EList (org.eclipse.emf.common.util.EList)1 EObject (org.eclipse.emf.ecore.EObject)1 ResourceSet (org.eclipse.emf.ecore.resource.ResourceSet)1 ImageDescriptor (org.eclipse.jface.resource.ImageDescriptor)1 StyledString (org.eclipse.jface.viewers.StyledString)1 ResolvedMethodImpl (org.eclipse.xtend.core.macro.declaration.ResolvedMethodImpl)1 XtendClass (org.eclipse.xtend.core.xtend.XtendClass)1 XtendFunction (org.eclipse.xtend.core.xtend.XtendFunction)1