Make parameter names of fictitious function classes non-stable

To be able to change them when overriding invoke in subclasses without a
warning
This commit is contained in:
Alexander Udalov
2015-05-28 20:18:08 +03:00
parent 16b20cf910
commit 158b3ba102
11 changed files with 111 additions and 38 deletions
@@ -16,15 +16,14 @@
package org.jetbrains.kotlin.cfg.pseudocode 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 com.intellij.util.SmartFMap
import org.jetbrains.kotlin.builtins.KotlinBuiltIns 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.TypeUtils
import org.jetbrains.kotlin.types.checker.JetTypeChecker
public trait TypePredicate: (JetType) -> Boolean { public trait TypePredicate: (JetType) -> Boolean {
[suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")]
override fun invoke(typeToCheck: JetType): Boolean override fun invoke(typeToCheck: JetType): Boolean
} }
@@ -397,7 +397,12 @@ public interface Errors {
DiagnosticFactory0<JetReferenceExpression> ARGUMENT_PASSED_TWICE = DiagnosticFactory0.create(ERROR); DiagnosticFactory0<JetReferenceExpression> ARGUMENT_PASSED_TWICE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory1<JetReferenceExpression, JetReferenceExpression> NAMED_PARAMETER_NOT_FOUND = DiagnosticFactory1<JetReferenceExpression, JetReferenceExpression> NAMED_PARAMETER_NOT_FOUND =
DiagnosticFactory1.create(ERROR, FOR_UNRESOLVED_REFERENCE); DiagnosticFactory1.create(ERROR, FOR_UNRESOLVED_REFERENCE);
DiagnosticFactory0<PsiElement> NAMED_ARGUMENTS_NOT_ALLOWED = DiagnosticFactory0.create(ERROR); DiagnosticFactory1<PsiElement, BadNamedArgumentsTarget> NAMED_ARGUMENTS_NOT_ALLOWED = DiagnosticFactory1.create(ERROR);
enum BadNamedArgumentsTarget {
NON_KOTLIN_FUNCTION,
INVOKE_ON_FUNCTION_TYPE
}
DiagnosticFactory0<JetExpression> VARARG_OUTSIDE_PARENTHESES = DiagnosticFactory0.create(ERROR); DiagnosticFactory0<JetExpression> VARARG_OUTSIDE_PARENTHESES = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<LeafPsiElement> NON_VARARG_SPREAD = DiagnosticFactory0.create(ERROR); DiagnosticFactory0<LeafPsiElement> NON_VARARG_SPREAD = DiagnosticFactory0.create(ERROR);
@@ -155,7 +155,21 @@ public class DefaultErrorMessages {
MAP.put(MIXING_NAMED_AND_POSITIONED_ARGUMENTS, "Mixing named and positioned arguments is not allowed"); 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(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_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<BadNamedArgumentsTarget>() {
@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(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"); MAP.put(NON_VARARG_SPREAD, "The spread operator (*foo) may only be applied in a vararg position");
@@ -21,6 +21,7 @@ import com.google.common.collect.Sets;
import com.intellij.psi.impl.source.tree.LeafPsiElement; import com.intellij.psi.impl.source.tree.LeafPsiElement;
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.descriptors.CallableDescriptor; import org.jetbrains.kotlin.descriptors.CallableDescriptor;
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor; import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor;
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor; import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
@@ -37,6 +38,8 @@ 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.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.*;
@@ -150,11 +153,17 @@ public class ValueArgumentsToParametersMapper {
public ProcessorState processNamedArgument(@NotNull ValueArgument argument) { public ProcessorState processNamedArgument(@NotNull ValueArgument argument) {
assert argument.isNamed(); assert argument.isNamed();
D candidate = candidateCall.getCandidateDescriptor();
JetSimpleNameExpression nameReference = argument.getArgumentName().getReferenceExpression(); JetSimpleNameExpression nameReference = argument.getArgumentName().getReferenceExpression();
ValueParameterDescriptor valueParameterDescriptor = parameterByName.get(nameReference.getReferencedNameAsName()); ValueParameterDescriptor valueParameterDescriptor = parameterByName.get(nameReference.getReferencedNameAsName());
if (!candidateCall.getCandidateDescriptor().hasStableParameterNames()) { if (!candidate.hasStableParameterNames()) {
report(NAMED_ARGUMENTS_NOT_ALLOWED.on(nameReference)); report(NAMED_ARGUMENTS_NOT_ALLOWED.on(
nameReference,
candidate instanceof FunctionInvokeDescriptor ? INVOKE_ON_FUNCTION_TYPE : NON_KOTLIN_FUNCTION
));
} }
if (valueParameterDescriptor == null) { if (valueParameterDescriptor == null) {
report(NAMED_PARAMETER_NOT_FOUND.on(nameReference, nameReference)); report(NAMED_PARAMETER_NOT_FOUND.on(nameReference, nameReference));
unmappedArguments.add(argument); unmappedArguments.add(argument);
@@ -0,0 +1,27 @@
class Function1Impl : (String) -> Unit {
override fun invoke(myParamName: String) {}
}
fun test1(f: Function1Impl) {
f("")
f(<!NAMED_PARAMETER_NOT_FOUND!>p0<!> = ""<!NO_VALUE_FOR_PARAMETER!>)<!>
f(myParamName = "")
f.invoke("")
f.invoke(<!NAMED_PARAMETER_NOT_FOUND!>p0<!> = ""<!NO_VALUE_FOR_PARAMETER!>)<!>
f.invoke(myParamName = "")
}
fun test2(f: (String) -> Unit) {
f("")
f(<!NAMED_ARGUMENTS_NOT_ALLOWED, NAMED_PARAMETER_NOT_FOUND!>p0<!> = ""<!NO_VALUE_FOR_PARAMETER!>)<!>
f(<!NAMED_ARGUMENTS_NOT_ALLOWED, NAMED_PARAMETER_NOT_FOUND!>myParamName<!> = ""<!NO_VALUE_FOR_PARAMETER!>)<!>
f.invoke("")
f.invoke(<!NAMED_ARGUMENTS_NOT_ALLOWED, NAMED_PARAMETER_NOT_FOUND!>p0<!> = ""<!NO_VALUE_FOR_PARAMETER!>)<!>
f.invoke(<!NAMED_ARGUMENTS_NOT_ALLOWED, NAMED_PARAMETER_NOT_FOUND!>myParamName<!> = ""<!NO_VALUE_FOR_PARAMETER!>)<!>
}
fun test3(f: String.(String) -> Unit) {
"".f("")
"".f(<!NAMED_PARAMETER_NOT_FOUND!>p0<!> = ""<!NO_VALUE_FOR_PARAMETER!>)<!>
"".f(<!NAMED_PARAMETER_NOT_FOUND!>zzz<!> = ""<!NO_VALUE_FOR_PARAMETER!>)<!>
}
@@ -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
}
@@ -1,5 +1,3 @@
// !DIAGNOSTICS: -PARAMETER_NAME_CHANGED_ON_OVERRIDE
//If this test hangs, it means something is broken. //If this test hangs, it means something is broken.
object A { object A {
val iii = 42 val iii = 42
@@ -9431,6 +9431,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName); 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") @TestMetadata("jjkHierarchy.kt")
public void testJjkHierarchy() throws Exception { public void testJjkHierarchy() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/override/parameterNames/jjkHierarchy.kt"); String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/override/parameterNames/jjkHierarchy.kt");
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.Variance
// TODO: make parameter names synthetic / non-stable
public class FunctionInvokeDescriptor private constructor( public class FunctionInvokeDescriptor private constructor(
private val container: DeclarationDescriptor, private val container: DeclarationDescriptor,
private val original: FunctionInvokeDescriptor?, private val original: FunctionInvokeDescriptor?,
@@ -36,6 +35,9 @@ public class FunctionInvokeDescriptor private constructor(
callableKind, callableKind,
SourceElement.NO_SOURCE SourceElement.NO_SOURCE
) { ) {
// "p0", "p1", etc. should not be baked into the language
override fun hasStableParameterNames(): Boolean = false
override fun createSubstitutedCopy( override fun createSubstitutedCopy(
newOwner: DeclarationDescriptor, newOwner: DeclarationDescriptor,
original: FunctionDescriptor?, original: FunctionDescriptor?,
@@ -16,34 +16,38 @@
package org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine package org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import com.intellij.openapi.util.text.StringUtil
import com.intellij.util.containers.MultiMap
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference import com.intellij.util.containers.ContainerUtil
import org.jetbrains.kotlin.name.FqName import com.intellij.util.containers.MultiMap
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference.ShorteningMode import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.AnalysisResult.Status 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.JetRefactoringBundle
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.AnalysisResult.ErrorMessage import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.AnalysisResult.ErrorMessage
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.AnalysisResult.Status
import com.intellij.openapi.util.text.StringUtil import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.OutputValue.ExpressionValue
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.OutputValue.Initializer
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.OutputValue.* import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.OutputValue.Jump
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.idea.references.JetSimpleNameReference
import kotlin.properties.Delegates import org.jetbrains.kotlin.idea.references.JetSimpleNameReference.ShorteningMode
import com.intellij.util.containers.ContainerUtil
import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.idea.util.approximateFlexibleTypes import org.jetbrains.kotlin.idea.util.approximateFlexibleTypes
import org.jetbrains.kotlin.idea.util.isAnnotatedNotNull import org.jetbrains.kotlin.idea.util.isAnnotatedNotNull
import org.jetbrains.kotlin.idea.util.isAnnotatedNullable 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.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 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.types.*
import org.jetbrains.kotlin.psi.psiUtil.* import java.util.Collections
import kotlin.properties.Delegates
trait Parameter { trait Parameter {
val argumentText: String val argumentText: String
@@ -76,7 +80,6 @@ trait ParameterReplacement : Replacement {
class RenameReplacement(override val parameter: Parameter): ParameterReplacement { class RenameReplacement(override val parameter: Parameter): ParameterReplacement {
override fun copy(parameter: Parameter) = RenameReplacement(parameter) override fun copy(parameter: Parameter) = RenameReplacement(parameter)
[suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")]
override fun invoke(e: JetElement): JetElement { override fun invoke(e: JetElement): JetElement {
var expressionToReplace = (e.getParent() as? JetThisExpression ?: e).getQualifiedExpressionForSelectorOrThis() var expressionToReplace = (e.getParent() as? JetThisExpression ?: e).getQualifiedExpressionForSelectorOrThis()
val psiFactory = JetPsiFactory(e) val psiFactory = JetPsiFactory(e)
@@ -94,7 +97,6 @@ class RenameReplacement(override val parameter: Parameter): ParameterReplacement
class AddPrefixReplacement(override val parameter: Parameter): ParameterReplacement { class AddPrefixReplacement(override val parameter: Parameter): ParameterReplacement {
override fun copy(parameter: Parameter) = AddPrefixReplacement(parameter) override fun copy(parameter: Parameter) = AddPrefixReplacement(parameter)
[suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")]
override fun invoke(e: JetElement): JetElement { override fun invoke(e: JetElement): JetElement {
val selector = (e.getParent() as? JetCallExpression) ?: e val selector = (e.getParent() as? JetCallExpression) ?: e
val newExpr = selector.replace(JetPsiFactory(e).createExpression("${parameter.nameForRef}.${selector.getText()}") 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 { class FqNameReplacement(val fqName: FqName): Replacement {
[suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")]
override fun invoke(e: JetElement): JetElement { override fun invoke(e: JetElement): JetElement {
val thisExpr = e.getParent() as? JetThisExpression val thisExpr = e.getParent() as? JetThisExpression
if (thisExpr != null) { if (thisExpr != null) {
@@ -16,11 +16,13 @@
package org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations package org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Ref import com.intellij.openapi.util.Ref
import com.intellij.openapi.util.text.StringUtil 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.psi.search.searches.ReferencesSearch
import com.intellij.refactoring.BaseRefactoringProcessor import com.intellij.refactoring.BaseRefactoringProcessor
import com.intellij.refactoring.move.MoveCallback 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.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.idea.codeInsight.JetFileReferencesResolver import org.jetbrains.kotlin.idea.codeInsight.JetFileReferencesResolver
import org.jetbrains.kotlin.idea.codeInsight.shorten.addToShorteningWaitSet 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.core.refactoring.getUsageContext
import org.jetbrains.kotlin.idea.refactoring.JetRefactoringBundle import org.jetbrains.kotlin.idea.refactoring.JetRefactoringBundle
import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName
@@ -65,7 +66,6 @@ import java.util.HashSet
trait Mover: (originalElement: JetNamedDeclaration, targetFile: JetFile) -> JetNamedDeclaration { trait Mover: (originalElement: JetNamedDeclaration, targetFile: JetFile) -> JetNamedDeclaration {
object Default: Mover { object Default: Mover {
@suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")
override fun invoke(originalElement: JetNamedDeclaration, targetFile: JetFile): JetNamedDeclaration { override fun invoke(originalElement: JetNamedDeclaration, targetFile: JetFile): JetNamedDeclaration {
val newElement = targetFile.add(originalElement) as JetNamedDeclaration val newElement = targetFile.add(originalElement) as JetNamedDeclaration
originalElement.delete() originalElement.delete()
@@ -74,7 +74,6 @@ trait Mover: (originalElement: JetNamedDeclaration, targetFile: JetFile) -> JetN
} }
object Idle: Mover { object Idle: Mover {
@suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")
override fun invoke(originalElement: JetNamedDeclaration, targetFile: JetFile) = originalElement override fun invoke(originalElement: JetNamedDeclaration, targetFile: JetFile) = originalElement
} }
} }