fix KT-9484 Don't allow named arguments for inherited functions with parameter name conflicts

#KT9484 Fixed
This commit is contained in:
Michael Nedzelsky
2015-10-09 01:07:53 +03:00
parent ae15443413
commit b92a06929e
18 changed files with 353 additions and 0 deletions
@@ -403,6 +403,8 @@ public interface Errors {
DiagnosticFactory2<JetClassOrObject, Collection<? extends CallableMemberDescriptor>, Integer> DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES =
DiagnosticFactory2.create(WARNING, DECLARATION_NAME);
DiagnosticFactory0<JetReferenceExpression> NAME_FOR_AMBIGUOUS_PARAMETER = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> DATA_CLASS_WITHOUT_PARAMETERS = DiagnosticFactory0.create(WARNING);
DiagnosticFactory0<JetParameter> DATA_CLASS_VARARG_PARAMETER = DiagnosticFactory0.create(WARNING);
DiagnosticFactory0<JetParameter> DATA_CLASS_NOT_PROPERTY_PARAMETER = DiagnosticFactory0.create(WARNING);
@@ -651,6 +651,8 @@ public class DefaultErrorMessages {
"Names of the parameter #{1} conflict in the following members of supertypes: ''{0}''. " +
"This may cause problems when calling this function with named arguments.", commaSeparated(FQ_NAMES_IN_TYPES), TO_STRING);
MAP.put(NAME_FOR_AMBIGUOUS_PARAMETER, "Named argument is not allowed for a parameter with an ambiguous name");
MAP.put(DATA_CLASS_WITHOUT_PARAMETERS, "Data class without primary constructor parameters are deprecated");
MAP.put(DATA_CLASS_VARARG_PARAMETER, "Primary constructor vararg parameters are deprecated for data classes");
MAP.put(DATA_CLASS_NOT_PROPERTY_PARAMETER, "Primary constructor parameters without val / var are deprecated for data classes");
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
import org.jetbrains.kotlin.diagnostics.Diagnostic;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.OverrideResolver;
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage;
import org.jetbrains.kotlin.resolve.calls.model.*;
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy;
@@ -163,6 +164,14 @@ public class ValueArgumentsToParametersMapper {
));
}
if (candidate.hasStableParameterNames() && nameReference != null && valueParameterDescriptor != null) {
for (ValueParameterDescriptor parameterFromSuperclass : valueParameterDescriptor.getOverriddenDescriptors()) {
if (OverrideResolver.shouldReportParameterNameOverrideWarning(valueParameterDescriptor, parameterFromSuperclass)) {
report(NAME_FOR_AMBIGUOUS_PARAMETER.on(nameReference));
}
}
}
if (valueParameterDescriptor == null) {
if (nameReference != null) {
report(NAMED_PARAMETER_NOT_FOUND.on(nameReference, nameReference));
@@ -0,0 +1,15 @@
interface A {
fun foo(x : Int)
}
interface B {
fun foo(y : Int)
}
<!DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES!>interface C<!> : A, B
<!DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES!>interface D<!> : B, A
fun foo(x : C, y : D){
x.foo(<!NAME_FOR_AMBIGUOUS_PARAMETER!>y<!> = 0)
y.foo(<!NAME_FOR_AMBIGUOUS_PARAMETER!>x<!> = 0)
}
@@ -0,0 +1,31 @@
package
public fun foo(/*0*/ x: C, /*1*/ y: D): kotlin.Unit
public interface A {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract fun foo(/*0*/ x: kotlin.Int): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface B {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract fun foo(/*0*/ y: kotlin.Int): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface C : A, B {
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
}
@@ -0,0 +1,20 @@
interface A {
fun foo(a1: Int, a2: Double)
fun bar(a1: Int, a2: Double, a3: String)
fun baz(a1: Int, a2: Double, a3: String, a4: Int, a5: String)
}
interface B {
fun foo(b1: Int, b2: Double)
fun bar(a1: Int, a2: Double, b3: String)
fun baz(a1: Int, b2: Double, a3: String, b4: Int, a5: String)
}
<!DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES, DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES, DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES, DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES, DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES!>interface C<!> : A, B { // Warning here, this is correct
}
fun test(c: C) {
c.foo(<!NAME_FOR_AMBIGUOUS_PARAMETER!>b1<!> = 1, <!NAME_FOR_AMBIGUOUS_PARAMETER!>b2<!> = 1.0)
c.bar(a1 = 1, a2 = 1.0, <!NAME_FOR_AMBIGUOUS_PARAMETER!>b3<!>= "")
c.baz(a1 = 1, <!NAME_FOR_AMBIGUOUS_PARAMETER!>b2<!> = 1.0, a3 = "", <!NAME_FOR_AMBIGUOUS_PARAMETER!>b4<!> = 2, a5 = "")
}
@@ -0,0 +1,30 @@
package
public fun test(/*0*/ c: C): kotlin.Unit
public interface A {
public abstract fun bar(/*0*/ a1: kotlin.Int, /*1*/ a2: kotlin.Double, /*2*/ a3: kotlin.String): kotlin.Unit
public abstract fun baz(/*0*/ a1: kotlin.Int, /*1*/ a2: kotlin.Double, /*2*/ a3: kotlin.String, /*3*/ a4: kotlin.Int, /*4*/ a5: kotlin.String): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract fun foo(/*0*/ a1: kotlin.Int, /*1*/ a2: kotlin.Double): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface B {
public abstract fun bar(/*0*/ a1: kotlin.Int, /*1*/ a2: kotlin.Double, /*2*/ b3: kotlin.String): kotlin.Unit
public abstract fun baz(/*0*/ a1: kotlin.Int, /*1*/ b2: kotlin.Double, /*2*/ a3: kotlin.String, /*3*/ b4: kotlin.Int, /*4*/ a5: kotlin.String): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract fun foo(/*0*/ b1: kotlin.Int, /*1*/ b2: kotlin.Double): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface C : A, B {
public abstract override /*2*/ /*fake_override*/ fun bar(/*0*/ a1: kotlin.Int, /*1*/ a2: kotlin.Double, /*2*/ b3: kotlin.String): kotlin.Unit
public abstract override /*2*/ /*fake_override*/ fun baz(/*0*/ a1: kotlin.Int, /*1*/ b2: kotlin.Double, /*2*/ a3: kotlin.String, /*3*/ b4: kotlin.Int, /*4*/ a5: kotlin.String): kotlin.Unit
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract override /*2*/ /*fake_override*/ fun foo(/*0*/ b1: kotlin.Int, /*1*/ b2: kotlin.Double): kotlin.Unit
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,14 @@
interface A<T> {
fun foo(a: T)
}
interface B {
fun foo(b: Int)
}
<!DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES!>interface C<!> : A<Int>, B { // Warning here, this is correct
}
fun test(c: C) {
c.foo(<!NAME_FOR_AMBIGUOUS_PARAMETER!>b<!> = 1)
}
@@ -0,0 +1,24 @@
package
public fun test(/*0*/ c: C): kotlin.Unit
public interface A</*0*/ T> {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract fun foo(/*0*/ a: T): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface B {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract fun foo(/*0*/ b: kotlin.Int): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface C : A<kotlin.Int>, B {
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract override /*2*/ /*fake_override*/ fun foo(/*0*/ b: kotlin.Int): kotlin.Unit
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,14 @@
interface A {
fun <E> foo(a: E)
}
interface B {
fun <T> foo(b: T)
}
<!DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES!>interface C<!> : A, B { // Warning here, this is correct
}
fun test(c: C) {
c.foo(<!NAME_FOR_AMBIGUOUS_PARAMETER!>b<!> = 1)
}
@@ -0,0 +1,24 @@
package
public fun test(/*0*/ c: C): kotlin.Unit
public interface A {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract fun </*0*/ E> foo(/*0*/ a: E): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface B {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract fun </*0*/ T> foo(/*0*/ b: T): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface C : A, B {
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract override /*2*/ /*fake_override*/ fun </*0*/ T> foo(/*0*/ b: T): kotlin.Unit
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,14 @@
interface A<T> {
fun foo(a: T)
}
interface B<E> {
fun foo(b: E)
}
<!DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES!>interface C<!><U> : A<U>, B<U> { // Warning here, this is correct
}
fun test(c: C<Int>) {
c.foo(<!NAME_FOR_AMBIGUOUS_PARAMETER!>b<!> = 1)
}
@@ -0,0 +1,24 @@
package
public fun test(/*0*/ c: C<kotlin.Int>): kotlin.Unit
public interface A</*0*/ T> {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract fun foo(/*0*/ a: T): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface B</*0*/ E> {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract fun foo(/*0*/ b: E): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface C</*0*/ U> : A<U>, B<U> {
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract override /*2*/ /*fake_override*/ fun foo(/*0*/ b: U): kotlin.Unit
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,14 @@
interface A {
fun foo(a1: Int, a2: Double)
}
interface B {
fun foo(b1: Int, b2: String)
}
interface C : A, B {}
fun test(d: C) {
d.foo(a1 = 1, a2 = 1.0)
d.foo(b1 = 1, b2 = "")
}
@@ -0,0 +1,25 @@
package
public fun test(/*0*/ d: C): kotlin.Unit
public interface A {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract fun foo(/*0*/ a1: kotlin.Int, /*1*/ a2: kotlin.Double): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface B {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract fun foo(/*0*/ b1: kotlin.Int, /*1*/ b2: kotlin.String): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface C : A, B {
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract override /*1*/ /*fake_override*/ fun foo(/*0*/ a1: kotlin.Int, /*1*/ a2: kotlin.Double): kotlin.Unit
public abstract override /*1*/ /*fake_override*/ fun foo(/*0*/ b1: kotlin.Int, /*1*/ b2: kotlin.String): kotlin.Unit
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,18 @@
interface A {
fun foo(a1: Int, a2: Double)
}
interface B {
fun foo(b1: Int, b2: Double)
}
<!DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES, DIFFERENT_NAMES_FOR_THE_SAME_PARAMETER_IN_SUPERTYPES!>interface C<!> : A, B { // Warning here, this is correct, C.foo has no named parameters
}
interface D : C {
override fun foo(<!PARAMETER_NAME_CHANGED_ON_OVERRIDE!>d1<!>: Int, <!PARAMETER_NAME_CHANGED_ON_OVERRIDE!>d2<!>: Double)
}
fun test(d: D) {
d.foo(<!NAME_FOR_AMBIGUOUS_PARAMETER!>d1<!> = 1, <!NAME_FOR_AMBIGUOUS_PARAMETER!>d2<!> = 1.0)
}
@@ -0,0 +1,31 @@
package
public fun test(/*0*/ d: D): kotlin.Unit
public interface A {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract fun foo(/*0*/ a1: kotlin.Int, /*1*/ a2: kotlin.Double): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface B {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract fun foo(/*0*/ b1: kotlin.Int, /*1*/ b2: kotlin.Double): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface C : A, B {
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract override /*2*/ /*fake_override*/ fun foo(/*0*/ b1: kotlin.Int, /*1*/ b2: kotlin.Double): 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 : C {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract override /*1*/ fun foo(/*0*/ d1: kotlin.Int, /*1*/ d2: kotlin.Double): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -9678,6 +9678,36 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("ambiguousNamedArguments1.kt")
public void testAmbiguousNamedArguments1() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArguments1.kt");
doTest(fileName);
}
@TestMetadata("ambiguousNamedArguments2.kt")
public void testAmbiguousNamedArguments2() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArguments2.kt");
doTest(fileName);
}
@TestMetadata("ambiguousNamedArgumentsWithGenerics1.kt")
public void testAmbiguousNamedArgumentsWithGenerics1() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArgumentsWithGenerics1.kt");
doTest(fileName);
}
@TestMetadata("ambiguousNamedArgumentsWithGenerics2.kt")
public void testAmbiguousNamedArgumentsWithGenerics2() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArgumentsWithGenerics2.kt");
doTest(fileName);
}
@TestMetadata("ambiguousNamedArgumentsWithGenerics3.kt")
public void testAmbiguousNamedArgumentsWithGenerics3() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/namedArguments/ambiguousNamedArgumentsWithGenerics3.kt");
doTest(fileName);
}
@TestMetadata("disallowForJavaConstructor.kt")
public void testDisallowForJavaConstructor() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/namedArguments/disallowForJavaConstructor.kt");
@@ -9707,6 +9737,18 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/namedArguments/namedArgumentsAndDefaultValues.kt");
doTest(fileName);
}
@TestMetadata("namedArgumentsInOverloads.kt")
public void testNamedArgumentsInOverloads() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/namedArguments/namedArgumentsInOverloads.kt");
doTest(fileName);
}
@TestMetadata("namedArgumentsInOverrides.kt")
public void testNamedArgumentsInOverrides() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/namedArguments/namedArgumentsInOverrides.kt");
doTest(fileName);
}
}
@TestMetadata("compiler/testData/diagnostics/tests/nullabilityAndSmartCasts")