diff --git a/compiler/frontend/src/org/jetbrains/kotlin/cfg/pseudocode/TypePredicate.kt b/compiler/frontend/src/org/jetbrains/kotlin/cfg/pseudocode/TypePredicate.kt index d937ca14bef..18251ebb145 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/cfg/pseudocode/TypePredicate.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/cfg/pseudocode/TypePredicate.kt @@ -16,15 +16,14 @@ package org.jetbrains.kotlin.cfg.pseudocode -import org.jetbrains.kotlin.types.JetType -import org.jetbrains.kotlin.types.checker.JetTypeChecker -import org.jetbrains.kotlin.renderer.DescriptorRenderer import com.intellij.util.SmartFMap import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.renderer.DescriptorRenderer +import org.jetbrains.kotlin.types.JetType import org.jetbrains.kotlin.types.TypeUtils +import org.jetbrains.kotlin.types.checker.JetTypeChecker public trait TypePredicate: (JetType) -> Boolean { - [suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")] override fun invoke(typeToCheck: JetType): Boolean } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 527d299c3c3..9bc6eaf6b13 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -397,7 +397,12 @@ public interface Errors { DiagnosticFactory0 ARGUMENT_PASSED_TWICE = DiagnosticFactory0.create(ERROR); DiagnosticFactory1 NAMED_PARAMETER_NOT_FOUND = DiagnosticFactory1.create(ERROR, FOR_UNRESOLVED_REFERENCE); - DiagnosticFactory0 NAMED_ARGUMENTS_NOT_ALLOWED = DiagnosticFactory0.create(ERROR); + DiagnosticFactory1 NAMED_ARGUMENTS_NOT_ALLOWED = DiagnosticFactory1.create(ERROR); + + enum BadNamedArgumentsTarget { + NON_KOTLIN_FUNCTION, + INVOKE_ON_FUNCTION_TYPE + } DiagnosticFactory0 VARARG_OUTSIDE_PARENTHESES = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 NON_VARARG_SPREAD = DiagnosticFactory0.create(ERROR); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index 6ac0828d1ce..e0e9d20ada1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -155,7 +155,21 @@ public class DefaultErrorMessages { MAP.put(MIXING_NAMED_AND_POSITIONED_ARGUMENTS, "Mixing named and positioned arguments is not allowed"); MAP.put(ARGUMENT_PASSED_TWICE, "An argument is already passed for this parameter"); MAP.put(NAMED_PARAMETER_NOT_FOUND, "Cannot find a parameter with this name: {0}", ELEMENT_TEXT); - MAP.put(NAMED_ARGUMENTS_NOT_ALLOWED, "Named arguments are not allowed for non-Kotlin functions"); + MAP.put(NAMED_ARGUMENTS_NOT_ALLOWED, "Named arguments are not allowed for {0}", new Renderer() { + @NotNull + @Override + public String render(@NotNull BadNamedArgumentsTarget target) { + switch (target) { + case NON_KOTLIN_FUNCTION: + return "non-Kotlin functions"; + case INVOKE_ON_FUNCTION_TYPE: + return "function types"; + default: + throw new AssertionError(target); + } + } + }); + MAP.put(VARARG_OUTSIDE_PARENTHESES, "Passing value as a vararg is only allowed inside a parenthesized argument list"); MAP.put(NON_VARARG_SPREAD, "The spread operator (*foo) may only be applied in a vararg position"); 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 560d75706a7..f05d1e0a36b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ValueArgumentsToParametersMapper.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/ValueArgumentsToParametersMapper.java @@ -21,6 +21,7 @@ import com.google.common.collect.Sets; import com.intellij.psi.impl.source.tree.LeafPsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor; import org.jetbrains.kotlin.descriptors.CallableDescriptor; import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor; import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor; @@ -37,6 +38,8 @@ import java.util.Map; import java.util.Set; 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.NON_KOTLIN_FUNCTION; import static org.jetbrains.kotlin.resolve.BindingContext.REFERENCE_TARGET; import static org.jetbrains.kotlin.resolve.calls.ValueArgumentsToParametersMapper.Status.*; @@ -150,11 +153,17 @@ public class ValueArgumentsToParametersMapper { public ProcessorState processNamedArgument(@NotNull ValueArgument argument) { assert argument.isNamed(); + D candidate = candidateCall.getCandidateDescriptor(); + JetSimpleNameExpression nameReference = argument.getArgumentName().getReferenceExpression(); ValueParameterDescriptor valueParameterDescriptor = parameterByName.get(nameReference.getReferencedNameAsName()); - if (!candidateCall.getCandidateDescriptor().hasStableParameterNames()) { - report(NAMED_ARGUMENTS_NOT_ALLOWED.on(nameReference)); + if (!candidate.hasStableParameterNames()) { + report(NAMED_ARGUMENTS_NOT_ALLOWED.on( + nameReference, + candidate instanceof FunctionInvokeDescriptor ? INVOKE_ON_FUNCTION_TYPE : NON_KOTLIN_FUNCTION + )); } + if (valueParameterDescriptor == null) { report(NAMED_PARAMETER_NOT_FOUND.on(nameReference, nameReference)); unmappedArguments.add(argument); diff --git a/compiler/testData/diagnostics/tests/override/parameterNames/invokeInFunctionClass.kt b/compiler/testData/diagnostics/tests/override/parameterNames/invokeInFunctionClass.kt new file mode 100644 index 00000000000..faba565b15b --- /dev/null +++ b/compiler/testData/diagnostics/tests/override/parameterNames/invokeInFunctionClass.kt @@ -0,0 +1,27 @@ +class Function1Impl : (String) -> Unit { + override fun invoke(myParamName: String) {} +} + +fun test1(f: Function1Impl) { + f("") + f(p0 = "") + f(myParamName = "") + f.invoke("") + f.invoke(p0 = "") + f.invoke(myParamName = "") +} + +fun test2(f: (String) -> Unit) { + f("") + f(p0 = "") + f(myParamName = "") + f.invoke("") + f.invoke(p0 = "") + f.invoke(myParamName = "") +} + +fun test3(f: String.(String) -> Unit) { + "".f("") + "".f(p0 = "") + "".f(zzz = "") +} diff --git a/compiler/testData/diagnostics/tests/override/parameterNames/invokeInFunctionClass.txt b/compiler/testData/diagnostics/tests/override/parameterNames/invokeInFunctionClass.txt new file mode 100644 index 00000000000..3cf46259145 --- /dev/null +++ b/compiler/testData/diagnostics/tests/override/parameterNames/invokeInFunctionClass.txt @@ -0,0 +1,13 @@ +package + +internal fun test1(/*0*/ f: Function1Impl): kotlin.Unit +internal fun test2(/*0*/ f: (kotlin.String) -> kotlin.Unit): kotlin.Unit +internal fun test3(/*0*/ f: kotlin.String.(kotlin.String) -> kotlin.Unit): kotlin.Unit + +internal final class Function1Impl : (kotlin.String) -> kotlin.Unit { + public constructor Function1Impl() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ fun invoke(/*0*/ myParamName: kotlin.String): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/resolve/objectLiteralAsArgument.kt b/compiler/testData/diagnostics/tests/resolve/objectLiteralAsArgument.kt index 5013c93f0a0..9cae82ca8a4 100644 --- a/compiler/testData/diagnostics/tests/resolve/objectLiteralAsArgument.kt +++ b/compiler/testData/diagnostics/tests/resolve/objectLiteralAsArgument.kt @@ -1,5 +1,3 @@ -// !DIAGNOSTICS: -PARAMETER_NAME_CHANGED_ON_OVERRIDE - //If this test hangs, it means something is broken. object A { val iii = 42 diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index 4b1eebf4834..c7461ad8797 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -9431,6 +9431,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("invokeInFunctionClass.kt") + public void testInvokeInFunctionClass() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/override/parameterNames/invokeInFunctionClass.kt"); + doTest(fileName); + } + @TestMetadata("jjkHierarchy.kt") public void testJjkHierarchy() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/override/parameterNames/jjkHierarchy.kt"); diff --git a/core/descriptors/src/org/jetbrains/kotlin/builtins/functions/FunctionInvokeDescriptor.kt b/core/descriptors/src/org/jetbrains/kotlin/builtins/functions/FunctionInvokeDescriptor.kt index 939e2c68c6d..3c0a9ae0d36 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/builtins/functions/FunctionInvokeDescriptor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/builtins/functions/FunctionInvokeDescriptor.kt @@ -23,7 +23,6 @@ import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.types.Variance -// TODO: make parameter names synthetic / non-stable public class FunctionInvokeDescriptor private constructor( private val container: DeclarationDescriptor, private val original: FunctionInvokeDescriptor?, @@ -36,6 +35,9 @@ public class FunctionInvokeDescriptor private constructor( callableKind, SourceElement.NO_SOURCE ) { + // "p0", "p1", etc. should not be baked into the language + override fun hasStableParameterNames(): Boolean = false + override fun createSubstitutedCopy( newOwner: DeclarationDescriptor, original: FunctionDescriptor?, diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/ExtractableCodeDescriptor.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/ExtractableCodeDescriptor.kt index d38353ef2c3..058d6cd4af1 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/ExtractableCodeDescriptor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractionEngine/ExtractableCodeDescriptor.kt @@ -16,34 +16,38 @@ package org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine -import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import com.intellij.util.containers.MultiMap +import com.intellij.openapi.util.text.StringUtil import com.intellij.psi.PsiElement -import org.jetbrains.kotlin.idea.references.JetSimpleNameReference -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.idea.references.JetSimpleNameReference.ShorteningMode -import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.AnalysisResult.Status +import com.intellij.util.containers.ContainerUtil +import com.intellij.util.containers.MultiMap +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.idea.core.replaced import org.jetbrains.kotlin.idea.refactoring.JetRefactoringBundle import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.AnalysisResult.ErrorMessage -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import com.intellij.openapi.util.text.StringUtil -import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.OutputValue.* -import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import kotlin.properties.Delegates -import com.intellij.util.containers.ContainerUtil -import org.jetbrains.kotlin.idea.core.replaced +import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.AnalysisResult.Status +import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.OutputValue.ExpressionValue +import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.OutputValue.Initializer +import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.OutputValue.Jump +import org.jetbrains.kotlin.idea.references.JetSimpleNameReference +import org.jetbrains.kotlin.idea.references.JetSimpleNameReference.ShorteningMode import org.jetbrains.kotlin.idea.util.approximateFlexibleTypes import org.jetbrains.kotlin.idea.util.isAnnotatedNotNull import org.jetbrains.kotlin.idea.util.isAnnotatedNullable -import org.jetbrains.kotlin.idea.util.psi.patternMatching.JetPsiRange -import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.idea.util.isUnit -import org.jetbrains.kotlin.resolve.descriptorUtil.resolveTopLevelClass +import org.jetbrains.kotlin.idea.util.psi.patternMatching.JetPsiRange +import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.* -import java.util.* +import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector +import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis +import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType +import org.jetbrains.kotlin.resolve.BindingContext +import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.descriptorUtil.resolveTopLevelClass import org.jetbrains.kotlin.types.* -import org.jetbrains.kotlin.psi.psiUtil.* +import java.util.Collections +import kotlin.properties.Delegates trait Parameter { val argumentText: String @@ -76,7 +80,6 @@ trait ParameterReplacement : Replacement { class RenameReplacement(override val parameter: Parameter): ParameterReplacement { override fun copy(parameter: Parameter) = RenameReplacement(parameter) - [suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")] override fun invoke(e: JetElement): JetElement { var expressionToReplace = (e.getParent() as? JetThisExpression ?: e).getQualifiedExpressionForSelectorOrThis() val psiFactory = JetPsiFactory(e) @@ -94,7 +97,6 @@ class RenameReplacement(override val parameter: Parameter): ParameterReplacement class AddPrefixReplacement(override val parameter: Parameter): ParameterReplacement { override fun copy(parameter: Parameter) = AddPrefixReplacement(parameter) - [suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")] override fun invoke(e: JetElement): JetElement { val selector = (e.getParent() as? JetCallExpression) ?: e val newExpr = selector.replace(JetPsiFactory(e).createExpression("${parameter.nameForRef}.${selector.getText()}") @@ -105,7 +107,6 @@ class AddPrefixReplacement(override val parameter: Parameter): ParameterReplacem } class FqNameReplacement(val fqName: FqName): Replacement { - [suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")] override fun invoke(e: JetElement): JetElement { val thisExpr = e.getParent() as? JetThisExpression if (thisExpr != null) { diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveTopLevelDeclarations/MoveKotlinTopLevelDeclarationsProcessor.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveTopLevelDeclarations/MoveKotlinTopLevelDeclarationsProcessor.kt index 1f09c1ed36c..067fd823d20 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveTopLevelDeclarations/MoveKotlinTopLevelDeclarationsProcessor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveTopLevelDeclarations/MoveKotlinTopLevelDeclarationsProcessor.kt @@ -16,11 +16,13 @@ package org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations -import com.intellij.openapi.diagnostic.Logger import com.intellij.openapi.project.Project import com.intellij.openapi.util.Ref import com.intellij.openapi.util.text.StringUtil -import com.intellij.psi.* +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiModifier +import com.intellij.psi.PsiModifierListOwner +import com.intellij.psi.PsiReference import com.intellij.psi.search.searches.ReferencesSearch import com.intellij.refactoring.BaseRefactoringProcessor import com.intellij.refactoring.move.MoveCallback @@ -43,7 +45,6 @@ import org.jetbrains.kotlin.asJava.toLightElements import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde import org.jetbrains.kotlin.idea.codeInsight.JetFileReferencesResolver import org.jetbrains.kotlin.idea.codeInsight.shorten.addToShorteningWaitSet -import org.jetbrains.kotlin.idea.core.refactoring.createKotlinFile import org.jetbrains.kotlin.idea.core.refactoring.getUsageContext import org.jetbrains.kotlin.idea.refactoring.JetRefactoringBundle import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName @@ -65,7 +66,6 @@ import java.util.HashSet trait Mover: (originalElement: JetNamedDeclaration, targetFile: JetFile) -> JetNamedDeclaration { object Default: Mover { - @suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") override fun invoke(originalElement: JetNamedDeclaration, targetFile: JetFile): JetNamedDeclaration { val newElement = targetFile.add(originalElement) as JetNamedDeclaration originalElement.delete() @@ -74,7 +74,6 @@ trait Mover: (originalElement: JetNamedDeclaration, targetFile: JetFile) -> JetN } object Idle: Mover { - @suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") override fun invoke(originalElement: JetNamedDeclaration, targetFile: JetFile) = originalElement } }