Change Signature: Support conversion between extension and non-extension functions
This commit is contained in:
@@ -54,3 +54,25 @@ fun setTypeReference(declaration: JetCallableDeclaration, addAfter: PsiElement?,
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun JetCallableDeclaration.setReceiverTypeReference(typeRef: JetTypeReference?): JetTypeReference? {
|
||||||
|
val oldTypeRef = getReceiverTypeReference()
|
||||||
|
if (typeRef != null) {
|
||||||
|
if (oldTypeRef != null) {
|
||||||
|
return oldTypeRef.replace(typeRef) as JetTypeReference
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val anchor = getNameIdentifier()
|
||||||
|
val newTypeRef = addBefore(typeRef, anchor) as JetTypeReference
|
||||||
|
addAfter(JetPsiFactory(getProject()).createDot(), newTypeRef)
|
||||||
|
return newTypeRef
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (oldTypeRef != null) {
|
||||||
|
val dot = oldTypeRef.siblings(forward = true).firstOrNull { it.getNode().getElementType() == JetTokens.DOT }
|
||||||
|
deleteChildRange(oldTypeRef, dot ?: oldTypeRef)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,21 +17,28 @@
|
|||||||
package org.jetbrains.kotlin.idea.refactoring.changeSignature
|
package org.jetbrains.kotlin.idea.refactoring.changeSignature
|
||||||
|
|
||||||
import com.intellij.lang.Language
|
import com.intellij.lang.Language
|
||||||
|
import com.intellij.openapi.util.text.StringUtil
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiMethod
|
import com.intellij.psi.PsiMethod
|
||||||
import com.intellij.psi.PsiModifier
|
import com.intellij.psi.PsiModifier
|
||||||
import com.intellij.psi.PsiType
|
import com.intellij.psi.PsiType
|
||||||
import com.intellij.refactoring.changeSignature.*
|
import com.intellij.refactoring.changeSignature.*
|
||||||
import com.intellij.usageView.UsageInfo
|
import com.intellij.usageView.UsageInfo
|
||||||
|
import com.intellij.util.Function
|
||||||
import com.intellij.util.VisibilityUtil
|
import com.intellij.util.VisibilityUtil
|
||||||
|
import com.intellij.util.containers.ContainerUtil
|
||||||
|
import kotlin.Function1
|
||||||
|
import kotlin.Pair
|
||||||
import org.jetbrains.kotlin.asJava.*
|
import org.jetbrains.kotlin.asJava.*
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
import org.jetbrains.kotlin.descriptors.Visibility
|
import org.jetbrains.kotlin.descriptors.Visibility
|
||||||
import org.jetbrains.kotlin.psi.JetFunction
|
import org.jetbrains.kotlin.psi.JetFunction
|
||||||
import org.jetbrains.kotlin.psi.JetFunctionLiteral
|
import org.jetbrains.kotlin.psi.JetFunctionLiteral
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||||
import org.jetbrains.kotlin.types.JetType
|
import org.jetbrains.kotlin.types.JetType
|
||||||
|
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.lexer.JetTokens
|
import org.jetbrains.kotlin.lexer.JetTokens
|
||||||
import org.jetbrains.kotlin.idea.JetLanguage
|
import org.jetbrains.kotlin.idea.JetLanguage
|
||||||
@@ -40,6 +47,9 @@ import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.JetFunctionD
|
|||||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||||
import java.util.HashMap
|
import java.util.HashMap
|
||||||
import kotlin.properties.Delegates
|
import kotlin.properties.Delegates
|
||||||
|
import java.util.ArrayList
|
||||||
|
import java.util.Collections
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList
|
||||||
|
|
||||||
public class JetChangeInfo(
|
public class JetChangeInfo(
|
||||||
val methodDescriptor: JetMethodDescriptor,
|
val methodDescriptor: JetMethodDescriptor,
|
||||||
@@ -48,8 +58,17 @@ public class JetChangeInfo(
|
|||||||
var newReturnTypeText: String,
|
var newReturnTypeText: String,
|
||||||
var newVisibility: Visibility,
|
var newVisibility: Visibility,
|
||||||
parameterInfos: List<JetParameterInfo>,
|
parameterInfos: List<JetParameterInfo>,
|
||||||
|
receiver: JetParameterInfo?,
|
||||||
val context: PsiElement
|
val context: PsiElement
|
||||||
): ChangeInfo {
|
): ChangeInfo {
|
||||||
|
var receiverParameterInfo: JetParameterInfo? = receiver
|
||||||
|
set(value: JetParameterInfo?) {
|
||||||
|
if (value != null && value !in newParameters) {
|
||||||
|
newParameters.add(value)
|
||||||
|
}
|
||||||
|
$receiverParameterInfo = value
|
||||||
|
}
|
||||||
|
|
||||||
private val newParameters = parameterInfos.toArrayList()
|
private val newParameters = parameterInfos.toArrayList()
|
||||||
private val originalPsiMethod: PsiMethod? = getCurrentPsiMethod()
|
private val originalPsiMethod: PsiMethod? = getCurrentPsiMethod()
|
||||||
|
|
||||||
@@ -63,8 +82,10 @@ public class JetChangeInfo(
|
|||||||
}
|
}
|
||||||
|
|
||||||
public val isParameterSetOrOrderChanged: Boolean by Delegates.lazy {
|
public val isParameterSetOrOrderChanged: Boolean by Delegates.lazy {
|
||||||
newParameters.size() != methodDescriptor.getParametersCount() ||
|
val signatureParameters = getNonReceiverParameters()
|
||||||
newParameters.indices.any { i -> newParameters.get(i).getOldIndex() != i }
|
methodDescriptor.receiver != receiverParameterInfo ||
|
||||||
|
signatureParameters.size() != methodDescriptor.getParametersCount() ||
|
||||||
|
signatureParameters.indices.any { i -> signatureParameters[i].getOldIndex() != i }
|
||||||
}
|
}
|
||||||
|
|
||||||
private var isPrimaryMethodUpdated: Boolean = false
|
private var isPrimaryMethodUpdated: Boolean = false
|
||||||
@@ -88,6 +109,12 @@ public class JetChangeInfo(
|
|||||||
|
|
||||||
override fun getNewParameters(): Array<JetParameterInfo> = newParameters.copyToArray()
|
override fun getNewParameters(): Array<JetParameterInfo> = newParameters.copyToArray()
|
||||||
|
|
||||||
|
fun getNonReceiverParametersCount(): Int = newParameters.size() - (if (receiverParameterInfo != null) 1 else 0)
|
||||||
|
|
||||||
|
fun getNonReceiverParameters(): List<JetParameterInfo> {
|
||||||
|
return receiverParameterInfo?.let { receiver -> newParameters.filter { it != receiver } } ?: newParameters
|
||||||
|
}
|
||||||
|
|
||||||
public fun setNewParameter(index: Int, parameterInfo: JetParameterInfo) {
|
public fun setNewParameter(index: Int, parameterInfo: JetParameterInfo) {
|
||||||
newParameters.set(index, parameterInfo)
|
newParameters.set(index, parameterInfo)
|
||||||
}
|
}
|
||||||
@@ -97,9 +124,15 @@ public class JetChangeInfo(
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fun removeParameter(index: Int) {
|
public fun removeParameter(index: Int) {
|
||||||
newParameters.remove(index);
|
val parameterInfo = newParameters.remove(index);
|
||||||
|
if (parameterInfo == receiverParameterInfo) {
|
||||||
|
receiverParameterInfo = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fun hasParameter(parameterInfo: JetParameterInfo): Boolean =
|
||||||
|
parameterInfo in newParameters
|
||||||
|
|
||||||
override fun isGenerateDelegate(): Boolean = false
|
override fun isGenerateDelegate(): Boolean = false
|
||||||
|
|
||||||
override fun getNewName(): String = name
|
override fun getNewName(): String = name
|
||||||
@@ -118,6 +151,8 @@ public class JetChangeInfo(
|
|||||||
|
|
||||||
override fun isReturnTypeChanged(): Boolean = newReturnTypeText != methodDescriptor.renderOriginalReturnType()
|
override fun isReturnTypeChanged(): Boolean = newReturnTypeText != methodDescriptor.renderOriginalReturnType()
|
||||||
|
|
||||||
|
fun isReceiverTypeChanged(): Boolean = receiverParameterInfo?.getTypeText() != methodDescriptor.renderOriginalReceiverType()
|
||||||
|
|
||||||
override fun getLanguage(): Language = JetLanguage.INSTANCE
|
override fun getLanguage(): Language = JetLanguage.INSTANCE
|
||||||
|
|
||||||
public fun getNewSignature(inheritedFunction: JetFunctionDefinitionUsage<PsiElement>): String {
|
public fun getNewSignature(inheritedFunction: JetFunctionDefinitionUsage<PsiElement>): String {
|
||||||
@@ -135,9 +170,15 @@ public class JetChangeInfo(
|
|||||||
buffer.append(newVisibility).append(' ')
|
buffer.append(newVisibility).append(' ')
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.append(JetTokens.FUN_KEYWORD).append(' ').append(name)
|
buffer.append(JetTokens.FUN_KEYWORD).append(' ')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
receiverParameterInfo?.let {
|
||||||
|
buffer.append(it.currentTypeText).append('.')
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer.append(name)
|
||||||
|
|
||||||
buffer.append(getNewParametersSignature(inheritedFunction))
|
buffer.append(getNewParametersSignature(inheritedFunction))
|
||||||
|
|
||||||
if (newReturnType != null && !KotlinBuiltIns.isUnit(newReturnType) && !isConstructor)
|
if (newReturnType != null && !KotlinBuiltIns.isUnit(newReturnType) && !isConstructor)
|
||||||
@@ -152,16 +193,25 @@ public class JetChangeInfo(
|
|||||||
}
|
}
|
||||||
|
|
||||||
public fun getNewParametersSignature(inheritedFunction: JetFunctionDefinitionUsage<PsiElement>): String {
|
public fun getNewParametersSignature(inheritedFunction: JetFunctionDefinitionUsage<PsiElement>): String {
|
||||||
|
val signatureParameters = getNonReceiverParameters()
|
||||||
|
|
||||||
val isLambda = inheritedFunction.getDeclaration() is JetFunctionLiteral
|
val isLambda = inheritedFunction.getDeclaration() is JetFunctionLiteral
|
||||||
if (isLambda && newParameters.size() == 1 && !newParameters.get(0).requiresExplicitType(inheritedFunction)) {
|
if (isLambda && signatureParameters.size() == 1 && !signatureParameters.get(0).requiresExplicitType(inheritedFunction)) {
|
||||||
return newParameters.get(0).getDeclarationSignature(0, inheritedFunction)
|
return signatureParameters.get(0).getDeclarationSignature(0, inheritedFunction)
|
||||||
}
|
}
|
||||||
|
|
||||||
return newParameters.indices
|
return signatureParameters.indices
|
||||||
.map { i -> newParameters[i].getDeclarationSignature(i, inheritedFunction) }
|
.map { i -> signatureParameters[i].getDeclarationSignature(i, inheritedFunction) }
|
||||||
.joinToString(prefix = "(", separator = ", ", postfix = ")")
|
.joinToString(prefix = "(", separator = ", ", postfix = ")")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public fun renderReceiverType(inheritedFunction: JetFunctionDefinitionUsage<PsiElement>): String? {
|
||||||
|
val receiverTypeText = receiverParameterInfo?.currentTypeText ?: return null
|
||||||
|
val typeSubstitutor = inheritedFunction.getOrCreateTypeSubstitutor() ?: return receiverTypeText
|
||||||
|
val currentBaseFunction = inheritedFunction.getBaseFunction().getCurrentFunctionDescriptor() ?: return receiverTypeText
|
||||||
|
return currentBaseFunction.getExtensionReceiverParameter()!!.getType().renderTypeWithSubstitution(typeSubstitutor, receiverTypeText, false)
|
||||||
|
}
|
||||||
|
|
||||||
public fun renderReturnType(inheritedFunction: JetFunctionDefinitionUsage<PsiElement>): String {
|
public fun renderReturnType(inheritedFunction: JetFunctionDefinitionUsage<PsiElement>): String {
|
||||||
val typeSubstitutor = inheritedFunction.getOrCreateTypeSubstitutor() ?: return newReturnTypeText
|
val typeSubstitutor = inheritedFunction.getOrCreateTypeSubstitutor() ?: return newReturnTypeText
|
||||||
val currentBaseFunction = inheritedFunction.getBaseFunction().getCurrentFunctionDescriptor() ?: return newReturnTypeText
|
val currentBaseFunction = inheritedFunction.getBaseFunction().getCurrentFunctionDescriptor() ?: return newReturnTypeText
|
||||||
@@ -190,13 +240,24 @@ public class JetChangeInfo(
|
|||||||
else
|
else
|
||||||
PsiModifier.PACKAGE_LOCAL
|
PsiModifier.PACKAGE_LOCAL
|
||||||
|
|
||||||
val newJavaParameters = newParameters.withIndex().map { pair ->
|
val newParameterList = receiverParameterInfo.singletonOrEmptyList() + getNonReceiverParameters()
|
||||||
|
val newJavaParameters = newParameterList.withIndex().map { pair ->
|
||||||
val (i, info) = pair
|
val (i, info) = pair
|
||||||
|
|
||||||
val type = if (isPrimaryMethodUpdated)
|
val type = if (isPrimaryMethodUpdated)
|
||||||
currentPsiMethod.getParameterList().getParameters()[i].getType()
|
currentPsiMethod.getParameterList().getParameters()[i].getType()
|
||||||
else
|
else
|
||||||
PsiType.VOID
|
PsiType.VOID
|
||||||
ParameterInfoImpl(info.getOldIndex(), info.getName(), type, info.defaultValueForCall)
|
|
||||||
|
val oldIndex = info.getOldIndex()
|
||||||
|
val javaOldIndex = when {
|
||||||
|
methodDescriptor.receiver == null -> oldIndex
|
||||||
|
info == methodDescriptor.receiver -> 0
|
||||||
|
oldIndex >= 0 -> oldIndex + 1
|
||||||
|
else -> -1
|
||||||
|
}
|
||||||
|
|
||||||
|
ParameterInfoImpl(javaOldIndex, info.getName(), type, info.defaultValueForCall)
|
||||||
}.copyToArray()
|
}.copyToArray()
|
||||||
|
|
||||||
val returnType = if (isPrimaryMethodUpdated) currentPsiMethod.getReturnType() else PsiType.VOID
|
val returnType = if (isPrimaryMethodUpdated) currentPsiMethod.getReturnType() else PsiType.VOID
|
||||||
@@ -257,5 +318,6 @@ public fun ChangeInfo.toJetChangeInfo(originalChangeSignatureDescriptor: JetMeth
|
|||||||
returnTypeText,
|
returnTypeText,
|
||||||
functionDescriptor.getVisibility(),
|
functionDescriptor.getVisibility(),
|
||||||
newParameters,
|
newParameters,
|
||||||
|
null,
|
||||||
method)
|
method)
|
||||||
}
|
}
|
||||||
+42
-13
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2015 JetBrains s.r.o.
|
* Copyright 2010-2014 JetBrains s.r.o.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -32,6 +32,10 @@ import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.JetFunctionD
|
|||||||
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.properties.Delegates
|
import kotlin.properties.Delegates
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.CollectingValidator
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.JetNameSuggester
|
||||||
|
|
||||||
public class JetChangeSignatureData(
|
public class JetChangeSignatureData(
|
||||||
override val baseDescriptor: FunctionDescriptor,
|
override val baseDescriptor: FunctionDescriptor,
|
||||||
@@ -39,24 +43,49 @@ public class JetChangeSignatureData(
|
|||||||
private val descriptorsForSignatureChange: Collection<FunctionDescriptor>
|
private val descriptorsForSignatureChange: Collection<FunctionDescriptor>
|
||||||
) : JetMethodDescriptor {
|
) : JetMethodDescriptor {
|
||||||
private val parameters: MutableList<JetParameterInfo>
|
private val parameters: MutableList<JetParameterInfo>
|
||||||
|
override var receiver: JetParameterInfo?
|
||||||
|
set(value: JetParameterInfo?) {
|
||||||
|
if (value != null && value !in parameters) {
|
||||||
|
parameters.add(value)
|
||||||
|
}
|
||||||
|
$receiver = value
|
||||||
|
}
|
||||||
|
|
||||||
|
;{
|
||||||
|
$receiver = createReceiverInfoIfNeeded()
|
||||||
|
|
||||||
;{
|
|
||||||
val valueParameters = when {
|
val valueParameters = when {
|
||||||
baseDeclaration is JetFunction -> baseDeclaration.getValueParameters()
|
baseDeclaration is JetFunction -> baseDeclaration.getValueParameters()
|
||||||
baseDeclaration is JetClass -> baseDeclaration.getPrimaryConstructorParameters()
|
baseDeclaration is JetClass -> baseDeclaration.getPrimaryConstructorParameters()
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
parameters = baseDescriptor.getValueParameters().mapTo(ArrayList()) { parameterDescriptor ->
|
parameters = baseDescriptor.getValueParameters()
|
||||||
val jetParameter = valueParameters?.get(parameterDescriptor.getIndex())
|
.mapTo(receiver?.let{ arrayListOf(it) } ?: arrayListOf()) { parameterDescriptor ->
|
||||||
JetParameterInfo(
|
val jetParameter = valueParameters?.get(parameterDescriptor.getIndex())
|
||||||
originalIndex = parameterDescriptor.getIndex(),
|
JetParameterInfo(
|
||||||
name = parameterDescriptor.getName().asString(),
|
originalIndex = parameterDescriptor.getIndex(),
|
||||||
type = parameterDescriptor.getType(),
|
name = parameterDescriptor.getName().asString(),
|
||||||
defaultValueForParameter = jetParameter?.getDefaultValue(),
|
type = parameterDescriptor.getType(),
|
||||||
valOrVarNode = jetParameter?.getValOrVarNode(),
|
defaultValueForParameter = jetParameter?.getDefaultValue(),
|
||||||
modifierList = jetParameter?.getModifierList()
|
valOrVarNode = jetParameter?.getValOrVarNode(),
|
||||||
)
|
modifierList = jetParameter?.getModifierList()
|
||||||
}
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createReceiverInfoIfNeeded(): JetParameterInfo? {
|
||||||
|
val function = baseDeclaration as? JetFunction ?: return null
|
||||||
|
val bodyScope = function.getBodyExpression()?.let { it.analyze()[BindingContext.RESOLUTION_SCOPE, it] }
|
||||||
|
val paramNames = baseDescriptor.getValueParameters().map { it.getName().asString() }
|
||||||
|
val validator = bodyScope?.let { bodyScope ->
|
||||||
|
CollectingValidator(paramNames) {
|
||||||
|
val name = Name.identifier(it)
|
||||||
|
bodyScope.getLocalVariable(name) == null && bodyScope.getProperties(name).isEmpty()
|
||||||
|
}
|
||||||
|
} ?: CollectingValidator(paramNames)
|
||||||
|
val receiverType = baseDescriptor.getExtensionReceiverParameter()?.getType() ?: return null
|
||||||
|
val receiverName = JetNameSuggester.suggestNames(receiverType, validator, "receiver").first()
|
||||||
|
return JetParameterInfo(name = receiverName, type = receiverType)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val primaryFunctions: Collection<JetFunctionDefinitionUsage<PsiElement>> by Delegates.lazy {
|
override val primaryFunctions: Collection<JetFunctionDefinitionUsage<PsiElement>> by Delegates.lazy {
|
||||||
|
|||||||
+1
-1
@@ -420,7 +420,7 @@ public class JetChangeSignatureDialog extends ChangeSignatureDialogBase<
|
|||||||
|
|
||||||
String returnTypeText = myReturnTypeCodeFragment != null ? myReturnTypeCodeFragment.getText().trim() : "";
|
String returnTypeText = myReturnTypeCodeFragment != null ? myReturnTypeCodeFragment.getText().trim() : "";
|
||||||
return new JetChangeInfo(myMethod, getMethodName(), getReturnType(), returnTypeText,
|
return new JetChangeInfo(myMethod, getMethodName(), getReturnType(), returnTypeText,
|
||||||
getVisibility(), parameters, myDefaultValueContext
|
getVisibility(), parameters, null, myDefaultValueContext
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+201
-5
@@ -25,31 +25,43 @@ import com.intellij.psi.search.searches.ReferencesSearch;
|
|||||||
import com.intellij.psi.util.PsiTreeUtil;
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
import com.intellij.refactoring.changeSignature.*;
|
import com.intellij.refactoring.changeSignature.*;
|
||||||
import com.intellij.refactoring.rename.ResolveSnapshotProvider;
|
import com.intellij.refactoring.rename.ResolveSnapshotProvider;
|
||||||
|
import com.intellij.refactoring.util.CommonRefactoringUtil;
|
||||||
import com.intellij.refactoring.util.MoveRenameUsageInfo;
|
import com.intellij.refactoring.util.MoveRenameUsageInfo;
|
||||||
|
import com.intellij.refactoring.util.RefactoringUIUtil;
|
||||||
import com.intellij.refactoring.util.TextOccurrencesUtil;
|
import com.intellij.refactoring.util.TextOccurrencesUtil;
|
||||||
import com.intellij.usageView.UsageInfo;
|
import com.intellij.usageView.UsageInfo;
|
||||||
import com.intellij.util.Function;
|
import com.intellij.util.Function;
|
||||||
import com.intellij.util.containers.ContainerUtil;
|
import com.intellij.util.containers.ContainerUtil;
|
||||||
import com.intellij.util.containers.HashSet;
|
import com.intellij.util.containers.HashSet;
|
||||||
import com.intellij.util.containers.MultiMap;
|
import com.intellij.util.containers.MultiMap;
|
||||||
|
import kotlin.Function1;
|
||||||
|
import kotlin.KotlinPackage;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage;
|
import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage;
|
||||||
|
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToDeclarationUtil;
|
||||||
|
import org.jetbrains.kotlin.idea.codeInsight.JetFileReferencesResolver;
|
||||||
import org.jetbrains.kotlin.idea.refactoring.RefactoringPackage;
|
import org.jetbrains.kotlin.idea.refactoring.RefactoringPackage;
|
||||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.*;
|
import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.*;
|
||||||
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference;
|
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference;
|
||||||
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
|
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
|
||||||
import org.jetbrains.kotlin.name.Name;
|
import org.jetbrains.kotlin.name.Name;
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
|
import org.jetbrains.kotlin.psi.typeRefHelpers.TypeRefHelpersPackage;
|
||||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
|
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage;
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||||
import org.jetbrains.kotlin.resolve.scopes.JetScope;
|
import org.jetbrains.kotlin.resolve.scopes.JetScope;
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ThisReceiver;
|
||||||
import org.jetbrains.kotlin.types.JetType;
|
import org.jetbrains.kotlin.types.JetType;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsageProcessor {
|
public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsageProcessor {
|
||||||
@@ -79,7 +91,7 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void findOneMethodUsages(
|
private static void findOneMethodUsages(
|
||||||
@NotNull JetFunctionDefinitionUsage functionUsageInfo,
|
@NotNull JetFunctionDefinitionUsage<?> functionUsageInfo,
|
||||||
JetChangeInfo changeInfo,
|
JetChangeInfo changeInfo,
|
||||||
Set<UsageInfo> result
|
Set<UsageInfo> result
|
||||||
) {
|
) {
|
||||||
@@ -92,7 +104,6 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
|
|||||||
PsiElement functionPsi = functionUsageInfo.getElement();
|
PsiElement functionPsi = functionUsageInfo.getElement();
|
||||||
if (functionPsi == null) return;
|
if (functionPsi == null) return;
|
||||||
|
|
||||||
|
|
||||||
for (PsiReference reference : ReferencesSearch.search(functionPsi, functionPsi.getUseScope())) {
|
for (PsiReference reference : ReferencesSearch.search(functionPsi, functionPsi.getUseScope())) {
|
||||||
PsiElement element = reference.getElement();
|
PsiElement element = reference.getElement();
|
||||||
|
|
||||||
@@ -119,12 +130,14 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
|
|||||||
? ((JetFunction) functionPsi).getValueParameters()
|
? ((JetFunction) functionPsi).getValueParameters()
|
||||||
: ((JetClass) functionPsi).getPrimaryConstructorParameters();
|
: ((JetClass) functionPsi).getPrimaryConstructorParameters();
|
||||||
|
|
||||||
|
JetParameterInfo newReceiverInfo = changeInfo.getReceiverParameterInfo();
|
||||||
|
|
||||||
for (JetParameterInfo parameterInfo : changeInfo.getNewParameters()) {
|
for (JetParameterInfo parameterInfo : changeInfo.getNewParameters()) {
|
||||||
if (parameterInfo.getOldIndex() >= 0 && parameterInfo.getOldIndex() < oldParameters.size()) {
|
if (parameterInfo.getOldIndex() >= 0 && parameterInfo.getOldIndex() < oldParameters.size()) {
|
||||||
JetParameter oldParam = oldParameters.get(parameterInfo.getOldIndex());
|
JetParameter oldParam = oldParameters.get(parameterInfo.getOldIndex());
|
||||||
String oldParamName = oldParam.getName();
|
String oldParamName = oldParam.getName();
|
||||||
|
|
||||||
if (oldParamName != null && !oldParamName.equals(parameterInfo.getName())) {
|
if (parameterInfo == newReceiverInfo || (oldParamName != null && !oldParamName.equals(parameterInfo.getName()))) {
|
||||||
for (PsiReference reference : ReferencesSearch.search(oldParam, oldParam.getUseScope())) {
|
for (PsiReference reference : ReferencesSearch.search(oldParam, oldParam.getUseScope())) {
|
||||||
PsiElement element = reference.getElement();
|
PsiElement element = reference.getElement();
|
||||||
|
|
||||||
@@ -140,6 +153,10 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (functionPsi instanceof JetFunction && newReceiverInfo != changeInfo.getMethodDescriptor().getReceiver()) {
|
||||||
|
findOriginalReceiversUsages(functionUsageInfo, result, changeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
if (functionPsi instanceof JetClass && ((JetClass) functionPsi).isEnum()) {
|
if (functionPsi instanceof JetClass && ((JetClass) functionPsi).isEnum()) {
|
||||||
for (JetDeclaration declaration : ((JetClass) functionPsi).getDeclarations()) {
|
for (JetDeclaration declaration : ((JetClass) functionPsi).getDeclarations()) {
|
||||||
if (declaration instanceof JetEnumEntry && ((JetEnumEntry) declaration).getDelegationSpecifierList() == null) {
|
if (declaration instanceof JetEnumEntry && ((JetEnumEntry) declaration).getDelegationSpecifierList() == null) {
|
||||||
@@ -149,6 +166,90 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void processInternalReferences(
|
||||||
|
JetFunctionDefinitionUsage functionUsageInfo,
|
||||||
|
JetTreeVisitor<BindingContext> visitor
|
||||||
|
) {
|
||||||
|
JetFunction jetFunction = (JetFunction) functionUsageInfo.getDeclaration();
|
||||||
|
JetExpression body = jetFunction.getBodyExpression();
|
||||||
|
if (body != null) {
|
||||||
|
body.accept(visitor, ResolvePackage.analyze(body));
|
||||||
|
}
|
||||||
|
for (JetParameter parameter : jetFunction.getValueParameters()) {
|
||||||
|
JetExpression defaultValue = parameter.getDefaultValue();
|
||||||
|
if (defaultValue != null) {
|
||||||
|
defaultValue.accept(visitor, ResolvePackage.analyze(defaultValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void findOriginalReceiversUsages(
|
||||||
|
@NotNull final JetFunctionDefinitionUsage<?> functionUsageInfo,
|
||||||
|
@NotNull final Set<UsageInfo> result,
|
||||||
|
@NotNull final JetChangeInfo changeInfo
|
||||||
|
) {
|
||||||
|
final JetParameterInfo originalReceiverInfo = changeInfo.getMethodDescriptor().getReceiver();
|
||||||
|
final FunctionDescriptor functionDescriptor = functionUsageInfo.getOriginalFunctionDescriptor();
|
||||||
|
processInternalReferences(
|
||||||
|
functionUsageInfo,
|
||||||
|
new JetTreeVisitor<BindingContext>() {
|
||||||
|
private void processExplicitThis(
|
||||||
|
@NotNull JetSimpleNameExpression expression,
|
||||||
|
@NotNull ReceiverParameterDescriptor receiverDescriptor
|
||||||
|
) {
|
||||||
|
if (originalReceiverInfo != null && !changeInfo.hasParameter(originalReceiverInfo)) return;
|
||||||
|
if (!(expression.getParent() instanceof JetThisExpression)) return;
|
||||||
|
|
||||||
|
if (receiverDescriptor == functionDescriptor.getExtensionReceiverParameter()) {
|
||||||
|
assert originalReceiverInfo != null : "No original receiver info provided: " + functionUsageInfo.getDeclaration().getText();
|
||||||
|
result.add(new JetParameterUsage(expression, originalReceiverInfo, functionUsageInfo));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ClassifierDescriptor targetDescriptor = receiverDescriptor.getType().getConstructor().getDeclarationDescriptor();
|
||||||
|
assert targetDescriptor != null : "Receiver type has no descriptor: " + functionUsageInfo.getDeclaration().getText();
|
||||||
|
result.add(new JetNonQualifiedOuterThisUsage((JetThisExpression) expression.getParent(), targetDescriptor));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processImplicitThis(
|
||||||
|
@NotNull JetElement callElement,
|
||||||
|
@NotNull ThisReceiver receiverValue
|
||||||
|
) {
|
||||||
|
DeclarationDescriptor targetDescriptor = receiverValue.getDeclarationDescriptor();
|
||||||
|
if (targetDescriptor == functionDescriptor) {
|
||||||
|
assert originalReceiverInfo != null : "No original receiver info provided: " + functionUsageInfo.getDeclaration().getText();
|
||||||
|
result.add(new JetImplicitThisToParameterUsage(callElement, originalReceiverInfo, functionUsageInfo));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result.add(new JetImplicitOuterThisToQualifiedThisUsage(callElement, targetDescriptor));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Void visitSimpleNameExpression(@NotNull JetSimpleNameExpression expression, BindingContext context) {
|
||||||
|
ResolvedCall<? extends CallableDescriptor> resolvedCall = CallUtilPackage.getResolvedCall(expression, context);
|
||||||
|
if (resolvedCall == null) return null;
|
||||||
|
|
||||||
|
CallableDescriptor resultingDescriptor = resolvedCall.getResultingDescriptor();
|
||||||
|
if (resultingDescriptor instanceof ReceiverParameterDescriptor) {
|
||||||
|
processExplicitThis(expression, (ReceiverParameterDescriptor) resultingDescriptor);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReceiverValue receiverValue = resolvedCall.getExtensionReceiver();
|
||||||
|
if (!(receiverValue instanceof ThisReceiver)) {
|
||||||
|
receiverValue = resolvedCall.getDispatchReceiver();
|
||||||
|
}
|
||||||
|
if (receiverValue instanceof ThisReceiver) {
|
||||||
|
processImplicitThis(resolvedCall.getCall().getCallElement(), (ThisReceiver) receiverValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private static void findSAMUsages(ChangeInfo changeInfo, Set<UsageInfo> result) {
|
private static void findSAMUsages(ChangeInfo changeInfo, Set<UsageInfo> result) {
|
||||||
PsiElement method = changeInfo.getMethod();
|
PsiElement method = changeInfo.getMethod();
|
||||||
if (!RefactoringPackage.isTrueJavaMethod(method)) return;
|
if (!RefactoringPackage.isTrueJavaMethod(method)) return;
|
||||||
@@ -203,9 +304,9 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
|
|||||||
PsiElement element = function != null ? function : changeInfo.getContext();
|
PsiElement element = function != null ? function : changeInfo.getContext();
|
||||||
BindingContext bindingContext = ResolvePackage.analyze((JetElement) element);
|
BindingContext bindingContext = ResolvePackage.analyze((JetElement) element);
|
||||||
FunctionDescriptor oldDescriptor = ChangeSignaturePackage.getOriginalBaseFunctionDescriptor(changeInfo);
|
FunctionDescriptor oldDescriptor = ChangeSignaturePackage.getOriginalBaseFunctionDescriptor(changeInfo);
|
||||||
JetScope parametersScope = null;
|
DeclarationDescriptor containingDeclaration = oldDescriptor.getContainingDeclaration();
|
||||||
DeclarationDescriptor containingDeclaration = oldDescriptor != null ? oldDescriptor.getContainingDeclaration() : null;
|
|
||||||
|
|
||||||
|
JetScope parametersScope = null;
|
||||||
if (oldDescriptor instanceof ConstructorDescriptor && containingDeclaration instanceof ClassDescriptorWithResolutionScopes)
|
if (oldDescriptor instanceof ConstructorDescriptor && containingDeclaration instanceof ClassDescriptorWithResolutionScopes)
|
||||||
parametersScope = ((ClassDescriptorWithResolutionScopes) containingDeclaration).getScopeForInitializerResolution();
|
parametersScope = ((ClassDescriptorWithResolutionScopes) containingDeclaration).getScopeForInitializerResolution();
|
||||||
else if (function instanceof JetFunction)
|
else if (function instanceof JetFunction)
|
||||||
@@ -256,9 +357,104 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JetParameterInfo newReceiverInfo = changeInfo.getReceiverParameterInfo();
|
||||||
|
JetParameterInfo originalReceiverInfo = changeInfo.getMethodDescriptor().getReceiver();
|
||||||
|
if (function instanceof JetNamedFunction && newReceiverInfo != originalReceiverInfo) {
|
||||||
|
findReceiverIntroducingConflicts(result, function, newReceiverInfo);
|
||||||
|
findInternalExplicitReceiverConflicts(refUsages.get(), result, originalReceiverInfo);
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void findInternalExplicitReceiverConflicts(
|
||||||
|
UsageInfo[] usages,
|
||||||
|
MultiMap<PsiElement, String> result,
|
||||||
|
JetParameterInfo originalReceiverInfo
|
||||||
|
) {
|
||||||
|
if (originalReceiverInfo == null) {
|
||||||
|
for (UsageInfo usageInfo : usages) {
|
||||||
|
if (!(usageInfo instanceof JetFunctionCallUsage)) continue;
|
||||||
|
|
||||||
|
JetFunctionCallUsage callUsage = (JetFunctionCallUsage) usageInfo;
|
||||||
|
JetElement callElement = callUsage.getElement();
|
||||||
|
if (callElement == null) continue;
|
||||||
|
|
||||||
|
PsiElement parent = callElement.getParent();
|
||||||
|
if (parent instanceof JetQualifiedExpression && ((JetQualifiedExpression) parent).getSelectorExpression() == callElement) {
|
||||||
|
String message = "Explicit receiver is already present in call element: " +
|
||||||
|
CommonRefactoringUtil.htmlEmphasize(parent.getText());
|
||||||
|
result.putValue(callElement, message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void findReceiverIntroducingConflicts(
|
||||||
|
MultiMap<PsiElement, String> result,
|
||||||
|
PsiElement callable,
|
||||||
|
JetParameterInfo newReceiverInfo
|
||||||
|
) {
|
||||||
|
if (newReceiverInfo != null && ((JetNamedFunction) callable).getBodyExpression() != null) {
|
||||||
|
Map<JetReferenceExpression, BindingContext> noReceiverRefToContext = KotlinPackage.filter(
|
||||||
|
JetFileReferencesResolver.INSTANCE$.resolve((JetNamedFunction) callable, true, true),
|
||||||
|
new Function1<Map.Entry<? extends JetReferenceExpression, ? extends BindingContext>, Boolean>() {
|
||||||
|
@Override
|
||||||
|
public Boolean invoke(Map.Entry<? extends JetReferenceExpression, ? extends BindingContext> entry) {
|
||||||
|
ResolvedCall<?> resolvedCall = CallUtilPackage.getResolvedCall(entry.getKey(), entry.getValue());
|
||||||
|
return resolvedCall != null
|
||||||
|
&& !resolvedCall.getDispatchReceiver().exists()
|
||||||
|
&& !resolvedCall.getExtensionReceiver().exists();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
JetPsiFactory psiFactory = new JetPsiFactory(callable.getProject());
|
||||||
|
JetFile tempFile = RefactoringPackage.createTempCopy(
|
||||||
|
(JetFile) callable.getContainingFile(),
|
||||||
|
new Function1<String, String>() {
|
||||||
|
@Override
|
||||||
|
public String invoke(String s) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
JetNamedFunction functionWithReceiver =
|
||||||
|
PsiTreeUtil.getParentOfType(tempFile.findElementAt(callable.getTextOffset()), JetNamedFunction.class);
|
||||||
|
JetTypeReference receiverTypeRef = psiFactory.createType(newReceiverInfo.getCurrentTypeText());
|
||||||
|
TypeRefHelpersPackage.setReceiverTypeReference(functionWithReceiver, receiverTypeRef);
|
||||||
|
//noinspection ConstantConditions
|
||||||
|
BindingContext newContext = ResolvePackage.analyze(functionWithReceiver.getBodyExpression());
|
||||||
|
|
||||||
|
//noinspection ConstantConditions
|
||||||
|
int originalOffset = ((JetNamedFunction) callable).getBodyExpression().getTextOffset();
|
||||||
|
JetExpression newBody = functionWithReceiver.getBodyExpression();
|
||||||
|
for (Map.Entry<JetReferenceExpression, BindingContext> entry : noReceiverRefToContext.entrySet()) {
|
||||||
|
JetReferenceExpression originalRef = entry.getKey();
|
||||||
|
BindingContext originalContext = entry.getValue();
|
||||||
|
//noinspection ConstantConditions
|
||||||
|
JetReferenceExpression newRef = PsiTreeUtil.getParentOfType(
|
||||||
|
newBody.findElementAt(originalRef.getTextOffset() - originalOffset),
|
||||||
|
JetReferenceExpression.class
|
||||||
|
);
|
||||||
|
ResolvedCall<?> newResolvedCall = CallUtilPackage.getResolvedCall(newRef, newContext);
|
||||||
|
if (newResolvedCall == null
|
||||||
|
|| newResolvedCall.getExtensionReceiver().exists()
|
||||||
|
|| newResolvedCall.getDispatchReceiver().exists()) {
|
||||||
|
//noinspection ConstantConditions
|
||||||
|
CallableDescriptor descriptor =
|
||||||
|
CallUtilPackage.getResolvedCall(originalRef, originalContext).getCandidateDescriptor();
|
||||||
|
PsiElement declaration = DescriptorToDeclarationUtil.INSTANCE$.getDeclaration(callable.getProject(), descriptor);
|
||||||
|
String prefix = declaration != null ? RefactoringUIUtil.getDescription(declaration, true) : originalRef.getText();
|
||||||
|
result.putValue(
|
||||||
|
originalRef,
|
||||||
|
KotlinPackage.capitalize(prefix + " will no longer be accessible after signature change")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static List<JetType> getFunctionParameterTypes(FunctionDescriptor descriptor) {
|
private static List<JetType> getFunctionParameterTypes(FunctionDescriptor descriptor) {
|
||||||
return ContainerUtil.map(descriptor.getValueParameters(), new Function<ValueParameterDescriptor, JetType>() {
|
return ContainerUtil.map(descriptor.getValueParameters(), new Function<ValueParameterDescriptor, JetType>() {
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+6
-1
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2015 JetBrains s.r.o.
|
* Copyright 2010-2014 JetBrains s.r.o.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -32,6 +32,8 @@ public trait JetMethodDescriptor : MethodDescriptor<JetParameterInfo, Visibility
|
|||||||
val originalPrimaryFunction: JetFunctionDefinitionUsage<PsiElement>
|
val originalPrimaryFunction: JetFunctionDefinitionUsage<PsiElement>
|
||||||
val primaryFunctions: Collection<JetFunctionDefinitionUsage<PsiElement>>
|
val primaryFunctions: Collection<JetFunctionDefinitionUsage<PsiElement>>
|
||||||
val affectedFunctions: Collection<UsageInfo>
|
val affectedFunctions: Collection<UsageInfo>
|
||||||
|
|
||||||
|
val receiver: JetParameterInfo?
|
||||||
}
|
}
|
||||||
|
|
||||||
val JetMethodDescriptor.isConstructor: Boolean
|
val JetMethodDescriptor.isConstructor: Boolean
|
||||||
@@ -39,3 +41,6 @@ val JetMethodDescriptor.isConstructor: Boolean
|
|||||||
|
|
||||||
fun JetMethodDescriptor.renderOriginalReturnType(): String =
|
fun JetMethodDescriptor.renderOriginalReturnType(): String =
|
||||||
baseDescriptor.getReturnType()?.let { IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(it) } ?: ""
|
baseDescriptor.getReturnType()?.let { IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(it) } ?: ""
|
||||||
|
|
||||||
|
fun JetMethodDescriptor.renderOriginalReceiverType(): String? =
|
||||||
|
baseDescriptor.getExtensionReceiverParameter()?.getType()?.let { IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(it) }
|
||||||
+91
-17
@@ -18,9 +18,19 @@ package org.jetbrains.kotlin.idea.refactoring.changeSignature.usages;
|
|||||||
|
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage;
|
||||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeInfo;
|
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeInfo;
|
||||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetParameterInfo;
|
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetParameterInfo;
|
||||||
import org.jetbrains.kotlin.psi.*;
|
import org.jetbrains.kotlin.psi.*;
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage;
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||||
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ThisReceiver;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -29,42 +39,48 @@ import java.util.Map;
|
|||||||
import static org.jetbrains.kotlin.psi.PsiPackage.JetPsiFactory;
|
import static org.jetbrains.kotlin.psi.PsiPackage.JetPsiFactory;
|
||||||
|
|
||||||
public class JetFunctionCallUsage extends JetUsageInfo<JetCallElement> {
|
public class JetFunctionCallUsage extends JetUsageInfo<JetCallElement> {
|
||||||
private final JetFunctionDefinitionUsage callee;
|
private final JetFunctionDefinitionUsage<?> callee;
|
||||||
|
private final ResolvedCall<? extends CallableDescriptor> resolvedCall;
|
||||||
|
|
||||||
public JetFunctionCallUsage(@NotNull JetCallElement element, JetFunctionDefinitionUsage callee) {
|
public JetFunctionCallUsage(@NotNull JetCallElement element, JetFunctionDefinitionUsage callee) {
|
||||||
super(element);
|
super(element);
|
||||||
this.callee = callee;
|
this.callee = callee;
|
||||||
|
this.resolvedCall = CallUtilPackage.getResolvedCall(element, ResolvePackage.analyze(element));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean processUsage(JetChangeInfo changeInfo, JetCallElement element) {
|
public boolean processUsage(JetChangeInfo changeInfo, JetCallElement element) {
|
||||||
JetValueArgumentList arguments = element.getValueArgumentList();
|
|
||||||
|
|
||||||
if (changeInfo.isNameChanged()) {
|
if (changeInfo.isNameChanged()) {
|
||||||
JetExpression callee = element.getCalleeExpression();
|
JetExpression callee = element.getCalleeExpression();
|
||||||
|
|
||||||
if (callee instanceof JetSimpleNameExpression)
|
if (callee instanceof JetSimpleNameExpression) {
|
||||||
callee.replace(JetPsiFactory(getProject()).createSimpleName(changeInfo.getNewName()));
|
callee.replace(JetPsiFactory(getProject()).createSimpleName(changeInfo.getNewName()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arguments != null) {
|
if (element.getValueArgumentList() != null) {
|
||||||
List<JetValueArgument> oldArguments = arguments.getArguments();
|
if (changeInfo.isParameterSetOrOrderChanged()) {
|
||||||
|
updateArgumentsAndReceiver(changeInfo, element);
|
||||||
if (changeInfo.isParameterSetOrOrderChanged())
|
}
|
||||||
arguments.replace(generateNewArgumentList(changeInfo, oldArguments));
|
else {
|
||||||
else
|
changeArgumentNames(changeInfo, element);
|
||||||
changeArgumentNames(changeInfo, oldArguments);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private JetValueArgumentList generateNewArgumentList(JetChangeInfo changeInfo, List<JetValueArgument> oldArguments) {
|
private void updateArgumentsAndReceiver(JetChangeInfo changeInfo, JetCallElement element) {
|
||||||
|
JetValueArgumentList arguments = element.getValueArgumentList();
|
||||||
|
assert arguments != null : "Argument list is expected: " + element.getText();
|
||||||
|
List<JetValueArgument> oldArguments = arguments.getArguments();
|
||||||
|
|
||||||
boolean isNamedCall = oldArguments.size() > 1 && oldArguments.get(0).getArgumentName() != null;
|
boolean isNamedCall = oldArguments.size() > 1 && oldArguments.get(0).getArgumentName() != null;
|
||||||
StringBuilder parametersBuilder = new StringBuilder("(");
|
StringBuilder parametersBuilder = new StringBuilder("(");
|
||||||
boolean isFirst = true;
|
boolean isFirst = true;
|
||||||
|
|
||||||
for (JetParameterInfo parameterInfo : changeInfo.getNewParameters()) {
|
List<JetParameterInfo> newSignatureParameters = changeInfo.getNonReceiverParameters();
|
||||||
|
for (JetParameterInfo parameterInfo : newSignatureParameters) {
|
||||||
if (isFirst)
|
if (isFirst)
|
||||||
isFirst = false;
|
isFirst = false;
|
||||||
else
|
else
|
||||||
@@ -86,8 +102,35 @@ public class JetFunctionCallUsage extends JetUsageInfo<JetCallElement> {
|
|||||||
Map<Integer, JetValueArgument> argumentMap = getParamIndexToArgumentMap(changeInfo, oldArguments);
|
Map<Integer, JetValueArgument> argumentMap = getParamIndexToArgumentMap(changeInfo, oldArguments);
|
||||||
int argIndex = 0;
|
int argIndex = 0;
|
||||||
|
|
||||||
|
JetParameterInfo newReceiverInfo = changeInfo.getReceiverParameterInfo();
|
||||||
|
JetParameterInfo originalReceiverInfo = changeInfo.getMethodDescriptor().getReceiver();
|
||||||
|
|
||||||
|
ReceiverValue extensionReceiver = resolvedCall != null ? resolvedCall.getExtensionReceiver() : ReceiverValue.NO_RECEIVER;
|
||||||
|
ReceiverValue dispatchReceiver = resolvedCall != null ? resolvedCall.getDispatchReceiver() : ReceiverValue.NO_RECEIVER;
|
||||||
|
|
||||||
|
JetPsiFactory psiFactory = new JetPsiFactory(element.getProject());
|
||||||
|
|
||||||
|
PsiElement elementToReplace = element;
|
||||||
|
PsiElement parent = element.getParent();
|
||||||
|
if (parent instanceof JetQualifiedExpression && ((JetQualifiedExpression) parent).getSelectorExpression() == element) {
|
||||||
|
elementToReplace = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do not add extension receiver to calls with explicit dispatch receiver
|
||||||
|
if (newReceiverInfo != null
|
||||||
|
&& elementToReplace instanceof JetQualifiedExpression
|
||||||
|
&& dispatchReceiver instanceof ExpressionReceiver) return;
|
||||||
|
|
||||||
for (JetValueArgument newArgument : newArguments.getArguments()) {
|
for (JetValueArgument newArgument : newArguments.getArguments()) {
|
||||||
JetParameterInfo parameterInfo = changeInfo.getNewParameters()[argIndex++];
|
JetParameterInfo parameterInfo = newSignatureParameters.get(argIndex++);
|
||||||
|
if (parameterInfo == originalReceiverInfo) {
|
||||||
|
JetExpression receiverExpression = getReceiverExpression(extensionReceiver, psiFactory);
|
||||||
|
if (receiverExpression != null) {
|
||||||
|
newArgument.replace(receiverExpression);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
JetValueArgument oldArgument = argumentMap.get(parameterInfo.getOldIndex());
|
JetValueArgument oldArgument = argumentMap.get(parameterInfo.getOldIndex());
|
||||||
|
|
||||||
if (oldArgument != null) {
|
if (oldArgument != null) {
|
||||||
@@ -100,7 +143,38 @@ public class JetFunctionCallUsage extends JetUsageInfo<JetCallElement> {
|
|||||||
newArgument.delete();
|
newArgument.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
return newArguments;
|
arguments.replace(newArguments);
|
||||||
|
|
||||||
|
if (newReceiverInfo == originalReceiverInfo) return;
|
||||||
|
|
||||||
|
PsiElement replacingElement = element;
|
||||||
|
if (newReceiverInfo != null) {
|
||||||
|
JetValueArgument receiverArgument = argumentMap.get(newReceiverInfo.getOldIndex());
|
||||||
|
JetExpression extensionReceiverExpression = receiverArgument != null ? receiverArgument.getArgumentExpression() : null;
|
||||||
|
String receiverText = extensionReceiverExpression != null
|
||||||
|
? extensionReceiverExpression.getText()
|
||||||
|
: newReceiverInfo.getDefaultValueForCall();
|
||||||
|
if (receiverText.isEmpty()) {
|
||||||
|
receiverText = "_";
|
||||||
|
}
|
||||||
|
|
||||||
|
replacingElement = psiFactory.createExpression(receiverText + "." + element.getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
elementToReplace.replace(replacingElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static JetExpression getReceiverExpression(@NotNull ReceiverValue receiver, @NotNull JetPsiFactory psiFactory) {
|
||||||
|
if (receiver instanceof ExpressionReceiver) {
|
||||||
|
return ((ExpressionReceiver) receiver).getExpression();
|
||||||
|
}
|
||||||
|
else if (receiver instanceof ThisReceiver) {
|
||||||
|
DeclarationDescriptor descriptor = ((ThisReceiver) receiver).getDeclarationDescriptor();
|
||||||
|
String thisText = descriptor instanceof ClassDescriptor ? "this@" + descriptor.getName().asString() : "this";
|
||||||
|
return psiFactory.createExpression(thisText);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Map<Integer, JetValueArgument> getParamIndexToArgumentMap(JetChangeInfo changeInfo, List<JetValueArgument> oldArguments) {
|
private static Map<Integer, JetValueArgument> getParamIndexToArgumentMap(JetChangeInfo changeInfo, List<JetValueArgument> oldArguments) {
|
||||||
@@ -125,8 +199,8 @@ public class JetFunctionCallUsage extends JetUsageInfo<JetCallElement> {
|
|||||||
return argumentMap;
|
return argumentMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void changeArgumentNames(JetChangeInfo changeInfo, List<JetValueArgument> oldArguments) {
|
private void changeArgumentNames(JetChangeInfo changeInfo, JetCallElement element) {
|
||||||
for (JetValueArgument argument : oldArguments) {
|
for (ValueArgument argument : element.getValueArguments()) {
|
||||||
JetValueArgumentName argumentName = argument.getArgumentName();
|
JetValueArgumentName argumentName = argument.getArgumentName();
|
||||||
JetSimpleNameExpression argumentNameExpression = argumentName != null ? argumentName.getReferenceExpression() : null;
|
JetSimpleNameExpression argumentNameExpression = argumentName != null ? argumentName.getReferenceExpression() : null;
|
||||||
|
|
||||||
|
|||||||
+21
-9
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2015 JetBrains s.r.o.
|
* Copyright 2010-2013 JetBrains s.r.o.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -26,11 +26,19 @@ import kotlin.KotlinPackage;
|
|||||||
import kotlin.Pair;
|
import kotlin.Pair;
|
||||||
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.KotlinBuiltIns;
|
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
||||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
|
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
|
||||||
|
import org.jetbrains.kotlin.idea.util.ShortenReferences;
|
||||||
|
import org.jetbrains.kotlin.psi.*;
|
||||||
|
import org.jetbrains.kotlin.psi.typeRefHelpers.TypeRefHelpersPackage;
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||||
|
import org.jetbrains.kotlin.types.JetType;
|
||||||
|
import org.jetbrains.kotlin.types.TypeSubstitutor;
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||||
|
import org.jetbrains.kotlin.lexer.JetModifierKeywordToken;
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage;
|
import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage;
|
||||||
import org.jetbrains.kotlin.idea.util.ShortenReferences.Options;
|
import org.jetbrains.kotlin.idea.util.ShortenReferences.Options;
|
||||||
import org.jetbrains.kotlin.idea.codeInsight.shorten.ShortenPackage;
|
import org.jetbrains.kotlin.idea.codeInsight.shorten.ShortenPackage;
|
||||||
@@ -39,12 +47,6 @@ import org.jetbrains.kotlin.idea.refactoring.changeSignature.ChangeSignaturePack
|
|||||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeInfo;
|
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeInfo;
|
||||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetParameterInfo;
|
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetParameterInfo;
|
||||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetValVar;
|
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetValVar;
|
||||||
import org.jetbrains.kotlin.lexer.JetModifierKeywordToken;
|
|
||||||
import org.jetbrains.kotlin.psi.*;
|
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
|
||||||
import org.jetbrains.kotlin.types.JetType;
|
|
||||||
import org.jetbrains.kotlin.types.TypeSubstitutor;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -212,6 +214,16 @@ public class JetFunctionDefinitionUsage<T extends PsiElement> extends JetUsageIn
|
|||||||
ShortenPackage.addToShorteningWaitSet(parameterList, Options.DEFAULT);
|
ShortenPackage.addToShorteningWaitSet(parameterList, Options.DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (element instanceof JetFunction && changeInfo.isReceiverTypeChanged()) {
|
||||||
|
//noinspection unchecked
|
||||||
|
String receiverTypeText = changeInfo.renderReceiverType((JetFunctionDefinitionUsage<PsiElement>) this);
|
||||||
|
JetTypeReference receiverTypeRef = receiverTypeText != null ? psiFactory.createType(receiverTypeText) : null;
|
||||||
|
JetTypeReference newReceiverTypeRef = TypeRefHelpersPackage.setReceiverTypeReference((JetFunction) element, receiverTypeRef);
|
||||||
|
if (newReceiverTypeRef != null) {
|
||||||
|
ShortenPackage.addToShorteningWaitSet(newReceiverTypeRef, ShortenReferences.Options.DEFAULT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (changeInfo.isVisibilityChanged() && !JetPsiUtil.isLocal((JetDeclaration) element)) {
|
if (changeInfo.isVisibilityChanged() && !JetPsiUtil.isLocal((JetDeclaration) element)) {
|
||||||
changeVisibility(changeInfo, element);
|
changeVisibility(changeInfo, element);
|
||||||
}
|
}
|
||||||
@@ -225,7 +237,7 @@ public class JetFunctionDefinitionUsage<T extends PsiElement> extends JetUsageIn
|
|||||||
JetParameterList parameterList,
|
JetParameterList parameterList,
|
||||||
JetPsiFactory psiFactory
|
JetPsiFactory psiFactory
|
||||||
) {
|
) {
|
||||||
int parametersCount = changeInfo.getNewParametersCount();
|
int parametersCount = changeInfo.getNonReceiverParametersCount();
|
||||||
boolean isLambda = element instanceof JetFunctionLiteral;
|
boolean isLambda = element instanceof JetFunctionLiteral;
|
||||||
boolean canReplaceEntireList = false;
|
boolean canReplaceEntireList = false;
|
||||||
|
|
||||||
|
|||||||
+65
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2014 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.refactoring.changeSignature.usages
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeInfo
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetParameterInfo
|
||||||
|
import org.jetbrains.kotlin.psi.JetPsiFactory
|
||||||
|
import org.jetbrains.kotlin.psi.JetQualifiedExpression
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
|
import org.jetbrains.kotlin.psi.JetElement
|
||||||
|
import org.jetbrains.kotlin.idea.codeInsight.shorten.addToShorteningWaitSet
|
||||||
|
import org.jetbrains.kotlin.idea.util.ShortenReferences.Options
|
||||||
|
|
||||||
|
public abstract class JetImplicitReceiverUsage(callElement: JetElement): JetUsageInfo<JetElement>(callElement) {
|
||||||
|
protected abstract fun getNewReceiverText(): String
|
||||||
|
|
||||||
|
protected open fun processReplacedElement(element: JetElement) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun processUsage(changeInfo: JetChangeInfo, element: JetElement): Boolean {
|
||||||
|
val newQualifiedCall = JetPsiFactory(element.getProject()).createExpression(
|
||||||
|
"${getNewReceiverText()}.${element.getText()}"
|
||||||
|
) as JetQualifiedExpression
|
||||||
|
processReplacedElement(element.replace(newQualifiedCall) as JetElement)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class JetImplicitThisToParameterUsage(
|
||||||
|
callElement: JetElement,
|
||||||
|
val parameterInfo: JetParameterInfo,
|
||||||
|
val containingFunction: JetFunctionDefinitionUsage<*>
|
||||||
|
): JetImplicitReceiverUsage(callElement) {
|
||||||
|
override fun getNewReceiverText(): String = parameterInfo.getInheritedName(containingFunction)
|
||||||
|
|
||||||
|
override fun processReplacedElement(element: JetElement) {
|
||||||
|
element.addToShorteningWaitSet(Options(removeThisLabels = true))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class JetImplicitOuterThisToQualifiedThisUsage(
|
||||||
|
callElement: JetElement,
|
||||||
|
val targetDescriptor: DeclarationDescriptor
|
||||||
|
): JetImplicitReceiverUsage(callElement) {
|
||||||
|
override fun getNewReceiverText(): String = "this@${targetDescriptor.getName().asString()}"
|
||||||
|
|
||||||
|
override fun processReplacedElement(element: JetElement) {
|
||||||
|
element.addToShorteningWaitSet(Options(removeThisLabels = true, removeThis = true))
|
||||||
|
}
|
||||||
|
}
|
||||||
+42
-6
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2010-2015 JetBrains s.r.o.
|
* Copyright 2010-2014 JetBrains s.r.o.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -20,15 +20,51 @@ import org.jetbrains.kotlin.psi.JetSimpleNameExpression
|
|||||||
import org.jetbrains.kotlin.psi.JetPsiFactory
|
import org.jetbrains.kotlin.psi.JetPsiFactory
|
||||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeInfo
|
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeInfo
|
||||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetParameterInfo
|
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetParameterInfo
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.codeInsight.shorten.addToShorteningWaitSet
|
||||||
|
import org.jetbrains.kotlin.psi.JetQualifiedExpression
|
||||||
|
import org.jetbrains.kotlin.psi.JetElement
|
||||||
|
import org.jetbrains.kotlin.psi.JetThisExpression
|
||||||
|
import org.jetbrains.kotlin.idea.util.ShortenReferences.Options
|
||||||
|
|
||||||
|
// Explicit reference to function parameter or outer this
|
||||||
|
public abstract class JetExplicitReferenceUsage<T: JetElement>(element: T) : JetUsageInfo<T>(element) {
|
||||||
|
protected abstract fun getReplacementText(changeInfo: JetChangeInfo): String
|
||||||
|
|
||||||
|
protected open fun processReplacedElement(element: JetElement) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun processUsage(changeInfo: JetChangeInfo, element: T): Boolean {
|
||||||
|
val newElement = JetPsiFactory(element.getProject()).createExpression(getReplacementText(changeInfo))
|
||||||
|
processReplacedElement(element.replace(newElement) as JetElement)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class JetParameterUsage(
|
public class JetParameterUsage(
|
||||||
element: JetSimpleNameExpression,
|
element: JetSimpleNameExpression,
|
||||||
private val parameterInfo: JetParameterInfo,
|
private val parameterInfo: JetParameterInfo,
|
||||||
private val containingFunction: JetFunctionDefinitionUsage<*>
|
private val containingFunction: JetFunctionDefinitionUsage<*>
|
||||||
) : JetUsageInfo<JetSimpleNameExpression>(element) {
|
) : JetExplicitReferenceUsage<JetSimpleNameExpression>(element) {
|
||||||
override fun processUsage(changeInfo: JetChangeInfo, element: JetSimpleNameExpression): Boolean {
|
override fun processReplacedElement(element: JetElement) {
|
||||||
val newName = parameterInfo.getInheritedName(containingFunction)
|
val qualifiedExpression = element.getParent() as? JetQualifiedExpression
|
||||||
element.replace(JetPsiFactory(element.getProject()).createSimpleName(newName))
|
if (qualifiedExpression?.getReceiverExpression() == element) {
|
||||||
return false
|
qualifiedExpression!!.addToShorteningWaitSet(Options(removeThis = true))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getReplacementText(changeInfo: JetChangeInfo): String =
|
||||||
|
if (changeInfo.receiverParameterInfo != parameterInfo) parameterInfo.getInheritedName(containingFunction) else "this"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class JetNonQualifiedOuterThisUsage(
|
||||||
|
element: JetThisExpression,
|
||||||
|
val targetDescriptor: DeclarationDescriptor
|
||||||
|
) : JetExplicitReferenceUsage<JetThisExpression>(element) {
|
||||||
|
override fun processReplacedElement(element: JetElement) {
|
||||||
|
element.addToShorteningWaitSet(Options(removeThisLabels = true))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getReplacementText(changeInfo: JetChangeInfo): String = "this@${targetDescriptor.getName().asString()}"
|
||||||
|
}
|
||||||
+8
@@ -20,6 +20,7 @@ import com.intellij.psi.PsiElement;
|
|||||||
import com.intellij.psi.PsiReference;
|
import com.intellij.psi.PsiReference;
|
||||||
import com.intellij.usageView.UsageInfo;
|
import com.intellij.usageView.UsageInfo;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeInfo;
|
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeInfo;
|
||||||
|
|
||||||
public abstract class JetUsageInfo<T extends PsiElement> extends UsageInfo {
|
public abstract class JetUsageInfo<T extends PsiElement> extends UsageInfo {
|
||||||
@@ -31,5 +32,12 @@ public abstract class JetUsageInfo<T extends PsiElement> extends UsageInfo {
|
|||||||
super(reference);
|
super(reference);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public T getElement() {
|
||||||
|
//noinspection unchecked
|
||||||
|
return (T) super.getElement();
|
||||||
|
}
|
||||||
|
|
||||||
public abstract boolean processUsage(JetChangeInfo changeInfo, T element);
|
public abstract boolean processUsage(JetChangeInfo changeInfo, T element);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class J {
|
||||||
|
void test() {
|
||||||
|
_DefaultPackage.foo(X(0), "1", 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
fun X.foo(s: String, k: Int): Boolean {
|
||||||
|
return s.length() - k > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
class X(val k: Int)
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
X(0).foo("1", 2)
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class J {
|
||||||
|
void test() {
|
||||||
|
_DefaultPackage.foo("1", 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
fun <caret>foo(s: String, k: Int): Boolean {
|
||||||
|
return s.length() - k > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
class X(val k: Int)
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
foo("1", 2)
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
fun length(): Int = 1
|
||||||
|
|
||||||
|
fun <caret>foo(k: Int): Boolean {
|
||||||
|
return length() - k > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
class X(val k: Int) {
|
||||||
|
fun length() = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
foo(2)
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Function length will no longer be accessible after signature change
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class J {
|
||||||
|
void test() {
|
||||||
|
new A(3).foo(X(0), "1", 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
class A(val k: Int) {
|
||||||
|
fun X.foo(s: String, n: Int): Boolean {
|
||||||
|
return s.length() * this@A.k - n.inc() + this@A.k > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
X(0).foo("1", 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class X(val k: Int)
|
||||||
|
|
||||||
|
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
with(A(3)) {
|
||||||
|
X(0).foo("1", 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class J {
|
||||||
|
void test() {
|
||||||
|
new A(3).foo("1", 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
class A(val k: Int) {
|
||||||
|
fun <caret>foo(s: String, n: Int): Boolean {
|
||||||
|
return s.length() * this.k - n.inc() + k > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
foo("1", 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class X(val k: Int)
|
||||||
|
|
||||||
|
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
with(A(3)) {
|
||||||
|
foo("1", 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
class A(val k: Int) {
|
||||||
|
fun <caret>foo(s: String, n: Int): Boolean {
|
||||||
|
return s.length()*this.k - n.inc() + k > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
foo("1", 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class X(val k: Int)
|
||||||
|
|
||||||
|
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
A(3).foo("1", 2)
|
||||||
|
with(A(3)) {
|
||||||
|
foo("1", 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Explicit receiver is already present in call element: A(3).foo("1", 2)
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
interface J<A> extends T<A> {
|
||||||
|
@Override
|
||||||
|
<B> int foofoofoo(U<A> a, B b);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class J1<X> implements J<U<X>> {
|
||||||
|
@Override
|
||||||
|
public <C> int foofoofoo(U<U<X>> xu, C c) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class J2 extends J1<String> {
|
||||||
|
@Override
|
||||||
|
public <C> int foofoofoo(U<U<String>> xu, C c) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
class U<A>
|
||||||
|
|
||||||
|
trait T<A> {
|
||||||
|
fun U<A>.foofoofoo<B>(b: B): Int
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class T1<X> : T<U<X>> {
|
||||||
|
override fun <B> U<U<X>>.foofoofoo(b: B): Int {
|
||||||
|
throw UnsupportedOperationException()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class T2 : T1<String>() {
|
||||||
|
override fun <C> U<U<String>>.foofoofoo(b: C): Int {
|
||||||
|
throw UnsupportedOperationException()
|
||||||
|
}
|
||||||
|
}
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
interface J<A> extends T<A> {
|
||||||
|
@Override
|
||||||
|
<B> int foofoofoo(A a, B b);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class J1<X> implements J<U<X>> {
|
||||||
|
@Override
|
||||||
|
public <C> int foofoofoo(U<X> xu, C c) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class J2 extends J1<String> {
|
||||||
|
@Override
|
||||||
|
public <C> int foofoofoo(U<String> xu, C c) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
class U<A>
|
||||||
|
|
||||||
|
trait T<A> {
|
||||||
|
fun <caret>foofoofoo<B>(a: A, b: B): Int
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class T1<X> : T<U<X>> {
|
||||||
|
override fun <B> foofoofoo(a: U<X>, b: B): Int {
|
||||||
|
throw UnsupportedOperationException()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class T2 : T1<String>() {
|
||||||
|
override fun <C> foofoofoo(a: U<String>, b: C): Int {
|
||||||
|
throw UnsupportedOperationException()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class J {
|
||||||
|
void test() {
|
||||||
|
_DefaultPackage.foo("1", new X(0), 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
fun String.foo(x: X, k: Int): Boolean {
|
||||||
|
return x.k + length() - k > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
class X(val k: Int)
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
"1".foo(X(0), 2)
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class J {
|
||||||
|
void test() {
|
||||||
|
_DefaultPackage.foo(new X(0), "1", 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
fun X.<caret>foo(s: String, k: Int): Boolean {
|
||||||
|
return this.k + s.length() - k > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
class X(val k: Int)
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
X(0).foo("1", 2)
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class J {
|
||||||
|
void test() {
|
||||||
|
new A(3).foo("1", new X(0), 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
class A(val k: Int) {
|
||||||
|
fun String.foo(x: X, k: Int): Boolean {
|
||||||
|
return x.k + length() - k + this@A.k/2 > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
"1".foo(X(0), 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class X(val k: Int)
|
||||||
|
|
||||||
|
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
with(A(3)) {
|
||||||
|
"1".foo(X(0), 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class J {
|
||||||
|
void test() {
|
||||||
|
new A(3).foo(new X(0), "1", 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
class A(val k: Int) {
|
||||||
|
fun X.<caret>foo(s: String, k: Int): Boolean {
|
||||||
|
return this.k + s.length() - k + this@A.k/2 > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
X(0).foo("1", 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class X(val k: Int)
|
||||||
|
|
||||||
|
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
with(A(3)) {
|
||||||
|
X(0).foo("1", 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class J {
|
||||||
|
void test() {
|
||||||
|
_DefaultPackage.foo(new X(0), "1", 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
fun X.foo(s: String, k: Int): Boolean {
|
||||||
|
return this.k + s.length() - k > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
class X(val k: Int)
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
X(0).foo("1", 2)
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class J {
|
||||||
|
void test() {
|
||||||
|
_DefaultPackage.foo(new X(0), "1", 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
fun <caret>foo(x: X, s: String, k: Int): Boolean {
|
||||||
|
return x.k + s.length() - k > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
class X(val k: Int)
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
foo(X(0), "1", 2)
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class J {
|
||||||
|
void test() {
|
||||||
|
_DefaultPackage.foo(new X(0), "1", 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
fun X.foo(s: String, k: Int): Boolean {
|
||||||
|
return this.k + s.length() - k > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
class X(val k: Int)
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
X(0).foo("1", 2)
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class J {
|
||||||
|
void test() {
|
||||||
|
_DefaultPackage.foo("1", new X(0), 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
fun <caret>foo(s: String, x: X, k: Int): Boolean {
|
||||||
|
return x.k + s.length() - k > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
class X(val k: Int)
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
foo("1", X(0), 2)
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
class J {
|
||||||
|
void test() {
|
||||||
|
new A(3).foo(new X(0), "1", 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
class A(val k: Int) {
|
||||||
|
fun X.foo(s: String, k: Int): Boolean {
|
||||||
|
return this.k + s.length() - k + this@A.k/2 > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
X(0).foo("1", 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class X(val k: Int)
|
||||||
|
|
||||||
|
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
with(A(3)) {
|
||||||
|
X(0).foo("1", 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
class J {
|
||||||
|
void test() {
|
||||||
|
new A(3).foo(new X(0), "1", 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
class A(val k: Int) {
|
||||||
|
fun <caret>foo(x: X, s: String, k: Int): Boolean {
|
||||||
|
return x.k + s.length() - k + this.k/2 > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
foo(X(0), "1", 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class X(val k: Int)
|
||||||
|
|
||||||
|
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
with(A(3)) {
|
||||||
|
foo(X(0), "1", 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
class J {
|
||||||
|
void test() {
|
||||||
|
new A(3).foo(new X(0), "1", 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
class A(val k: Int) {
|
||||||
|
fun X.foo(s: String, k: Int): Boolean {
|
||||||
|
return this.k + s.length() - k + this@A.k/2 > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
X(0).foo("1", 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class X(val k: Int)
|
||||||
|
|
||||||
|
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
with(A(3)) {
|
||||||
|
X(0).foo("1", 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
class J {
|
||||||
|
void test() {
|
||||||
|
new A(3).foo("1", new X(0), 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
class A(val k: Int) {
|
||||||
|
fun <caret>foo(s: String, x: X, k: Int): Boolean {
|
||||||
|
return x.k + s.length() - k + this.k/2 > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
foo("1", X(0), 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class X(val k: Int)
|
||||||
|
|
||||||
|
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
with(A(3)) {
|
||||||
|
foo("1", X(0), 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
class A(val k: Int) {
|
||||||
|
fun <caret>foo(x: X, s: String, k: Int): Boolean {
|
||||||
|
return x.k + s.length() - k + this.k/2 > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
foo(X(0), "1", 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class X(val k: Int)
|
||||||
|
|
||||||
|
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
A(3).foo(X(0), "1", 2)
|
||||||
|
with(A(3)) {
|
||||||
|
foo(X(0), "1", 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
Explicit receiver is already present in call element: A(3).foo(X(0), "1", 2)
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class J {
|
||||||
|
void test() {
|
||||||
|
_DefaultPackage.foo(new X(0), "1", 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
fun <caret>foo(x: X, s: String, k: Int): Boolean {
|
||||||
|
return x.k + s.length() - k > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
class X(val k: Int)
|
||||||
|
|
||||||
|
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
foo(X(0), "1", 2)
|
||||||
|
with(X(0)) {
|
||||||
|
foo(this, "1", 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class J {
|
||||||
|
void test() {
|
||||||
|
_DefaultPackage.foo(new X(0), "1", 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
fun X.<caret>foo(s: String, k: Int): Boolean {
|
||||||
|
return this.k + s.length() - k > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
class X(val k: Int)
|
||||||
|
|
||||||
|
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
X(0).foo("1", 2)
|
||||||
|
with(X(0)) {
|
||||||
|
foo("1", 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class J {
|
||||||
|
void test() {
|
||||||
|
_DefaultPackage.foo("1", new X(0), 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
fun <caret>foo(s: String, x: X, k: Int): Boolean {
|
||||||
|
return x.k + s.length() - k > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
class X(val k: Int)
|
||||||
|
|
||||||
|
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
foo("1", X(0), 2)
|
||||||
|
with(X(0)) {
|
||||||
|
foo("1", this, 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class J {
|
||||||
|
void test() {
|
||||||
|
_DefaultPackage.foo(new X(0), "1", 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
fun X.<caret>foo(s: String, k: Int): Boolean {
|
||||||
|
return this.k + s.length() - k > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
class X(val k: Int)
|
||||||
|
|
||||||
|
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
X(0).foo("1", 2)
|
||||||
|
with(X(0)) {
|
||||||
|
foo("1", 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
class X(val k: Int)
|
||||||
|
|
||||||
|
fun foo(abc: X, n: Int): Boolean {
|
||||||
|
return abc.k > n
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
class X(val k: Int)
|
||||||
|
|
||||||
|
fun X.<caret>foo(n: Int): Boolean {
|
||||||
|
return this.k > n
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
class J {
|
||||||
|
void test() {
|
||||||
|
new A(3).foo(new X(0), "1", 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
class A(val k: Int) {
|
||||||
|
fun foo(x: X, s: String, k: Int): Boolean {
|
||||||
|
return x.k + s.length() - k + this.k/2 > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
foo(X(0), "1", 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class X(val k: Int)
|
||||||
|
|
||||||
|
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
with(A(3)) {
|
||||||
|
foo(X(0), "1", 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
class J {
|
||||||
|
void test() {
|
||||||
|
new A(3).foo(new X(0), "1", 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
class A(val k: Int) {
|
||||||
|
fun X.<caret>foo(s: String, k: Int): Boolean {
|
||||||
|
return this.k + s.length() - k + this@A.k/2 > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
X(0).foo("1", 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class X(val k: Int)
|
||||||
|
|
||||||
|
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
with(A(3)) {
|
||||||
|
X(0).foo("1", 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
class J {
|
||||||
|
void test() {
|
||||||
|
new A(3).foo("1", new X(0), 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
class A(val k: Int) {
|
||||||
|
fun foo(s: String, x: X, k: Int): Boolean {
|
||||||
|
return x.k + s.length() - k + this.k/2 > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
foo("1", X(0), 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class X(val k: Int)
|
||||||
|
|
||||||
|
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
with(A(3)) {
|
||||||
|
foo("1", X(0), 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
class J {
|
||||||
|
void test() {
|
||||||
|
new A(3).foo(new X(0), "1", 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
class A(val k: Int) {
|
||||||
|
fun X.<caret>foo(s: String, k: Int): Boolean {
|
||||||
|
return this.k + s.length() - k + this@A.k/2 > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
X(0).foo("1", 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class X(val k: Int)
|
||||||
|
|
||||||
|
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
with(A(3)) {
|
||||||
|
X(0).foo("1", 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
val x1: Int
|
||||||
|
|
||||||
|
class X(val x: Int)
|
||||||
|
|
||||||
|
fun foo(x2: X, x: Int): Boolean {
|
||||||
|
return x2.x + x > x1
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
val x1: Int
|
||||||
|
|
||||||
|
class X(val x: Int)
|
||||||
|
|
||||||
|
fun X.<caret>foo(x: Int): Boolean {
|
||||||
|
return this.x + x > x1
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class J {
|
||||||
|
void test() {
|
||||||
|
_DefaultPackage.foo("1", 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
fun foo(s: String, k: Int): Boolean {
|
||||||
|
return this.k + s.length() - k > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
class X(val k: Int)
|
||||||
|
|
||||||
|
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
with(X(0)) {
|
||||||
|
foo("1", 2)
|
||||||
|
}
|
||||||
|
foo("1", 2)
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class J {
|
||||||
|
void test() {
|
||||||
|
_DefaultPackage.foo(new X(0), "1", 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
fun X.<caret>foo(s: String, k: Int): Boolean {
|
||||||
|
return this.k + s.length() - k > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
class X(val k: Int)
|
||||||
|
|
||||||
|
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
with(X(0)) {
|
||||||
|
foo("1", 2)
|
||||||
|
}
|
||||||
|
X(0).foo("1", 2)
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class J {
|
||||||
|
void test() {
|
||||||
|
new A(3).foo(1, "2");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
class A(val k: Int) {
|
||||||
|
fun foo(s: String, n: Int): Boolean {
|
||||||
|
return s.length() * this.k - n.inc() + this@A.k > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
foo("1", 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class X(val k: Int)
|
||||||
|
|
||||||
|
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
with(A(3)) {
|
||||||
|
foo("1", 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
class J {
|
||||||
|
void test() {
|
||||||
|
new A(3).foo(new X(0), 1, "2");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
class A(val k: Int) {
|
||||||
|
fun X.<caret>foo(s: String, n: Int): Boolean {
|
||||||
|
return s.length() * this.k - n.inc() + this@A.k > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
X(0).foo("1", 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class X(val k: Int)
|
||||||
|
|
||||||
|
fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
with(A(3)) {
|
||||||
|
X(0).foo("1", 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
+141
-1
@@ -318,7 +318,8 @@ public class JetChangeSignatureTest extends KotlinCodeInsightTestCase {
|
|||||||
public void testFunctionJavaUsagesAndOverridesAddParam() throws Exception {
|
public void testFunctionJavaUsagesAndOverridesAddParam() throws Exception {
|
||||||
JetChangeInfo changeInfo = getChangeInfo();
|
JetChangeInfo changeInfo = getChangeInfo();
|
||||||
changeInfo.addParameter(new JetParameterInfo(-1, "s", KotlinBuiltIns.getInstance().getStringType(), null, "\"abc\"", null, null));
|
changeInfo.addParameter(new JetParameterInfo(-1, "s", KotlinBuiltIns.getInstance().getStringType(), null, "\"abc\"", null, null));
|
||||||
changeInfo.addParameter(new JetParameterInfo(-1, "o", KotlinBuiltIns.getInstance().getNullableAnyType(), null, "\"def\"", null, null));
|
changeInfo.addParameter(
|
||||||
|
new JetParameterInfo(-1, "o", KotlinBuiltIns.getInstance().getNullableAnyType(), null, "\"def\"", null, null));
|
||||||
doTest(changeInfo);
|
doTest(changeInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,6 +361,16 @@ public class JetChangeSignatureTest extends KotlinCodeInsightTestCase {
|
|||||||
doTest(changeInfo);
|
doTest(changeInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testAddReceiverToGenericsWithOverrides() throws Exception {
|
||||||
|
JetChangeInfo changeInfo = getChangeInfo();
|
||||||
|
|
||||||
|
JetParameterInfo parameterInfo = changeInfo.getNewParameters()[0];
|
||||||
|
parameterInfo.setCurrentTypeText("U<A>");
|
||||||
|
changeInfo.setReceiverParameterInfo(parameterInfo);
|
||||||
|
|
||||||
|
doTest(changeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
public void testJavaMethodKotlinUsages() throws Exception {
|
public void testJavaMethodKotlinUsages() throws Exception {
|
||||||
doJavaTest(
|
doJavaTest(
|
||||||
new JavaRefactoringProvider() {
|
new JavaRefactoringProvider() {
|
||||||
@@ -582,6 +593,135 @@ public class JetChangeSignatureTest extends KotlinCodeInsightTestCase {
|
|||||||
doTest(changeInfo);
|
doTest(changeInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testAddNewReceiver() throws Exception {
|
||||||
|
JetChangeInfo changeInfo = getChangeInfo();
|
||||||
|
JetParameterInfo parameterInfo = new JetParameterInfo(-1, "_", KotlinBuiltIns.getInstance().getAnyType(), null, "X(0)", null, null);
|
||||||
|
parameterInfo.setCurrentTypeText("X");
|
||||||
|
changeInfo.setReceiverParameterInfo(parameterInfo);
|
||||||
|
doTest(changeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAddNewReceiverForMember() throws Exception {
|
||||||
|
JetChangeInfo changeInfo = getChangeInfo();
|
||||||
|
JetParameterInfo parameterInfo = new JetParameterInfo(-1, "_", KotlinBuiltIns.getInstance().getAnyType(), null, "X(0)", null, null);
|
||||||
|
parameterInfo.setCurrentTypeText("X");
|
||||||
|
changeInfo.setReceiverParameterInfo(parameterInfo);
|
||||||
|
doTest(changeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAddNewReceiverForMemberConflict() throws Exception {
|
||||||
|
JetChangeInfo changeInfo = getChangeInfo();
|
||||||
|
JetParameterInfo parameterInfo = new JetParameterInfo(-1, "_", KotlinBuiltIns.getInstance().getAnyType(), null, "X(0)", null, null);
|
||||||
|
parameterInfo.setCurrentTypeText("X");
|
||||||
|
changeInfo.setReceiverParameterInfo(parameterInfo);
|
||||||
|
doTestConflict(changeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAddNewReceiverConflict() throws Exception {
|
||||||
|
JetChangeInfo changeInfo = getChangeInfo();
|
||||||
|
JetParameterInfo parameterInfo = new JetParameterInfo(-1, "_", KotlinBuiltIns.getInstance().getAnyType(), null, "X(0)", null, null);
|
||||||
|
parameterInfo.setCurrentTypeText("X");
|
||||||
|
changeInfo.setReceiverParameterInfo(parameterInfo);
|
||||||
|
doTestConflict(changeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRemoveReceiver() throws Exception {
|
||||||
|
JetChangeInfo changeInfo = getChangeInfo();
|
||||||
|
changeInfo.removeParameter(0);
|
||||||
|
doTest(changeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRemoveReceiverForMember() throws Exception {
|
||||||
|
JetChangeInfo changeInfo = getChangeInfo();
|
||||||
|
changeInfo.removeParameter(0);
|
||||||
|
doTest(changeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testConvertParameterToReceiver1() throws Exception {
|
||||||
|
JetChangeInfo changeInfo = getChangeInfo();
|
||||||
|
changeInfo.setReceiverParameterInfo(changeInfo.getNewParameters()[0]);
|
||||||
|
doTest(changeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testConvertParameterToReceiver2() throws Exception {
|
||||||
|
JetChangeInfo changeInfo = getChangeInfo();
|
||||||
|
changeInfo.setReceiverParameterInfo(changeInfo.getNewParameters()[1]);
|
||||||
|
doTest(changeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testConvertReceiverToParameter1() throws Exception {
|
||||||
|
JetChangeInfo changeInfo = getChangeInfo();
|
||||||
|
changeInfo.setReceiverParameterInfo(null);
|
||||||
|
doTest(changeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testConvertReceiverToParameter2() throws Exception {
|
||||||
|
JetChangeInfo changeInfo = getChangeInfo();
|
||||||
|
changeInfo.setReceiverParameterInfo(null);
|
||||||
|
JetParameterInfo[] parameters = changeInfo.getNewParameters();
|
||||||
|
changeInfo.setNewParameter(0, parameters[1]);
|
||||||
|
changeInfo.setNewParameter(1, parameters[0]);
|
||||||
|
doTest(changeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testConvertParameterToReceiverForMember1() throws Exception {
|
||||||
|
JetChangeInfo changeInfo = getChangeInfo();
|
||||||
|
changeInfo.setReceiverParameterInfo(changeInfo.getNewParameters()[0]);
|
||||||
|
doTest(changeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testConvertParameterToReceiverForMember2() throws Exception {
|
||||||
|
JetChangeInfo changeInfo = getChangeInfo();
|
||||||
|
changeInfo.setReceiverParameterInfo(changeInfo.getNewParameters()[1]);
|
||||||
|
doTest(changeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testConvertParameterToReceiverForMemberConflict() throws Exception {
|
||||||
|
JetChangeInfo changeInfo = getChangeInfo();
|
||||||
|
changeInfo.setReceiverParameterInfo(changeInfo.getNewParameters()[0]);
|
||||||
|
doTestConflict(changeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testConvertReceiverToParameterForMember1() throws Exception {
|
||||||
|
JetChangeInfo changeInfo = getChangeInfo();
|
||||||
|
changeInfo.setReceiverParameterInfo(null);
|
||||||
|
doTest(changeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testConvertReceiverToParameterForMember2() throws Exception {
|
||||||
|
JetChangeInfo changeInfo = getChangeInfo();
|
||||||
|
changeInfo.setReceiverParameterInfo(null);
|
||||||
|
JetParameterInfo[] parameters = changeInfo.getNewParameters();
|
||||||
|
changeInfo.setNewParameter(0, parameters[1]);
|
||||||
|
changeInfo.setNewParameter(1, parameters[0]);
|
||||||
|
doTest(changeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testConvertReceiverToParameterWithNameClash() throws Exception {
|
||||||
|
JetChangeInfo changeInfo = getChangeInfo();
|
||||||
|
changeInfo.setReceiverParameterInfo(null);
|
||||||
|
doTest(changeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testConvertReceiverToParameterAndChangeName() throws Exception {
|
||||||
|
JetChangeInfo changeInfo = getChangeInfo();
|
||||||
|
changeInfo.setReceiverParameterInfo(null);
|
||||||
|
changeInfo.getNewParameters()[0].setName("abc");
|
||||||
|
doTest(changeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testChangeReceiver() throws Exception {
|
||||||
|
JetChangeInfo changeInfo = getChangeInfo();
|
||||||
|
changeInfo.setReceiverParameterInfo(changeInfo.getNewParameters()[1]);
|
||||||
|
doTest(changeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testChangeReceiverForMember() throws Exception {
|
||||||
|
JetChangeInfo changeInfo = getChangeInfo();
|
||||||
|
changeInfo.setReceiverParameterInfo(changeInfo.getNewParameters()[1]);
|
||||||
|
doTest(changeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
protected String getTestDataPath() {
|
protected String getTestDataPath() {
|
||||||
|
|||||||
Reference in New Issue
Block a user