From 27b13dda65593ed7857805cbad2b30e321bbca6f Mon Sep 17 00:00:00 2001 From: Michael Nedzelsky Date: Tue, 13 Oct 2015 16:14:51 +0300 Subject: [PATCH] improve diagnostic for KT-9484 Don't allow named arguments for inherited functions with parameter name conflicts #KT-9484 Fixed --- .../ValueArgumentsToParametersMapper.java | 27 ++++++++++++++++--- .../ambiguousNamedArguments1.kt | 12 +++++++++ .../ambiguousNamedArguments1.txt | 17 ++++++++++++ .../ambiguousNamedArguments2.kt | 4 +++ .../ambiguousNamedArgumentsWithGenerics1.kt | 1 + .../ambiguousNamedArgumentsWithGenerics2.kt | 1 + .../ambiguousNamedArgumentsWithGenerics3.kt | 1 + 7 files changed, 60 insertions(+), 3 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ValueArgumentsToParametersMapper.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ValueArgumentsToParametersMapper.java index 2a48fbeb8de..99c3d0b6b5d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ValueArgumentsToParametersMapper.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ValueArgumentsToParametersMapper.java @@ -84,6 +84,7 @@ public class ValueArgumentsToParametersMapper { private final MutableResolvedCall candidateCall; private final Map parameterByName; + private Map parameterByNameInOverriddenMethods; private final Set unmappedArguments = Sets.newHashSet(); private final Map varargs = Maps.newHashMap(); @@ -101,6 +102,20 @@ public class ValueArgumentsToParametersMapper { } } + @Nullable + private ValueParameterDescriptor getParameterByNameInOverriddenMethods(Name name) { + if (parameterByNameInOverriddenMethods == null) { + parameterByNameInOverriddenMethods = Maps.newHashMap(); + for (ValueParameterDescriptor valueParameter : candidateCall.getCandidateDescriptor().getValueParameters()) { + for (ValueParameterDescriptor parameterDescriptor : valueParameter.getOverriddenDescriptors()) { + parameterByNameInOverriddenMethods.put(parameterDescriptor.getName(), valueParameter); + } + } + } + + return parameterByNameInOverriddenMethods.get(name); + } + // We saw only positioned arguments so far private final ProcessorState positionedOnly = new ProcessorState() { @@ -163,11 +178,17 @@ public class ValueArgumentsToParametersMapper { )); } - if (candidate.hasStableParameterNames() && nameReference != null && valueParameterDescriptor != null && + if (candidate.hasStableParameterNames() && nameReference != null && candidate instanceof CallableMemberDescriptor && ((CallableMemberDescriptor)candidate).getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { - for (ValueParameterDescriptor parameterFromSuperclass : valueParameterDescriptor.getOverriddenDescriptors()) { - if (OverrideResolver.shouldReportParameterNameOverrideWarning(valueParameterDescriptor, parameterFromSuperclass)) { + if (valueParameterDescriptor == null) { + valueParameterDescriptor = getParameterByNameInOverriddenMethods(argumentName.getAsName()); + } + + if (valueParameterDescriptor != null) { + for (ValueParameterDescriptor parameterFromSuperclass : valueParameterDescriptor.getOverriddenDescriptors()) { + if (OverrideResolver.shouldReportParameterNameOverrideWarning(valueParameterDescriptor, parameterFromSuperclass)) { report(NAME_FOR_AMBIGUOUS_PARAMETER.on(nameReference)); + } } } } diff --git a/compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArguments1.kt b/compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArguments1.kt index 8aa11d1f37f..c9ce8deb415 100644 --- a/compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArguments1.kt +++ b/compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArguments1.kt @@ -10,6 +10,18 @@ interface B { interface D : B, A fun foo(x : C, y : D){ + x.foo(x = 0) x.foo(y = 0) y.foo(x = 0) + y.foo(y = 0) +} + +abstract class C1 : A, B +abstract class D1 : A, B + +fun bar(x : C1, y : D1){ + x.foo(x = 0) + x.foo(y = 0) + y.foo(x = 0) + y.foo(y = 0) } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArguments1.txt b/compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArguments1.txt index 8574b4c4d65..8a41feb7b32 100644 --- a/compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArguments1.txt +++ b/compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArguments1.txt @@ -1,5 +1,6 @@ package +public fun bar(/*0*/ x: C1, /*1*/ y: D1): kotlin.Unit public fun foo(/*0*/ x: C, /*1*/ y: D): kotlin.Unit public interface A { @@ -23,9 +24,25 @@ public interface C : A, B { public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String } +public abstract class C1 : A, B { + public constructor C1() + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract override /*2*/ /*fake_override*/ fun foo(/*0*/ y: kotlin.Int): kotlin.Unit + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String +} + public interface D : B, A { public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public abstract override /*2*/ /*fake_override*/ fun foo(/*0*/ x: kotlin.Int): kotlin.Unit public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String } + +public abstract class D1 : A, B { + public constructor D1() + public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract override /*2*/ /*fake_override*/ fun foo(/*0*/ y: kotlin.Int): kotlin.Unit + public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArguments2.kt b/compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArguments2.kt index 5353a5f12f4..682d60493ae 100644 --- a/compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArguments2.kt +++ b/compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArguments2.kt @@ -15,6 +15,10 @@ interface B { fun test(c: C) { c.foo(b1 = 1, b2 = 1.0) + c.foo(a1 = 1, b2 = 1.0) + c.foo(a1 = 1, a2 = 1.0) + c.foo(a1 = 1, a2 = 1.0) c.bar(a1 = 1, a2 = 1.0, b3= "") c.baz(a1 = 1, b2 = 1.0, a3 = "", b4 = 2, a5 = "") + c.baz(a1 = 1, a2 = 1.0, a3 = "", b4 = 2, a5 = "") } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArgumentsWithGenerics1.kt b/compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArgumentsWithGenerics1.kt index 84126aa2cf0..70a2691cb9b 100644 --- a/compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArgumentsWithGenerics1.kt +++ b/compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArgumentsWithGenerics1.kt @@ -10,5 +10,6 @@ interface B { } fun test(c: C) { + c.foo(a = 1) c.foo(b = 1) } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArgumentsWithGenerics2.kt b/compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArgumentsWithGenerics2.kt index 3bac3a84330..01956c3c713 100644 --- a/compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArgumentsWithGenerics2.kt +++ b/compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArgumentsWithGenerics2.kt @@ -10,5 +10,6 @@ interface B { } fun test(c: C) { + c.foo(a = 1) c.foo(b = 1) } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArgumentsWithGenerics3.kt b/compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArgumentsWithGenerics3.kt index 892d0b28d41..b9d05609b45 100644 --- a/compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArgumentsWithGenerics3.kt +++ b/compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArgumentsWithGenerics3.kt @@ -10,5 +10,6 @@ interface B { } fun test(c: C) { + c.foo(a = 1) c.foo(b = 1) } \ No newline at end of file