Refactor OverrideResolver.checkOverrideForMember()

Create CheckOverrideReportStrategy interface to report override errors
(will be used later for synthesized members override checks).

Add diagnostic test on OVERRIDING_FINAL_MEMBER, as no such test happened
to exist before.
This commit is contained in:
Alexander Udalov
2012-08-31 20:39:18 +04:00
parent 2aadfa47ee
commit c29312043c
3 changed files with 86 additions and 31 deletions
@@ -551,68 +551,111 @@ public class OverrideResolver {
return factoredMembers;
}
private void checkOverrideForMember(@NotNull CallableMemberDescriptor declared) {
private interface CheckOverrideReportStrategy {
void overridingFinalMember(@NotNull CallableMemberDescriptor overridden);
void returnTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overridden);
void varOverriddenByVal(@NotNull CallableMemberDescriptor overridden);
void cannotOverrideInvisibleMember(@NotNull CallableMemberDescriptor invisibleOverridden);
void nothingToOverride();
}
private void checkOverrideForMember(@NotNull final CallableMemberDescriptor declared) {
if (declared.getKind() != CallableMemberDescriptor.Kind.DECLARATION) {
return;
}
JetNamedDeclaration member = (JetNamedDeclaration) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), declared);
final JetNamedDeclaration member = (JetNamedDeclaration) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), declared);
if (member == null) {
if (declared.getKind() != CallableMemberDescriptor.Kind.DELEGATION) {
throw new IllegalStateException(
"descriptor is not resolved to declaration" +
" and it is not delegate: " + declared);
}
return;
throw new IllegalStateException("declared descriptor is not resolved to declaration: " + declared);
}
JetModifierList modifierList = member.getModifierList();
ASTNode overrideNode = modifierList != null ? modifierList.getModifierNode(JetTokens.OVERRIDE_KEYWORD) : null;
boolean hasOverrideModifier = overrideNode != null;
final ASTNode overrideNode = modifierList != null ? modifierList.getModifierNode(JetTokens.OVERRIDE_KEYWORD) : null;
Set<? extends CallableMemberDescriptor> overriddenDescriptors = declared.getOverriddenDescriptors();
boolean finalOverriddenError = false;
boolean typeMismatchError = false;
boolean kindMismatchError = false;
for (CallableMemberDescriptor overridden : declared.getOverriddenDescriptors()) {
if (overridden != null) {
if (hasOverrideModifier) {
if (!overridden.getModality().isOverridable() && !finalOverriddenError) {
trace.report(OVERRIDING_FINAL_MEMBER.on(overrideNode.getPsi(), overridden, overridden.getContainingDeclaration()));
if (overrideNode != null) {
checkOverridesForMemberMarkedOverride(declared, new CheckOverrideReportStrategy() {
private boolean finalOverriddenError = false;
private boolean typeMismatchError = false;
private boolean kindMismatchError = false;
@Override
public void overridingFinalMember( @NotNull CallableMemberDescriptor overridden) {
if (!finalOverriddenError) {
finalOverriddenError = true;
trace.report(OVERRIDING_FINAL_MEMBER.on(overrideNode.getPsi(), overridden, overridden.getContainingDeclaration()));
}
}
if (!OverridingUtil.isReturnTypeOkForOverride(JetTypeChecker.INSTANCE, overridden, declared) && !typeMismatchError) {
trace.report(RETURN_TYPE_MISMATCH_ON_OVERRIDE.on(member, declared, overridden));
@Override
public void returnTypeMismatchOnOverride(@NotNull CallableMemberDescriptor overridden) {
if (!typeMismatchError) {
typeMismatchError = true;
trace.report(RETURN_TYPE_MISMATCH_ON_OVERRIDE.on(member, declared, overridden));
}
}
if (checkPropertyKind(overridden, true) && checkPropertyKind(declared, false) && !kindMismatchError) {
trace.report(VAR_OVERRIDDEN_BY_VAL.on((JetProperty) member, (PropertyDescriptor) declared, (PropertyDescriptor) overridden));
@Override
public void varOverriddenByVal(@NotNull CallableMemberDescriptor overridden) {
if (!kindMismatchError) {
kindMismatchError = true;
trace.report(VAR_OVERRIDDEN_BY_VAL.on((JetProperty) member, (PropertyDescriptor) declared, (PropertyDescriptor) overridden));
}
}
@Override
public void cannotOverrideInvisibleMember(@NotNull CallableMemberDescriptor invisibleOverridden) {
trace.report(CANNOT_OVERRIDE_INVISIBLE_MEMBER.on(member, declared, invisibleOverridden, invisibleOverridden.getContainingDeclaration()));
}
@Override
public void nothingToOverride() {
trace.report(NOTHING_TO_OVERRIDE.on(member, declared));
}
});
}
else if (!overriddenDescriptors.isEmpty()) {
CallableMemberDescriptor overridden = overriddenDescriptors.iterator().next();
trace.report(VIRTUAL_MEMBER_HIDDEN.on(member, declared, overridden, overridden.getContainingDeclaration()));
}
}
private void checkOverridesForMemberMarkedOverride(@NotNull CallableMemberDescriptor declared, @NotNull CheckOverrideReportStrategy reportError) {
Set<? extends CallableMemberDescriptor> overriddenDescriptors = declared.getOverriddenDescriptors();
for (CallableMemberDescriptor overridden : overriddenDescriptors) {
if (overridden != null) {
if (!overridden.getModality().isOverridable()) {
reportError.overridingFinalMember(overridden);
}
if (!OverridingUtil.isReturnTypeOkForOverride(JetTypeChecker.INSTANCE, overridden, declared)) {
reportError.returnTypeMismatchOnOverride(overridden);
}
if (checkPropertyKind(overridden, true) && checkPropertyKind(declared, false)) {
reportError.varOverriddenByVal(overridden);
}
}
}
if (hasOverrideModifier && declared.getOverriddenDescriptors().size() == 0) {
if (overriddenDescriptors.isEmpty()) {
DeclarationDescriptor containingDeclaration = declared.getContainingDeclaration();
assert containingDeclaration instanceof ClassDescriptor : "Overrides may only be resolved in a class, but " + declared + " comes from " + containingDeclaration;
ClassDescriptor declaringClass = (ClassDescriptor) containingDeclaration;
CallableMemberDescriptor invisibleOverriddenDescriptor = findInvisibleOverriddenDescriptor(declared, declaringClass);
if (invisibleOverriddenDescriptor != null) {
trace.report(CANNOT_OVERRIDE_INVISIBLE_MEMBER.on(member, declared, invisibleOverriddenDescriptor,
invisibleOverriddenDescriptor.getContainingDeclaration()));
reportError.cannotOverrideInvisibleMember(invisibleOverriddenDescriptor);
}
else {
trace.report(NOTHING_TO_OVERRIDE.on(member, declared));
reportError.nothingToOverride();
}
}
PsiElement nameIdentifier = member.getNameIdentifier();
if (!hasOverrideModifier && declared.getOverriddenDescriptors().size() > 0 && nameIdentifier != null) {
CallableMemberDescriptor overridden = declared.getOverriddenDescriptors().iterator().next();
trace.report(VIRTUAL_MEMBER_HIDDEN.on(member, declared, overridden, overridden.getContainingDeclaration()));
}
}
private CallableMemberDescriptor findInvisibleOverriddenDescriptor(CallableMemberDescriptor declared, ClassDescriptor declaringClass) {
@@ -0,0 +1,7 @@
open class A {
final fun foo() {}
}
class B : A() {
<!OVERRIDING_FINAL_MEMBER!>override<!> fun foo() {}
}
@@ -2352,6 +2352,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
doTest("compiler/testData/diagnostics/tests/override/NonGenerics.kt");
}
@TestMetadata("OverridingFinalMember.kt")
public void testOverridingFinalMember() throws Exception {
doTest("compiler/testData/diagnostics/tests/override/OverridingFinalMember.kt");
}
@TestMetadata("ParameterDefaultValues-DefaultValueFromOnlyOneSupertype.kt")
public void testParameterDefaultValues_DefaultValueFromOnlyOneSupertype() throws Exception {
doTest("compiler/testData/diagnostics/tests/override/ParameterDefaultValues-DefaultValueFromOnlyOneSupertype.kt");