Disallow using named arguments for members of header classes
#KT-17083 Fixed
This commit is contained in:
@@ -570,7 +570,8 @@ public interface Errors {
|
|||||||
|
|
||||||
enum BadNamedArgumentsTarget {
|
enum BadNamedArgumentsTarget {
|
||||||
NON_KOTLIN_FUNCTION,
|
NON_KOTLIN_FUNCTION,
|
||||||
INVOKE_ON_FUNCTION_TYPE
|
INVOKE_ON_FUNCTION_TYPE,
|
||||||
|
HEADER_CLASS_MEMBER,
|
||||||
}
|
}
|
||||||
|
|
||||||
DiagnosticFactory0<KtExpression> VARARG_OUTSIDE_PARENTHESES = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<KtExpression> VARARG_OUTSIDE_PARENTHESES = DiagnosticFactory0.create(ERROR);
|
||||||
|
|||||||
+2
@@ -207,6 +207,8 @@ public class DefaultErrorMessages {
|
|||||||
return "non-Kotlin functions";
|
return "non-Kotlin functions";
|
||||||
case INVOKE_ON_FUNCTION_TYPE:
|
case INVOKE_ON_FUNCTION_TYPE:
|
||||||
return "function types";
|
return "function types";
|
||||||
|
case HEADER_CLASS_MEMBER:
|
||||||
|
return "members of header classes";
|
||||||
default:
|
default:
|
||||||
throw new AssertionError(target);
|
throw new AssertionError(target);
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-10
@@ -23,9 +23,7 @@ import kotlin.collections.CollectionsKt;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor;
|
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor;
|
|
||||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
|
|
||||||
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
import org.jetbrains.kotlin.diagnostics.Diagnostic;
|
||||||
import org.jetbrains.kotlin.name.Name;
|
import org.jetbrains.kotlin.name.Name;
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
@@ -42,8 +40,7 @@ import java.util.Map;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.jetbrains.kotlin.diagnostics.Errors.*;
|
import static org.jetbrains.kotlin.diagnostics.Errors.*;
|
||||||
import static org.jetbrains.kotlin.diagnostics.Errors.BadNamedArgumentsTarget.INVOKE_ON_FUNCTION_TYPE;
|
import static org.jetbrains.kotlin.diagnostics.Errors.BadNamedArgumentsTarget.*;
|
||||||
import static org.jetbrains.kotlin.diagnostics.Errors.BadNamedArgumentsTarget.NON_KOTLIN_FUNCTION;
|
|
||||||
import static org.jetbrains.kotlin.resolve.BindingContext.REFERENCE_TARGET;
|
import static org.jetbrains.kotlin.resolve.BindingContext.REFERENCE_TARGET;
|
||||||
import static org.jetbrains.kotlin.resolve.calls.ValueArgumentsToParametersMapper.Status.*;
|
import static org.jetbrains.kotlin.resolve.calls.ValueArgumentsToParametersMapper.Status.*;
|
||||||
|
|
||||||
@@ -189,11 +186,19 @@ public class ValueArgumentsToParametersMapper {
|
|||||||
KtSimpleNameExpression nameReference = argumentName.getReferenceExpression();
|
KtSimpleNameExpression nameReference = argumentName.getReferenceExpression();
|
||||||
|
|
||||||
KtPsiUtilKt.checkReservedYield(nameReference, candidateCall.getTrace());
|
KtPsiUtilKt.checkReservedYield(nameReference, candidateCall.getTrace());
|
||||||
if (!candidate.hasStableParameterNames() && nameReference != null) {
|
if (nameReference != null) {
|
||||||
report(NAMED_ARGUMENTS_NOT_ALLOWED.on(
|
if (candidate instanceof MemberDescriptor && ((MemberDescriptor) candidate).isHeader() &&
|
||||||
nameReference,
|
candidate.getContainingDeclaration() instanceof ClassDescriptor) {
|
||||||
candidate instanceof FunctionInvokeDescriptor ? INVOKE_ON_FUNCTION_TYPE : NON_KOTLIN_FUNCTION
|
// We do not allow named arguments for members of header classes until we're able to use both
|
||||||
));
|
// headers and platform definitions when compiling platform code
|
||||||
|
report(NAMED_ARGUMENTS_NOT_ALLOWED.on(nameReference, HEADER_CLASS_MEMBER));
|
||||||
|
}
|
||||||
|
else if (!candidate.hasStableParameterNames()) {
|
||||||
|
report(NAMED_ARGUMENTS_NOT_ALLOWED.on(
|
||||||
|
nameReference,
|
||||||
|
candidate instanceof FunctionInvokeDescriptor ? INVOKE_ON_FUNCTION_TYPE : NON_KOTLIN_FUNCTION
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (candidate.hasStableParameterNames() && nameReference != null &&
|
if (candidate.hasStableParameterNames() && nameReference != null &&
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
// !LANGUAGE: +MultiPlatformProjects
|
||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
|
||||||
|
header class Foo(zzz: Int) {
|
||||||
|
constructor(aaa: Boolean)
|
||||||
|
|
||||||
|
fun f1(xxx: String): String
|
||||||
|
}
|
||||||
|
|
||||||
|
header fun f2(xxx: Int)
|
||||||
|
|
||||||
|
fun testCommon() {
|
||||||
|
Foo(<!NAMED_ARGUMENTS_NOT_ALLOWED!>zzz<!> = 0)
|
||||||
|
val f = Foo(<!NAMED_ARGUMENTS_NOT_ALLOWED!>aaa<!> = true)
|
||||||
|
f.f1(<!NAMED_ARGUMENTS_NOT_ALLOWED!>xxx<!> = "")
|
||||||
|
f2(xxx = 42)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MODULE: m2-jvm(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
|
||||||
|
impl class Foo(val aaa: Boolean) {
|
||||||
|
impl constructor(zzz: Int) : this(zzz == 0)
|
||||||
|
|
||||||
|
impl fun f1(xxx: String) = xxx
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fun f2(xxx: Int) {}
|
||||||
|
|
||||||
|
fun testPlatform() {
|
||||||
|
Foo(zzz = 0)
|
||||||
|
val f = Foo(aaa = true)
|
||||||
|
f.f1(xxx = "")
|
||||||
|
f2(xxx = 42)
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
// -- Module: <m1-common> --
|
||||||
|
package
|
||||||
|
|
||||||
|
public header fun f2(/*0*/ xxx: kotlin.Int): kotlin.Unit
|
||||||
|
public fun testCommon(): kotlin.Unit
|
||||||
|
|
||||||
|
public final header class Foo {
|
||||||
|
public constructor Foo(/*0*/ aaa: kotlin.Boolean)
|
||||||
|
public constructor Foo(/*0*/ zzz: kotlin.Int)
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public final header fun f1(/*0*/ xxx: kotlin.String): kotlin.String
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -- Module: <m2-jvm> --
|
||||||
|
package
|
||||||
|
|
||||||
|
public impl fun f2(/*0*/ xxx: kotlin.Int): kotlin.Unit
|
||||||
|
public fun testCommon(): kotlin.Unit
|
||||||
|
public fun testPlatform(): kotlin.Unit
|
||||||
|
|
||||||
|
public final impl class Foo {
|
||||||
|
public constructor Foo(/*0*/ aaa: kotlin.Boolean)
|
||||||
|
public constructor Foo(/*0*/ zzz: kotlin.Int)
|
||||||
|
public final val aaa: kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public final impl fun f1(/*0*/ xxx: kotlin.String): kotlin.String
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
@@ -13120,6 +13120,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("namedArguments.kt")
|
||||||
|
public void testNamedArguments() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/namedArguments.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/diagnostics/tests/multiplatform/enum")
|
@TestMetadata("compiler/testData/diagnostics/tests/multiplatform/enum")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user