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
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
}
@@ -397,7 +397,12 @@ public interface Errors {
DiagnosticFactory0<JetReferenceExpression> ARGUMENT_PASSED_TWICE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory1<JetReferenceExpression, JetReferenceExpression> NAMED_PARAMETER_NOT_FOUND =
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<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(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<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(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 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);
@@ -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.
object A {
val iii = 42
@@ -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");
@@ -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?,
@@ -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) {
@@ -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
}
}