Skip to content

Commit

Permalink
interface: check extended type references are interfaces
Browse files Browse the repository at this point in the history
  • Loading branch information
LorenzoBettini committed Dec 18, 2023
1 parent ab97c67 commit 54c936b
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ private IssueCodes() {
public static final String WRONG_PACKAGE = ISSUE_CODE_PREFIX + "wrong_package";
public static final String WRONG_FILE = ISSUE_CODE_PREFIX + "wrong_file";
public static final String CLASS_EXPECTED = ISSUE_CODE_PREFIX + "class_expected";
public static final String INTERFACE_EXPECTED = ISSUE_CODE_PREFIX + "interface_expected";
public static final String DUPLICATE_METHOD = ISSUE_CODE_PREFIX + "duplicate_method";
public static final String DUPLICATE_FIELD = ISSUE_CODE_PREFIX + "duplicate_field";
public static final String DUPLICATE_TYPE_NAME = org.eclipse.xtext.xbase.validation.IssueCodes.DUPLICATE_TYPE;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -674,9 +674,6 @@ public void checkSuperTypes(XtendClass xtendClass) {
public void checkSuperTypes(XtendInterface xtendInterface) {
for (int i = 0; i < xtendInterface.getExtends().size(); ++i) {
JvmTypeReference extendedType = xtendInterface.getExtends().get(i);
if (!isInterface(extendedType.getType()) && !isAnnotation(extendedType.getType())) {
error("Extended interface must be an interface", XTEND_INTERFACE__EXTENDS, i, INTERFACE_EXPECTED);
}
checkWildcardSupertype(xtendInterface, extendedType, XTEND_INTERFACE__EXTENDS, i);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5569,7 +5569,7 @@ public void missingImplementedInterface() {
_builder.newLine();
_builder.append("}");
_builder.newLine();
this.builder.create("Foo.xtend", _builder.toString()).assertIssueCodes(Diagnostic.LINKING_DIAGNOSTIC, org.eclipse.xtend.core.validation.IssueCodes.INTERFACE_EXPECTED).assertResolutionLabelsSubset("Create Java interface \'Bar\'", "Create Xtend interface \'Bar\'", "Create local Xtend interface \'Bar\'").assertNoResolutionLabels("Create Xtend class \'Bar\'", "Create Java class \'Bar\'", "Create local Xtend class \'Bar\'");
this.builder.create("Foo.xtend", _builder.toString()).assertIssueCodes(Diagnostic.LINKING_DIAGNOSTIC, IssueCodes.INTERFACE_EXPECTED).assertResolutionLabelsSubset("Create Java interface \'Bar\'", "Create Xtend interface \'Bar\'", "Create local Xtend interface \'Bar\'").assertNoResolutionLabels("Create Xtend class \'Bar\'", "Create Java class \'Bar\'", "Create local Xtend class \'Bar\'");
}

@Test
Expand All @@ -5579,7 +5579,7 @@ public void missingSuperInterface() {
_builder.newLine();
_builder.append("}");
_builder.newLine();
QuickfixTestBuilder _assertNoResolutionLabels = this.builder.create("Foo.xtend", _builder.toString()).assertIssueCodes(Diagnostic.LINKING_DIAGNOSTIC, org.eclipse.xtend.core.validation.IssueCodes.INTERFACE_EXPECTED).assertResolutionLabelsSubset("Create Java interface \'Bar\'", "Create Xtend interface \'Bar\'", "Create local Xtend interface \'Bar\'").assertNoResolutionLabels("Create Java class \'Bar\'", "Create Xtend class \'Bar\'", "Create local Xtend class \'Bar\'");
QuickfixTestBuilder _assertNoResolutionLabels = this.builder.create("Foo.xtend", _builder.toString()).assertIssueCodes(Diagnostic.LINKING_DIAGNOSTIC, IssueCodes.INTERFACE_EXPECTED).assertResolutionLabelsSubset("Create Java interface \'Bar\'", "Create Xtend interface \'Bar\'", "Create local Xtend interface \'Bar\'").assertNoResolutionLabels("Create Java class \'Bar\'", "Create Xtend class \'Bar\'", "Create local Xtend class \'Bar\'");
StringConcatenation _builder_1 = new StringConcatenation();
_builder_1.append("interface Foo extends Bar {");
_builder_1.newLine();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,10 @@ public class IssueCodes extends org.eclipse.xtext.validation.IssueCodes {
* @since 2.34
*/
public static final String CYCLIC_INHERITANCE = ISSUE_CODE_PREFIX + "cyclic_inheritance";
/**
* @since 2.34
*/
public static final String INTERFACE_EXPECTED = ISSUE_CODE_PREFIX + "interface_expected";

private IssueCodes() {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,14 @@

import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.xtext.common.types.JvmAnnotationType;
import org.eclipse.xtext.common.types.JvmDeclaredType;
import org.eclipse.xtext.common.types.JvmGenericType;
import org.eclipse.xtext.common.types.JvmParameterizedTypeReference;
import org.eclipse.xtext.common.types.JvmSpecializedTypeReference;
import org.eclipse.xtext.common.types.JvmType;
import org.eclipse.xtext.common.types.JvmTypeReference;
import org.eclipse.xtext.common.types.JvmWildcardTypeReference;
import org.eclipse.xtext.validation.AbstractDeclarativeValidator;
import org.eclipse.xtext.validation.Check;
import org.eclipse.xtext.validation.EValidatorRegistrar;
Expand Down Expand Up @@ -63,11 +68,27 @@ protected void checkJvmGenericType(JvmGenericType type) {

protected void checkSuperTypes(JvmGenericType type) {
var primarySourceElement = associations.getPrimarySourceElement(type);
if (primarySourceElement != null && hasCycleInHierarchy(type, new HashSet<>())) {
if (primarySourceElement == null)
return;
if (hasCycleInHierarchy(type, new HashSet<>())) {
error("The inheritance hierarchy of " + notNull(type.getSimpleName()) + " contains cycles",
primarySourceElement,
getFeatureForIssue(primarySourceElement), CYCLIC_INHERITANCE);
}
if (type.isInterface()) {
var superTypes = type.getSuperTypes();
for (int i = 0; i < superTypes.size(); ++i) {
JvmTypeReference extendedType = superTypes.get(i);
if (!isInterface(extendedType.getType()) && !isAnnotation(extendedType.getType())) {
var associated = associations.getPrimarySourceElement(extendedType);
var eContainingFeature = associated.eContainingFeature();
error("Extended interface must be an interface",
primarySourceElement,
eContainingFeature, i, INTERFACE_EXPECTED);
}
// checkWildcardSupertype(xtendInterface, extendedType, XTEND_INTERFACE__EXTENDS, i);
}
}
}

private boolean hasCycleInHierarchy(JvmGenericType type, Set<JvmGenericType> processedSuperTypes) {
Expand All @@ -88,6 +109,28 @@ private boolean hasCycleInHierarchy(JvmGenericType type, Set<JvmGenericType> pro
return false;
}

protected boolean isInterface(JvmType type) {
return type instanceof JvmGenericType && ((JvmGenericType) type).isInterface();
}

protected boolean isAnnotation(JvmType jvmType) {
return jvmType instanceof JvmAnnotationType;
}

protected boolean isInvalidWildcard(JvmTypeReference typeRef) {
if (typeRef instanceof JvmWildcardTypeReference)
return true;
else if (typeRef instanceof JvmParameterizedTypeReference) {
for(JvmTypeReference typeArgument: ((JvmParameterizedTypeReference) typeRef).getArguments()) {
if(typeArgument instanceof JvmWildcardTypeReference)
return true;
}
} else if (typeRef instanceof JvmSpecializedTypeReference) {
return isInvalidWildcard(((JvmSpecializedTypeReference) typeRef).getEquivalent());
}
return false;
}

/**
* The default implementation returns the feature "name".
*/
Expand Down

0 comments on commit 54c936b

Please sign in to comment.