Refactor OverrideResolver and OverridingUtil

Fix warnings, simplify code. Untangle a very complex code related to
diagnostics on multiple default values and different names of parameters in
supertypes; fix a bug there, add test
This commit is contained in:
Alexander Udalov
2014-03-27 21:17:29 +04:00
parent adec89f74d
commit 3dffd428ad
5 changed files with 145 additions and 111 deletions
+1 -2
View File
@@ -21,7 +21,6 @@ import org.jetbrains.jet.lang.resolve.DescriptorUtils
import org.jetbrains.jet.lang.resolve.OverridingUtil
import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil
import org.jetbrains.jet.lang.types.TypeUtils
import java.util.LinkedHashSet
public fun <Signature> generateBridgesForFunctionDescriptor(
descriptor: FunctionDescriptor,
@@ -74,7 +73,7 @@ public fun findTraitImplementation(descriptor: CallableMemberDescriptor): Callab
// TODO: this logic is quite common for bridge generation, find a way to abstract it to a single place
// TODO: don't use filterOutOverridden() here, it's an internal front-end utility (see its implementation)
val overriddenDeclarations = OverridingUtil.getOverriddenDeclarations(descriptor)
val filteredOverriddenDeclarations = OverridingUtil.filterOutOverridden(LinkedHashSet(overriddenDeclarations))
val filteredOverriddenDeclarations = OverridingUtil.filterOutOverridden(overriddenDeclarations)
var implementation: CallableMemberDescriptor? = null
for (overriddenDeclaration in filteredOverriddenDeclarations) {
@@ -24,12 +24,11 @@ import com.intellij.psi.PsiElement;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.LinkedMultiMap;
import com.intellij.util.containers.MultiMap;
import kotlin.KotlinPackage;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor;
import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil;
import org.jetbrains.jet.lang.resolve.name.Name;
@@ -150,9 +149,10 @@ public class OverrideResolver {
@Override
public void conflict(@NotNull CallableMemberDescriptor fromSuper, @NotNull CallableMemberDescriptor fromCurrent) {
JetDeclaration declaration = (JetDeclaration) BindingContextUtils
.descriptorToDeclaration(trace.getBindingContext(), fromCurrent);
trace.report(Errors.CONFLICTING_OVERLOADS.on(declaration, fromCurrent, fromCurrent.getContainingDeclaration().getName().asString()));
JetDeclaration declaration =
(JetDeclaration) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), fromCurrent);
//noinspection ConstantConditions
trace.report(CONFLICTING_OVERLOADS.on(declaration, fromCurrent, fromCurrent.getContainingDeclaration().getName().asString()));
}
});
}
@@ -238,38 +238,24 @@ public class OverrideResolver {
}
if (nameIdentifier == null) return;
for (CallableMemberDescriptor memberDescriptor : manyImpl) {
trace.report(MANY_IMPL_MEMBER_NOT_IMPLEMENTED.on(nameIdentifier, klass, memberDescriptor));
break;
if (!manyImpl.isEmpty()) {
trace.report(MANY_IMPL_MEMBER_NOT_IMPLEMENTED.on(nameIdentifier, klass, manyImpl.iterator().next()));
}
if (classDescriptor.getModality() == Modality.ABSTRACT) {
return;
}
for (CallableMemberDescriptor memberDescriptor : abstractNoImpl) {
trace.report(ABSTRACT_MEMBER_NOT_IMPLEMENTED.on(nameIdentifier, klass, memberDescriptor));
break;
if (classDescriptor.getModality() != Modality.ABSTRACT && !abstractNoImpl.isEmpty()) {
trace.report(ABSTRACT_MEMBER_NOT_IMPLEMENTED.on(nameIdentifier, klass, abstractNoImpl.iterator().next()));
}
}
public static void collectMissingImplementations(
MutableClassDescriptor classDescriptor, Set<CallableMemberDescriptor> abstractNoImpl, Set<CallableMemberDescriptor> manyImpl
@NotNull ClassDescriptor classDescriptor,
@NotNull Set<CallableMemberDescriptor> abstractNoImpl,
@NotNull Set<CallableMemberDescriptor> manyImpl
) {
for (CallableMemberDescriptor descriptor : classDescriptor.getAllCallableMembers()) {
collectMissingImplementations(descriptor, abstractNoImpl, manyImpl);
}
}
public static void collectMissingImplementations(
ClassDescriptor classDescriptor, Set<CallableMemberDescriptor> abstractNoImpl, Set<CallableMemberDescriptor> manyImpl
) {
Iterator<CallableMemberDescriptor> callableMembers = KotlinPackage.filterIsInstance(
classDescriptor.getDefaultType().getMemberScope().getAllDescriptors().iterator(), CallableMemberDescriptor.class
);
while (callableMembers.hasNext()) {
collectMissingImplementations(callableMembers.next(), abstractNoImpl, manyImpl);
for (DeclarationDescriptor member : classDescriptor.getDefaultType().getMemberScope().getAllDescriptors()) {
if (member instanceof CallableMemberDescriptor) {
collectMissingImplementations((CallableMemberDescriptor) member, abstractNoImpl, manyImpl);
}
}
}
@@ -398,14 +384,9 @@ public class OverrideResolver {
) {
Map<CallableMemberDescriptor, Set<CallableMemberDescriptor>> overriddenDeclarationsByDirectParent = Maps.newLinkedHashMap();
for (CallableMemberDescriptor descriptor : directOverriddenDescriptors) {
Collection<CallableMemberDescriptor> overriddenDeclarations = OverridingUtil.getOverriddenDeclarations(descriptor);
Set<CallableMemberDescriptor> filteredOverrides = OverridingUtil.filterOutOverridden(
Sets.newLinkedHashSet(overriddenDeclarations));
Set<CallableMemberDescriptor> overridden = Sets.newLinkedHashSet();
for (CallableMemberDescriptor memberDescriptor : filteredOverrides) {
overridden.add(memberDescriptor);
}
overriddenDeclarationsByDirectParent.put(descriptor, overridden);
Set<CallableMemberDescriptor> overriddenDeclarations = OverridingUtil.getOverriddenDeclarations(descriptor);
Set<CallableMemberDescriptor> filteredOverrides = OverridingUtil.filterOutOverridden(overriddenDeclarations);
overriddenDeclarationsByDirectParent.put(descriptor, new LinkedHashSet<CallableMemberDescriptor>(filteredOverrides));
}
return overriddenDeclarationsByDirectParent;
}
@@ -501,7 +482,7 @@ public class OverrideResolver {
}
}
private void checkOverridesForMemberMarkedOverride(
private static void checkOverridesForMemberMarkedOverride(
@NotNull CallableMemberDescriptor declared,
boolean checkIfOverridesNothing,
@NotNull CheckOverrideReportStrategy reportError
@@ -599,24 +580,27 @@ public class OverrideResolver {
annotation);
}
private CallableMemberDescriptor findInvisibleOverriddenDescriptor(CallableMemberDescriptor declared, ClassDescriptor declaringClass) {
CallableMemberDescriptor invisibleOverride = null;
outer:
@Nullable
private static CallableMemberDescriptor findInvisibleOverriddenDescriptor(
@NotNull CallableMemberDescriptor declared,
@NotNull ClassDescriptor declaringClass
) {
for (JetType supertype : declaringClass.getTypeConstructor().getSupertypes()) {
Set<CallableMemberDescriptor> all = Sets.newLinkedHashSet();
all.addAll(supertype.getMemberScope().getFunctions(declared.getName()));
//noinspection unchecked
all.addAll((Collection) supertype.getMemberScope().getProperties(declared.getName()));
for (CallableMemberDescriptor fromSuper : all) {
if (OverridingUtil.isOverridableBy(fromSuper, declared).getResult() == OVERRIDABLE) {
invisibleOverride = fromSuper;
if (Visibilities.isVisible(fromSuper, declared)) {
throw new IllegalStateException("Descriptor " + fromSuper + " is overridable by " + declared + " and visible but does not appear in its getOverriddenDescriptors()");
throw new IllegalStateException("Descriptor " + fromSuper + " is overridable by " + declared +
" and visible but does not appear in its getOverriddenDescriptors()");
}
break outer;
return fromSuper;
}
}
}
return invisibleOverride;
return null;
}
private void checkParameterOverridesForAllClasses(@NotNull TopDownAnalysisContext c) {
@@ -630,12 +614,12 @@ public class OverrideResolver {
}
private void checkOverridesForParameters(@NotNull CallableMemberDescriptor declared) {
boolean noDeclaration = declared.getKind() != CallableMemberDescriptor.Kind.DECLARATION;
if (!noDeclaration) {
boolean isDeclaration = declared.getKind() == CallableMemberDescriptor.Kind.DECLARATION;
if (isDeclaration) {
// No check if the function is not marked as 'override'
JetModifierListOwner declaration =
(JetModifierListOwner) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), declared);
if (!declaration.hasModifier(JetTokens.OVERRIDE_KEYWORD)) {
if (declaration != null && !declaration.hasModifier(JetTokens.OVERRIDE_KEYWORD)) {
return;
}
}
@@ -646,55 +630,85 @@ public class OverrideResolver {
// a) p1 is not allowed to have a default value declared
// b) p1 must have the same name as p2
for (ValueParameterDescriptor parameterFromSubclass : declared.getValueParameters()) {
JetParameter parameter =
noDeclaration ? null :
(JetParameter) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), parameterFromSubclass);
JetClassOrObject classElement = noDeclaration ? (JetClassOrObject) BindingContextUtils
.descriptorToDeclaration(trace.getBindingContext(), declared.getContainingDeclaration()) : null;
if (parameterFromSubclass.declaresDefaultValue() && !noDeclaration) {
trace.report(DEFAULT_VALUE_NOT_ALLOWED_IN_OVERRIDE.on(parameter));
}
boolean superWithDefault = false;
int defaultsInSuper = 0;
for (ValueParameterDescriptor parameterFromSuperclass : parameterFromSubclass.getOverriddenDescriptors()) {
if (parameterFromSuperclass.declaresDefaultValue()) {
if (!superWithDefault) {
superWithDefault = true;
}
else {
if (noDeclaration) {
trace.report(MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_WHEN_NO_EXPLICIT_OVERRIDE.on(classElement, parameterFromSubclass));
}
else {
trace.report(MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES.on(parameter, parameterFromSubclass));
}
break;
}
defaultsInSuper++;
}
}
boolean multipleDefaultsInSuper = defaultsInSuper > 1;
DeclarationDescriptor superFunction = parameterFromSuperclass.getContainingDeclaration();
if (declared.hasStableParameterNames() &&
superFunction instanceof CallableDescriptor && ((CallableDescriptor) superFunction).hasStableParameterNames() &&
!parameterFromSuperclass.getName().equals(parameterFromSubclass.getName())) {
if (noDeclaration) {
trace.report(DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES.on(classElement, declared.getOverriddenDescriptors(), parameterFromSuperclass.getIndex() + 1));
}
else {
trace.report(PARAMETER_NAME_CHANGED_ON_OVERRIDE.on(parameter, (ClassDescriptor) superFunction.getContainingDeclaration(), parameterFromSuperclass));
}
}
if (isDeclaration) {
checkNameAndDefaultForDeclaredParameter(parameterFromSubclass, multipleDefaultsInSuper);
}
else {
checkNameAndDefaultForFakeOverrideParameter(declared, parameterFromSubclass, multipleDefaultsInSuper);
}
}
}
private boolean checkPropertyKind(CallableMemberDescriptor descriptor, boolean isVar) {
if (descriptor instanceof PropertyDescriptor) {
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
return propertyDescriptor.isVar() == isVar;
private void checkNameAndDefaultForDeclaredParameter(@NotNull ValueParameterDescriptor descriptor, boolean multipleDefaultsInSuper) {
JetParameter parameter = (JetParameter) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), descriptor);
assert parameter != null : "Declaration not found for parameter: " + descriptor;
if (descriptor.declaresDefaultValue()) {
trace.report(DEFAULT_VALUE_NOT_ALLOWED_IN_OVERRIDE.on(parameter));
}
return false;
if (multipleDefaultsInSuper) {
trace.report(MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES.on(parameter, descriptor));
}
for (ValueParameterDescriptor parameterFromSuperclass : descriptor.getOverriddenDescriptors()) {
if (shouldReportParameterNameOverrideWarning(descriptor, parameterFromSuperclass)) {
//noinspection ConstantConditions
trace.report(PARAMETER_NAME_CHANGED_ON_OVERRIDE.on(
parameter,
(ClassDescriptor) parameterFromSuperclass.getContainingDeclaration().getContainingDeclaration(),
parameterFromSuperclass)
);
}
}
}
private void checkNameAndDefaultForFakeOverrideParameter(
@NotNull CallableMemberDescriptor containingFunction,
@NotNull ValueParameterDescriptor descriptor,
boolean multipleDefaultsInSuper
) {
DeclarationDescriptor containingClass = containingFunction.getContainingDeclaration();
JetClassOrObject classElement =
(JetClassOrObject) BindingContextUtils.descriptorToDeclaration(trace.getBindingContext(), containingClass);
assert classElement != null : "Declaration not found for class: " + containingClass;
if (multipleDefaultsInSuper) {
trace.report(MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_WHEN_NO_EXPLICIT_OVERRIDE.on(classElement, descriptor));
}
for (ValueParameterDescriptor parameterFromSuperclass : descriptor.getOverriddenDescriptors()) {
if (shouldReportParameterNameOverrideWarning(descriptor, parameterFromSuperclass)) {
trace.report(DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES.on(
classElement,
containingFunction.getOverriddenDescriptors(),
parameterFromSuperclass.getIndex() + 1)
);
}
}
}
private static boolean shouldReportParameterNameOverrideWarning(
@NotNull ValueParameterDescriptor parameterFromSubclass,
@NotNull ValueParameterDescriptor parameterFromSuperclass
) {
DeclarationDescriptor subFunction = parameterFromSubclass.getContainingDeclaration();
DeclarationDescriptor superFunction = parameterFromSuperclass.getContainingDeclaration();
return subFunction instanceof CallableDescriptor && ((CallableDescriptor) subFunction).hasStableParameterNames() &&
superFunction instanceof CallableDescriptor && ((CallableDescriptor) superFunction).hasStableParameterNames() &&
!parameterFromSuperclass.getName().equals(parameterFromSubclass.getName());
}
private static boolean checkPropertyKind(@NotNull CallableMemberDescriptor descriptor, boolean isVar) {
return descriptor instanceof PropertyDescriptor && ((PropertyDescriptor) descriptor).isVar() == isVar;
}
private void checkVisibility(@NotNull TopDownAnalysisContext c) {
@@ -0,0 +1,13 @@
trait A {
fun foo(x: Int = 42): Int
}
open class B {
fun foo(x: Int = 239) = x
}
trait C {
fun foo(y: Int)
}
class <!MULTIPLE_DEFAULTS_INHERITED_FROM_SUPERTYPES_WHEN_NO_EXPLICIT_OVERRIDE, DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES!>Z<!> : A, B(), C
@@ -5404,6 +5404,11 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest("compiler/testData/diagnostics/tests/override/MultipleDefaultParametersInSupertypesNoOverride.kt");
}
@TestMetadata("MultipleDefaultsAndNamesInSupertypes.kt")
public void testMultipleDefaultsAndNamesInSupertypes() throws Exception {
doTest("compiler/testData/diagnostics/tests/override/MultipleDefaultsAndNamesInSupertypes.kt");
}
@TestMetadata("MultipleDefaultsInSupertypesNoExplicitOverride.kt")
public void testMultipleDefaultsInSupertypesNoExplicitOverride() throws Exception {
doTest("compiler/testData/diagnostics/tests/override/MultipleDefaultsInSupertypesNoExplicitOverride.kt");
@@ -55,11 +55,13 @@ public class OverridingUtil {
@NotNull
public static <D extends CallableDescriptor> Set<D> filterOutOverridden(@NotNull Set<D> candidateSet) {
//noinspection unchecked
return filterOverrides(candidateSet, Function.ID, Filtering.RETAIN_OVERRIDING);
}
@NotNull
public static <D> Set<D> filterOutOverriding(@NotNull Set<D> candidateSet) {
//noinspection unchecked
return filterOverrides(candidateSet, Function.ID, Filtering.RETAIN_OVERRIDDEN);
}
@@ -293,48 +295,49 @@ public class OverridingUtil {
Map<TypeConstructor, TypeProjection> substitutionContext = Maps.newHashMap();
for (int i = 0; i < superTypeParameters.size(); i++) {
TypeParameterDescriptor superTypeParameter = superTypeParameters.get(i);
TypeParameterDescriptor subTypeParameter = subTypeParameters.get(i);
substitutionContext.put(
superTypeParameter.getTypeConstructor(),
new TypeProjectionImpl(subTypeParameter.getDefaultType()));
superTypeParameters.get(i).getTypeConstructor(),
new TypeProjectionImpl(subTypeParameters.get(i).getDefaultType())
);
}
return TypeSubstitutor.create(substitutionContext);
}
public static boolean isPropertyTypeOkForOverride(@NotNull JetTypeChecker typeChecker, @NotNull PropertyDescriptor superDescriptor, @NotNull PropertyDescriptor subDescriptor) {
public static boolean isPropertyTypeOkForOverride(
@NotNull JetTypeChecker typeChecker,
@NotNull PropertyDescriptor superDescriptor,
@NotNull PropertyDescriptor subDescriptor
) {
TypeSubstitutor typeSubstitutor = prepareTypeSubstitutor(superDescriptor, subDescriptor);
JetType substitutedSuperReturnType = typeSubstitutor.substitute(superDescriptor.getReturnType(), Variance.OUT_VARIANCE);
if (typeSubstitutor == null) return false;
JetType substitutedSuperReturnType = typeSubstitutor.substitute(superDescriptor.getType(), Variance.OUT_VARIANCE);
assert substitutedSuperReturnType != null;
if (superDescriptor.isVar() && !typeChecker.equalTypes(subDescriptor.getReturnType(), substitutedSuperReturnType)) {
return false;
}
return true;
return !superDescriptor.isVar() || typeChecker.equalTypes(subDescriptor.getType(), substitutedSuperReturnType);
}
/**
* Get overridden descriptors that are declarations or delegations.
*
* @see CallableMemberDescriptor.Kind#isReal()
* Get overridden descriptors that are declarations, delegations or synthesized and are not dominated by any other such descriptor
*/
@NotNull
public static Collection<CallableMemberDescriptor> getOverriddenDeclarations(@NotNull CallableMemberDescriptor descriptor) {
Map<ClassDescriptor, CallableMemberDescriptor> result = Maps.newHashMap();
public static Set<CallableMemberDescriptor> getOverriddenDeclarations(@NotNull CallableMemberDescriptor descriptor) {
Set<CallableMemberDescriptor> result = new LinkedHashSet<CallableMemberDescriptor>();
getOverriddenDeclarations(descriptor, result);
return result.values();
return result;
}
private static void getOverriddenDeclarations(CallableMemberDescriptor descriptor, Map<ClassDescriptor, CallableMemberDescriptor> r) {
private static void getOverriddenDeclarations(
@NotNull CallableMemberDescriptor descriptor,
@NotNull Set<CallableMemberDescriptor> result
) {
if (descriptor.getKind().isReal()) {
r.put((ClassDescriptor) descriptor.getContainingDeclaration(), descriptor);
result.add(descriptor);
}
else {
if (descriptor.getOverriddenDescriptors().isEmpty()) {
throw new IllegalStateException("No overridden descriptors found for (fake override) " + descriptor);
}
for (CallableMemberDescriptor overridden : descriptor.getOverriddenDescriptors()) {
getOverriddenDeclarations(overridden, r);
getOverriddenDeclarations(overridden, result);
}
}
}