Fix for Bug 304344 - Overriding "extends" incorrectly flagged as incompatible
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/copyinheritance/CopyInheritance.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/copyinheritance/CopyInheritance.java
index 4fc908c..f7eb245 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/copyinheritance/CopyInheritance.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/copyinheritance/CopyInheritance.java
@@ -493,7 +493,7 @@
TypeDeclaration localDecl = copyRoleNestedInternal(teamModel, roleModel, tsuperNestedBinding);
if (localDecl != null) {
TypeLevel.mergeSuperinterfaces(superTeam, tsuperNestedBinding, localDecl.binding);
- TypeLevel.copyAdjustSuperclass(tsuperNestedBinding, localDecl);
+ TypeLevel.copyAdjustSuperclass(tsuperNestedBinding, localDecl, null);
}
}
}
@@ -767,17 +767,19 @@
static class SupertypeObligation {
ReferenceBinding thatSuperType;
ReferenceBinding thisSuperType;
- SupertypeObligation(ReferenceBinding thisSupertype, ReferenceBinding thatSupertype)
+ ASTNode location;
+ SupertypeObligation(ReferenceBinding thisSupertype, ReferenceBinding thatSupertype, ASTNode location)
{
this.thisSuperType = thisSupertype;
this.thatSuperType = thatSupertype;
+ this.location = location;
}
void check(TypeDeclaration subRole) {
if (!this.thisSuperType.isCompatibleWith(this.thatSuperType))
// this message is not precise (could be superinterfaces),
// and I'm not sure whether the parameters actually make sense..
subRole.scope.problemReporter().incompatibleSuperclasses(
- subRole,
+ (this.location != null) ? this.location : subRole,
this.thisSuperType,
this.thatSuperType);
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/copyinheritance/TypeLevel.java b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/copyinheritance/TypeLevel.java
index db5e93d..7c2f277 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/copyinheritance/TypeLevel.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/objectteams/otdt/internal/core/compiler/statemachine/copyinheritance/TypeLevel.java
@@ -83,12 +83,12 @@
if (!tsuperRoles[i].isInterface()) // inherited instead of merged
mergeSuperinterfaces(superTeam, tsuperRoles[i], destRole);
if (!roleDecl.isInterface())
- copyAdjustSuperclass(tsuperRoles[i], roleDecl);
+ copyAdjustSuperclass(tsuperRoles[i], roleDecl, obligations);
copyBaseclass(tsuperRoles[i], roleDecl);
}
if (tsuperRoles.length == 0)
// no tsupers to merge with, but still need to adjust the super class:
- copyAdjustSuperclass(null, roleDecl);
+ copyAdjustSuperclass(null, roleDecl, obligations);
adjustSuperinterfaces(superTeam, destRole, obligations);
// compatibility may have changed, clear negative cache entries:
@@ -124,7 +124,7 @@
teamType.getMemberType(superinterfaces[i].internalName());
if (superinterface != destRole) // not for the tsuper link.
{
- obligations.add(new SupertypeObligation(superinterface, superinterfaces[i]));
+ obligations.add(new SupertypeObligation(superinterface, superinterfaces[i], null));
superinterfaces[i] = superinterfaces[i].transferTypeArguments(superinterface);
destRole.scope.compilationUnitScope().recordSuperTypeReference(superinterface);
}
@@ -340,8 +340,9 @@
*
* @param tsuperRole may be null
* @param destRoleDecl @pre: !isInterface()
+ * @param obligations
*/
- static void copyAdjustSuperclass(ReferenceBinding tsuperRole, TypeDeclaration destRoleDecl) {
+ static void copyAdjustSuperclass(ReferenceBinding tsuperRole, TypeDeclaration destRoleDecl, ArrayList<SupertypeObligation> obligations) {
if(tsuperRole != null) {
if ( destRoleDecl.superclass == null
&& CharOperation.equals(tsuperRole.internalName(), IOTConstants.OTCONFINED))
@@ -358,7 +359,7 @@
return; // no hope without a binding
ReferenceBinding destTeam = destRoleDecl.binding.enclosingType();
assert(destTeam != null);
- checkAdjustSuperclass(destRoleDecl, destTeam, tsuperRole);
+ checkAdjustSuperclass(destRoleDecl, destTeam, tsuperRole, obligations);
}
/**
@@ -368,11 +369,13 @@
* @param destRoleDecl @pre: !isInterface()
* @param destTeam
* @param tsuperRole (may be null)
+ * @param obligations record here any sub-type relations that need checking after all roles have been adjusted
*/
private static void checkAdjustSuperclass(
TypeDeclaration destRoleDecl,
ReferenceBinding destTeam,
- ReferenceBinding tsuperRole)
+ ReferenceBinding tsuperRole,
+ ArrayList<SupertypeObligation> obligations)
{
ClassScope destScope = destRoleDecl.scope;
@@ -415,32 +418,29 @@
return;
}
}
+ if (newSuperclass != null)
+ newSuperclass = strengthenSuper(destTeam, newSuperclass);
if (inheritedSuperclass != null)
{
+ inheritedSuperclass = strengthenSuper(destTeam, inheritedSuperclass);
if (newSuperclass == null) {
newSuperclass = inheritedSuperclass;
} else if (newSuperclass != inheritedSuperclass) {
- if (TeamModel.isTeamContainingRole(destTeam.superclass(), inheritedSuperclass))
- inheritedSuperclass = destTeam.getMemberType(inheritedSuperclass.internalName());
- if (!newSuperclass.isCompatibleWith(inheritedSuperclass))
- {
- // is the old superclass actually a tsuper version of the new superclass?
- if ( newSuperclass.roleModel == null
- || !newSuperclass.roleModel.hasTSuperRole(inheritedSuperclass))
- {
- destScope.problemReporter().incompatibleSuperclasses(
- newExtends,
- newSuperclass,
- inheritedSuperclass);
- return;
- }
- }
+ // is the old superclass actually a tsuper version of the new superclass?
+ if ( newSuperclass.roleModel == null
+ || !newSuperclass.roleModel.hasTSuperRole(inheritedSuperclass))
+ {
+ SupertypeObligation oblig = new SupertypeObligation(newSuperclass, inheritedSuperclass, newExtends);
+ // check now or later?
+ if (obligations != null)
+ obligations.add(oblig);
+ else
+ oblig.check(destRoleDecl);
+ }
destRoleDecl.getRoleModel()._refinesExtends = true;
}
}
if (newSuperclass != null) {
- if (TeamModel.isTeamContainingRole(destTeam, newSuperclass))
- newSuperclass = destTeam.getMemberType(newSuperclass.internalName());
if (newSuperclass == destRoleDecl.binding) {
// a role extends its implicit super role: circularity!
// error is already reported on behalf of the interface part (real circularity)
@@ -459,5 +459,25 @@
// and then only the old node has source positions..
}
}
+
+ // don't use TeamModel.strengthenRole because we don't want a RoleTypeBinding.
+ static ReferenceBinding strengthenSuper(ReferenceBinding destTeam, ReferenceBinding superRole) {
+ if (!superRole.isRole())
+ return superRole;
+ if (TeamModel.isTeamContainingRole(destTeam.superclass(), superRole))
+ return destTeam.getMemberType(superRole.internalName());
+ if (destTeam.isRole())
+ for (ReferenceBinding tsuperTeam : destTeam.roleModel.getTSuperRoleBindings()) {
+ if (tsuperTeam == superRole.enclosingType())
+ return destTeam.getMemberType(superRole.internalName());
+ if (TeamModel.isTeamContainingRole(tsuperTeam, superRole)) {
+ ReferenceBinding strongEnclosing = destTeam.getMemberType(superRole.enclosingType().internalName());
+ if (strongEnclosing != null)
+ return strengthenSuper(strongEnclosing, superRole);
+ return superRole;
+ }
+ }
+ return superRole;
+ }
}
\ No newline at end of file