Change Signature: Property support

#KT-6599 Fixed
This commit is contained in:
Alexey Sedunov
2015-06-24 14:17:23 +03:00
parent c96349f42b
commit 2ff63d37c2
60 changed files with 1431 additions and 377 deletions
@@ -270,7 +270,7 @@ usageType.packageMemberAccess = Package member access
x.in.y={0} in {1} x.in.y={0} in {1}
x.implements.y={0} in {1} implements {2} in {3}. x.implements.y={0} in {1} implements {2} in {3}.
x.overrides.y.in.class.list={0} in {1} overrides functions in the following classes/interfaces: {2} Do you want to {3} the base functions? x.overrides.y.in.class.list={0} in {1} overrides declarations in the following classes/interfaces: {2} Do you want to {3} the base declarations?
unused.overriding.methods.title=Unused Overriding Members unused.overriding.methods.title=Unused Overriding Members
there.are.unused.methods.that.override.methods.you.delete=There are unused members that override methods you delete. there.are.unused.methods.that.override.methods.you.delete=There are unused members that override methods you delete.
@@ -147,7 +147,7 @@ public class AddFunctionParametersFix extends ChangeFunctionSignatureFix {
} }
else { else {
JetParameterInfo parameterInfo = JetParameterInfo parameterInfo =
getNewParameterInfo(originalDescriptor.getBaseDescriptor(), bindingContext, argument, validator); getNewParameterInfo((FunctionDescriptor) originalDescriptor.getBaseDescriptor(), bindingContext, argument, validator);
typesToShorten.add(parameterInfo.getOriginalType()); typesToShorten.add(parameterInfo.getOriginalType());
if (expression != null) { if (expression != null) {
@@ -115,7 +115,7 @@ object CreateParameterActionFactory: JetSingleIntentionActionFactory() {
return CreateParameterFromUsageFix( return CreateParameterFromUsageFix(
functionDescriptor, functionDescriptor,
context, context,
JetParameterInfo(functionDescriptor = functionDescriptor, JetParameterInfo(callableDescriptor = functionDescriptor,
name = refExpr.getReferencedName(), name = refExpr.getReferencedName(),
type = paramType, type = paramType,
valOrVar = valOrVar), valOrVar = valOrVar),
@@ -60,7 +60,7 @@ public object CreateParameterByNamedArgumentActionFactory: JetSingleIntentionAct
if (paramType.hasTypeParametersToAdd(functionDescriptor, context)) return null if (paramType.hasTypeParametersToAdd(functionDescriptor, context)) return null
val parameterInfo = JetParameterInfo( val parameterInfo = JetParameterInfo(
functionDescriptor = functionDescriptor, callableDescriptor = functionDescriptor,
name = name, name = name,
type = paramType, type = paramType,
defaultValueForCall = argumentExpression defaultValueForCall = argumentExpression
@@ -19,28 +19,35 @@ package org.jetbrains.kotlin.idea.refactoring.changeSignature
import com.intellij.lang.Language import com.intellij.lang.Language
import com.intellij.lang.java.JavaLanguage import com.intellij.lang.java.JavaLanguage
import com.intellij.psi.* import com.intellij.psi.*
import com.intellij.refactoring.changeSignature.* import com.intellij.refactoring.changeSignature.ChangeInfo
import com.intellij.refactoring.changeSignature.ChangeSignatureProcessor
import com.intellij.refactoring.changeSignature.JavaChangeInfo
import com.intellij.refactoring.changeSignature.ParameterInfoImpl
import com.intellij.usageView.UsageInfo import com.intellij.usageView.UsageInfo
import com.intellij.util.VisibilityUtil import com.intellij.util.VisibilityUtil
import org.jetbrains.kotlin.asJava.* import org.jetbrains.kotlin.asJava.toLightMethods
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.codegen.PropertyCodegen
import org.jetbrains.kotlin.descriptors.CallableDescriptor
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.idea.JetLanguage
import org.jetbrains.kotlin.idea.caches.resolve.getJavaMethodDescriptor
import org.jetbrains.kotlin.idea.core.refactoring.j2k
import org.jetbrains.kotlin.idea.project.ProjectStructureUtil
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetMethodDescriptor.Kind
import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.JetCallableDefinitionUsage
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.parameterIndex
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.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.idea.JetLanguage
import org.jetbrains.kotlin.idea.caches.resolve.*
import org.jetbrains.kotlin.idea.core.refactoring.j2k
import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.JetFunctionDefinitionUsage
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import java.util.HashMap
import kotlin.properties.Delegates
import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList import org.jetbrains.kotlin.utils.addToStdlib.singletonOrEmptyList
import org.jetbrains.kotlin.idea.project.* import java.util.*
import org.jetbrains.kotlin.psi.* import kotlin.properties.Delegates
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetMethodDescriptor.Kind
public class JetChangeInfo( public class JetChangeInfo(
val methodDescriptor: JetMethodDescriptor, val methodDescriptor: JetMethodDescriptor,
@@ -61,7 +68,7 @@ public class JetChangeInfo(
} }
private val newParameters = parameterInfos.toArrayList() private val newParameters = parameterInfos.toArrayList()
private val originalPsiMethod: PsiMethod? = getCurrentPsiMethod() private val originalPsiMethods: List<PsiMethod> = getMethod().toLightMethods()
private val oldNameToParameterIndex: Map<String, Int> by Delegates.lazy { private val oldNameToParameterIndex: Map<String, Int> by Delegates.lazy {
val map = HashMap<String, Int>() val map = HashMap<String, Int>()
@@ -80,13 +87,7 @@ public class JetChangeInfo(
} }
private var isPrimaryMethodUpdated: Boolean = false private var isPrimaryMethodUpdated: Boolean = false
private var javaChangeInfo: JavaChangeInfo? = null private var javaChangeInfos: List<JavaChangeInfo>? = null
private fun getCurrentPsiMethod(): PsiMethod? {
val psiMethods = getMethod().toLightMethods()
assert(psiMethods.size() <= 1) { "Multiple light methods: " + getMethod().getText() }
return psiMethods.firstOrNull()
}
public fun getOldParameterIndex(oldParameterName: String): Int? = oldNameToParameterIndex[oldParameterName] public fun getOldParameterIndex(oldParameterName: String): Int? = oldNameToParameterIndex[oldParameterName]
@@ -103,6 +104,7 @@ public class JetChangeInfo(
fun getNonReceiverParametersCount(): Int = newParameters.size() - (if (receiverParameterInfo != null) 1 else 0) fun getNonReceiverParametersCount(): Int = newParameters.size() - (if (receiverParameterInfo != null) 1 else 0)
fun getNonReceiverParameters(): List<JetParameterInfo> { fun getNonReceiverParameters(): List<JetParameterInfo> {
if (methodDescriptor.baseDeclaration is JetProperty) return emptyList()
return receiverParameterInfo?.let { receiver -> newParameters.filter { it != receiver } } ?: newParameters return receiverParameterInfo?.let { receiver -> newParameters.filter { it != receiver } } ?: newParameters
} }
@@ -146,7 +148,7 @@ public class JetChangeInfo(
override fun getLanguage(): Language = JetLanguage.INSTANCE override fun getLanguage(): Language = JetLanguage.INSTANCE
public fun getNewSignature(inheritedFunction: JetFunctionDefinitionUsage<PsiElement>): String { public fun getNewSignature(inheritedCallable: JetCallableDefinitionUsage<PsiElement>): String {
val buffer = StringBuilder() val buffer = StringBuilder()
val defaultVisibility = if (kind.isConstructor) Visibilities.PUBLIC else Visibilities.INTERNAL val defaultVisibility = if (kind.isConstructor) Visibilities.PUBLIC else Visibilities.INTERNAL
@@ -174,7 +176,7 @@ public class JetChangeInfo(
buffer.append(name) buffer.append(name)
} }
buffer.append(getNewParametersSignature(inheritedFunction)) buffer.append(getNewParametersSignature(inheritedCallable))
if (newReturnType != null && !KotlinBuiltIns.isUnit(newReturnType) && kind == Kind.FUNCTION) if (newReturnType != null && !KotlinBuiltIns.isUnit(newReturnType) && kind == Kind.FUNCTION)
buffer.append(": ").append(newReturnTypeText) buffer.append(": ").append(newReturnTypeText)
@@ -182,63 +184,75 @@ public class JetChangeInfo(
return buffer.toString() return buffer.toString()
} }
public fun isRefactoringTarget(inheritedFunctionDescriptor: FunctionDescriptor?): Boolean { public fun isRefactoringTarget(inheritedCallableDescriptor: CallableDescriptor?): Boolean {
return inheritedFunctionDescriptor != null return inheritedCallableDescriptor != null
&& getMethod() == DescriptorToSourceUtils.descriptorToDeclaration(inheritedFunctionDescriptor) && getMethod() == DescriptorToSourceUtils.descriptorToDeclaration(inheritedCallableDescriptor)
} }
public fun getNewParametersSignature(inheritedFunction: JetFunctionDefinitionUsage<PsiElement>): String { public fun getNewParametersSignature(inheritedCallable: JetCallableDefinitionUsage<PsiElement>): String {
val signatureParameters = getNonReceiverParameters() val signatureParameters = getNonReceiverParameters()
val isLambda = inheritedFunction.getDeclaration() is JetFunctionLiteral val isLambda = inheritedCallable.getDeclaration() is JetFunctionLiteral
if (isLambda && signatureParameters.size() == 1 && !signatureParameters.get(0).requiresExplicitType(inheritedFunction)) { if (isLambda && signatureParameters.size() == 1 && !signatureParameters.get(0).requiresExplicitType(inheritedCallable)) {
return signatureParameters.get(0).getDeclarationSignature(0, inheritedFunction) return signatureParameters.get(0).getDeclarationSignature(0, inheritedCallable)
} }
return signatureParameters.indices return signatureParameters.indices
.map { i -> signatureParameters[i].getDeclarationSignature(i, inheritedFunction) } .map { i -> signatureParameters[i].getDeclarationSignature(i, inheritedCallable) }
.joinToString(prefix = "(", separator = ", ", postfix = ")") .joinToString(prefix = "(", separator = ", ", postfix = ")")
} }
public fun renderReceiverType(inheritedFunction: JetFunctionDefinitionUsage<PsiElement>): String? { public fun renderReceiverType(inheritedCallable: JetCallableDefinitionUsage<PsiElement>): String? {
val receiverTypeText = receiverParameterInfo?.currentTypeText ?: return null val receiverTypeText = receiverParameterInfo?.currentTypeText ?: return null
val typeSubstitutor = inheritedFunction.getOrCreateTypeSubstitutor() ?: return receiverTypeText val typeSubstitutor = inheritedCallable.getOrCreateTypeSubstitutor() ?: return receiverTypeText
val currentBaseFunction = inheritedFunction.getBaseFunction().getCurrentFunctionDescriptor() ?: return receiverTypeText val currentBaseFunction = inheritedCallable.getBaseFunction().getCurrentCallableDescriptor() ?: return receiverTypeText
return currentBaseFunction.getExtensionReceiverParameter()!!.getType().renderTypeWithSubstitution(typeSubstitutor, receiverTypeText, false) return currentBaseFunction.getExtensionReceiverParameter()!!.getType().renderTypeWithSubstitution(typeSubstitutor, receiverTypeText, false)
} }
public fun renderReturnType(inheritedFunction: JetFunctionDefinitionUsage<PsiElement>): String { public fun renderReturnType(inheritedCallable: JetCallableDefinitionUsage<PsiElement>): String {
val typeSubstitutor = inheritedFunction.getOrCreateTypeSubstitutor() ?: return newReturnTypeText val typeSubstitutor = inheritedCallable.getOrCreateTypeSubstitutor() ?: return newReturnTypeText
val currentBaseFunction = inheritedFunction.getBaseFunction().getCurrentFunctionDescriptor() ?: return newReturnTypeText val currentBaseFunction = inheritedCallable.getBaseFunction().getCurrentCallableDescriptor() ?: return newReturnTypeText
return currentBaseFunction.getReturnType().renderTypeWithSubstitution(typeSubstitutor, newReturnTypeText, false) return currentBaseFunction.getReturnType().renderTypeWithSubstitution(typeSubstitutor, newReturnTypeText, false)
} }
public fun primaryMethodUpdated() { public fun primaryMethodUpdated() {
isPrimaryMethodUpdated = true isPrimaryMethodUpdated = true
javaChangeInfo = null javaChangeInfos = null
} }
public fun getOrCreateJavaChangeInfo(): JavaChangeInfo? { public fun getOrCreateJavaChangeInfos(): List<JavaChangeInfo>? {
if (ProjectStructureUtil.isJsKotlinModule(getMethod().getContainingFile() as JetFile)) return null /*
* When primaryMethodUpdated is false, changes to the primary Kotlin declaration are already confirmed, but not yet applied.
* It means that originalPsiMethod has already expired, but new one can't be created until Kotlin declaration is updated
* (signified by primaryMethodUpdated being true). It means we can't know actual PsiType, visibility, etc.
* to use in JavaChangeInfo. However they are not actually used at this point since only parameter count and order matters here
* So we resort to this hack and pass around "default" type (void) and visibility (package-local)
*/
if (javaChangeInfo == null) { fun createJavaChangeInfo(originalPsiMethod: PsiMethod,
val currentPsiMethod = getCurrentPsiMethod() currentPsiMethod: PsiMethod,
if (originalPsiMethod == null || currentPsiMethod == null) return null newName: String,
newReturnType: PsiType?,
/* newParameters: Array<ParameterInfoImpl>
* When primaryMethodUpdated is false, changes to the primary Kotlin declaration are already confirmed, but not yet applied. ): JavaChangeInfo? {
* It means that originalPsiMethod has already expired, but new one can't be created until Kotlin declaration is updated val newVisibility = if (isPrimaryMethodUpdated)
* (signified by primaryMethodUpdated being true). It means we can't know actual PsiType, visibility, etc.
* to use in JavaChangeInfo. However they are not actually used at this point since only parameter count and order matters here
* So we resort to this hack and pass around "default" type (void) and visibility (package-local)
*/
val javaVisibility = if (isPrimaryMethodUpdated)
VisibilityUtil.getVisibilityModifier(currentPsiMethod.getModifierList()) VisibilityUtil.getVisibilityModifier(currentPsiMethod.getModifierList())
else else
PsiModifier.PACKAGE_LOCAL PsiModifier.PACKAGE_LOCAL
val javaChangeInfo = ChangeSignatureProcessor(getMethod().getProject(),
originalPsiMethod,
false,
newVisibility,
newName,
newReturnType ?: PsiType.VOID,
newParameters).getChangeInfo()
javaChangeInfo.updateMethod(currentPsiMethod)
val newParameterList = receiverParameterInfo.singletonOrEmptyList() + getNonReceiverParameters() return javaChangeInfo
val newJavaParameters = newParameterList.withIndex().map { pair -> }
fun getJavaParameterInfos(currentPsiMethod: PsiMethod, newParameterList: List<JetParameterInfo>): MutableList<ParameterInfoImpl> {
return newParameterList.withIndex().mapTo(ArrayList()) { pair ->
val (i, info) = pair val (i, info) = pair
val type = if (isPrimaryMethodUpdated) val type = if (isPrimaryMethodUpdated)
@@ -255,25 +269,66 @@ public class JetChangeInfo(
} }
ParameterInfoImpl(javaOldIndex, info.getName(), type, info.defaultValueForCall?.getText() ?: "") ParameterInfoImpl(javaOldIndex, info.getName(), type, info.defaultValueForCall?.getText() ?: "")
}.toTypedArray() }
val returnType = if (isPrimaryMethodUpdated) currentPsiMethod.getReturnType() else PsiType.VOID
javaChangeInfo = ChangeSignatureProcessor(getMethod().getProject(),
originalPsiMethod,
false,
javaVisibility,
getNewName(),
returnType,
newJavaParameters).getChangeInfo()
javaChangeInfo!!.updateMethod(currentPsiMethod)
} }
return javaChangeInfo fun createJavaChangeInfoForFunctionOrGetter(
originalPsiMethod: PsiMethod,
currentPsiMethod: PsiMethod,
isGetter: Boolean
): JavaChangeInfo? {
val newParameterList = receiverParameterInfo.singletonOrEmptyList() + getNonReceiverParameters()
val newJavaParameters = getJavaParameterInfos(currentPsiMethod, newParameterList).toTypedArray()
val newName = if (isGetter) PropertyCodegen.getterName(Name.identifier(getNewName())) else getNewName()
return createJavaChangeInfo(originalPsiMethod, currentPsiMethod, newName, currentPsiMethod.getReturnType(), newJavaParameters)
}
fun createJavaChangeInfoForSetter(originalPsiMethod: PsiMethod, currentPsiMethod: PsiMethod): JavaChangeInfo? {
val newJavaParameters = getJavaParameterInfos(currentPsiMethod, receiverParameterInfo.singletonOrEmptyList())
val oldIndex = if (methodDescriptor.receiver != null) 1 else 0
if (isPrimaryMethodUpdated) {
val newIndex = if (receiverParameterInfo != null) 1 else 0
val setterParameter = currentPsiMethod.getParameterList().getParameters()[newIndex]
newJavaParameters.add(ParameterInfoImpl(oldIndex, setterParameter.getName(), setterParameter.getType()))
}
else {
newJavaParameters.add(ParameterInfoImpl(oldIndex, "receiver", PsiType.VOID))
}
val newName = PropertyCodegen.setterName(Name.identifier(getNewName()))
return createJavaChangeInfo(originalPsiMethod, currentPsiMethod, newName, PsiType.VOID, newJavaParameters.toTypedArray())
}
if (ProjectStructureUtil.isJsKotlinModule(getMethod().getContainingFile() as JetFile)) return null
if (javaChangeInfos == null) {
val method = getMethod()
javaChangeInfos = (originalPsiMethods zip method.toLightMethods()).map {
val (originalPsiMethod, currentPsiMethod) = it
when (method) {
is JetFunction, is JetClassOrObject ->
createJavaChangeInfoForFunctionOrGetter(originalPsiMethod, currentPsiMethod, false)
is JetProperty -> {
val accessorName = originalPsiMethod.getName()
when {
accessorName.startsWith(JvmAbi.GETTER_PREFIX) ->
createJavaChangeInfoForFunctionOrGetter(originalPsiMethod, currentPsiMethod, true)
accessorName.startsWith(JvmAbi.SETTER_PREFIX) ->
createJavaChangeInfoForSetter(originalPsiMethod, currentPsiMethod)
else -> null
}
}
else -> null
}
}.filterNotNull()
}
return javaChangeInfos
} }
} }
public val JetChangeInfo.originalBaseFunctionDescriptor: FunctionDescriptor public val JetChangeInfo.originalBaseFunctionDescriptor: CallableDescriptor
get() = methodDescriptor.baseDescriptor get() = methodDescriptor.baseDescriptor
public val JetChangeInfo.kind: Kind get() = methodDescriptor.kind public val JetChangeInfo.kind: Kind get() = methodDescriptor.kind
@@ -281,7 +336,7 @@ public val JetChangeInfo.kind: Kind get() = methodDescriptor.kind
public val JetChangeInfo.oldName: String? public val JetChangeInfo.oldName: String?
get() = (methodDescriptor.getMethod() as? JetFunction)?.getName() get() = (methodDescriptor.getMethod() as? JetFunction)?.getName()
public val JetChangeInfo.affectedFunctions: Collection<UsageInfo> get() = methodDescriptor.affectedFunctions public val JetChangeInfo.affectedFunctions: Collection<UsageInfo> get() = methodDescriptor.affectedCallables
public fun ChangeInfo.toJetChangeInfo(originalChangeSignatureDescriptor: JetMethodDescriptor): JetChangeInfo { public fun ChangeInfo.toJetChangeInfo(originalChangeSignatureDescriptor: JetMethodDescriptor): JetChangeInfo {
val method = getMethod() as PsiMethod val method = getMethod() as PsiMethod
@@ -305,7 +360,7 @@ public fun ChangeInfo.toJetChangeInfo(originalChangeSignatureDescriptor: JetMeth
} }
else null else null
with(JetParameterInfo(functionDescriptor = functionDescriptor, with(JetParameterInfo(callableDescriptor = functionDescriptor,
originalIndex = oldIndex, originalIndex = oldIndex,
name = info.getName(), name = info.getName(),
type = if (oldIndex >= 0) originalParameterDescriptors[oldIndex].getType() else currentType, type = if (oldIndex >= 0) originalParameterDescriptors[oldIndex].getType() else currentType,
@@ -0,0 +1,174 @@
/*
* Copyright 2010-2015 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
import com.intellij.openapi.options.ConfigurationException
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiElement
import com.intellij.refactoring.BaseRefactoringProcessor
import com.intellij.refactoring.ui.ComboBoxVisibilityPanel
import com.intellij.refactoring.ui.RefactoringDialog
import com.intellij.ui.EditorTextField
import com.intellij.ui.NonFocusableCheckBox
import com.intellij.util.ui.FormBuilder
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.idea.JetFileType
import org.jetbrains.kotlin.idea.core.refactoring.validateElement
import org.jetbrains.kotlin.psi.JetExpression
import org.jetbrains.kotlin.psi.JetProperty
import org.jetbrains.kotlin.psi.JetPsiFactory
import org.jetbrains.kotlin.psi.JetTypeCodeFragment
import org.jetbrains.kotlin.resolve.AnalyzingUtils
import javax.swing.JCheckBox
import javax.swing.JComboBox
import javax.swing.JComponent
import javax.swing.JLabel
import kotlin.properties.Delegates
public class JetChangePropertySignatureDialog(
project: Project,
private val methodDescriptor: JetMethodDescriptor,
private val commandName: String?
): RefactoringDialog(project, true) {
private val visibilityCombo = JComboBox(
arrayOf(Visibilities.INTERNAL, Visibilities.PRIVATE, Visibilities.PROTECTED, Visibilities.PUBLIC)
)
private val nameField = EditorTextField(methodDescriptor.getName())
private var returnTypeField: EditorTextField by Delegates.notNull()
private var receiverTypeCheckBox: JCheckBox by Delegates.notNull()
var receiverTypeLabel: JLabel by Delegates.notNull()
private var receiverTypeField: EditorTextField by Delegates.notNull()
var receiverDefaultValueLabel: JLabel? = null
private var receiverDefaultValueField: EditorTextField? = null
init {
setTitle("Change Signature")
init()
}
override fun getPreferredFocusedComponent() = nameField
override fun createCenterPanel(): JComponent? {
fun updateReceiverUI() {
val withReceiver = receiverTypeCheckBox.isSelected()
receiverTypeLabel.setEnabled(withReceiver)
receiverTypeField.setEnabled(withReceiver)
receiverDefaultValueLabel?.setEnabled(withReceiver)
receiverDefaultValueField?.setEnabled(withReceiver)
}
val documentManager = PsiDocumentManager.getInstance(myProject)
val psiFactory = JetPsiFactory(myProject)
return with(FormBuilder.createFormBuilder()) {
if (!((methodDescriptor.baseDeclaration as? JetProperty)?.isLocal() ?: false)) {
visibilityCombo.setSelectedItem(methodDescriptor.getVisibility())
addLabeledComponent("&Visibility: ", visibilityCombo)
}
addLabeledComponent("&Name: ", nameField)
val returnTypeCodeFragment = psiFactory.createTypeCodeFragment(methodDescriptor.renderOriginalReturnType(),
methodDescriptor.baseDeclaration)
returnTypeField = EditorTextField(documentManager.getDocument(returnTypeCodeFragment), myProject, JetFileType.INSTANCE)
addLabeledComponent("&Type: ", returnTypeField)
addSeparator()
val receiverTypeCheckBox = JCheckBox("Extension property: ")
receiverTypeCheckBox.setMnemonic('x')
receiverTypeCheckBox.addActionListener { updateReceiverUI() }
receiverTypeCheckBox.setSelected(methodDescriptor.receiver != null)
addComponent(receiverTypeCheckBox)
this@JetChangePropertySignatureDialog.receiverTypeCheckBox = receiverTypeCheckBox
val receiverTypeCodeFragment = psiFactory.createTypeCodeFragment(methodDescriptor.renderOriginalReceiverType() ?: "",
methodDescriptor.baseDeclaration)
receiverTypeField = EditorTextField(documentManager.getDocument(receiverTypeCodeFragment), myProject, JetFileType.INSTANCE)
receiverTypeLabel = JLabel("Receiver type: ")
receiverTypeLabel.setDisplayedMnemonic('t')
addLabeledComponent(receiverTypeLabel, receiverTypeField)
if (methodDescriptor.receiver == null) {
val receiverDefaultValueCodeFragment = psiFactory.createExpressionCodeFragment("", methodDescriptor.baseDeclaration)
receiverDefaultValueField = EditorTextField(documentManager.getDocument(receiverDefaultValueCodeFragment),
myProject,
JetFileType.INSTANCE)
receiverDefaultValueLabel = JLabel("Default receiver value: ")
receiverDefaultValueLabel!!.setDisplayedMnemonic('D')
addLabeledComponent(receiverDefaultValueLabel, receiverDefaultValueField!!)
}
updateReceiverUI()
getPanel()
}
}
private fun getDefaultReceiverValue(): JetExpression? {
val receiverDefaultValue = receiverDefaultValueField?.getText() ?: ""
return if (receiverDefaultValue.isNotEmpty()) JetPsiFactory(myProject).createExpression(receiverDefaultValue) else null
}
override fun canRun() {
val psiFactory = JetPsiFactory(myProject)
psiFactory.createSimpleName(nameField.getText()).validateElement("Invalid name")
psiFactory.createType(returnTypeField.getText()).validateElement("Invalid return type")
if (receiverTypeCheckBox.isSelected()) {
psiFactory.createType(receiverTypeField.getText()).validateElement("Invalid receiver type")
}
getDefaultReceiverValue()?.validateElement("Invalid default receiver value")
}
override fun doAction() {
val descriptor = (methodDescriptor as? JetMutableMethodDescriptor)?.original ?: methodDescriptor
val receiver = if (receiverTypeCheckBox.isSelected()) {
descriptor.receiver ?: JetParameterInfo(callableDescriptor = descriptor.baseDescriptor,
name = "receiver",
defaultValueForCall = getDefaultReceiverValue())
} else null
receiver?.currentTypeText = receiverTypeField.getText()
val changeInfo = JetChangeInfo(descriptor,
nameField.getText(),
null,
returnTypeField.getText(),
visibilityCombo.getSelectedItem() as Visibility,
emptyList(),
receiver,
descriptor.getMethod())
invokeRefactoring(JetChangeSignatureProcessor(myProject, changeInfo, commandName ?: getTitle()))
}
companion object {
fun createProcessorForSilentRefactoring(
project: Project,
commandName: String,
descriptor: JetMethodDescriptor
): BaseRefactoringProcessor {
val originalDescriptor = (descriptor as? JetMutableMethodDescriptor)?.original ?: descriptor
val changeInfo = JetChangeInfo(methodDescriptor = originalDescriptor, context = originalDescriptor.getMethod())
changeInfo.setNewName(descriptor.getName())
changeInfo.receiverParameterInfo = descriptor.receiver
return JetChangeSignatureProcessor(project, changeInfo, commandName)
}
}
}
@@ -23,11 +23,15 @@ import com.intellij.psi.PsiElement
import com.intellij.refactoring.changeSignature.ChangeSignatureHandler import com.intellij.refactoring.changeSignature.ChangeSignatureHandler
import org.jetbrains.annotations.TestOnly import org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.idea.refactoring.CallableRefactoring import org.jetbrains.kotlin.idea.refactoring.CallableRefactoring
import org.jetbrains.kotlin.psi.JetClass
import org.jetbrains.kotlin.psi.JetFunction
import org.jetbrains.kotlin.psi.JetProperty
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.OverrideResolver import org.jetbrains.kotlin.resolve.OverrideResolver
@@ -50,55 +54,64 @@ fun JetMethodDescriptor.modify(action: (JetMutableMethodDescriptor) -> Unit): Je
} }
public fun runChangeSignature(project: Project, public fun runChangeSignature(project: Project,
functionDescriptor: FunctionDescriptor, callableDescriptor: CallableDescriptor,
configuration: JetChangeSignatureConfiguration, configuration: JetChangeSignatureConfiguration,
bindingContext: BindingContext, bindingContext: BindingContext,
defaultValueContext: PsiElement, defaultValueContext: PsiElement,
commandName: String? = null): Boolean { commandName: String? = null): Boolean {
return JetChangeSignature(project, functionDescriptor, configuration, bindingContext, defaultValueContext, commandName).run() return JetChangeSignature(project, callableDescriptor, configuration, bindingContext, defaultValueContext, commandName).run()
} }
public class JetChangeSignature(project: Project, public class JetChangeSignature(project: Project,
functionDescriptor: FunctionDescriptor, callableDescriptor: CallableDescriptor,
val configuration: JetChangeSignatureConfiguration, val configuration: JetChangeSignatureConfiguration,
bindingContext: BindingContext, bindingContext: BindingContext,
val defaultValueContext: PsiElement, val defaultValueContext: PsiElement,
commandName: String?): CallableRefactoring<FunctionDescriptor>(project, functionDescriptor, bindingContext, commandName) { commandName: String?): CallableRefactoring<CallableDescriptor>(project, callableDescriptor, bindingContext, commandName) {
private val LOG = Logger.getInstance(javaClass<JetChangeSignature>()) private val LOG = Logger.getInstance(javaClass<JetChangeSignature>())
override fun forcePerformForSelectedFunctionOnly() = configuration.forcePerformForSelectedFunctionOnly() override fun forcePerformForSelectedFunctionOnly() = configuration.forcePerformForSelectedFunctionOnly()
override fun performRefactoring(descriptorsForChange: Collection<CallableDescriptor>) { private fun runSilentRefactoring(descriptor: JetMethodDescriptor) {
assert (descriptorsForChange.all { it is FunctionDescriptor }) { val commandName = commandName ?: ChangeSignatureHandler.REFACTORING_NAME
"Function descriptors expected: " + descriptorsForChange.joinToString(separator = "\n") val processor = when (descriptor.baseDeclaration) {
is JetFunction, is JetClass -> {
JetChangeSignatureDialog.createRefactoringProcessorForSilentChangeSignature(project, commandName, descriptor, defaultValueContext)
}
is JetProperty -> {
JetChangePropertySignatureDialog.createProcessorForSilentRefactoring(project, commandName, descriptor)
}
else -> throw AssertionError("Unexpected declaration: ${descriptor.baseDeclaration.getElementTextWithContext()}")
}
processor.run()
}
private fun runInteractiveRefactoring(descriptor: JetMethodDescriptor) {
val dialog = when (descriptor.baseDeclaration) {
is JetFunction, is JetClass -> JetChangeSignatureDialog(project, descriptor, defaultValueContext, commandName)
is JetProperty -> JetChangePropertySignatureDialog(project, descriptor, commandName)
else -> throw AssertionError("Unexpected declaration: ${descriptor.baseDeclaration.getElementTextWithContext()}")
} }
@suppress("UNCHECKED_CAST") dialog.show()
val adjustedDescriptor = adjustDescriptor(descriptorsForChange as Collection<FunctionDescriptor>) }
if (adjustedDescriptor == null) return
val affectedFunctions = adjustedDescriptor.affectedFunctions.map { it.getElement() }.filterNotNull() override fun performRefactoring(descriptorsForChange: Collection<CallableDescriptor>) {
val adjustedDescriptor = adjustDescriptor(descriptorsForChange) ?: return
val affectedFunctions = adjustedDescriptor.affectedCallables.map { it.getElement() }.filterNotNull()
if (affectedFunctions.any { !checkModifiable(it) }) return if (affectedFunctions.any { !checkModifiable(it) }) return
if (configuration.performSilently(affectedFunctions) if (configuration.performSilently(affectedFunctions) || ApplicationManager.getApplication()!!.isUnitTestMode()) {
|| ApplicationManager.getApplication()!!.isUnitTestMode()) { runSilentRefactoring(adjustedDescriptor)
JetChangeSignatureDialog.createRefactoringProcessorForSilentChangeSignature(
project,
commandName ?: ChangeSignatureHandler.REFACTORING_NAME,
adjustedDescriptor,
defaultValueContext
).run()
} }
else { else {
val dialog = JetChangeSignatureDialog(project, adjustedDescriptor, defaultValueContext, commandName) runInteractiveRefactoring(adjustedDescriptor)
dialog.show()
} }
} }
fun adjustDescriptor(descriptorsForSignatureChange: Collection<FunctionDescriptor>): JetMethodDescriptor? { fun adjustDescriptor(descriptorsForSignatureChange: Collection<CallableDescriptor>): JetMethodDescriptor? {
val baseDescriptor = preferContainedInClass(descriptorsForSignatureChange) val baseDescriptor = preferContainedInClass(descriptorsForSignatureChange)
val functionDeclaration = DescriptorToSourceUtilsIde.getAnyDeclaration(project, baseDescriptor) val functionDeclaration = DescriptorToSourceUtilsIde.getAnyDeclaration(project, baseDescriptor)
if (functionDeclaration == null) { if (functionDeclaration == null) {
@@ -114,7 +127,7 @@ public class JetChangeSignature(project: Project,
return configuration.configure(originalDescriptor, bindingContext) return configuration.configure(originalDescriptor, bindingContext)
} }
private fun preferContainedInClass(descriptorsForSignatureChange: Collection<FunctionDescriptor>): FunctionDescriptor { private fun preferContainedInClass(descriptorsForSignatureChange: Collection<CallableDescriptor>): CallableDescriptor {
for (descriptor in descriptorsForSignatureChange) { for (descriptor in descriptorsForSignatureChange) {
val containingDeclaration = descriptor.getContainingDeclaration() val containingDeclaration = descriptor.getContainingDeclaration()
if (containingDeclaration is ClassDescriptor && containingDeclaration.getKind() != ClassKind.INTERFACE) { if (containingDeclaration is ClassDescriptor && containingDeclaration.getKind() != ClassKind.INTERFACE) {
@@ -127,15 +140,22 @@ public class JetChangeSignature(project: Project,
} }
TestOnly public fun createChangeInfo(project: Project, TestOnly public fun createChangeInfo(project: Project,
functionDescriptor: FunctionDescriptor, callableDescriptor: CallableDescriptor,
configuration: JetChangeSignatureConfiguration, configuration: JetChangeSignatureConfiguration,
bindingContext: BindingContext, bindingContext: BindingContext,
defaultValueContext: PsiElement): JetChangeInfo? { defaultValueContext: PsiElement): JetChangeInfo? {
val jetChangeSignature = JetChangeSignature(project, functionDescriptor, configuration, bindingContext, defaultValueContext, null) val jetChangeSignature = JetChangeSignature(project, callableDescriptor, configuration, bindingContext, defaultValueContext, null)
val declarations = OverrideResolver.getDeepestSuperDeclarations(functionDescriptor) val declarations = if (callableDescriptor is CallableMemberDescriptor) {
OverrideResolver.getDeepestSuperDeclarations(callableDescriptor)
} else listOf(callableDescriptor)
val adjustedDescriptor = jetChangeSignature.adjustDescriptor(declarations) ?: return null val adjustedDescriptor = jetChangeSignature.adjustDescriptor(declarations) ?: return null
val processor = JetChangeSignatureDialog.createRefactoringProcessorForSilentChangeSignature(project, ChangeSignatureHandler.REFACTORING_NAME, adjustedDescriptor, defaultValueContext) as JetChangeSignatureProcessor val processor = JetChangeSignatureDialog.createRefactoringProcessorForSilentChangeSignature(
project,
ChangeSignatureHandler.REFACTORING_NAME,
adjustedDescriptor,
defaultValueContext
) as JetChangeSignatureProcessor
return processor.getChangeInfo() return processor.getChangeInfo()
} }
@@ -23,6 +23,8 @@ import com.intellij.refactoring.changeSignature.OverriderUsageInfo
import com.intellij.usageView.UsageInfo import com.intellij.usageView.UsageInfo
import org.jetbrains.kotlin.asJava.KotlinLightMethod import org.jetbrains.kotlin.asJava.KotlinLightMethod
import org.jetbrains.kotlin.asJava.LightClassUtil import org.jetbrains.kotlin.asJava.LightClassUtil
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
import org.jetbrains.kotlin.asJava.toLightMethods
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.analyze
@@ -30,10 +32,14 @@ import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.idea.core.CollectingNameValidator import org.jetbrains.kotlin.idea.core.CollectingNameValidator
import org.jetbrains.kotlin.idea.core.KotlinNameSuggester import org.jetbrains.kotlin.idea.core.KotlinNameSuggester
import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.JetFunctionDefinitionUsage import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.JetCallableDefinitionUsage
import org.jetbrains.kotlin.idea.search.declarationsSearch.HierarchySearchRequest
import org.jetbrains.kotlin.idea.search.declarationsSearch.searchOverriders
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.JetCallableDeclaration
import org.jetbrains.kotlin.psi.JetClass import org.jetbrains.kotlin.psi.JetClass
import org.jetbrains.kotlin.psi.JetFunction import org.jetbrains.kotlin.psi.JetFunction
import org.jetbrains.kotlin.psi.JetNamedDeclaration
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import java.util.Collections import java.util.Collections
@@ -41,9 +47,9 @@ import java.util.HashSet
import kotlin.properties.Delegates import kotlin.properties.Delegates
public class JetChangeSignatureData( public class JetChangeSignatureData(
override val baseDescriptor: FunctionDescriptor, override val baseDescriptor: CallableDescriptor,
override val baseDeclaration: PsiElement, override val baseDeclaration: PsiElement,
private val descriptorsForSignatureChange: Collection<FunctionDescriptor> private val descriptorsForSignatureChange: Collection<CallableDescriptor>
) : JetMethodDescriptor { ) : JetMethodDescriptor {
private val parameters: List<JetParameterInfo> private val parameters: List<JetParameterInfo>
override val receiver: JetParameterInfo? override val receiver: JetParameterInfo?
@@ -60,7 +66,7 @@ public class JetChangeSignatureData(
.mapTo(receiver?.let{ arrayListOf(it) } ?: arrayListOf()) { parameterDescriptor -> .mapTo(receiver?.let{ arrayListOf(it) } ?: arrayListOf()) { parameterDescriptor ->
val jetParameter = valueParameters?.get(parameterDescriptor.getIndex()) val jetParameter = valueParameters?.get(parameterDescriptor.getIndex())
JetParameterInfo( JetParameterInfo(
functionDescriptor = baseDescriptor, callableDescriptor = baseDescriptor,
originalIndex = parameterDescriptor.getIndex(), originalIndex = parameterDescriptor.getIndex(),
name = parameterDescriptor.getName().asString(), name = parameterDescriptor.getName().asString(),
type = parameterDescriptor.getType(), type = parameterDescriptor.getType(),
@@ -72,8 +78,8 @@ public class JetChangeSignatureData(
} }
private fun createReceiverInfoIfNeeded(): JetParameterInfo? { private fun createReceiverInfoIfNeeded(): JetParameterInfo? {
val function = baseDeclaration as? JetFunction ?: return null val callable = baseDeclaration as? JetCallableDeclaration ?: return null
val bodyScope = function.getBodyExpression()?.let { it.analyze()[BindingContext.RESOLUTION_SCOPE, it] } val bodyScope = (callable as? JetFunction)?.getBodyExpression()?.let { it.analyze()[BindingContext.RESOLUTION_SCOPE, it] }
val paramNames = baseDescriptor.getValueParameters().map { it.getName().asString() } val paramNames = baseDescriptor.getValueParameters().map { it.getName().asString() }
val validator = bodyScope?.let { bodyScope -> val validator = bodyScope?.let { bodyScope ->
CollectingNameValidator(paramNames) { CollectingNameValidator(paramNames) {
@@ -83,34 +89,37 @@ public class JetChangeSignatureData(
} ?: CollectingNameValidator(paramNames) } ?: CollectingNameValidator(paramNames)
val receiverType = baseDescriptor.getExtensionReceiverParameter()?.getType() ?: return null val receiverType = baseDescriptor.getExtensionReceiverParameter()?.getType() ?: return null
val receiverName = KotlinNameSuggester.suggestNamesByType(receiverType, validator, "receiver").first() val receiverName = KotlinNameSuggester.suggestNamesByType(receiverType, validator, "receiver").first()
return JetParameterInfo(functionDescriptor = baseDescriptor, name = receiverName, type = receiverType) return JetParameterInfo(callableDescriptor = baseDescriptor, name = receiverName, type = receiverType)
} }
override val primaryFunctions: Collection<JetFunctionDefinitionUsage<PsiElement>> by Delegates.lazy { override val primaryCallables: Collection<JetCallableDefinitionUsage<PsiElement>> by Delegates.lazy {
descriptorsForSignatureChange.map { descriptorsForSignatureChange.map {
val declaration = DescriptorToSourceUtilsIde.getAnyDeclaration(baseDeclaration.getProject(), it) val declaration = DescriptorToSourceUtilsIde.getAnyDeclaration(baseDeclaration.getProject(), it)
assert(declaration != null) { "No declaration found for " + baseDescriptor } assert(declaration != null) { "No declaration found for " + baseDescriptor }
JetFunctionDefinitionUsage<PsiElement>(declaration, it, null, null) JetCallableDefinitionUsage<PsiElement>(declaration, it, null, null)
} }
} }
override val originalPrimaryFunction: JetFunctionDefinitionUsage<PsiElement> by Delegates.lazy { override val originalPrimaryCallable: JetCallableDefinitionUsage<PsiElement> by Delegates.lazy {
primaryFunctions.first { it.getDeclaration() == baseDeclaration } primaryCallables.first { it.getDeclaration() == baseDeclaration }
} }
override val affectedFunctions: Collection<UsageInfo> by Delegates.lazy { override val affectedCallables: Collection<UsageInfo> by Delegates.lazy {
primaryFunctions + primaryFunctions.flatMapTo(HashSet<UsageInfo>()) { primaryFunction -> primaryCallables + primaryCallables.flatMapTo(HashSet<UsageInfo>()) { primaryFunction ->
val primaryDeclaration = primaryFunction.getDeclaration() as? JetFunction val primaryDeclaration = primaryFunction.getDeclaration() as? JetCallableDeclaration
val lightMethod = primaryDeclaration?.let { LightClassUtil.getLightClassMethod(it) } val lightMethods = primaryDeclaration?.toLightMethods() ?: Collections.emptyList()
val overrides = lightMethod?.let { OverridingMethodsSearch.search(it).findAll() } ?: Collections.emptyList() lightMethods.flatMap { baseMethod ->
overrides.map { method -> OverridingMethodsSearch
if (method is KotlinLightMethod) { .search(baseMethod)
val overridingDeclaration = method.getOrigin() .map { overridingMethod ->
val overridingDescriptor = overridingDeclaration?.resolveToDescriptor() as FunctionDescriptor if (overridingMethod is KotlinLightMethod) {
JetFunctionDefinitionUsage<PsiElement>(overridingDeclaration, overridingDescriptor, primaryFunction, null) val overridingDeclaration = overridingMethod.namedUnwrappedElement as JetNamedDeclaration
} val overridingDescriptor = overridingDeclaration.resolveToDescriptor() as CallableDescriptor
else OverriderUsageInfo(method, lightMethod, true, true, true) JetCallableDefinitionUsage<PsiElement>(overridingDeclaration, overridingDescriptor, primaryFunction, null)
}.filterNotNullTo(HashSet<UsageInfo>()) }
else OverriderUsageInfo(overridingMethod, baseMethod, true, true, true)
}.filterNotNullTo(HashSet<UsageInfo>())
}
} }
} }
@@ -416,7 +416,7 @@ public class JetChangeSignatureDialog extends ChangeSignatureDialogBase<
getMethodName(), getMethodName(),
myDefaultValueContext myDefaultValueContext
); );
return changeInfo.getNewSignature(getMethodDescriptor().getOriginalPrimaryFunction()); return changeInfo.getNewSignature(getMethodDescriptor().getOriginalPrimaryCallable());
} }
@Override @Override
@@ -34,10 +34,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly; import org.jetbrains.annotations.TestOnly;
import org.jetbrains.kotlin.asJava.AsJavaPackage; import org.jetbrains.kotlin.asJava.AsJavaPackage;
import org.jetbrains.kotlin.descriptors.ClassDescriptor; import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage; import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage;
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils; import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils;
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde; import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde;
@@ -57,44 +54,44 @@ public class JetChangeSignatureHandler implements ChangeSignatureHandler {
@Nullable @Nullable
public static PsiElement findTargetForRefactoring(@NotNull PsiElement element) { public static PsiElement findTargetForRefactoring(@NotNull PsiElement element) {
if (PsiTreeUtil.getParentOfType(element, JetParameterList.class) != null) { if (PsiTreeUtil.getParentOfType(element, JetParameterList.class) != null) {
return PsiTreeUtil.getParentOfType(element, JetFunction.class, JetClass.class); return PsiTreeUtil.getParentOfType(element, JetFunction.class, JetProperty.class, JetClass.class);
} }
JetTypeParameterList typeParameterList = PsiTreeUtil.getParentOfType(element, JetTypeParameterList.class); JetTypeParameterList typeParameterList = PsiTreeUtil.getParentOfType(element, JetTypeParameterList.class);
if (typeParameterList != null) { if (typeParameterList != null) {
return PsiTreeUtil.getParentOfType(typeParameterList, JetFunction.class, JetClass.class); return PsiTreeUtil.getParentOfType(typeParameterList, JetFunction.class, JetProperty.class, JetClass.class);
} }
PsiElement elementParent = element.getParent(); PsiElement elementParent = element.getParent();
if (elementParent instanceof JetNamedFunction && ((JetNamedFunction) elementParent).getNameIdentifier() == element) { if ((elementParent instanceof JetNamedFunction || elementParent instanceof JetClass || elementParent instanceof JetProperty)
return elementParent; && ((JetNamedDeclaration) elementParent).getNameIdentifier() == element) return elementParent;
}
if (elementParent instanceof JetClass && ((JetClass) elementParent).getNameIdentifier() == element) {
return elementParent;
}
if (elementParent instanceof JetSecondaryConstructor &&
((JetSecondaryConstructor) elementParent).getConstructorKeyword() == element) {
return elementParent;
}
if (elementParent instanceof JetSecondaryConstructor &&
((JetSecondaryConstructor) elementParent).getConstructorKeyword() == element) return elementParent;
JetExpression calleeExpr;
JetCallElement call = PsiTreeUtil.getParentOfType(element, JetCallElement call = PsiTreeUtil.getParentOfType(element,
JetCallExpression.class, JetCallExpression.class,
JetDelegatorToSuperCall.class, JetDelegatorToSuperCall.class,
JetConstructorDelegationCall.class); JetConstructorDelegationCall.class);
if (call == null) return null; if (call != null) {
calleeExpr = call.getCalleeExpression();
JetExpression receiverExpr = call.getCalleeExpression();
if (receiverExpr instanceof JetConstructorCalleeExpression) {
receiverExpr = ((JetConstructorCalleeExpression) receiverExpr).getConstructorReferenceExpression();
} }
if (receiverExpr instanceof JetSimpleNameExpression || receiverExpr instanceof JetConstructorDelegationReferenceExpression) { else {
calleeExpr = PsiTreeUtil.getParentOfType(element, JetSimpleNameExpression.class);
}
if (calleeExpr instanceof JetConstructorCalleeExpression) {
calleeExpr = ((JetConstructorCalleeExpression) calleeExpr).getConstructorReferenceExpression();
}
if (calleeExpr instanceof JetSimpleNameExpression || calleeExpr instanceof JetConstructorDelegationReferenceExpression) {
JetElement jetElement = PsiTreeUtil.getParentOfType(element, JetElement.class); JetElement jetElement = PsiTreeUtil.getParentOfType(element, JetElement.class);
if (jetElement == null) return null; if (jetElement == null) return null;
BindingContext bindingContext = ResolvePackage.analyze(jetElement, BodyResolveMode.FULL); BindingContext bindingContext = ResolvePackage.analyze(jetElement, BodyResolveMode.FULL);
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, (JetReferenceExpression) receiverExpr); DeclarationDescriptor descriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, (JetReferenceExpression) calleeExpr);
if (descriptor instanceof ClassDescriptor || descriptor instanceof FunctionDescriptor) return receiverExpr; if (descriptor instanceof ClassDescriptor || descriptor instanceof CallableDescriptor) return calleeExpr;
} }
return null; return null;
@@ -108,19 +105,19 @@ public class JetChangeSignatureHandler implements ChangeSignatureHandler {
) { ) {
BindingContext bindingContext = ResolvePackage.analyze(element, BodyResolveMode.FULL); BindingContext bindingContext = ResolvePackage.analyze(element, BodyResolveMode.FULL);
FunctionDescriptor functionDescriptor = findDescriptor(element, project, editor, bindingContext); CallableDescriptor callableDescriptor = findDescriptor(element, project, editor, bindingContext);
if (functionDescriptor == null) { if (callableDescriptor == null) {
return; return;
} }
if (functionDescriptor instanceof JavaCallableMemberDescriptor) { if (callableDescriptor instanceof JavaCallableMemberDescriptor) {
PsiElement declaration = DescriptorToSourceUtilsIde.INSTANCE$.getAnyDeclaration(project, functionDescriptor); PsiElement declaration = DescriptorToSourceUtilsIde.INSTANCE$.getAnyDeclaration(project, callableDescriptor);
assert declaration instanceof PsiMethod : "PsiMethod expected: " + functionDescriptor; assert declaration instanceof PsiMethod : "PsiMethod expected: " + callableDescriptor;
ChangeSignatureUtil.invokeChangeSignatureOn((PsiMethod) declaration, project); ChangeSignatureUtil.invokeChangeSignatureOn((PsiMethod) declaration, project);
return; return;
} }
if (TasksPackage.isDynamic(functionDescriptor)) { if (TasksPackage.isDynamic(callableDescriptor)) {
if (editor != null) { if (editor != null) {
CodeInsightUtils.showErrorHint( CodeInsightUtils.showErrorHint(
project, project,
@@ -133,7 +130,7 @@ public class JetChangeSignatureHandler implements ChangeSignatureHandler {
return; return;
} }
runChangeSignature(project, functionDescriptor, emptyConfiguration(), bindingContext, context, null); runChangeSignature(project, callableDescriptor, emptyConfiguration(), bindingContext, context, null);
} }
@TestOnly @TestOnly
@@ -208,7 +205,7 @@ public class JetChangeSignatureHandler implements ChangeSignatureHandler {
} }
@Nullable @Nullable
public static FunctionDescriptor findDescriptor( public static CallableDescriptor findDescriptor(
@NotNull PsiElement element, @NotNull PsiElement element,
@NotNull Project project, @NotNull Project project,
@Nullable Editor editor, @Nullable Editor editor,
@@ -244,6 +241,9 @@ public class JetChangeSignatureHandler implements ChangeSignatureHandler {
return (FunctionDescriptor) descriptor; return (FunctionDescriptor) descriptor;
} }
else if (descriptor instanceof PropertyDescriptor) {
return (PropertyDescriptor) descriptor;
}
else { else {
String message = RefactoringBundle.getCannotRefactorMessage(JetRefactoringBundle.message( String message = RefactoringBundle.getCannotRefactorMessage(JetRefactoringBundle.message(
"error.wrong.caret.position.function.or.constructor.name")); "error.wrong.caret.position.function.or.constructor.name"));
@@ -21,7 +21,10 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.Ref;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.changeSignature.*; import com.intellij.refactoring.changeSignature.ChangeSignatureProcessorBase;
import com.intellij.refactoring.changeSignature.ChangeSignatureUsageProcessor;
import com.intellij.refactoring.changeSignature.JavaChangeInfo;
import com.intellij.refactoring.changeSignature.JavaChangeSignatureUsageProcessor;
import com.intellij.refactoring.rename.RenameUtil; import com.intellij.refactoring.rename.RenameUtil;
import com.intellij.refactoring.ui.ConflictsDialog; import com.intellij.refactoring.ui.ConflictsDialog;
import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageInfo;
@@ -29,8 +32,6 @@ import com.intellij.usageView.UsageViewDescriptor;
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.KotlinPackage; import kotlin.KotlinPackage;
import kotlin.Pair;
import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.JetUsageInfo; import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.JetUsageInfo;
import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.KotlinWrapperForJavaUsageInfos; import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.KotlinWrapperForJavaUsageInfos;
@@ -62,10 +63,13 @@ public class JetChangeSignatureProcessor extends ChangeSignatureProcessorBase {
protected UsageInfo[] findUsages() { protected UsageInfo[] findUsages() {
List<UsageInfo> allUsages = new ArrayList<UsageInfo>(); List<UsageInfo> allUsages = new ArrayList<UsageInfo>();
JavaChangeInfo javaChangeInfo = getChangeInfo().getOrCreateJavaChangeInfo(); List<JavaChangeInfo> javaChangeInfos = getChangeInfo().getOrCreateJavaChangeInfos();
if (javaChangeInfo != null) { if (javaChangeInfos != null) {
UsageInfo[] javaUsages = new JavaChangeSignatureUsageProcessor().findUsages(javaChangeInfo); JavaChangeSignatureUsageProcessor javaProcessor = new JavaChangeSignatureUsageProcessor();
allUsages.add(new KotlinWrapperForJavaUsageInfos(javaUsages, getChangeInfo().getMethod())); for (JavaChangeInfo javaChangeInfo : javaChangeInfos) {
UsageInfo[] javaUsages = javaProcessor.findUsages(javaChangeInfo);
allUsages.add(new KotlinWrapperForJavaUsageInfos(javaChangeInfo, javaUsages, getChangeInfo().getMethod()));
}
} }
KotlinPackage.filterIsInstanceTo(super.findUsages(), allUsages, JetUsageInfo.class); KotlinPackage.filterIsInstanceTo(super.findUsages(), allUsages, JetUsageInfo.class);
@@ -21,9 +21,9 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.Ref;
import com.intellij.psi.*; import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.search.searches.OverridingMethodsSearch;
import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.SearchScope; import com.intellij.psi.search.SearchScope;
import com.intellij.psi.search.searches.OverridingMethodsSearch;
import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.changeSignature.ChangeInfo; import com.intellij.refactoring.changeSignature.ChangeInfo;
@@ -40,7 +40,6 @@ 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 jet.runtime.typeinfo.JetValueParameter;
import kotlin.KotlinPackage; import kotlin.KotlinPackage;
import kotlin.Unit; import kotlin.Unit;
import kotlin.jvm.functions.Function1; import kotlin.jvm.functions.Function1;
@@ -56,13 +55,13 @@ import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde;
import org.jetbrains.kotlin.idea.codeInsight.JetFileReferencesResolver; import org.jetbrains.kotlin.idea.codeInsight.JetFileReferencesResolver;
import org.jetbrains.kotlin.idea.core.refactoring.RefactoringPackage; import org.jetbrains.kotlin.idea.core.refactoring.RefactoringPackage;
import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.*; import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.*;
import org.jetbrains.kotlin.idea.refactoring.rename.UnresolvableConventionViolationUsageInfo;
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference; import org.jetbrains.kotlin.idea.references.JetSimpleNameReference;
import org.jetbrains.kotlin.idea.search.usagesSearch.UsagesSearchPackage; import org.jetbrains.kotlin.idea.search.usagesSearch.UsagesSearchPackage;
import org.jetbrains.kotlin.kdoc.psi.impl.KDocName; import org.jetbrains.kotlin.kdoc.psi.impl.KDocName;
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.psiUtil.PsiUtilPackage;
import org.jetbrains.kotlin.psi.typeRefHelpers.TypeRefHelpersPackage; 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;
@@ -72,7 +71,6 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage; import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage;
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo; import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind;
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode; import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode;
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.ReceiverValue;
@@ -80,10 +78,7 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ThisReceiver;
import org.jetbrains.kotlin.types.JetType; import org.jetbrains.kotlin.types.JetType;
import org.jetbrains.kotlin.types.TypeUtils; import org.jetbrains.kotlin.types.TypeUtils;
import java.util.Collections; import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsageProcessor { public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsageProcessor {
@Override @Override
@@ -104,8 +99,8 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
private static void findAllMethodUsages(JetChangeInfo changeInfo, Set<UsageInfo> result) { private static void findAllMethodUsages(JetChangeInfo changeInfo, Set<UsageInfo> result) {
for (UsageInfo functionUsageInfo : ChangeSignaturePackage.getAffectedFunctions(changeInfo)) { for (UsageInfo functionUsageInfo : ChangeSignaturePackage.getAffectedFunctions(changeInfo)) {
if (functionUsageInfo instanceof JetFunctionDefinitionUsage) { if (functionUsageInfo instanceof JetCallableDefinitionUsage) {
findOneMethodUsages((JetFunctionDefinitionUsage) functionUsageInfo, changeInfo, result); findOneMethodUsages((JetCallableDefinitionUsage) functionUsageInfo, changeInfo, result);
} }
else { else {
result.add(functionUsageInfo); result.add(functionUsageInfo);
@@ -123,7 +118,7 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
JetCallElement callElement = PsiTreeUtil.getParentOfType(element, JetCallElement.class); JetCallElement callElement = PsiTreeUtil.getParentOfType(element, JetCallElement.class);
JetExpression calleeExpression = callElement != null ? callElement.getCalleeExpression() : null; JetExpression calleeExpression = callElement != null ? callElement.getCalleeExpression() : null;
if (calleeExpression != null && PsiTreeUtil.isAncestor(calleeExpression, element, false)) { if (calleeExpression != null && PsiTreeUtil.isAncestor(calleeExpression, element, false)) {
result.add(new JetFunctionCallUsage(callElement, changeInfo.getMethodDescriptor().getOriginalPrimaryFunction())); result.add(new JetFunctionCallUsage(callElement, changeInfo.getMethodDescriptor().getOriginalPrimaryCallable()));
} }
} }
} }
@@ -131,7 +126,7 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
} }
private static void findOneMethodUsages( private static void findOneMethodUsages(
@NotNull JetFunctionDefinitionUsage<?> functionUsageInfo, @NotNull JetCallableDefinitionUsage<?> functionUsageInfo,
final JetChangeInfo changeInfo, final JetChangeInfo changeInfo,
final Set<UsageInfo> result final Set<UsageInfo> result
) { ) {
@@ -160,6 +155,9 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
if (parent instanceof JetConstructorCalleeExpression && parent.getParent() instanceof JetDelegatorToSuperCall) if (parent instanceof JetConstructorCalleeExpression && parent.getParent() instanceof JetDelegatorToSuperCall)
result.add(new JetFunctionCallUsage((JetDelegatorToSuperCall)parent.getParent(), functionUsageInfo)); result.add(new JetFunctionCallUsage((JetDelegatorToSuperCall)parent.getParent(), functionUsageInfo));
} }
else if (element instanceof JetSimpleNameExpression && functionPsi instanceof JetProperty) {
result.add(new JetPropertyCallUsage((JetSimpleNameExpression) element));
}
} }
} }
@@ -168,9 +166,7 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
if (oldName != null) if (oldName != null)
TextOccurrencesUtil.findNonCodeUsages(functionPsi, oldName, true, true, changeInfo.getNewName(), result); TextOccurrencesUtil.findNonCodeUsages(functionPsi, oldName, true, true, changeInfo.getNewName(), result);
List<JetParameter> oldParameters = functionPsi instanceof JetFunction List<JetParameter> oldParameters = PsiUtilPackage.getValueParameters((JetNamedDeclaration) functionPsi);
? ((JetFunction) functionPsi).getValueParameters()
: ((JetClass) functionPsi).getPrimaryConstructorParameters();
JetParameterInfo newReceiverInfo = changeInfo.getReceiverParameterInfo(); JetParameterInfo newReceiverInfo = changeInfo.getReceiverParameterInfo();
@@ -221,7 +217,7 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
} }
private static void processInternalReferences( private static void processInternalReferences(
JetFunctionDefinitionUsage functionUsageInfo, JetCallableDefinitionUsage functionUsageInfo,
JetTreeVisitor<BindingContext> visitor JetTreeVisitor<BindingContext> visitor
) { ) {
JetFunction jetFunction = (JetFunction) functionUsageInfo.getDeclaration(); JetFunction jetFunction = (JetFunction) functionUsageInfo.getDeclaration();
@@ -238,12 +234,12 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
} }
private static void findOriginalReceiversUsages( private static void findOriginalReceiversUsages(
@NotNull final JetFunctionDefinitionUsage<?> functionUsageInfo, @NotNull final JetCallableDefinitionUsage<?> functionUsageInfo,
@NotNull final Set<UsageInfo> result, @NotNull final Set<UsageInfo> result,
@NotNull final JetChangeInfo changeInfo @NotNull final JetChangeInfo changeInfo
) { ) {
final JetParameterInfo originalReceiverInfo = changeInfo.getMethodDescriptor().getReceiver(); final JetParameterInfo originalReceiverInfo = changeInfo.getMethodDescriptor().getReceiver();
final FunctionDescriptor functionDescriptor = functionUsageInfo.getOriginalFunctionDescriptor(); final CallableDescriptor callableDescriptor = functionUsageInfo.getOriginalCallableDescriptor();
processInternalReferences( processInternalReferences(
functionUsageInfo, functionUsageInfo,
new JetTreeVisitor<BindingContext>() { new JetTreeVisitor<BindingContext>() {
@@ -254,7 +250,7 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
if (originalReceiverInfo != null && !changeInfo.hasParameter(originalReceiverInfo)) return; if (originalReceiverInfo != null && !changeInfo.hasParameter(originalReceiverInfo)) return;
if (!(expression.getParent() instanceof JetThisExpression)) return; if (!(expression.getParent() instanceof JetThisExpression)) return;
if (receiverDescriptor == functionDescriptor.getExtensionReceiverParameter()) { if (receiverDescriptor == callableDescriptor.getExtensionReceiverParameter()) {
assert originalReceiverInfo != null : "No original receiver info provided: " + functionUsageInfo.getDeclaration().getText(); assert originalReceiverInfo != null : "No original receiver info provided: " + functionUsageInfo.getDeclaration().getText();
result.add(new JetParameterUsage(expression, originalReceiverInfo, functionUsageInfo)); result.add(new JetParameterUsage(expression, originalReceiverInfo, functionUsageInfo));
} }
@@ -270,7 +266,7 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
@NotNull ThisReceiver receiverValue @NotNull ThisReceiver receiverValue
) { ) {
DeclarationDescriptor targetDescriptor = receiverValue.getDeclarationDescriptor(); DeclarationDescriptor targetDescriptor = receiverValue.getDeclarationDescriptor();
if (targetDescriptor == functionDescriptor) { if (targetDescriptor == callableDescriptor) {
assert originalReceiverInfo != null : "No original receiver info provided: " + functionUsageInfo.getDeclaration().getText(); assert originalReceiverInfo != null : "No original receiver info provided: " + functionUsageInfo.getDeclaration().getText();
result.add(new JetImplicitThisToParameterUsage(callElement, originalReceiverInfo, functionUsageInfo)); result.add(new JetImplicitThisToParameterUsage(callElement, originalReceiverInfo, functionUsageInfo));
} }
@@ -407,7 +403,7 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
PsiElement function = info.getMethod(); PsiElement function = info.getMethod();
PsiElement element = function != null ? function : changeInfo.getContext(); PsiElement element = function != null ? function : changeInfo.getContext();
BindingContext bindingContext = ResolvePackage.analyze((JetElement) element, BodyResolveMode.FULL); BindingContext bindingContext = ResolvePackage.analyze((JetElement) element, BodyResolveMode.FULL);
FunctionDescriptor oldDescriptor = ChangeSignaturePackage.getOriginalBaseFunctionDescriptor(changeInfo); CallableDescriptor oldDescriptor = ChangeSignaturePackage.getOriginalBaseFunctionDescriptor(changeInfo);
DeclarationDescriptor containingDeclaration = oldDescriptor.getContainingDeclaration(); DeclarationDescriptor containingDeclaration = oldDescriptor.getContainingDeclaration();
JetScope parametersScope = null; JetScope parametersScope = null;
@@ -416,17 +412,21 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
else if (function instanceof JetFunction) else if (function instanceof JetFunction)
parametersScope = org.jetbrains.kotlin.idea.refactoring.RefactoringPackage.getBodyScope((JetFunction) function, bindingContext); parametersScope = org.jetbrains.kotlin.idea.refactoring.RefactoringPackage.getBodyScope((JetFunction) function, bindingContext);
JetScope functionScope = org.jetbrains.kotlin.idea.refactoring.RefactoringPackage.getContainingScope(oldDescriptor, bindingContext); JetScope callableScope = org.jetbrains.kotlin.idea.refactoring.RefactoringPackage.getContainingScope(oldDescriptor, bindingContext);
JetMethodDescriptor.Kind kind = ChangeSignaturePackage.getKind(changeInfo); JetMethodDescriptor.Kind kind = ChangeSignaturePackage.getKind(changeInfo);
if (!kind.getIsConstructor() && functionScope != null && !info.getNewName().isEmpty()) { if (!kind.getIsConstructor() && callableScope != null && !info.getNewName().isEmpty()) {
for (FunctionDescriptor conflict : functionScope.getFunctions(Name.identifier(info.getNewName()))) { Name newName = Name.identifier(info.getNewName());
Collection<? extends CallableDescriptor> conflicts = oldDescriptor instanceof FunctionDescriptor
? callableScope.getFunctions(newName)
: callableScope.getProperties(newName);
for (CallableDescriptor conflict : conflicts) {
if (conflict == oldDescriptor) continue; if (conflict == oldDescriptor) continue;
PsiElement conflictElement = DescriptorToSourceUtils.descriptorToDeclaration(conflict); PsiElement conflictElement = DescriptorToSourceUtils.descriptorToDeclaration(conflict);
if (conflictElement == changeInfo.getMethod()) continue; if (conflictElement == changeInfo.getMethod()) continue;
if (getFunctionParameterTypes(conflict).equals(getFunctionParameterTypes(oldDescriptor))) { if (getCallableParameterTypes(conflict).equals(getCallableParameterTypes(oldDescriptor))) {
result.putValue(conflictElement, "Function already exists: '" + DescriptorRenderer.SHORT_NAMES_IN_TYPES.render(conflict) + "'"); result.putValue(conflictElement, "Function already exists: '" + DescriptorRenderer.SHORT_NAMES_IN_TYPES.render(conflict) + "'");
break; break;
} }
@@ -464,7 +464,7 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
JetParameterInfo newReceiverInfo = changeInfo.getReceiverParameterInfo(); JetParameterInfo newReceiverInfo = changeInfo.getReceiverParameterInfo();
JetParameterInfo originalReceiverInfo = changeInfo.getMethodDescriptor().getReceiver(); JetParameterInfo originalReceiverInfo = changeInfo.getMethodDescriptor().getReceiver();
if (function instanceof JetNamedFunction && newReceiverInfo != originalReceiverInfo) { if (function instanceof JetCallableDeclaration && newReceiverInfo != originalReceiverInfo) {
findReceiverIntroducingConflicts(result, function, newReceiverInfo); findReceiverIntroducingConflicts(result, function, newReceiverInfo);
findInternalExplicitReceiverConflicts(refUsages.get(), result, originalReceiverInfo); findInternalExplicitReceiverConflicts(refUsages.get(), result, originalReceiverInfo);
findThisLabelConflicts((JetChangeInfo) info, refUsages, result, changeInfo, function); findThisLabelConflicts((JetChangeInfo) info, refUsages, result, changeInfo, function);
@@ -525,10 +525,9 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
) { ) {
if (originalReceiverInfo == null) { if (originalReceiverInfo == null) {
for (UsageInfo usageInfo : usages) { for (UsageInfo usageInfo : usages) {
if (!(usageInfo instanceof JetFunctionCallUsage)) continue; if (!(usageInfo instanceof JetFunctionCallUsage || usageInfo instanceof JetPropertyCallUsage)) continue;
JetFunctionCallUsage callUsage = (JetFunctionCallUsage) usageInfo; JetElement callElement = (JetElement) usageInfo.getElement();
JetElement callElement = callUsage.getElement();
if (callElement == null) continue; if (callElement == null) continue;
PsiElement parent = callElement.getParent(); PsiElement parent = callElement.getParent();
@@ -546,7 +545,7 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
PsiElement callable, PsiElement callable,
JetParameterInfo newReceiverInfo JetParameterInfo newReceiverInfo
) { ) {
if (newReceiverInfo != null && ((JetNamedFunction) callable).getBodyExpression() != null) { if (newReceiverInfo != null && (callable instanceof JetNamedFunction) && ((JetNamedFunction) callable).getBodyExpression() != null) {
Map<JetReferenceExpression, BindingContext> noReceiverRefToContext = KotlinPackage.filter( Map<JetReferenceExpression, BindingContext> noReceiverRefToContext = KotlinPackage.filter(
JetFileReferencesResolver.INSTANCE$.resolve((JetNamedFunction) callable, true, true), JetFileReferencesResolver.INSTANCE$.resolve((JetNamedFunction) callable, true, true),
new Function1<Map.Entry<? extends JetReferenceExpression, ? extends BindingContext>, Boolean>() { new Function1<Map.Entry<? extends JetReferenceExpression, ? extends BindingContext>, Boolean>() {
@@ -606,7 +605,7 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
} }
} }
private static List<JetType> getFunctionParameterTypes(FunctionDescriptor descriptor) { private static List<JetType> getCallableParameterTypes(CallableDescriptor descriptor) {
return ContainerUtil.map(descriptor.getValueParameters(), new Function<ValueParameterDescriptor, JetType>() { return ContainerUtil.map(descriptor.getValueParameters(), new Function<ValueParameterDescriptor, JetType>() {
@Override @Override
public JetType fun(ValueParameterDescriptor descriptor) { public JetType fun(ValueParameterDescriptor descriptor) {
@@ -710,26 +709,33 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
boolean isJavaMethodUsage = isJavaMethodUsage(usageInfo); boolean isJavaMethodUsage = isJavaMethodUsage(usageInfo);
if (usageInfo instanceof KotlinWrapperForJavaUsageInfos) { if (usageInfo instanceof KotlinWrapperForJavaUsageInfos) {
JavaChangeInfo javaChangeInfo = ((JetChangeInfo) changeInfo).getOrCreateJavaChangeInfo(); List<JavaChangeInfo> javaChangeInfos = ((JetChangeInfo) changeInfo).getOrCreateJavaChangeInfos();
assert javaChangeInfo != null : "JavaChangeInfo not found: " + method.getText(); assert javaChangeInfos != null : "JavaChangeInfo not found: " + method.getText();
UsageInfo[] javaUsageInfos = ((KotlinWrapperForJavaUsageInfos) usageInfo).getJavaUsageInfos();
KotlinWrapperForJavaUsageInfos wrapperForJavaUsageInfos = (KotlinWrapperForJavaUsageInfos) usageInfo;
UsageInfo[] javaUsageInfos = wrapperForJavaUsageInfos.getJavaUsageInfos();
ChangeSignatureUsageProcessor[] processors = ChangeSignatureUsageProcessor.EP_NAME.getExtensions(); ChangeSignatureUsageProcessor[] processors = ChangeSignatureUsageProcessor.EP_NAME.getExtensions();
NullabilityPropagator nullabilityPropagator = new NullabilityPropagator(javaChangeInfo.getMethod()); for (JavaChangeInfo javaChangeInfo : javaChangeInfos) {
// Match names so that getter/setter usages are not confused with each other
if (!javaChangeInfo.getOldName().equals(wrapperForJavaUsageInfos.getJavaChangeInfo().getOldName())) continue;
for (UsageInfo usage : javaUsageInfos) { NullabilityPropagator nullabilityPropagator = new NullabilityPropagator(javaChangeInfo.getMethod());
if (usage instanceof OverriderUsageInfo && beforeMethodChange) continue;
for (ChangeSignatureUsageProcessor processor : processors) { for (UsageInfo usage : javaUsageInfos) {
if (processor instanceof JetChangeSignatureUsageProcessor) continue; if (usage instanceof OverriderUsageInfo && beforeMethodChange) continue;
if (usage instanceof OverriderUsageInfo) { for (ChangeSignatureUsageProcessor processor : processors) {
processor.processUsage(javaChangeInfo, usage, true, javaUsageInfos); if (processor instanceof JetChangeSignatureUsageProcessor) continue;
if (usage instanceof OverriderUsageInfo) {
processor.processUsage(javaChangeInfo, usage, true, javaUsageInfos);
}
if (processor.processUsage(javaChangeInfo, usage, beforeMethodChange, javaUsageInfos)) break;
} }
if (processor.processUsage(javaChangeInfo, usage, beforeMethodChange, javaUsageInfos)) break; if (usage instanceof OverriderUsageInfo) {
} PsiMethod overridingMethod = ((OverriderUsageInfo) usage).getOverridingMethod();
if (usage instanceof OverriderUsageInfo) { if (overridingMethod != null && !(overridingMethod instanceof KotlinLightMethod)) {
PsiMethod overridingMethod = ((OverriderUsageInfo)usage).getOverridingMethod(); nullabilityPropagator.processMethod(overridingMethod);
if (overridingMethod != null && !(overridingMethod instanceof KotlinLightMethod)) { }
nullabilityPropagator.processMethod(overridingMethod);
} }
} }
} }
@@ -792,7 +798,7 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
if (!(changeInfo instanceof JetChangeInfo)) return false; if (!(changeInfo instanceof JetChangeInfo)) return false;
JetChangeInfo jetChangeInfo = (JetChangeInfo) changeInfo; JetChangeInfo jetChangeInfo = (JetChangeInfo) changeInfo;
for (JetFunctionDefinitionUsage primaryFunction : jetChangeInfo.getMethodDescriptor().getPrimaryFunctions()) { for (JetCallableDefinitionUsage primaryFunction : jetChangeInfo.getMethodDescriptor().getPrimaryCallables()) {
primaryFunction.processUsage(jetChangeInfo, primaryFunction.getDeclaration()); primaryFunction.processUsage(jetChangeInfo, primaryFunction.getDeclaration());
} }
jetChangeInfo.primaryMethodUpdated(); jetChangeInfo.primaryMethodUpdated();
@@ -19,10 +19,10 @@ package org.jetbrains.kotlin.idea.refactoring.changeSignature
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.refactoring.changeSignature.MethodDescriptor import com.intellij.refactoring.changeSignature.MethodDescriptor
import com.intellij.usageView.UsageInfo import com.intellij.usageView.UsageInfo
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.JetFunctionDefinitionUsage
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.JetCallableDefinitionUsage
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
public trait JetMethodDescriptor : MethodDescriptor<JetParameterInfo, Visibility> { public trait JetMethodDescriptor : MethodDescriptor<JetParameterInfo, Visibility> {
@@ -42,11 +42,11 @@ public trait JetMethodDescriptor : MethodDescriptor<JetParameterInfo, Visibility
} }
val baseDeclaration: PsiElement val baseDeclaration: PsiElement
val baseDescriptor: FunctionDescriptor val baseDescriptor: CallableDescriptor
val originalPrimaryFunction: JetFunctionDefinitionUsage<PsiElement> val originalPrimaryCallable: JetCallableDefinitionUsage<PsiElement>
val primaryFunctions: Collection<JetFunctionDefinitionUsage<PsiElement>> val primaryCallables: Collection<JetCallableDefinitionUsage<PsiElement>>
val affectedFunctions: Collection<UsageInfo> val affectedCallables: Collection<UsageInfo>
val receiver: JetParameterInfo? val receiver: JetParameterInfo?
} }
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.core.compareDescriptors import org.jetbrains.kotlin.idea.core.compareDescriptors
import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.JetFunctionDefinitionUsage import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.JetCallableDefinitionUsage
import org.jetbrains.kotlin.idea.references.JetReference import org.jetbrains.kotlin.idea.references.JetReference
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
@@ -36,7 +36,7 @@ import org.jetbrains.kotlin.types.JetType
import java.util.LinkedHashMap import java.util.LinkedHashMap
public class JetParameterInfo( public class JetParameterInfo(
val functionDescriptor: FunctionDescriptor, val callableDescriptor: CallableDescriptor,
val originalIndex: Int = -1, val originalIndex: Int = -1,
private var name: String, private var name: String,
type: JetType? = null, type: JetType? = null,
@@ -61,7 +61,7 @@ public class JetParameterInfo(
object : JetTreeVisitorVoid() { object : JetTreeVisitorVoid() {
private fun selfParameterOrNull(parameter: DeclarationDescriptor?): ValueParameterDescriptor? { private fun selfParameterOrNull(parameter: DeclarationDescriptor?): ValueParameterDescriptor? {
return if (parameter is ValueParameterDescriptor && return if (parameter is ValueParameterDescriptor &&
compareDescriptors(project, parameter.getContainingDeclaration(), functionDescriptor)) { compareDescriptors(project, parameter.getContainingDeclaration(), callableDescriptor)) {
parameter parameter
} else null } else null
} }
@@ -69,12 +69,12 @@ public class JetParameterInfo(
private fun selfReceiverOrNull(receiverDescriptor: DeclarationDescriptor?): DeclarationDescriptor? { private fun selfReceiverOrNull(receiverDescriptor: DeclarationDescriptor?): DeclarationDescriptor? {
if (compareDescriptors(project, if (compareDescriptors(project,
receiverDescriptor, receiverDescriptor,
functionDescriptor.getExtensionReceiverParameter()?.getContainingDeclaration())) { callableDescriptor.getExtensionReceiverParameter()?.getContainingDeclaration())) {
return receiverDescriptor return receiverDescriptor
} }
if (compareDescriptors(project, if (compareDescriptors(project,
receiverDescriptor, receiverDescriptor,
functionDescriptor.getDispatchReceiverParameter()?.getContainingDeclaration())) { callableDescriptor.getDispatchReceiverParameter()?.getContainingDeclaration())) {
return receiverDescriptor return receiverDescriptor
} }
return null return null
@@ -93,7 +93,7 @@ public class JetParameterInfo(
val descriptor = ref.resolveToDescriptors(context).singleOrNull() val descriptor = ref.resolveToDescriptors(context).singleOrNull()
if (descriptor is ValueParameterDescriptor) return selfParameterOrNull(descriptor) if (descriptor is ValueParameterDescriptor) return selfParameterOrNull(descriptor)
if (descriptor is PropertyDescriptor && functionDescriptor is ConstructorDescriptor) { if (descriptor is PropertyDescriptor && callableDescriptor is ConstructorDescriptor) {
val parameter = DescriptorToSourceUtils.getSourceFromDescriptor(descriptor) as? JetParameter val parameter = DescriptorToSourceUtils.getSourceFromDescriptor(descriptor) as? JetParameter
return parameter?.let { selfParameterOrNull(context[BindingContext.VALUE_PARAMETER, it]) } return parameter?.let { selfParameterOrNull(context[BindingContext.VALUE_PARAMETER, it]) }
} }
@@ -149,20 +149,20 @@ public class JetParameterInfo(
throw UnsupportedOperationException() throw UnsupportedOperationException()
} }
public fun renderType(parameterIndex: Int, inheritedFunction: JetFunctionDefinitionUsage<*>): String { public fun renderType(parameterIndex: Int, inheritedCallable: JetCallableDefinitionUsage<*>): String {
val typeSubstitutor = inheritedFunction.getOrCreateTypeSubstitutor() ?: return currentTypeText val typeSubstitutor = inheritedCallable.getOrCreateTypeSubstitutor() ?: return currentTypeText
val currentBaseFunction = inheritedFunction.getBaseFunction().getCurrentFunctionDescriptor() ?: return currentTypeText val currentBaseFunction = inheritedCallable.getBaseFunction().getCurrentCallableDescriptor() ?: return currentTypeText
val parameterType = currentBaseFunction.getValueParameters().get(parameterIndex).getType() val parameterType = currentBaseFunction.getValueParameters().get(parameterIndex).getType()
return parameterType.renderTypeWithSubstitution(typeSubstitutor, currentTypeText, true) return parameterType.renderTypeWithSubstitution(typeSubstitutor, currentTypeText, true)
} }
public fun getInheritedName(inheritedFunction: JetFunctionDefinitionUsage<*>): String { public fun getInheritedName(inheritedCallable: JetCallableDefinitionUsage<*>): String {
if (!inheritedFunction.isInherited()) return name if (!inheritedCallable.isInherited()) return name
val baseFunction = inheritedFunction.getBaseFunction() val baseFunction = inheritedCallable.getBaseFunction()
val baseFunctionDescriptor = baseFunction.getOriginalFunctionDescriptor() val baseFunctionDescriptor = baseFunction.getOriginalCallableDescriptor()
val inheritedFunctionDescriptor = inheritedFunction.getOriginalFunctionDescriptor() val inheritedFunctionDescriptor = inheritedCallable.getOriginalCallableDescriptor()
val inheritedParameterDescriptors = inheritedFunctionDescriptor.getValueParameters() val inheritedParameterDescriptors = inheritedFunctionDescriptor.getValueParameters()
if (originalIndex < 0 if (originalIndex < 0
|| originalIndex >= baseFunctionDescriptor.getValueParameters().size() || originalIndex >= baseFunctionDescriptor.getValueParameters().size()
@@ -177,18 +177,18 @@ public class JetParameterInfo(
} }
} }
public fun requiresExplicitType(inheritedFunction: JetFunctionDefinitionUsage<PsiElement>): Boolean { public fun requiresExplicitType(inheritedCallable: JetCallableDefinitionUsage<PsiElement>): Boolean {
val inheritedFunctionDescriptor = inheritedFunction.getOriginalFunctionDescriptor() val inheritedFunctionDescriptor = inheritedCallable.getOriginalCallableDescriptor()
if (inheritedFunctionDescriptor !is AnonymousFunctionDescriptor) return true if (inheritedFunctionDescriptor !is AnonymousFunctionDescriptor) return true
if (originalIndex < 0) return !inheritedFunction.hasExpectedType() if (originalIndex < 0) return !inheritedCallable.hasExpectedType()
val inheritedParameterDescriptor = inheritedFunctionDescriptor.getValueParameters().get(originalIndex) val inheritedParameterDescriptor = inheritedFunctionDescriptor.getValueParameters().get(originalIndex)
val parameter = DescriptorToSourceUtils.descriptorToDeclaration(inheritedParameterDescriptor) as? JetParameter ?: return false val parameter = DescriptorToSourceUtils.descriptorToDeclaration(inheritedParameterDescriptor) as? JetParameter ?: return false
return parameter.getTypeReference() != null return parameter.getTypeReference() != null
} }
public fun getDeclarationSignature(parameterIndex: Int, inheritedFunction: JetFunctionDefinitionUsage<PsiElement>): String { public fun getDeclarationSignature(parameterIndex: Int, inheritedCallable: JetCallableDefinitionUsage<PsiElement>): String {
val buffer = StringBuilder() val buffer = StringBuilder()
if (modifierList != null) { if (modifierList != null) {
@@ -199,13 +199,13 @@ public class JetParameterInfo(
buffer.append(valOrVar).append(' ') buffer.append(valOrVar).append(' ')
} }
buffer.append(getInheritedName(inheritedFunction)) buffer.append(getInheritedName(inheritedCallable))
if (requiresExplicitType(inheritedFunction)) { if (requiresExplicitType(inheritedCallable)) {
buffer.append(": ").append(renderType(parameterIndex, inheritedFunction)) buffer.append(": ").append(renderType(parameterIndex, inheritedCallable))
} }
if (!inheritedFunction.isInherited()) { if (!inheritedCallable.isInherited()) {
defaultValueForParameter?.let { buffer.append(" = ").append(it.getText()) } defaultValueForParameter?.let { buffer.append(" = ").append(it.getText()) }
} }
@@ -16,18 +16,13 @@
package org.jetbrains.kotlin.idea.refactoring.changeSignature package org.jetbrains.kotlin.idea.refactoring.changeSignature
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.types.TypeSubstitutor import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.JetCallableDefinitionUsage
import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.types.TypeProjection
import java.util.LinkedHashMap
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.types.checker.TypeCheckingProcedure
import org.jetbrains.kotlin.types.TypeProjectionImpl
import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.JetFunctionDefinitionUsage
import org.jetbrains.kotlin.types.JetType
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.TypeCheckingProcedure
import java.util.LinkedHashMap
private fun getTypeSubstitution(baseType: JetType, derivedType: JetType): LinkedHashMap<TypeConstructor, TypeProjection>? { private fun getTypeSubstitution(baseType: JetType, derivedType: JetType): LinkedHashMap<TypeConstructor, TypeProjection>? {
val substitutedType = TypeCheckingProcedure.findCorrespondingSupertype(derivedType, baseType) ?: return null val substitutedType = TypeCheckingProcedure.findCorrespondingSupertype(derivedType, baseType) ?: return null
@@ -40,15 +35,15 @@ private fun getTypeSubstitution(baseType: JetType, derivedType: JetType): Linked
return substitution return substitution
} }
private fun getFunctionSubstitution( private fun getCallableSubstitution(
baseFunction: FunctionDescriptor, baseCallable: CallableDescriptor,
derivedFunction: FunctionDescriptor derivedCallable: CallableDescriptor
): MutableMap<TypeConstructor, TypeProjection>? { ): MutableMap<TypeConstructor, TypeProjection>? {
val baseClass = baseFunction.getContainingDeclaration() as? ClassDescriptor ?: return null val baseClass = baseCallable.getContainingDeclaration() as? ClassDescriptor ?: return null
val derivedClass = derivedFunction.getContainingDeclaration() as? ClassDescriptor ?: return null val derivedClass = derivedCallable.getContainingDeclaration() as? ClassDescriptor ?: return null
val substitution = getTypeSubstitution(baseClass.getDefaultType(), derivedClass.getDefaultType()) ?: return null val substitution = getTypeSubstitution(baseClass.getDefaultType(), derivedClass.getDefaultType()) ?: return null
for ((baseParam, derivedParam) in baseFunction.getTypeParameters() zip derivedFunction.getTypeParameters()) { for ((baseParam, derivedParam) in baseCallable.getTypeParameters() zip derivedCallable.getTypeParameters()) {
substitution[baseParam.getTypeConstructor()] = TypeProjectionImpl(derivedParam.getDefaultType()) substitution[baseParam.getTypeConstructor()] = TypeProjectionImpl(derivedParam.getDefaultType())
} }
@@ -59,15 +54,15 @@ fun getTypeSubstitutor(baseType: JetType, derivedType: JetType): TypeSubstitutor
return getTypeSubstitution(baseType, derivedType)?.let { TypeSubstitutor.create(it) } return getTypeSubstitution(baseType, derivedType)?.let { TypeSubstitutor.create(it) }
} }
fun getFunctionSubstitutor( fun getCallableSubstitutor(
baseFunction: JetFunctionDefinitionUsage<*>, baseFunction: JetCallableDefinitionUsage<*>,
derivedFunction: JetFunctionDefinitionUsage<*> derivedCallable: JetCallableDefinitionUsage<*>
): TypeSubstitutor? { ): TypeSubstitutor? {
val currentBaseFunction = baseFunction.getCurrentFunctionDescriptor() val currentBaseFunction = baseFunction.getCurrentCallableDescriptor()
val currentDerivedFunction = derivedFunction.getCurrentFunctionDescriptor() val currentDerivedFunction = derivedCallable.getCurrentCallableDescriptor()
if (currentBaseFunction == null || currentDerivedFunction == null) return null if (currentBaseFunction == null || currentDerivedFunction == null) return null
return getFunctionSubstitution(currentBaseFunction, currentDerivedFunction)?.let { TypeSubstitutor.create(it) } return getCallableSubstitution(currentBaseFunction, currentDerivedFunction)?.let { TypeSubstitutor.create(it) }
} }
fun JetType.renderTypeWithSubstitution(substitutor: TypeSubstitutor?, defaultText: String, inArgumentPosition: Boolean): String { fun JetType.renderTypeWithSubstitution(substitutor: TypeSubstitutor?, defaultText: String, inArgumentPosition: Boolean): String {
@@ -35,10 +35,10 @@ public class DeferredJavaMethodOverrideOrSAMUsage(
): JavaMethodDeferredKotlinUsage<JetFunction>(function) { ): JavaMethodDeferredKotlinUsage<JetFunction>(function) {
override fun resolve(javaMethodChangeInfo: JetChangeInfo): JavaMethodKotlinUsageWithDelegate<JetFunction> { override fun resolve(javaMethodChangeInfo: JetChangeInfo): JavaMethodKotlinUsageWithDelegate<JetFunction> {
return object : JavaMethodKotlinUsageWithDelegate<JetFunction>(function, javaMethodChangeInfo) { return object : JavaMethodKotlinUsageWithDelegate<JetFunction>(function, javaMethodChangeInfo) {
override val delegateUsage = JetFunctionDefinitionUsage( override val delegateUsage = JetCallableDefinitionUsage(
function, function,
functionDescriptor, functionDescriptor,
javaMethodChangeInfo.methodDescriptor.originalPrimaryFunction, javaMethodChangeInfo.methodDescriptor.originalPrimaryCallable,
samCallType samCallType
) )
} }
@@ -34,7 +34,7 @@ public abstract class JavaMethodKotlinUsageWithDelegate<T: PsiElement>(
public class JavaMethodKotlinCallUsage( public class JavaMethodKotlinCallUsage(
callElement: JetCallElement, callElement: JetCallElement,
javaMethodChangeInfo: JetChangeInfo): JavaMethodKotlinUsageWithDelegate<JetCallElement>(callElement, javaMethodChangeInfo) { javaMethodChangeInfo: JetChangeInfo): JavaMethodKotlinUsageWithDelegate<JetCallElement>(callElement, javaMethodChangeInfo) {
override protected val delegateUsage = JetFunctionCallUsage(psiElement, javaMethodChangeInfo.methodDescriptor.originalPrimaryFunction) override protected val delegateUsage = JetFunctionCallUsage(psiElement, javaMethodChangeInfo.methodDescriptor.originalPrimaryCallable)
} }
public class JavaMethodKotlinDerivedDefinitionUsage( public class JavaMethodKotlinDerivedDefinitionUsage(
@@ -42,10 +42,10 @@ public class JavaMethodKotlinDerivedDefinitionUsage(
functionDescriptor: FunctionDescriptor, functionDescriptor: FunctionDescriptor,
javaMethodChangeInfo: JetChangeInfo): JavaMethodKotlinUsageWithDelegate<JetFunction>(function, javaMethodChangeInfo) { javaMethodChangeInfo: JetChangeInfo): JavaMethodKotlinUsageWithDelegate<JetFunction>(function, javaMethodChangeInfo) {
@suppress("CAST_NEVER_SUCCEEDS") @suppress("CAST_NEVER_SUCCEEDS")
override protected val delegateUsage = JetFunctionDefinitionUsage( override protected val delegateUsage = JetCallableDefinitionUsage(
psiElement, psiElement,
functionDescriptor, functionDescriptor,
javaMethodChangeInfo.methodDescriptor.originalPrimaryFunction, javaMethodChangeInfo.methodDescriptor.originalPrimaryCallable,
null null
) )
} }
@@ -26,9 +26,9 @@ 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.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
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.impl.AnonymousFunctionDescriptor; import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage; import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage;
import org.jetbrains.kotlin.idea.codeInsight.shorten.ShortenPackage; import org.jetbrains.kotlin.idea.codeInsight.shorten.ShortenPackage;
@@ -41,6 +41,7 @@ import org.jetbrains.kotlin.idea.util.ShortenReferences;
import org.jetbrains.kotlin.idea.util.ShortenReferences.Options; import org.jetbrains.kotlin.idea.util.ShortenReferences.Options;
import org.jetbrains.kotlin.lexer.JetModifierKeywordToken; import org.jetbrains.kotlin.lexer.JetModifierKeywordToken;
import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage;
import org.jetbrains.kotlin.psi.typeRefHelpers.TypeRefHelpersPackage; import org.jetbrains.kotlin.psi.typeRefHelpers.TypeRefHelpersPackage;
import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils; import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
@@ -52,14 +53,14 @@ import java.util.List;
import static org.jetbrains.kotlin.psi.PsiPackage.JetPsiFactory; import static org.jetbrains.kotlin.psi.PsiPackage.JetPsiFactory;
public class JetFunctionDefinitionUsage<T extends PsiElement> extends JetUsageInfo<T> { public class JetCallableDefinitionUsage<T extends PsiElement> extends JetUsageInfo<T> {
@NotNull @NotNull
private final FunctionDescriptor originalFunctionDescriptor; private final CallableDescriptor originalCallableDescriptor;
private FunctionDescriptor currentFunctionDescriptor; private CallableDescriptor currentCallableDescriptor;
@NotNull @NotNull
private final JetFunctionDefinitionUsage<? extends PsiElement> baseFunction; private final JetCallableDefinitionUsage<? extends PsiElement> baseFunction;
private final boolean hasExpectedType; private final boolean hasExpectedType;
@@ -69,24 +70,25 @@ public class JetFunctionDefinitionUsage<T extends PsiElement> extends JetUsageIn
@Nullable @Nullable
private TypeSubstitutor typeSubstitutor; private TypeSubstitutor typeSubstitutor;
public JetFunctionDefinitionUsage( public JetCallableDefinitionUsage(
@NotNull T function, @NotNull T function,
@NotNull FunctionDescriptor originalFunctionDescriptor, @NotNull CallableDescriptor originalCallableDescriptor,
@Nullable JetFunctionDefinitionUsage<PsiElement> baseFunction, @Nullable JetCallableDefinitionUsage<PsiElement> baseFunction,
@Nullable JetType samCallType) { @Nullable JetType samCallType
) {
super(function); super(function);
this.originalFunctionDescriptor = originalFunctionDescriptor; this.originalCallableDescriptor = originalCallableDescriptor;
this.baseFunction = baseFunction != null ? baseFunction : this; this.baseFunction = baseFunction != null ? baseFunction : this;
this.hasExpectedType = checkIfHasExpectedType(originalFunctionDescriptor, isInherited()); this.hasExpectedType = checkIfHasExpectedType(originalCallableDescriptor, isInherited());
this.samCallType = samCallType; this.samCallType = samCallType;
} }
private static boolean checkIfHasExpectedType(@NotNull FunctionDescriptor functionDescriptor, boolean isInherited) { private static boolean checkIfHasExpectedType(@NotNull CallableDescriptor callableDescriptor, boolean isInherited) {
if (!(functionDescriptor instanceof AnonymousFunctionDescriptor && isInherited)) return false; if (!(callableDescriptor instanceof AnonymousFunctionDescriptor && isInherited)) return false;
JetFunctionLiteral functionLiteral = JetFunctionLiteral functionLiteral =
(JetFunctionLiteral) DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor); (JetFunctionLiteral) DescriptorToSourceUtils.descriptorToDeclaration(callableDescriptor);
assert functionLiteral != null : "No declaration found for " + functionDescriptor; assert functionLiteral != null : "No declaration found for " + callableDescriptor;
PsiElement parent = functionLiteral.getParent(); PsiElement parent = functionLiteral.getParent();
if (!(parent instanceof JetFunctionLiteralExpression)) return false; if (!(parent instanceof JetFunctionLiteralExpression)) return false;
@@ -96,7 +98,7 @@ public class JetFunctionDefinitionUsage<T extends PsiElement> extends JetUsageIn
} }
@NotNull @NotNull
public JetFunctionDefinitionUsage getBaseFunction() { public JetCallableDefinitionUsage getBaseFunction() {
return baseFunction; return baseFunction;
} }
@@ -112,10 +114,10 @@ public class JetFunctionDefinitionUsage<T extends PsiElement> extends JetUsageIn
if (typeSubstitutor == null) { if (typeSubstitutor == null) {
if (samCallType == null) { if (samCallType == null) {
typeSubstitutor = ChangeSignaturePackage.getFunctionSubstitutor(baseFunction, this); typeSubstitutor = ChangeSignaturePackage.getCallableSubstitutor(baseFunction, this);
} }
else { else {
DeclarationDescriptor currentBaseDescriptor = baseFunction.getCurrentFunctionDescriptor(); DeclarationDescriptor currentBaseDescriptor = baseFunction.getCurrentCallableDescriptor();
DeclarationDescriptor classDescriptor = currentBaseDescriptor != null DeclarationDescriptor classDescriptor = currentBaseDescriptor != null
? currentBaseDescriptor.getContainingDeclaration() ? currentBaseDescriptor.getContainingDeclaration()
: null; : null;
@@ -140,71 +142,51 @@ public class JetFunctionDefinitionUsage<T extends PsiElement> extends JetUsageIn
} }
@NotNull @NotNull
public final FunctionDescriptor getOriginalFunctionDescriptor() { public final CallableDescriptor getOriginalCallableDescriptor() {
return originalFunctionDescriptor; return originalCallableDescriptor;
} }
@Nullable @Nullable
public final FunctionDescriptor getCurrentFunctionDescriptor() { public final CallableDescriptor getCurrentCallableDescriptor() {
if (currentFunctionDescriptor == null) { if (currentCallableDescriptor == null) {
PsiElement element = getDeclaration(); PsiElement element = getDeclaration();
if (element instanceof JetFunction) { if (element instanceof JetFunction || element instanceof JetProperty) {
currentFunctionDescriptor = (FunctionDescriptor) ResolvePackage.resolveToDescriptor((JetFunction) element); currentCallableDescriptor = (CallableDescriptor) ResolvePackage.resolveToDescriptor((JetDeclaration) element);
} }
else if (element instanceof JetClass) { else if (element instanceof JetClass) {
currentFunctionDescriptor = ((ClassDescriptor) ResolvePackage.resolveToDescriptor((JetClass) element)).getUnsubstitutedPrimaryConstructor(); currentCallableDescriptor = ((ClassDescriptor) ResolvePackage.resolveToDescriptor((JetClass) element)).getUnsubstitutedPrimaryConstructor();
} }
else if (element instanceof PsiMethod) { else if (element instanceof PsiMethod) {
currentFunctionDescriptor = ResolvePackage.getJavaMethodDescriptor((PsiMethod) element); currentCallableDescriptor = ResolvePackage.getJavaMethodDescriptor((PsiMethod) element);
} }
} }
return currentFunctionDescriptor; return currentCallableDescriptor;
} }
@Override @Override
public boolean processUsage(JetChangeInfo changeInfo, PsiElement element) { public boolean processUsage(JetChangeInfo changeInfo, PsiElement element) {
JetParameterList parameterList; if (!(element instanceof JetNamedDeclaration)) return true;
JetPsiFactory psiFactory = JetPsiFactory(element.getProject()); JetPsiFactory psiFactory = JetPsiFactory(element.getProject());
if (element instanceof JetFunction) {
JetFunction function = (JetFunction) element;
parameterList = function.getValueParameterList();
if (changeInfo.isNameChanged()) { if (changeInfo.isNameChanged()) {
PsiElement identifier = function.getNameIdentifier(); PsiElement identifier = ((JetCallableDeclaration) element).getNameIdentifier();
if (identifier != null) { if (identifier != null) {
identifier.replace(psiFactory.createIdentifier(changeInfo.getNewName())); identifier.replace(psiFactory.createIdentifier(changeInfo.getNewName()));
}
}
boolean returnTypeIsNeeded = (changeInfo.isRefactoringTarget(originalFunctionDescriptor)
|| !(function instanceof JetFunctionLiteral)
|| function.getTypeReference() != null) &&
!(function instanceof JetConstructor);
if (changeInfo.isReturnTypeChanged() && returnTypeIsNeeded) {
function.setTypeReference(null);
String returnTypeText = changeInfo.renderReturnType((JetFunctionDefinitionUsage<PsiElement>) this);
//TODO use ChangeFunctionReturnTypeFix.invoke when JetTypeCodeFragment.getType() is ready
if (!KotlinBuiltIns.getInstance().getUnitType().toString().equals(returnTypeText)) {
ShortenPackage.addToShorteningWaitSet(
function.setTypeReference(JetPsiFactory(function).createType(returnTypeText)),
Options.DEFAULT
);
}
} }
} }
else {
parameterList = ((JetClass) element).getPrimaryConstructorParameterList(); changeReturnTypeIfNeeded(changeInfo, element);
}
JetParameterList parameterList = PsiUtilPackage.getValueParameterList((JetNamedDeclaration) element);
if (changeInfo.isParameterSetOrOrderChanged()) { if (changeInfo.isParameterSetOrOrderChanged()) {
processParameterListWithStructuralChanges(changeInfo, element, parameterList, psiFactory); processParameterListWithStructuralChanges(changeInfo, element, parameterList, psiFactory);
} }
else if (parameterList != null) { else if (parameterList != null) {
int paramIndex = originalFunctionDescriptor.getExtensionReceiverParameter() != null ? 1 : 0; int paramIndex = originalCallableDescriptor.getExtensionReceiverParameter() != null ? 1 : 0;
for (JetParameter parameter : parameterList.getParameters()) { for (JetParameter parameter : parameterList.getParameters()) {
JetParameterInfo parameterInfo = changeInfo.getNewParameters()[paramIndex]; JetParameterInfo parameterInfo = changeInfo.getNewParameters()[paramIndex];
@@ -215,11 +197,11 @@ public class JetFunctionDefinitionUsage<T extends PsiElement> extends JetUsageIn
ShortenPackage.addToShorteningWaitSet(parameterList, Options.DEFAULT); ShortenPackage.addToShorteningWaitSet(parameterList, Options.DEFAULT);
} }
if (element instanceof JetFunction && changeInfo.isReceiverTypeChanged()) { if (element instanceof JetCallableDeclaration && changeInfo.isReceiverTypeChanged()) {
//noinspection unchecked //noinspection unchecked
String receiverTypeText = changeInfo.renderReceiverType((JetFunctionDefinitionUsage<PsiElement>) this); String receiverTypeText = changeInfo.renderReceiverType((JetCallableDefinitionUsage<PsiElement>) this);
JetTypeReference receiverTypeRef = receiverTypeText != null ? psiFactory.createType(receiverTypeText) : null; JetTypeReference receiverTypeRef = receiverTypeText != null ? psiFactory.createType(receiverTypeText) : null;
JetTypeReference newReceiverTypeRef = TypeRefHelpersPackage.setReceiverTypeReference((JetFunction) element, receiverTypeRef); JetTypeReference newReceiverTypeRef = TypeRefHelpersPackage.setReceiverTypeReference((JetCallableDeclaration) element, receiverTypeRef);
if (newReceiverTypeRef != null) { if (newReceiverTypeRef != null) {
ShortenPackage.addToShorteningWaitSet(newReceiverTypeRef, ShortenReferences.Options.DEFAULT); ShortenPackage.addToShorteningWaitSet(newReceiverTypeRef, ShortenReferences.Options.DEFAULT);
} }
@@ -232,6 +214,36 @@ public class JetFunctionDefinitionUsage<T extends PsiElement> extends JetUsageIn
return true; return true;
} }
protected void changeReturnTypeIfNeeded(JetChangeInfo changeInfo, PsiElement element) {
if (!(element instanceof JetCallableDeclaration)) return;
if (element instanceof JetConstructor) return;
JetCallableDeclaration callable = (JetCallableDeclaration) element;
boolean returnTypeIsNeeded;
if (element instanceof JetFunction) {
returnTypeIsNeeded = (changeInfo.isRefactoringTarget(originalCallableDescriptor) ||
!(callable instanceof JetFunctionLiteral) ||
callable.getTypeReference() != null);
}
else {
returnTypeIsNeeded = element instanceof JetProperty;
}
if (changeInfo.isReturnTypeChanged() && returnTypeIsNeeded) {
callable.setTypeReference(null);
String returnTypeText = changeInfo.renderReturnType((JetCallableDefinitionUsage<PsiElement>) this);
//TODO use ChangeFunctionReturnTypeFix.invoke when JetTypeCodeFragment.getType() is ready
if (!KotlinBuiltIns.getInstance().getUnitType().toString().equals(returnTypeText)) {
ShortenPackage.addToShorteningWaitSet(
callable.setTypeReference(JetPsiFactory(callable).createType(returnTypeText)),
Options.DEFAULT
);
}
}
}
private void processParameterListWithStructuralChanges( private void processParameterListWithStructuralChanges(
JetChangeInfo changeInfo, JetChangeInfo changeInfo,
PsiElement element, PsiElement element,
@@ -256,14 +268,14 @@ public class JetFunctionDefinitionUsage<T extends PsiElement> extends JetUsageIn
} }
else { else {
newParameterList = psiFactory.createFunctionLiteralParameterList(changeInfo.getNewParametersSignature( newParameterList = psiFactory.createFunctionLiteralParameterList(changeInfo.getNewParametersSignature(
(JetFunctionDefinitionUsage<PsiElement>) this) (JetCallableDefinitionUsage<PsiElement>) this)
); );
canReplaceEntireList = true; canReplaceEntireList = true;
} }
} }
else { else if (!(element instanceof JetProperty)) {
newParameterList = psiFactory.createParameterList(changeInfo.getNewParametersSignature( newParameterList = psiFactory.createParameterList(changeInfo.getNewParametersSignature(
(JetFunctionDefinitionUsage<PsiElement>) this) (JetCallableDefinitionUsage<PsiElement>) this)
); );
} }
@@ -339,14 +351,15 @@ public class JetFunctionDefinitionUsage<T extends PsiElement> extends JetUsageIn
private static void changeVisibility(JetChangeInfo changeInfo, PsiElement element) { private static void changeVisibility(JetChangeInfo changeInfo, PsiElement element) {
JetModifierKeywordToken newVisibilityToken = JetRefactoringUtil.getVisibilityToken(changeInfo.getNewVisibility()); JetModifierKeywordToken newVisibilityToken = JetRefactoringUtil.getVisibilityToken(changeInfo.getNewVisibility());
if (element instanceof JetFunction) { if (element instanceof JetCallableDeclaration) {
((JetFunction)element).addModifier(newVisibilityToken); ((JetCallableDeclaration)element).addModifier(newVisibilityToken);
} }
else { else if (element instanceof JetClass) {
JetPrimaryConstructor constructor = ((JetClass) element).getPrimaryConstructor(); JetPrimaryConstructor constructor = ((JetClass) element).getPrimaryConstructor();
assert constructor != null : "Primary constructor should be created before changing visibility"; assert constructor != null : "Primary constructor should be created before changing visibility";
constructor.addModifier(newVisibilityToken); constructor.addModifier(newVisibilityToken);
} }
else throw new AssertionError("Invalid element: " + PsiUtilPackage.getElementTextWithContext(element));
} }
private void changeParameter(int parameterIndex, JetParameter parameter, JetParameterInfo parameterInfo) { private void changeParameter(int parameterIndex, JetParameter parameter, JetParameterInfo parameterInfo) {
@@ -365,6 +378,7 @@ public class JetFunctionDefinitionUsage<T extends PsiElement> extends JetUsageIn
} }
else if (valOrVar != JetValVar.None) { else if (valOrVar != JetValVar.None) {
PsiElement firstChild = parameter.getFirstChild(); PsiElement firstChild = parameter.getFirstChild();
//noinspection ConstantConditions
parameter.addBefore(valOrVar.createKeyword(psiFactory), firstChild); parameter.addBefore(valOrVar.createKeyword(psiFactory), firstChild);
parameter.addBefore(psiFactory.createWhiteSpace(), firstChild); parameter.addBefore(psiFactory.createWhiteSpace(), firstChild);
} }
@@ -378,7 +392,7 @@ public class JetFunctionDefinitionUsage<T extends PsiElement> extends JetUsageIn
if (identifier != null) { if (identifier != null) {
//noinspection unchecked //noinspection unchecked
String newName = parameterInfo.getInheritedName((JetFunctionDefinitionUsage<PsiElement>) this); String newName = parameterInfo.getInheritedName(this);
identifier.replace(psiFactory.createIdentifier(newName)); identifier.replace(psiFactory.createIdentifier(newName));
} }
} }
@@ -25,7 +25,7 @@ public class JetConstructorDelegationCallUsage(
call: JetConstructorDelegationCall, call: JetConstructorDelegationCall,
changeInfo: JetChangeInfo changeInfo: JetChangeInfo
) : JetUsageInfo<JetConstructorDelegationCall>(call) { ) : JetUsageInfo<JetConstructorDelegationCall>(call) {
val delegate = JetFunctionCallUsage(call, changeInfo.methodDescriptor.originalPrimaryFunction) val delegate = JetFunctionCallUsage(call, changeInfo.methodDescriptor.originalPrimaryCallable)
override fun processUsage(changeInfo: JetChangeInfo, element: JetConstructorDelegationCall): Boolean { override fun processUsage(changeInfo: JetChangeInfo, element: JetConstructorDelegationCall): Boolean {
val isThisCall = element.isCallToThis() val isThisCall = element.isCallToThis()
@@ -35,7 +35,7 @@ public class JetEnumEntryWithoutSuperCallUsage(enumEntry: JetEnumEntry) : JetUsa
) as JetDelegatorToSuperCall ) as JetDelegatorToSuperCall
element.addBefore(psiFactory.createColon(), delegatorToSuperCall) element.addBefore(psiFactory.createColon(), delegatorToSuperCall)
return JetFunctionCallUsage(delegatorToSuperCall, changeInfo.methodDescriptor.originalPrimaryFunction) return JetFunctionCallUsage(delegatorToSuperCall, changeInfo.methodDescriptor.originalPrimaryCallable)
.processUsage(changeInfo, delegatorToSuperCall) .processUsage(changeInfo, delegatorToSuperCall)
} }
@@ -29,6 +29,7 @@ import kotlin.Unit;
import kotlin.jvm.functions.Function1; import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.PropertyCodegen;
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.shorten.ShortenPackage; import org.jetbrains.kotlin.idea.codeInsight.shorten.ShortenPackage;
@@ -38,6 +39,9 @@ import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetParameterInfo;
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.ExtractionEnginePackage; import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.ExtractionEnginePackage;
import org.jetbrains.kotlin.idea.refactoring.introduce.introduceVariable.KotlinIntroduceVariableHandler; import org.jetbrains.kotlin.idea.refactoring.introduce.introduceVariable.KotlinIntroduceVariableHandler;
import org.jetbrains.kotlin.idea.util.ShortenReferences; import org.jetbrains.kotlin.idea.util.ShortenReferences;
import org.jetbrains.kotlin.load.java.JvmAbi;
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage; import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage;
@@ -75,11 +79,11 @@ public class JetFunctionCallUsage extends JetUsageInfo<JetCallElement> {
private static final ShortenReferences.Options SHORTEN_ARGUMENTS_OPTIONS = new ShortenReferences.Options(true, true); private static final ShortenReferences.Options SHORTEN_ARGUMENTS_OPTIONS = new ShortenReferences.Options(true, true);
private final JetFunctionDefinitionUsage<?> callee; private final JetCallableDefinitionUsage<?> callee;
private final BindingContext context; private final BindingContext context;
private final ResolvedCall<? extends CallableDescriptor> resolvedCall; private final ResolvedCall<? extends CallableDescriptor> resolvedCall;
public JetFunctionCallUsage(@NotNull JetCallElement element, JetFunctionDefinitionUsage callee) { public JetFunctionCallUsage(@NotNull JetCallElement element, JetCallableDefinitionUsage callee) {
super(element); super(element);
this.callee = callee; this.callee = callee;
this.context = ResolvePackage.analyze(element, BodyResolveMode.FULL); this.context = ResolvePackage.analyze(element, BodyResolveMode.FULL);
@@ -88,13 +92,7 @@ public class JetFunctionCallUsage extends JetUsageInfo<JetCallElement> {
@Override @Override
public boolean processUsage(JetChangeInfo changeInfo, JetCallElement element) { public boolean processUsage(JetChangeInfo changeInfo, JetCallElement element) {
if (changeInfo.isNameChanged()) { changeNameIfNeeded(changeInfo, element);
JetExpression callee = element.getCalleeExpression();
if (callee instanceof JetSimpleNameExpression) {
callee.replace(JetPsiFactory(getProject()).createSimpleName(changeInfo.getNewName()));
}
}
if (element.getValueArgumentList() != null) { if (element.getValueArgumentList() != null) {
if (changeInfo.isParameterSetOrOrderChanged()) { if (changeInfo.isParameterSetOrOrderChanged()) {
@@ -118,6 +116,27 @@ public class JetFunctionCallUsage extends JetUsageInfo<JetCallElement> {
return true; return true;
} }
private boolean isPropertyJavaUsage() {
return this.callee.getElement() instanceof JetProperty
&& resolvedCall != null && resolvedCall.getResultingDescriptor() instanceof JavaMethodDescriptor;
}
protected void changeNameIfNeeded(JetChangeInfo changeInfo, JetCallElement element) {
if (!changeInfo.isNameChanged()) return;
JetExpression callee = element.getCalleeExpression();
if (!(callee instanceof JetSimpleNameExpression)) return;
String newName = changeInfo.getNewName();
if (isPropertyJavaUsage()) {
String currentName = ((JetSimpleNameExpression) callee).getReferencedName();
if (currentName.startsWith(JvmAbi.GETTER_PREFIX)) newName = PropertyCodegen.getterName(Name.identifier(newName));
else if (currentName.startsWith(JvmAbi.SETTER_PREFIX)) newName = PropertyCodegen.setterName(Name.identifier(newName));
}
callee.replace(JetPsiFactory(getProject()).createSimpleName(newName));
}
@Nullable @Nullable
private JetExpression getReceiverExpressionIfMatched( private JetExpression getReceiverExpressionIfMatched(
@NotNull ReceiverValue receiverValue, @NotNull ReceiverValue receiverValue,
@@ -288,6 +307,11 @@ public class JetFunctionCallUsage extends JetUsageInfo<JetCallElement> {
assert arguments != null : "Argument list is expected: " + element.getText(); assert arguments != null : "Argument list is expected: " + element.getText();
List<? extends ValueArgument> oldArguments = element.getValueArguments(); List<? extends ValueArgument> oldArguments = element.getValueArguments();
if (isPropertyJavaUsage()) {
updateJavaPropertyCall(changeInfo, element);
return;
}
boolean isNamedCall = oldArguments.size() > 1 && oldArguments.get(0).isNamed(); boolean isNamedCall = oldArguments.size() > 1 && oldArguments.get(0).isNamed();
StringBuilder parametersBuilder = new StringBuilder("("); StringBuilder parametersBuilder = new StringBuilder("(");
boolean isFirst = true; boolean isFirst = true;
@@ -388,7 +412,8 @@ public class JetFunctionCallUsage extends JetUsageInfo<JetCallElement> {
//TODO: this is not correct! //TODO: this is not correct!
JetValueArgument lastArgument = KotlinPackage.lastOrNull(newArgumentList.getArguments()); JetValueArgument lastArgument = KotlinPackage.lastOrNull(newArgumentList.getArguments());
boolean hasTrailingLambdaInArgumentListAfter = lastArgument != null && PsiPackage.unpackFunctionLiteral(lastArgument.getArgumentExpression()) != null; boolean hasTrailingLambdaInArgumentListAfter =
lastArgument != null && PsiPackage.unpackFunctionLiteral(lastArgument.getArgumentExpression()) != null;
arguments = (JetValueArgumentList) arguments.replace(newArgumentList); arguments = (JetValueArgumentList) arguments.replace(newArgumentList);
@@ -435,6 +460,38 @@ public class JetFunctionCallUsage extends JetUsageInfo<JetCallElement> {
} }
} }
private static void updateJavaPropertyCall(JetChangeInfo changeInfo, JetCallElement element) {
JetParameterInfo newReceiverInfo = changeInfo.getReceiverParameterInfo();
JetParameterInfo originalReceiverInfo = changeInfo.getMethodDescriptor().getReceiver();
if (newReceiverInfo == originalReceiverInfo) return;
JetValueArgumentList arguments = element.getValueArgumentList();
assert arguments != null : "Argument list is expected: " + element.getText();
List<? extends ValueArgument> oldArguments = element.getValueArguments();
JetPsiFactory psiFactory = new JetPsiFactory(element.getProject());
JetValueArgument firstArgument = oldArguments.isEmpty() ? null : (JetValueArgument) oldArguments.get(0);
if (newReceiverInfo == null) {
if (firstArgument != null) arguments.removeArgument(firstArgument);
}
else {
JetExpression defaultValueForCall = newReceiverInfo.getDefaultValueForCall();
if (defaultValueForCall == null) {
defaultValueForCall = psiFactory.createExpression("_");
}
JetValueArgument newReceiverArgument = psiFactory.createArgument(defaultValueForCall, null, false);
if (originalReceiverInfo != null) {
if (firstArgument != null) firstArgument.replace(newReceiverArgument);
}
else {
arguments.addArgumentAfter(newReceiverArgument, null);
}
}
}
@Nullable @Nullable
private static JetExpression getReceiverExpression(@NotNull ReceiverValue receiver, @NotNull JetPsiFactory psiFactory) { private static JetExpression getReceiverExpression(@NotNull ReceiverValue receiver, @NotNull JetPsiFactory psiFactory) {
if (receiver instanceof ExpressionReceiver) { if (receiver instanceof ExpressionReceiver) {
@@ -44,9 +44,9 @@ public abstract class JetImplicitReceiverUsage(callElement: JetElement): JetUsag
public class JetImplicitThisToParameterUsage( public class JetImplicitThisToParameterUsage(
callElement: JetElement, callElement: JetElement,
val parameterInfo: JetParameterInfo, val parameterInfo: JetParameterInfo,
val containingFunction: JetFunctionDefinitionUsage<*> val containingCallable: JetCallableDefinitionUsage<*>
): JetImplicitReceiverUsage(callElement) { ): JetImplicitReceiverUsage(callElement) {
override fun getNewReceiverText(): String = parameterInfo.getInheritedName(containingFunction) override fun getNewReceiverText(): String = parameterInfo.getInheritedName(containingCallable)
override fun processReplacedElement(element: JetElement) { override fun processReplacedElement(element: JetElement) {
element.addToShorteningWaitSet(Options(removeThisLabels = true)) element.addToShorteningWaitSet(Options(removeThisLabels = true))
@@ -46,7 +46,7 @@ public abstract class JetExplicitReferenceUsage<T: JetElement>(element: T) : Jet
public class JetParameterUsage( public class JetParameterUsage(
element: JetElement, element: JetElement,
private val parameterInfo: JetParameterInfo, private val parameterInfo: JetParameterInfo,
val containingFunction: JetFunctionDefinitionUsage<*> val containingCallable: JetCallableDefinitionUsage<*>
) : JetExplicitReferenceUsage<JetElement>(element) { ) : JetExplicitReferenceUsage<JetElement>(element) {
override fun processReplacedElement(element: JetElement) { override fun processReplacedElement(element: JetElement) {
val qualifiedExpression = element.getParent() as? JetQualifiedExpression val qualifiedExpression = element.getParent() as? JetQualifiedExpression
@@ -56,7 +56,7 @@ public class JetParameterUsage(
override fun getReplacementText(changeInfo: JetChangeInfo): String = override fun getReplacementText(changeInfo: JetChangeInfo): String =
if (changeInfo.receiverParameterInfo != parameterInfo) { if (changeInfo.receiverParameterInfo != parameterInfo) {
parameterInfo.getInheritedName(containingFunction) parameterInfo.getInheritedName(containingCallable)
} else "this@${changeInfo.getNewName()}" } else "this@${changeInfo.getNewName()}"
} }
@@ -0,0 +1,64 @@
/*
* Copyright 2010-2015 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.caches.resolve.analyze
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeInfo
import org.jetbrains.kotlin.psi.JetPsiFactory
import org.jetbrains.kotlin.psi.JetQualifiedExpression
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
import org.jetbrains.kotlin.psi.createExpressionByPattern
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
public class JetPropertyCallUsage(element: JetSimpleNameExpression): JetUsageInfo<JetSimpleNameExpression>(element) {
private val resolvedCall = element.getResolvedCall(element.analyze())
override fun processUsage(changeInfo: JetChangeInfo, element: JetSimpleNameExpression): Boolean {
updateName(changeInfo, element)
updateReceiver(changeInfo, element)
return true
}
private fun updateName(changeInfo: JetChangeInfo, element: JetSimpleNameExpression) {
if (changeInfo.isNameChanged()) {
element.getReference()?.handleElementRename(changeInfo.getNewName())
}
}
private fun updateReceiver(changeInfo: JetChangeInfo, element: JetSimpleNameExpression) {
val newReceiver = changeInfo.receiverParameterInfo
val oldReceiver = changeInfo.methodDescriptor.receiver
if (newReceiver == oldReceiver) return
val elementToReplace = element.getQualifiedExpressionForSelectorOrThis()
// Do not add extension receiver to calls with explicit dispatch receiver
if (newReceiver != null
&& elementToReplace is JetQualifiedExpression
&& resolvedCall?.getDispatchReceiver() is ExpressionReceiver) return
val replacingElement = newReceiver?.let {
val psiFactory = JetPsiFactory(getProject())
val receiver = it.defaultValueForCall ?: psiFactory.createExpression("_")
psiFactory.createExpressionByPattern("$0.$1", receiver, element)
} ?: element
elementToReplace.replace(replacingElement)
}
}
@@ -17,9 +17,19 @@
package org.jetbrains.kotlin.idea.refactoring.changeSignature.usages package org.jetbrains.kotlin.idea.refactoring.changeSignature.usages
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.refactoring.changeSignature.JavaChangeInfo
import com.intellij.usageView.UsageInfo import com.intellij.usageView.UsageInfo
public class KotlinWrapperForJavaUsageInfos( public class KotlinWrapperForJavaUsageInfos(
val javaChangeInfo: JavaChangeInfo,
val javaUsageInfos: Array<UsageInfo>, val javaUsageInfos: Array<UsageInfo>,
val primaryMethod: PsiElement val primaryMethod: PsiElement
): UsageInfo(primaryMethod) ): UsageInfo(primaryMethod) {
override fun hashCode(): Int {
return javaChangeInfo.getMethod().hashCode();
}
override fun equals(other: Any?): Boolean {
return other == this || (other is KotlinWrapperForJavaUsageInfos && javaChangeInfo.getMethod() == other.javaChangeInfo.getMethod())
}
}
@@ -32,6 +32,7 @@ import com.intellij.usageView.UsageInfo
import org.jetbrains.kotlin.idea.JetFileType import org.jetbrains.kotlin.idea.JetFileType
import org.jetbrains.kotlin.idea.core.refactoring.isMultiLine import org.jetbrains.kotlin.idea.core.refactoring.isMultiLine
import org.jetbrains.kotlin.idea.core.refactoring.runRefactoringWithPostprocessing import org.jetbrains.kotlin.idea.core.refactoring.runRefactoringWithPostprocessing
import org.jetbrains.kotlin.idea.core.refactoring.validateElement
import org.jetbrains.kotlin.idea.refactoring.introduce.extractFunction.ui.KotlinExtractFunctionDialog import org.jetbrains.kotlin.idea.refactoring.introduce.extractFunction.ui.KotlinExtractFunctionDialog
import org.jetbrains.kotlin.idea.refactoring.introduce.extractFunction.ui.KotlinParameterTablePanel import org.jetbrains.kotlin.idea.refactoring.introduce.extractFunction.ui.KotlinParameterTablePanel
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.* import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.*
@@ -233,18 +234,9 @@ public class KotlinIntroduceParameterDialog private constructor(
override fun createCenterPanel() = null override fun createCenterPanel() = null
override fun canRun() { override fun canRun() {
fun validateElement(e: PsiElement, errorMessage: String) {
try {
AnalyzingUtils.checkForSyntacticErrors(e)
}
catch(e: Exception) {
throw ConfigurationException(errorMessage)
}
}
val psiFactory = JetPsiFactory(myProject) val psiFactory = JetPsiFactory(myProject)
validateElement(psiFactory.createType(nameField.getEnteredName()), "Invalid parameter name") psiFactory.createSimpleName(nameField.getEnteredName()).validateElement("Invalid parameter name")
validateElement(psiFactory.createType(typeField.getEnteredName()), "Invalid parameter type") psiFactory.createType(typeField.getEnteredName()).validateElement("Invalid parameter type")
} }
override fun doAction() { override fun doAction() {
@@ -142,7 +142,7 @@ fun IntroduceParameterDescriptor.performRefactoring() {
.forEach { methodDescriptor.removeParameter(it) } .forEach { methodDescriptor.removeParameter(it) }
} }
val parameterInfo = JetParameterInfo(functionDescriptor = callableDescriptor, val parameterInfo = JetParameterInfo(callableDescriptor = callableDescriptor,
name = newParameterName, name = newParameterName,
defaultValueForCall = if (withDefaultValue) null else newArgumentValue, defaultValueForCall = if (withDefaultValue) null else newArgumentValue,
defaultValueForParameter = if (withDefaultValue) newArgumentValue else null, defaultValueForParameter = if (withDefaultValue) newArgumentValue else null,
@@ -77,7 +77,7 @@ public class KotlinIntroduceParameterMethodUsageProcessor : IntroduceParameterMe
// Temporarily assume that the new parameter is of Any type. Actual type is substituted during the signature update phase // Temporarily assume that the new parameter is of Any type. Actual type is substituted during the signature update phase
val defaultValueForCall = (data.getParameterInitializer().getExpression()!! as? PsiExpression)?.let { it.j2k() } val defaultValueForCall = (data.getParameterInitializer().getExpression()!! as? PsiExpression)?.let { it.j2k() }
changeInfo.addParameter(JetParameterInfo(functionDescriptor = psiMethodDescriptor, changeInfo.addParameter(JetParameterInfo(callableDescriptor = psiMethodDescriptor,
name = data.getParameterName(), name = data.getParameterName(),
type = KotlinBuiltIns.getInstance().getAnyType(), type = KotlinBuiltIns.getInstance().getAnyType(),
defaultValueForCall = defaultValueForCall)) defaultValueForCall = defaultValueForCall))
@@ -100,7 +100,7 @@ public class KotlinIntroduceParameterMethodUsageProcessor : IntroduceParameterMe
.map { it.unwrapped } .map { it.unwrapped }
.filterIsInstance<JetFunction>() .filterIsInstance<JetFunction>()
return (kotlinFunctions + element).all { return (kotlinFunctions + element).all {
JetFunctionDefinitionUsage(it, changeInfo.originalBaseFunctionDescriptor, null, null).processUsage(changeInfo, it) JetCallableDefinitionUsage(it, changeInfo.originalBaseFunctionDescriptor, null, null).processUsage(changeInfo, it)
} }
} }
@@ -114,7 +114,7 @@ public class KotlinIntroduceParameterMethodUsageProcessor : IntroduceParameterMe
(JetConstructorDelegationCallUsage(callElement, changeInfo) as JetUsageInfo<JetCallElement>) (JetConstructorDelegationCallUsage(callElement, changeInfo) as JetUsageInfo<JetCallElement>)
} }
else { else {
JetFunctionCallUsage(callElement, changeInfo.methodDescriptor.originalPrimaryFunction) JetFunctionCallUsage(callElement, changeInfo.methodDescriptor.originalPrimaryCallable)
} }
return delegateUsage.processUsage(changeInfo, callElement) return delegateUsage.processUsage(changeInfo, callElement)
} }
@@ -78,6 +78,7 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import com.intellij.lang.java.JavaLanguage import com.intellij.lang.java.JavaLanguage
import com.intellij.codeInsight.daemon.impl.quickfix.CreateFromUsageUtils import com.intellij.codeInsight.daemon.impl.quickfix.CreateFromUsageUtils
import com.intellij.openapi.options.ConfigurationException
import com.intellij.psi.* import com.intellij.psi.*
import com.intellij.refactoring.listeners.RefactoringEventData import com.intellij.refactoring.listeners.RefactoringEventData
import com.intellij.refactoring.listeners.RefactoringEventListener import com.intellij.refactoring.listeners.RefactoringEventListener
@@ -88,6 +89,7 @@ import org.jetbrains.kotlin.j2k.ConverterSettings
import org.jetbrains.kotlin.j2k.IdeaReferenceSearcher import org.jetbrains.kotlin.j2k.IdeaReferenceSearcher
import org.jetbrains.kotlin.j2k.JavaToKotlinConverter import org.jetbrains.kotlin.j2k.JavaToKotlinConverter
import org.jetbrains.kotlin.psi.psiUtil.* import org.jetbrains.kotlin.psi.psiUtil.*
import org.jetbrains.kotlin.resolve.AnalyzingUtils
fun <T: Any> PsiElement.getAndRemoveCopyableUserData(key: Key<T>): T? { fun <T: Any> PsiElement.getAndRemoveCopyableUserData(key: Key<T>): T? {
val data = getCopyableUserData(key) val data = getCopyableUserData(key)
@@ -605,3 +607,13 @@ public fun (() -> Any).runRefactoringWithPostprocessing(
}) })
this() this()
} }
@throws(ConfigurationException::class)
public fun JetElement.validateElement(errorMessage: String) {
try {
AnalyzingUtils.checkForSyntacticErrors(this)
}
catch(e: Exception) {
throw ConfigurationException(errorMessage)
}
}
@@ -0,0 +1,28 @@
import java.lang.Override;
class J extends A {
private int p;
@Override
public int getP(String receiver) {
return p;
}
@Override
public void setP(String receiver, int value) {
p = value;
}
}
class Test {
static void test() {
new A().getP("");
new A().setP("", 1);
new B().getP("");
new B().setP("", 2);
new J().getP("");
new J().setP("", 3);
}
}
@@ -0,0 +1,26 @@
public inline fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
open class A {
open var <caret>String.p: Int = 1
}
class B: A() {
override var String.p: Int = 2
}
fun test() {
with(A()) {
val t = "".p
"".p = 1
}
with(B()) {
val t = "".p
"".p = 2
}
with(J()) {
val t = getP("")
setP("", 3)
}
}
@@ -0,0 +1,28 @@
import java.lang.Override;
class J extends A {
private int p;
@Override
public int getP() {
return p;
}
@Override
public void setP(int value) {
p = value;
}
}
class Test {
static void test() {
new A().getP();
new A().setP(1);
new B().getP();
new B().setP(2);
new J().getP();
new J().setP(3);
}
}
@@ -0,0 +1,26 @@
public inline fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
open class A {
open var <caret>p: Int = 1
}
class B: A() {
override var p: Int = 2
}
fun test() {
with(A()) {
val t = p
p = 1
}
with(B()) {
val t = p
p = 2
}
with(J()) {
val t = getP()
setP(3)
}
}
@@ -0,0 +1,8 @@
open class A {
open var <caret>p: Int = 1
}
fun test() {
val t1 = A().p
A().p = 1
}
@@ -0,0 +1,2 @@
Explicit receiver is already present in call element: A().p
Explicit receiver is already present in call element: A().p
@@ -0,0 +1,8 @@
import test.TestPackage;
class Test {
static void test() {
TestPackage.getP(A());
TestPackage.setP(A(), 1);
}
}
@@ -0,0 +1,14 @@
package test
public inline fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
class A
open var <caret>A.p: Int
get() = 1
set(value: Int) {}
fun test() {
val t = A().p
A().p = 1
}
@@ -0,0 +1,8 @@
import test.TestPackage;
class Test {
static void test() {
TestPackage.getP();
TestPackage.setP(1);
}
}
@@ -0,0 +1,14 @@
package test
public inline fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
class A
open var <caret>p: Int
get() = 1
set(value: Int) {}
fun test() {
val t = p
p = 1
}
@@ -0,0 +1,31 @@
import org.jetbrains.annotations.NotNull;
import java.lang.Override;
class J extends A {
private int p;
@NotNull
@Override
public String getS() {
return p;
}
@Override
public void setS(@NotNull String value) {
p = value;
}
}
class Test {
static void test() {
new A().getS();
new A().setS(1);
new B().getS();
new B().setS(2);
new J().getS();
new J().setS(3);
}
}
@@ -0,0 +1,18 @@
open class A {
open var <caret>s: String = 1
}
class B: A() {
override var s: String = 2
}
fun test() {
val t1 = A().s
A().s = 1
val t2 = B().s
B().s = 2
val t3 = J().getS()
J().setS(3)
}
@@ -0,0 +1,28 @@
import java.lang.Override;
class J extends A {
private int p;
@Override
public int getP() {
return p;
}
@Override
public void setP(int value) {
p = value;
}
}
class Test {
static void test() {
new A().getP();
new A().setP(1);
new B().getP();
new B().setP(2);
new J().getP();
new J().setP(3);
}
}
@@ -0,0 +1,18 @@
open class A {
open var <caret>p: Int = 1
}
class B: A() {
override var p: Int = 2
}
fun test() {
val t1 = A().p
A().p = 1
val t2 = B().p
B().p = 2
val t3 = J().getP()
J().setP(3)
}
@@ -0,0 +1,28 @@
import java.lang.Override;
class J extends A {
private int p;
@Override
public int getP(int receiver) {
return p;
}
@Override
public void setP(int receiver, int value) {
p = value;
}
}
class Test {
static void test() {
new A().getP("");
new A().setP("", 1);
new B().getP("");
new B().setP("", 2);
new J().getP("");
new J().setP("", 3);
}
}
@@ -0,0 +1,26 @@
public inline fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
open class A {
open var Int.<caret>p: Int = 1
}
class B: A() {
override var Int.p: Int = 2
}
fun test() {
with(A()) {
val t = "".p
"".p = 1
}
with(B()) {
val t = "".p
"".p = 2
}
with(J()) {
val t = getP("")
setP("", 3)
}
}
@@ -0,0 +1,28 @@
import java.lang.Override;
class J extends A {
private int p;
@Override
public int getP(String receiver) {
return p;
}
@Override
public void setP(String receiver, int value) {
p = value;
}
}
class Test {
static void test() {
new A().getP("");
new A().setP("", 1);
new B().getP("");
new B().setP("", 2);
new J().getP("");
new J().setP("", 3);
}
}
@@ -0,0 +1,26 @@
public inline fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
open class A {
open var String.<caret>p: Int = 1
}
class B: A() {
override var String.p: Int = 2
}
fun test() {
with(A()) {
val t = "".p
"".p = 1
}
with(B()) {
val t = "".p
"".p = 2
}
with(J()) {
val t = getP("")
setP("", 3)
}
}
@@ -0,0 +1,8 @@
import test.TestPackage;
class Test {
static void test() {
TestPackage.getP(new A());
TestPackage.setP(new A(), 1);
}
}
@@ -0,0 +1,19 @@
package test
public inline fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
class A
open var String.<caret>p: Int
get() = 1
set(value: Int) {}
fun test() {
with(A()) {
val t = p
p = 1
}
val t1 = A().p
A().p = 1
}
@@ -0,0 +1,8 @@
import test.TestPackage;
class Test {
static void test() {
TestPackage.getP(new A());
TestPackage.setP(new A(), 1);
}
}
@@ -0,0 +1,19 @@
package test
public inline fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
class A
open var A.<caret>p: Int
get() = 1
set(value: Int) {}
fun test() {
with(A()) {
val t = p
p = 1
}
val t1 = A().p
A().p = 1
}
@@ -0,0 +1,28 @@
import java.lang.Override;
class J extends A {
private int p;
@Override
public int getP() {
return p;
}
@Override
public void setP(int value) {
p = value;
}
}
class Test {
static void test() {
new A().getP();
new A().setP(1);
new B().getP();
new B().setP(2);
new J().getP();
new J().setP(3);
}
}
@@ -0,0 +1,26 @@
public inline fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
open class A {
open var <caret>p: Int = 1
}
class B: A() {
override var p: Int = 2
}
fun test() {
with(A()) {
val t = p
p = 1
}
with(B()) {
val t = p
p = 2
}
with(J()) {
val t = getP()
setP(3)
}
}
@@ -0,0 +1,28 @@
import java.lang.Override;
class J extends A {
private int p;
@Override
public int getP(String receiver) {
return p;
}
@Override
public void setP(String receiver, int value) {
p = value;
}
}
class Test {
static void test() {
new A().getP("");
new A().setP("", 1);
new B().getP("");
new B().setP("", 2);
new J().getP("");
new J().setP("", 3);
}
}
@@ -0,0 +1,26 @@
public inline fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
open class A {
open var String.<caret>p: Int = 1
}
class B: A() {
override var String.p: Int = 2
}
fun test() {
with(A()) {
val t = "".p
"".p = 1
}
with(B()) {
val t = "".p
"".p = 2
}
with(J()) {
val t = getP("")
setP("", 3)
}
}
@@ -0,0 +1,8 @@
import test.TestPackage;
class Test {
static void test() {
TestPackage.getP();
TestPackage.setP(1);
}
}
@@ -0,0 +1,19 @@
package test
public inline fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
class A
open var <caret>p: Int
get() = 1
set(value: Int) {}
fun test() {
with(A()) {
val t = p
p = 1
}
val t1 = p
p = 1
}
@@ -0,0 +1,8 @@
import test.TestPackage;
class Test {
static void test() {
TestPackage.getP(new A());
TestPackage.setP(new A(), 1);
}
}
@@ -0,0 +1,19 @@
package test
public inline fun <T, R> with(receiver: T, f: T.() -> R): R = receiver.f()
class A
open var A.<caret>p: Int
get() = 1
set(value: Int) {}
fun test() {
with(A()) {
val t = p
p = 1
}
val t1 = A().p
A().p = 1
}
@@ -33,7 +33,7 @@ import com.intellij.util.VisibilityUtil;
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.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.descriptors.FunctionDescriptor; import org.jetbrains.kotlin.descriptors.CallableDescriptor;
import org.jetbrains.kotlin.descriptors.Visibilities; import org.jetbrains.kotlin.descriptors.Visibilities;
import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage; import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage;
import org.jetbrains.kotlin.idea.refactoring.JetRefactoringBundle; import org.jetbrains.kotlin.idea.refactoring.JetRefactoringBundle;
@@ -995,6 +995,67 @@ public class JetChangeSignatureTest extends KotlinCodeInsightTestCase {
); );
} }
public void testChangeProperty() throws Exception {
JetChangeInfo changeInfo = getChangeInfo();
changeInfo.setNewName("s");
changeInfo.setNewReturnTypeText("String");
doTest(changeInfo);
}
public void testAddPropertyReceiverConflict() throws Exception {
JetChangeInfo changeInfo = getChangeInfo();
JetParameterInfo newParameter = new JetParameterInfo(changeInfo.getMethodDescriptor().getBaseDescriptor(),
-1, "receiver", KotlinBuiltIns.getInstance().getStringType(), null,
new JetPsiFactory(getProject()).createExpression("\"\""), JetValVar.None, null);
changeInfo.setReceiverParameterInfo(newParameter);
doTestConflict(changeInfo);
}
public void testAddPropertyReceiver() throws Exception {
JetChangeInfo changeInfo = getChangeInfo();
JetParameterInfo newParameter = new JetParameterInfo(changeInfo.getMethodDescriptor().getBaseDescriptor(),
-1, "receiver", KotlinBuiltIns.getInstance().getStringType(), null,
new JetPsiFactory(getProject()).createExpression("\"\""), JetValVar.None, null);
changeInfo.setReceiverParameterInfo(newParameter);
doTest(changeInfo);
}
public void testChangePropertyReceiver() throws Exception {
JetChangeInfo changeInfo = getChangeInfo();
//noinspection ConstantConditions
changeInfo.getReceiverParameterInfo().setCurrentTypeText("Int");
doTest(changeInfo);
}
public void testRemovePropertyReceiver() throws Exception {
JetChangeInfo changeInfo = getChangeInfo();
changeInfo.setReceiverParameterInfo(null);
doTest(changeInfo);
}
public void testAddTopLevelPropertyReceiver() throws Exception {
JetChangeInfo changeInfo = getChangeInfo();
JetParameterInfo newParameter = new JetParameterInfo(changeInfo.getMethodDescriptor().getBaseDescriptor(),
-1, "receiver", null, null,
new JetPsiFactory(getProject()).createExpression("A()"), JetValVar.None, null);
newParameter.setCurrentTypeText("test.A");
changeInfo.setReceiverParameterInfo(newParameter);
doTest(changeInfo);
}
public void testChangeTopLevelPropertyReceiver() throws Exception {
JetChangeInfo changeInfo = getChangeInfo();
//noinspection ConstantConditions
changeInfo.getReceiverParameterInfo().setCurrentTypeText("String");
doTest(changeInfo);
}
public void testRemoveTopLevelPropertyReceiver() throws Exception {
JetChangeInfo changeInfo = getChangeInfo();
changeInfo.setReceiverParameterInfo(null);
doTest(changeInfo);
}
@NotNull @NotNull
@Override @Override
protected String getTestDataPath() { protected String getTestDataPath() {
@@ -1039,11 +1100,11 @@ public class JetChangeSignatureTest extends KotlinCodeInsightTestCase {
PsiElement context = file.findElementAt(editor.getCaretModel().getOffset()); PsiElement context = file.findElementAt(editor.getCaretModel().getOffset());
assertNotNull(context); assertNotNull(context);
FunctionDescriptor functionDescriptor = JetChangeSignatureHandler.findDescriptor(element, project, editor, bindingContext); CallableDescriptor callableDescriptor = JetChangeSignatureHandler.findDescriptor(element, project, editor, bindingContext);
assertNotNull(functionDescriptor); assertNotNull(callableDescriptor);
return ChangeSignaturePackage.createChangeInfo( return ChangeSignaturePackage.createChangeInfo(
project, functionDescriptor, JetChangeSignatureHandler.getConfiguration(), bindingContext, context); project, callableDescriptor, JetChangeSignatureHandler.getConfiguration(), bindingContext, context);
} }
private class JavaRefactoringProvider { private class JavaRefactoringProvider {