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.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
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 {
JetParameterInfo parameterInfo =
getNewParameterInfo(originalDescriptor.getBaseDescriptor(), bindingContext, argument, validator);
getNewParameterInfo((FunctionDescriptor) originalDescriptor.getBaseDescriptor(), bindingContext, argument, validator);
typesToShorten.add(parameterInfo.getOriginalType());
if (expression != null) {
@@ -115,7 +115,7 @@ object CreateParameterActionFactory: JetSingleIntentionActionFactory() {
return CreateParameterFromUsageFix(
functionDescriptor,
context,
JetParameterInfo(functionDescriptor = functionDescriptor,
JetParameterInfo(callableDescriptor = functionDescriptor,
name = refExpr.getReferencedName(),
type = paramType,
valOrVar = valOrVar),
@@ -60,7 +60,7 @@ public object CreateParameterByNamedArgumentActionFactory: JetSingleIntentionAct
if (paramType.hasTypeParametersToAdd(functionDescriptor, context)) return null
val parameterInfo = JetParameterInfo(
functionDescriptor = functionDescriptor,
callableDescriptor = functionDescriptor,
name = name,
type = paramType,
defaultValueForCall = argumentExpression
@@ -19,28 +19,35 @@ package org.jetbrains.kotlin.idea.refactoring.changeSignature
import com.intellij.lang.Language
import com.intellij.lang.java.JavaLanguage
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.util.VisibilityUtil
import org.jetbrains.kotlin.asJava.*
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.asJava.toLightMethods
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.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.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.idea.project.*
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetMethodDescriptor.Kind
import java.util.*
import kotlin.properties.Delegates
public class JetChangeInfo(
val methodDescriptor: JetMethodDescriptor,
@@ -61,7 +68,7 @@ public class JetChangeInfo(
}
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 {
val map = HashMap<String, Int>()
@@ -80,13 +87,7 @@ public class JetChangeInfo(
}
private var isPrimaryMethodUpdated: Boolean = false
private var javaChangeInfo: JavaChangeInfo? = null
private fun getCurrentPsiMethod(): PsiMethod? {
val psiMethods = getMethod().toLightMethods()
assert(psiMethods.size() <= 1) { "Multiple light methods: " + getMethod().getText() }
return psiMethods.firstOrNull()
}
private var javaChangeInfos: List<JavaChangeInfo>? = null
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 getNonReceiverParameters(): List<JetParameterInfo> {
if (methodDescriptor.baseDeclaration is JetProperty) return emptyList()
return receiverParameterInfo?.let { receiver -> newParameters.filter { it != receiver } } ?: newParameters
}
@@ -146,7 +148,7 @@ public class JetChangeInfo(
override fun getLanguage(): Language = JetLanguage.INSTANCE
public fun getNewSignature(inheritedFunction: JetFunctionDefinitionUsage<PsiElement>): String {
public fun getNewSignature(inheritedCallable: JetCallableDefinitionUsage<PsiElement>): String {
val buffer = StringBuilder()
val defaultVisibility = if (kind.isConstructor) Visibilities.PUBLIC else Visibilities.INTERNAL
@@ -174,7 +176,7 @@ public class JetChangeInfo(
buffer.append(name)
}
buffer.append(getNewParametersSignature(inheritedFunction))
buffer.append(getNewParametersSignature(inheritedCallable))
if (newReturnType != null && !KotlinBuiltIns.isUnit(newReturnType) && kind == Kind.FUNCTION)
buffer.append(": ").append(newReturnTypeText)
@@ -182,63 +184,75 @@ public class JetChangeInfo(
return buffer.toString()
}
public fun isRefactoringTarget(inheritedFunctionDescriptor: FunctionDescriptor?): Boolean {
return inheritedFunctionDescriptor != null
&& getMethod() == DescriptorToSourceUtils.descriptorToDeclaration(inheritedFunctionDescriptor)
public fun isRefactoringTarget(inheritedCallableDescriptor: CallableDescriptor?): Boolean {
return inheritedCallableDescriptor != null
&& getMethod() == DescriptorToSourceUtils.descriptorToDeclaration(inheritedCallableDescriptor)
}
public fun getNewParametersSignature(inheritedFunction: JetFunctionDefinitionUsage<PsiElement>): String {
public fun getNewParametersSignature(inheritedCallable: JetCallableDefinitionUsage<PsiElement>): String {
val signatureParameters = getNonReceiverParameters()
val isLambda = inheritedFunction.getDeclaration() is JetFunctionLiteral
if (isLambda && signatureParameters.size() == 1 && !signatureParameters.get(0).requiresExplicitType(inheritedFunction)) {
return signatureParameters.get(0).getDeclarationSignature(0, inheritedFunction)
val isLambda = inheritedCallable.getDeclaration() is JetFunctionLiteral
if (isLambda && signatureParameters.size() == 1 && !signatureParameters.get(0).requiresExplicitType(inheritedCallable)) {
return signatureParameters.get(0).getDeclarationSignature(0, inheritedCallable)
}
return signatureParameters.indices
.map { i -> signatureParameters[i].getDeclarationSignature(i, inheritedFunction) }
.map { i -> signatureParameters[i].getDeclarationSignature(i, inheritedCallable) }
.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 typeSubstitutor = inheritedFunction.getOrCreateTypeSubstitutor() ?: return receiverTypeText
val currentBaseFunction = inheritedFunction.getBaseFunction().getCurrentFunctionDescriptor() ?: return receiverTypeText
val typeSubstitutor = inheritedCallable.getOrCreateTypeSubstitutor() ?: return receiverTypeText
val currentBaseFunction = inheritedCallable.getBaseFunction().getCurrentCallableDescriptor() ?: return receiverTypeText
return currentBaseFunction.getExtensionReceiverParameter()!!.getType().renderTypeWithSubstitution(typeSubstitutor, receiverTypeText, false)
}
public fun renderReturnType(inheritedFunction: JetFunctionDefinitionUsage<PsiElement>): String {
val typeSubstitutor = inheritedFunction.getOrCreateTypeSubstitutor() ?: return newReturnTypeText
val currentBaseFunction = inheritedFunction.getBaseFunction().getCurrentFunctionDescriptor() ?: return newReturnTypeText
public fun renderReturnType(inheritedCallable: JetCallableDefinitionUsage<PsiElement>): String {
val typeSubstitutor = inheritedCallable.getOrCreateTypeSubstitutor() ?: return newReturnTypeText
val currentBaseFunction = inheritedCallable.getBaseFunction().getCurrentCallableDescriptor() ?: return newReturnTypeText
return currentBaseFunction.getReturnType().renderTypeWithSubstitution(typeSubstitutor, newReturnTypeText, false)
}
public fun primaryMethodUpdated() {
isPrimaryMethodUpdated = true
javaChangeInfo = null
javaChangeInfos = null
}
public fun getOrCreateJavaChangeInfo(): JavaChangeInfo? {
if (ProjectStructureUtil.isJsKotlinModule(getMethod().getContainingFile() as JetFile)) return null
public fun getOrCreateJavaChangeInfos(): List<JavaChangeInfo>? {
/*
* 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) {
val currentPsiMethod = getCurrentPsiMethod()
if (originalPsiMethod == null || currentPsiMethod == null) 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)
*/
val javaVisibility = if (isPrimaryMethodUpdated)
fun createJavaChangeInfo(originalPsiMethod: PsiMethod,
currentPsiMethod: PsiMethod,
newName: String,
newReturnType: PsiType?,
newParameters: Array<ParameterInfoImpl>
): JavaChangeInfo? {
val newVisibility = if (isPrimaryMethodUpdated)
VisibilityUtil.getVisibilityModifier(currentPsiMethod.getModifierList())
else
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()
val newJavaParameters = newParameterList.withIndex().map { pair ->
return javaChangeInfo
}
fun getJavaParameterInfos(currentPsiMethod: PsiMethod, newParameterList: List<JetParameterInfo>): MutableList<ParameterInfoImpl> {
return newParameterList.withIndex().mapTo(ArrayList()) { pair ->
val (i, info) = pair
val type = if (isPrimaryMethodUpdated)
@@ -255,25 +269,66 @@ public class JetChangeInfo(
}
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
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?
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 {
val method = getMethod() as PsiMethod
@@ -305,7 +360,7 @@ public fun ChangeInfo.toJetChangeInfo(originalChangeSignatureDescriptor: JetMeth
}
else null
with(JetParameterInfo(functionDescriptor = functionDescriptor,
with(JetParameterInfo(callableDescriptor = functionDescriptor,
originalIndex = oldIndex,
name = info.getName(),
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 org.jetbrains.annotations.TestOnly
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
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.OverrideResolver
@@ -50,55 +54,64 @@ fun JetMethodDescriptor.modify(action: (JetMutableMethodDescriptor) -> Unit): Je
}
public fun runChangeSignature(project: Project,
functionDescriptor: FunctionDescriptor,
callableDescriptor: CallableDescriptor,
configuration: JetChangeSignatureConfiguration,
bindingContext: BindingContext,
defaultValueContext: PsiElement,
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,
functionDescriptor: FunctionDescriptor,
callableDescriptor: CallableDescriptor,
val configuration: JetChangeSignatureConfiguration,
bindingContext: BindingContext,
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>())
override fun forcePerformForSelectedFunctionOnly() = configuration.forcePerformForSelectedFunctionOnly()
override fun performRefactoring(descriptorsForChange: Collection<CallableDescriptor>) {
assert (descriptorsForChange.all { it is FunctionDescriptor }) {
"Function descriptors expected: " + descriptorsForChange.joinToString(separator = "\n")
private fun runSilentRefactoring(descriptor: JetMethodDescriptor) {
val commandName = commandName ?: ChangeSignatureHandler.REFACTORING_NAME
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")
val adjustedDescriptor = adjustDescriptor(descriptorsForChange as Collection<FunctionDescriptor>)
if (adjustedDescriptor == null) return
dialog.show()
}
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 (configuration.performSilently(affectedFunctions)
|| ApplicationManager.getApplication()!!.isUnitTestMode()) {
JetChangeSignatureDialog.createRefactoringProcessorForSilentChangeSignature(
project,
commandName ?: ChangeSignatureHandler.REFACTORING_NAME,
adjustedDescriptor,
defaultValueContext
).run()
if (configuration.performSilently(affectedFunctions) || ApplicationManager.getApplication()!!.isUnitTestMode()) {
runSilentRefactoring(adjustedDescriptor)
}
else {
val dialog = JetChangeSignatureDialog(project, adjustedDescriptor, defaultValueContext, commandName)
dialog.show()
runInteractiveRefactoring(adjustedDescriptor)
}
}
fun adjustDescriptor(descriptorsForSignatureChange: Collection<FunctionDescriptor>): JetMethodDescriptor? {
fun adjustDescriptor(descriptorsForSignatureChange: Collection<CallableDescriptor>): JetMethodDescriptor? {
val baseDescriptor = preferContainedInClass(descriptorsForSignatureChange)
val functionDeclaration = DescriptorToSourceUtilsIde.getAnyDeclaration(project, baseDescriptor)
if (functionDeclaration == null) {
@@ -114,7 +127,7 @@ public class JetChangeSignature(project: Project,
return configuration.configure(originalDescriptor, bindingContext)
}
private fun preferContainedInClass(descriptorsForSignatureChange: Collection<FunctionDescriptor>): FunctionDescriptor {
private fun preferContainedInClass(descriptorsForSignatureChange: Collection<CallableDescriptor>): CallableDescriptor {
for (descriptor in descriptorsForSignatureChange) {
val containingDeclaration = descriptor.getContainingDeclaration()
if (containingDeclaration is ClassDescriptor && containingDeclaration.getKind() != ClassKind.INTERFACE) {
@@ -127,15 +140,22 @@ public class JetChangeSignature(project: Project,
}
TestOnly public fun createChangeInfo(project: Project,
functionDescriptor: FunctionDescriptor,
callableDescriptor: CallableDescriptor,
configuration: JetChangeSignatureConfiguration,
bindingContext: BindingContext,
defaultValueContext: PsiElement): JetChangeInfo? {
val jetChangeSignature = JetChangeSignature(project, functionDescriptor, configuration, bindingContext, defaultValueContext, null)
val declarations = OverrideResolver.getDeepestSuperDeclarations(functionDescriptor)
val jetChangeSignature = JetChangeSignature(project, callableDescriptor, configuration, bindingContext, defaultValueContext, null)
val declarations = if (callableDescriptor is CallableMemberDescriptor) {
OverrideResolver.getDeepestSuperDeclarations(callableDescriptor)
} else listOf(callableDescriptor)
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()
}
@@ -23,6 +23,8 @@ import com.intellij.refactoring.changeSignature.OverriderUsageInfo
import com.intellij.usageView.UsageInfo
import org.jetbrains.kotlin.asJava.KotlinLightMethod
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.impl.AnonymousFunctionDescriptor
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.core.CollectingNameValidator
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.psi.JetCallableDeclaration
import org.jetbrains.kotlin.psi.JetClass
import org.jetbrains.kotlin.psi.JetFunction
import org.jetbrains.kotlin.psi.JetNamedDeclaration
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils
import java.util.Collections
@@ -41,9 +47,9 @@ import java.util.HashSet
import kotlin.properties.Delegates
public class JetChangeSignatureData(
override val baseDescriptor: FunctionDescriptor,
override val baseDescriptor: CallableDescriptor,
override val baseDeclaration: PsiElement,
private val descriptorsForSignatureChange: Collection<FunctionDescriptor>
private val descriptorsForSignatureChange: Collection<CallableDescriptor>
) : JetMethodDescriptor {
private val parameters: List<JetParameterInfo>
override val receiver: JetParameterInfo?
@@ -60,7 +66,7 @@ public class JetChangeSignatureData(
.mapTo(receiver?.let{ arrayListOf(it) } ?: arrayListOf()) { parameterDescriptor ->
val jetParameter = valueParameters?.get(parameterDescriptor.getIndex())
JetParameterInfo(
functionDescriptor = baseDescriptor,
callableDescriptor = baseDescriptor,
originalIndex = parameterDescriptor.getIndex(),
name = parameterDescriptor.getName().asString(),
type = parameterDescriptor.getType(),
@@ -72,8 +78,8 @@ public class JetChangeSignatureData(
}
private fun createReceiverInfoIfNeeded(): JetParameterInfo? {
val function = baseDeclaration as? JetFunction ?: return null
val bodyScope = function.getBodyExpression()?.let { it.analyze()[BindingContext.RESOLUTION_SCOPE, it] }
val callable = baseDeclaration as? JetCallableDeclaration ?: return null
val bodyScope = (callable as? JetFunction)?.getBodyExpression()?.let { it.analyze()[BindingContext.RESOLUTION_SCOPE, it] }
val paramNames = baseDescriptor.getValueParameters().map { it.getName().asString() }
val validator = bodyScope?.let { bodyScope ->
CollectingNameValidator(paramNames) {
@@ -83,34 +89,37 @@ public class JetChangeSignatureData(
} ?: CollectingNameValidator(paramNames)
val receiverType = baseDescriptor.getExtensionReceiverParameter()?.getType() ?: return null
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 {
val declaration = DescriptorToSourceUtilsIde.getAnyDeclaration(baseDeclaration.getProject(), it)
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 {
primaryFunctions.first { it.getDeclaration() == baseDeclaration }
override val originalPrimaryCallable: JetCallableDefinitionUsage<PsiElement> by Delegates.lazy {
primaryCallables.first { it.getDeclaration() == baseDeclaration }
}
override val affectedFunctions: Collection<UsageInfo> by Delegates.lazy {
primaryFunctions + primaryFunctions.flatMapTo(HashSet<UsageInfo>()) { primaryFunction ->
val primaryDeclaration = primaryFunction.getDeclaration() as? JetFunction
val lightMethod = primaryDeclaration?.let { LightClassUtil.getLightClassMethod(it) }
val overrides = lightMethod?.let { OverridingMethodsSearch.search(it).findAll() } ?: Collections.emptyList()
overrides.map { method ->
if (method is KotlinLightMethod) {
val overridingDeclaration = method.getOrigin()
val overridingDescriptor = overridingDeclaration?.resolveToDescriptor() as FunctionDescriptor
JetFunctionDefinitionUsage<PsiElement>(overridingDeclaration, overridingDescriptor, primaryFunction, null)
}
else OverriderUsageInfo(method, lightMethod, true, true, true)
}.filterNotNullTo(HashSet<UsageInfo>())
override val affectedCallables: Collection<UsageInfo> by Delegates.lazy {
primaryCallables + primaryCallables.flatMapTo(HashSet<UsageInfo>()) { primaryFunction ->
val primaryDeclaration = primaryFunction.getDeclaration() as? JetCallableDeclaration
val lightMethods = primaryDeclaration?.toLightMethods() ?: Collections.emptyList()
lightMethods.flatMap { baseMethod ->
OverridingMethodsSearch
.search(baseMethod)
.map { overridingMethod ->
if (overridingMethod is KotlinLightMethod) {
val overridingDeclaration = overridingMethod.namedUnwrappedElement as JetNamedDeclaration
val overridingDescriptor = overridingDeclaration.resolveToDescriptor() as CallableDescriptor
JetCallableDefinitionUsage<PsiElement>(overridingDeclaration, overridingDescriptor, primaryFunction, null)
}
else OverriderUsageInfo(overridingMethod, baseMethod, true, true, true)
}.filterNotNullTo(HashSet<UsageInfo>())
}
}
}
@@ -416,7 +416,7 @@ public class JetChangeSignatureDialog extends ChangeSignatureDialogBase<
getMethodName(),
myDefaultValueContext
);
return changeInfo.getNewSignature(getMethodDescriptor().getOriginalPrimaryFunction());
return changeInfo.getNewSignature(getMethodDescriptor().getOriginalPrimaryCallable());
}
@Override
@@ -34,10 +34,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import org.jetbrains.kotlin.asJava.AsJavaPackage;
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage;
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils;
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde;
@@ -57,44 +54,44 @@ public class JetChangeSignatureHandler implements ChangeSignatureHandler {
@Nullable
public static PsiElement findTargetForRefactoring(@NotNull PsiElement element) {
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);
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();
if (elementParent instanceof JetNamedFunction && ((JetNamedFunction) 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 JetNamedFunction || elementParent instanceof JetClass || elementParent instanceof JetProperty)
&& ((JetNamedDeclaration) elementParent).getNameIdentifier() == element) return elementParent;
if (elementParent instanceof JetSecondaryConstructor &&
((JetSecondaryConstructor) elementParent).getConstructorKeyword() == element) return elementParent;
JetExpression calleeExpr;
JetCallElement call = PsiTreeUtil.getParentOfType(element,
JetCallExpression.class,
JetDelegatorToSuperCall.class,
JetConstructorDelegationCall.class);
if (call == null) return null;
JetExpression receiverExpr = call.getCalleeExpression();
if (receiverExpr instanceof JetConstructorCalleeExpression) {
receiverExpr = ((JetConstructorCalleeExpression) receiverExpr).getConstructorReferenceExpression();
if (call != null) {
calleeExpr = call.getCalleeExpression();
}
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);
if (jetElement == null) return null;
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;
@@ -107,20 +104,20 @@ public class JetChangeSignatureHandler implements ChangeSignatureHandler {
@Nullable Editor editor
) {
BindingContext bindingContext = ResolvePackage.analyze(element, BodyResolveMode.FULL);
FunctionDescriptor functionDescriptor = findDescriptor(element, project, editor, bindingContext);
if (functionDescriptor == null) {
CallableDescriptor callableDescriptor = findDescriptor(element, project, editor, bindingContext);
if (callableDescriptor == null) {
return;
}
if (functionDescriptor instanceof JavaCallableMemberDescriptor) {
PsiElement declaration = DescriptorToSourceUtilsIde.INSTANCE$.getAnyDeclaration(project, functionDescriptor);
assert declaration instanceof PsiMethod : "PsiMethod expected: " + functionDescriptor;
if (callableDescriptor instanceof JavaCallableMemberDescriptor) {
PsiElement declaration = DescriptorToSourceUtilsIde.INSTANCE$.getAnyDeclaration(project, callableDescriptor);
assert declaration instanceof PsiMethod : "PsiMethod expected: " + callableDescriptor;
ChangeSignatureUtil.invokeChangeSignatureOn((PsiMethod) declaration, project);
return;
}
if (TasksPackage.isDynamic(functionDescriptor)) {
if (TasksPackage.isDynamic(callableDescriptor)) {
if (editor != null) {
CodeInsightUtils.showErrorHint(
project,
@@ -133,7 +130,7 @@ public class JetChangeSignatureHandler implements ChangeSignatureHandler {
return;
}
runChangeSignature(project, functionDescriptor, emptyConfiguration(), bindingContext, context, null);
runChangeSignature(project, callableDescriptor, emptyConfiguration(), bindingContext, context, null);
}
@TestOnly
@@ -208,7 +205,7 @@ public class JetChangeSignatureHandler implements ChangeSignatureHandler {
}
@Nullable
public static FunctionDescriptor findDescriptor(
public static CallableDescriptor findDescriptor(
@NotNull PsiElement element,
@NotNull Project project,
@Nullable Editor editor,
@@ -244,6 +241,9 @@ public class JetChangeSignatureHandler implements ChangeSignatureHandler {
return (FunctionDescriptor) descriptor;
}
else if (descriptor instanceof PropertyDescriptor) {
return (PropertyDescriptor) descriptor;
}
else {
String message = RefactoringBundle.getCannotRefactorMessage(JetRefactoringBundle.message(
"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.psi.PsiElement;
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.ui.ConflictsDialog;
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.MultiMap;
import kotlin.KotlinPackage;
import kotlin.Pair;
import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.JetUsageInfo;
import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.KotlinWrapperForJavaUsageInfos;
@@ -62,10 +63,13 @@ public class JetChangeSignatureProcessor extends ChangeSignatureProcessorBase {
protected UsageInfo[] findUsages() {
List<UsageInfo> allUsages = new ArrayList<UsageInfo>();
JavaChangeInfo javaChangeInfo = getChangeInfo().getOrCreateJavaChangeInfo();
if (javaChangeInfo != null) {
UsageInfo[] javaUsages = new JavaChangeSignatureUsageProcessor().findUsages(javaChangeInfo);
allUsages.add(new KotlinWrapperForJavaUsageInfos(javaUsages, getChangeInfo().getMethod()));
List<JavaChangeInfo> javaChangeInfos = getChangeInfo().getOrCreateJavaChangeInfos();
if (javaChangeInfos != null) {
JavaChangeSignatureUsageProcessor javaProcessor = new JavaChangeSignatureUsageProcessor();
for (JavaChangeInfo javaChangeInfo : javaChangeInfos) {
UsageInfo[] javaUsages = javaProcessor.findUsages(javaChangeInfo);
allUsages.add(new KotlinWrapperForJavaUsageInfos(javaChangeInfo, javaUsages, getChangeInfo().getMethod()));
}
}
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.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.search.searches.OverridingMethodsSearch;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.search.searches.OverridingMethodsSearch;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiTreeUtil;
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.HashSet;
import com.intellij.util.containers.MultiMap;
import jet.runtime.typeinfo.JetValueParameter;
import kotlin.KotlinPackage;
import kotlin.Unit;
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.core.refactoring.RefactoringPackage;
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.search.usagesSearch.UsagesSearchPackage;
import org.jetbrains.kotlin.kdoc.psi.impl.KDocName;
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor;
import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage;
import org.jetbrains.kotlin.psi.typeRefHelpers.TypeRefHelpersPackage;
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
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.model.ResolvedCall;
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.scopes.JetScope;
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.TypeUtils;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;
public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsageProcessor {
@Override
@@ -104,8 +99,8 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
private static void findAllMethodUsages(JetChangeInfo changeInfo, Set<UsageInfo> result) {
for (UsageInfo functionUsageInfo : ChangeSignaturePackage.getAffectedFunctions(changeInfo)) {
if (functionUsageInfo instanceof JetFunctionDefinitionUsage) {
findOneMethodUsages((JetFunctionDefinitionUsage) functionUsageInfo, changeInfo, result);
if (functionUsageInfo instanceof JetCallableDefinitionUsage) {
findOneMethodUsages((JetCallableDefinitionUsage) functionUsageInfo, changeInfo, result);
}
else {
result.add(functionUsageInfo);
@@ -123,7 +118,7 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
JetCallElement callElement = PsiTreeUtil.getParentOfType(element, JetCallElement.class);
JetExpression calleeExpression = callElement != null ? callElement.getCalleeExpression() : null;
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(
@NotNull JetFunctionDefinitionUsage<?> functionUsageInfo,
@NotNull JetCallableDefinitionUsage<?> functionUsageInfo,
final JetChangeInfo changeInfo,
final Set<UsageInfo> result
) {
@@ -160,6 +155,9 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
if (parent instanceof JetConstructorCalleeExpression && parent.getParent() instanceof JetDelegatorToSuperCall)
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)
TextOccurrencesUtil.findNonCodeUsages(functionPsi, oldName, true, true, changeInfo.getNewName(), result);
List<JetParameter> oldParameters = functionPsi instanceof JetFunction
? ((JetFunction) functionPsi).getValueParameters()
: ((JetClass) functionPsi).getPrimaryConstructorParameters();
List<JetParameter> oldParameters = PsiUtilPackage.getValueParameters((JetNamedDeclaration) functionPsi);
JetParameterInfo newReceiverInfo = changeInfo.getReceiverParameterInfo();
@@ -221,7 +217,7 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
}
private static void processInternalReferences(
JetFunctionDefinitionUsage functionUsageInfo,
JetCallableDefinitionUsage functionUsageInfo,
JetTreeVisitor<BindingContext> visitor
) {
JetFunction jetFunction = (JetFunction) functionUsageInfo.getDeclaration();
@@ -238,12 +234,12 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
}
private static void findOriginalReceiversUsages(
@NotNull final JetFunctionDefinitionUsage<?> functionUsageInfo,
@NotNull final JetCallableDefinitionUsage<?> functionUsageInfo,
@NotNull final Set<UsageInfo> result,
@NotNull final JetChangeInfo changeInfo
) {
final JetParameterInfo originalReceiverInfo = changeInfo.getMethodDescriptor().getReceiver();
final FunctionDescriptor functionDescriptor = functionUsageInfo.getOriginalFunctionDescriptor();
final CallableDescriptor callableDescriptor = functionUsageInfo.getOriginalCallableDescriptor();
processInternalReferences(
functionUsageInfo,
new JetTreeVisitor<BindingContext>() {
@@ -254,7 +250,7 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
if (originalReceiverInfo != null && !changeInfo.hasParameter(originalReceiverInfo)) 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();
result.add(new JetParameterUsage(expression, originalReceiverInfo, functionUsageInfo));
}
@@ -270,7 +266,7 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
@NotNull ThisReceiver receiverValue
) {
DeclarationDescriptor targetDescriptor = receiverValue.getDeclarationDescriptor();
if (targetDescriptor == functionDescriptor) {
if (targetDescriptor == callableDescriptor) {
assert originalReceiverInfo != null : "No original receiver info provided: " + functionUsageInfo.getDeclaration().getText();
result.add(new JetImplicitThisToParameterUsage(callElement, originalReceiverInfo, functionUsageInfo));
}
@@ -407,7 +403,7 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
PsiElement function = info.getMethod();
PsiElement element = function != null ? function : changeInfo.getContext();
BindingContext bindingContext = ResolvePackage.analyze((JetElement) element, BodyResolveMode.FULL);
FunctionDescriptor oldDescriptor = ChangeSignaturePackage.getOriginalBaseFunctionDescriptor(changeInfo);
CallableDescriptor oldDescriptor = ChangeSignaturePackage.getOriginalBaseFunctionDescriptor(changeInfo);
DeclarationDescriptor containingDeclaration = oldDescriptor.getContainingDeclaration();
JetScope parametersScope = null;
@@ -416,17 +412,21 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
else if (function instanceof JetFunction)
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);
if (!kind.getIsConstructor() && functionScope != null && !info.getNewName().isEmpty()) {
for (FunctionDescriptor conflict : functionScope.getFunctions(Name.identifier(info.getNewName()))) {
if (!kind.getIsConstructor() && callableScope != null && !info.getNewName().isEmpty()) {
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;
PsiElement conflictElement = DescriptorToSourceUtils.descriptorToDeclaration(conflict);
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) + "'");
break;
}
@@ -464,7 +464,7 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
JetParameterInfo newReceiverInfo = changeInfo.getReceiverParameterInfo();
JetParameterInfo originalReceiverInfo = changeInfo.getMethodDescriptor().getReceiver();
if (function instanceof JetNamedFunction && newReceiverInfo != originalReceiverInfo) {
if (function instanceof JetCallableDeclaration && newReceiverInfo != originalReceiverInfo) {
findReceiverIntroducingConflicts(result, function, newReceiverInfo);
findInternalExplicitReceiverConflicts(refUsages.get(), result, originalReceiverInfo);
findThisLabelConflicts((JetChangeInfo) info, refUsages, result, changeInfo, function);
@@ -525,10 +525,9 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
) {
if (originalReceiverInfo == null) {
for (UsageInfo usageInfo : usages) {
if (!(usageInfo instanceof JetFunctionCallUsage)) continue;
if (!(usageInfo instanceof JetFunctionCallUsage || usageInfo instanceof JetPropertyCallUsage)) continue;
JetFunctionCallUsage callUsage = (JetFunctionCallUsage) usageInfo;
JetElement callElement = callUsage.getElement();
JetElement callElement = (JetElement) usageInfo.getElement();
if (callElement == null) continue;
PsiElement parent = callElement.getParent();
@@ -546,7 +545,7 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
PsiElement callable,
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(
JetFileReferencesResolver.INSTANCE$.resolve((JetNamedFunction) callable, true, true),
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>() {
@Override
public JetType fun(ValueParameterDescriptor descriptor) {
@@ -710,26 +709,33 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
boolean isJavaMethodUsage = isJavaMethodUsage(usageInfo);
if (usageInfo instanceof KotlinWrapperForJavaUsageInfos) {
JavaChangeInfo javaChangeInfo = ((JetChangeInfo) changeInfo).getOrCreateJavaChangeInfo();
assert javaChangeInfo != null : "JavaChangeInfo not found: " + method.getText();
UsageInfo[] javaUsageInfos = ((KotlinWrapperForJavaUsageInfos) usageInfo).getJavaUsageInfos();
List<JavaChangeInfo> javaChangeInfos = ((JetChangeInfo) changeInfo).getOrCreateJavaChangeInfos();
assert javaChangeInfos != null : "JavaChangeInfo not found: " + method.getText();
KotlinWrapperForJavaUsageInfos wrapperForJavaUsageInfos = (KotlinWrapperForJavaUsageInfos) usageInfo;
UsageInfo[] javaUsageInfos = wrapperForJavaUsageInfos.getJavaUsageInfos();
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) {
if (usage instanceof OverriderUsageInfo && beforeMethodChange) continue;
for (ChangeSignatureUsageProcessor processor : processors) {
if (processor instanceof JetChangeSignatureUsageProcessor) continue;
if (usage instanceof OverriderUsageInfo) {
processor.processUsage(javaChangeInfo, usage, true, javaUsageInfos);
NullabilityPropagator nullabilityPropagator = new NullabilityPropagator(javaChangeInfo.getMethod());
for (UsageInfo usage : javaUsageInfos) {
if (usage instanceof OverriderUsageInfo && beforeMethodChange) continue;
for (ChangeSignatureUsageProcessor processor : processors) {
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 (overridingMethod != null && !(overridingMethod instanceof KotlinLightMethod)) {
nullabilityPropagator.processMethod(overridingMethod);
if (usage instanceof OverriderUsageInfo) {
PsiMethod overridingMethod = ((OverriderUsageInfo) usage).getOverridingMethod();
if (overridingMethod != null && !(overridingMethod instanceof KotlinLightMethod)) {
nullabilityPropagator.processMethod(overridingMethod);
}
}
}
}
@@ -792,7 +798,7 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
if (!(changeInfo instanceof JetChangeInfo)) return false;
JetChangeInfo jetChangeInfo = (JetChangeInfo) changeInfo;
for (JetFunctionDefinitionUsage primaryFunction : jetChangeInfo.getMethodDescriptor().getPrimaryFunctions()) {
for (JetCallableDefinitionUsage primaryFunction : jetChangeInfo.getMethodDescriptor().getPrimaryCallables()) {
primaryFunction.processUsage(jetChangeInfo, primaryFunction.getDeclaration());
}
jetChangeInfo.primaryMethodUpdated();
@@ -19,10 +19,10 @@ package org.jetbrains.kotlin.idea.refactoring.changeSignature
import com.intellij.psi.PsiElement
import com.intellij.refactoring.changeSignature.MethodDescriptor
import com.intellij.usageView.UsageInfo
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.JetFunctionDefinitionUsage
import org.jetbrains.kotlin.descriptors.CallableDescriptor
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
public trait JetMethodDescriptor : MethodDescriptor<JetParameterInfo, Visibility> {
@@ -42,11 +42,11 @@ public trait JetMethodDescriptor : MethodDescriptor<JetParameterInfo, Visibility
}
val baseDeclaration: PsiElement
val baseDescriptor: FunctionDescriptor
val baseDescriptor: CallableDescriptor
val originalPrimaryFunction: JetFunctionDefinitionUsage<PsiElement>
val primaryFunctions: Collection<JetFunctionDefinitionUsage<PsiElement>>
val affectedFunctions: Collection<UsageInfo>
val originalPrimaryCallable: JetCallableDefinitionUsage<PsiElement>
val primaryCallables: Collection<JetCallableDefinitionUsage<PsiElement>>
val affectedCallables: Collection<UsageInfo>
val receiver: JetParameterInfo?
}
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
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.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.psi.*
@@ -36,7 +36,7 @@ import org.jetbrains.kotlin.types.JetType
import java.util.LinkedHashMap
public class JetParameterInfo(
val functionDescriptor: FunctionDescriptor,
val callableDescriptor: CallableDescriptor,
val originalIndex: Int = -1,
private var name: String,
type: JetType? = null,
@@ -61,7 +61,7 @@ public class JetParameterInfo(
object : JetTreeVisitorVoid() {
private fun selfParameterOrNull(parameter: DeclarationDescriptor?): ValueParameterDescriptor? {
return if (parameter is ValueParameterDescriptor &&
compareDescriptors(project, parameter.getContainingDeclaration(), functionDescriptor)) {
compareDescriptors(project, parameter.getContainingDeclaration(), callableDescriptor)) {
parameter
} else null
}
@@ -69,12 +69,12 @@ public class JetParameterInfo(
private fun selfReceiverOrNull(receiverDescriptor: DeclarationDescriptor?): DeclarationDescriptor? {
if (compareDescriptors(project,
receiverDescriptor,
functionDescriptor.getExtensionReceiverParameter()?.getContainingDeclaration())) {
callableDescriptor.getExtensionReceiverParameter()?.getContainingDeclaration())) {
return receiverDescriptor
}
if (compareDescriptors(project,
receiverDescriptor,
functionDescriptor.getDispatchReceiverParameter()?.getContainingDeclaration())) {
callableDescriptor.getDispatchReceiverParameter()?.getContainingDeclaration())) {
return receiverDescriptor
}
return null
@@ -93,7 +93,7 @@ public class JetParameterInfo(
val descriptor = ref.resolveToDescriptors(context).singleOrNull()
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
return parameter?.let { selfParameterOrNull(context[BindingContext.VALUE_PARAMETER, it]) }
}
@@ -149,20 +149,20 @@ public class JetParameterInfo(
throw UnsupportedOperationException()
}
public fun renderType(parameterIndex: Int, inheritedFunction: JetFunctionDefinitionUsage<*>): String {
val typeSubstitutor = inheritedFunction.getOrCreateTypeSubstitutor() ?: return currentTypeText
val currentBaseFunction = inheritedFunction.getBaseFunction().getCurrentFunctionDescriptor() ?: return currentTypeText
public fun renderType(parameterIndex: Int, inheritedCallable: JetCallableDefinitionUsage<*>): String {
val typeSubstitutor = inheritedCallable.getOrCreateTypeSubstitutor() ?: return currentTypeText
val currentBaseFunction = inheritedCallable.getBaseFunction().getCurrentCallableDescriptor() ?: return currentTypeText
val parameterType = currentBaseFunction.getValueParameters().get(parameterIndex).getType()
return parameterType.renderTypeWithSubstitution(typeSubstitutor, currentTypeText, true)
}
public fun getInheritedName(inheritedFunction: JetFunctionDefinitionUsage<*>): String {
if (!inheritedFunction.isInherited()) return name
public fun getInheritedName(inheritedCallable: JetCallableDefinitionUsage<*>): String {
if (!inheritedCallable.isInherited()) return name
val baseFunction = inheritedFunction.getBaseFunction()
val baseFunctionDescriptor = baseFunction.getOriginalFunctionDescriptor()
val baseFunction = inheritedCallable.getBaseFunction()
val baseFunctionDescriptor = baseFunction.getOriginalCallableDescriptor()
val inheritedFunctionDescriptor = inheritedFunction.getOriginalFunctionDescriptor()
val inheritedFunctionDescriptor = inheritedCallable.getOriginalCallableDescriptor()
val inheritedParameterDescriptors = inheritedFunctionDescriptor.getValueParameters()
if (originalIndex < 0
|| originalIndex >= baseFunctionDescriptor.getValueParameters().size()
@@ -177,18 +177,18 @@ public class JetParameterInfo(
}
}
public fun requiresExplicitType(inheritedFunction: JetFunctionDefinitionUsage<PsiElement>): Boolean {
val inheritedFunctionDescriptor = inheritedFunction.getOriginalFunctionDescriptor()
public fun requiresExplicitType(inheritedCallable: JetCallableDefinitionUsage<PsiElement>): Boolean {
val inheritedFunctionDescriptor = inheritedCallable.getOriginalCallableDescriptor()
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 parameter = DescriptorToSourceUtils.descriptorToDeclaration(inheritedParameterDescriptor) as? JetParameter ?: return false
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()
if (modifierList != null) {
@@ -199,13 +199,13 @@ public class JetParameterInfo(
buffer.append(valOrVar).append(' ')
}
buffer.append(getInheritedName(inheritedFunction))
buffer.append(getInheritedName(inheritedCallable))
if (requiresExplicitType(inheritedFunction)) {
buffer.append(": ").append(renderType(parameterIndex, inheritedFunction))
if (requiresExplicitType(inheritedCallable)) {
buffer.append(": ").append(renderType(parameterIndex, inheritedCallable))
}
if (!inheritedFunction.isInherited()) {
if (!inheritedCallable.isInherited()) {
defaultValueForParameter?.let { buffer.append(" = ").append(it.getText()) }
}
@@ -16,18 +16,13 @@
package org.jetbrains.kotlin.idea.refactoring.changeSignature
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.types.TypeSubstitutor
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.refactoring.changeSignature.usages.JetCallableDefinitionUsage
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>? {
val substitutedType = TypeCheckingProcedure.findCorrespondingSupertype(derivedType, baseType) ?: return null
@@ -40,15 +35,15 @@ private fun getTypeSubstitution(baseType: JetType, derivedType: JetType): Linked
return substitution
}
private fun getFunctionSubstitution(
baseFunction: FunctionDescriptor,
derivedFunction: FunctionDescriptor
private fun getCallableSubstitution(
baseCallable: CallableDescriptor,
derivedCallable: CallableDescriptor
): MutableMap<TypeConstructor, TypeProjection>? {
val baseClass = baseFunction.getContainingDeclaration() as? ClassDescriptor ?: return null
val derivedClass = derivedFunction.getContainingDeclaration() as? ClassDescriptor ?: return null
val baseClass = baseCallable.getContainingDeclaration() as? ClassDescriptor ?: return null
val derivedClass = derivedCallable.getContainingDeclaration() as? ClassDescriptor ?: 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())
}
@@ -59,15 +54,15 @@ fun getTypeSubstitutor(baseType: JetType, derivedType: JetType): TypeSubstitutor
return getTypeSubstitution(baseType, derivedType)?.let { TypeSubstitutor.create(it) }
}
fun getFunctionSubstitutor(
baseFunction: JetFunctionDefinitionUsage<*>,
derivedFunction: JetFunctionDefinitionUsage<*>
fun getCallableSubstitutor(
baseFunction: JetCallableDefinitionUsage<*>,
derivedCallable: JetCallableDefinitionUsage<*>
): TypeSubstitutor? {
val currentBaseFunction = baseFunction.getCurrentFunctionDescriptor()
val currentDerivedFunction = derivedFunction.getCurrentFunctionDescriptor()
val currentBaseFunction = baseFunction.getCurrentCallableDescriptor()
val currentDerivedFunction = derivedCallable.getCurrentCallableDescriptor()
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 {
@@ -35,10 +35,10 @@ public class DeferredJavaMethodOverrideOrSAMUsage(
): JavaMethodDeferredKotlinUsage<JetFunction>(function) {
override fun resolve(javaMethodChangeInfo: JetChangeInfo): JavaMethodKotlinUsageWithDelegate<JetFunction> {
return object : JavaMethodKotlinUsageWithDelegate<JetFunction>(function, javaMethodChangeInfo) {
override val delegateUsage = JetFunctionDefinitionUsage(
override val delegateUsage = JetCallableDefinitionUsage(
function,
functionDescriptor,
javaMethodChangeInfo.methodDescriptor.originalPrimaryFunction,
javaMethodChangeInfo.methodDescriptor.originalPrimaryCallable,
samCallType
)
}
@@ -34,7 +34,7 @@ public abstract class JavaMethodKotlinUsageWithDelegate<T: PsiElement>(
public class JavaMethodKotlinCallUsage(
callElement: JetCallElement,
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(
@@ -42,10 +42,10 @@ public class JavaMethodKotlinDerivedDefinitionUsage(
functionDescriptor: FunctionDescriptor,
javaMethodChangeInfo: JetChangeInfo): JavaMethodKotlinUsageWithDelegate<JetFunction>(function, javaMethodChangeInfo) {
@suppress("CAST_NEVER_SUCCEEDS")
override protected val delegateUsage = JetFunctionDefinitionUsage(
override protected val delegateUsage = JetCallableDefinitionUsage(
psiElement,
functionDescriptor,
javaMethodChangeInfo.methodDescriptor.originalPrimaryFunction,
javaMethodChangeInfo.methodDescriptor.originalPrimaryCallable,
null
)
}
@@ -26,9 +26,9 @@ import kotlin.Pair;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.descriptors.CallableDescriptor;
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage;
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.lexer.JetModifierKeywordToken;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage;
import org.jetbrains.kotlin.psi.typeRefHelpers.TypeRefHelpersPackage;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
@@ -52,14 +53,14 @@ import java.util.List;
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
private final FunctionDescriptor originalFunctionDescriptor;
private final CallableDescriptor originalCallableDescriptor;
private FunctionDescriptor currentFunctionDescriptor;
private CallableDescriptor currentCallableDescriptor;
@NotNull
private final JetFunctionDefinitionUsage<? extends PsiElement> baseFunction;
private final JetCallableDefinitionUsage<? extends PsiElement> baseFunction;
private final boolean hasExpectedType;
@@ -69,24 +70,25 @@ public class JetFunctionDefinitionUsage<T extends PsiElement> extends JetUsageIn
@Nullable
private TypeSubstitutor typeSubstitutor;
public JetFunctionDefinitionUsage(
public JetCallableDefinitionUsage(
@NotNull T function,
@NotNull FunctionDescriptor originalFunctionDescriptor,
@Nullable JetFunctionDefinitionUsage<PsiElement> baseFunction,
@Nullable JetType samCallType) {
@NotNull CallableDescriptor originalCallableDescriptor,
@Nullable JetCallableDefinitionUsage<PsiElement> baseFunction,
@Nullable JetType samCallType
) {
super(function);
this.originalFunctionDescriptor = originalFunctionDescriptor;
this.originalCallableDescriptor = originalCallableDescriptor;
this.baseFunction = baseFunction != null ? baseFunction : this;
this.hasExpectedType = checkIfHasExpectedType(originalFunctionDescriptor, isInherited());
this.hasExpectedType = checkIfHasExpectedType(originalCallableDescriptor, isInherited());
this.samCallType = samCallType;
}
private static boolean checkIfHasExpectedType(@NotNull FunctionDescriptor functionDescriptor, boolean isInherited) {
if (!(functionDescriptor instanceof AnonymousFunctionDescriptor && isInherited)) return false;
private static boolean checkIfHasExpectedType(@NotNull CallableDescriptor callableDescriptor, boolean isInherited) {
if (!(callableDescriptor instanceof AnonymousFunctionDescriptor && isInherited)) return false;
JetFunctionLiteral functionLiteral =
(JetFunctionLiteral) DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor);
assert functionLiteral != null : "No declaration found for " + functionDescriptor;
(JetFunctionLiteral) DescriptorToSourceUtils.descriptorToDeclaration(callableDescriptor);
assert functionLiteral != null : "No declaration found for " + callableDescriptor;
PsiElement parent = functionLiteral.getParent();
if (!(parent instanceof JetFunctionLiteralExpression)) return false;
@@ -96,7 +98,7 @@ public class JetFunctionDefinitionUsage<T extends PsiElement> extends JetUsageIn
}
@NotNull
public JetFunctionDefinitionUsage getBaseFunction() {
public JetCallableDefinitionUsage getBaseFunction() {
return baseFunction;
}
@@ -112,10 +114,10 @@ public class JetFunctionDefinitionUsage<T extends PsiElement> extends JetUsageIn
if (typeSubstitutor == null) {
if (samCallType == null) {
typeSubstitutor = ChangeSignaturePackage.getFunctionSubstitutor(baseFunction, this);
typeSubstitutor = ChangeSignaturePackage.getCallableSubstitutor(baseFunction, this);
}
else {
DeclarationDescriptor currentBaseDescriptor = baseFunction.getCurrentFunctionDescriptor();
DeclarationDescriptor currentBaseDescriptor = baseFunction.getCurrentCallableDescriptor();
DeclarationDescriptor classDescriptor = currentBaseDescriptor != null
? currentBaseDescriptor.getContainingDeclaration()
: null;
@@ -140,71 +142,51 @@ public class JetFunctionDefinitionUsage<T extends PsiElement> extends JetUsageIn
}
@NotNull
public final FunctionDescriptor getOriginalFunctionDescriptor() {
return originalFunctionDescriptor;
public final CallableDescriptor getOriginalCallableDescriptor() {
return originalCallableDescriptor;
}
@Nullable
public final FunctionDescriptor getCurrentFunctionDescriptor() {
if (currentFunctionDescriptor == null) {
public final CallableDescriptor getCurrentCallableDescriptor() {
if (currentCallableDescriptor == null) {
PsiElement element = getDeclaration();
if (element instanceof JetFunction) {
currentFunctionDescriptor = (FunctionDescriptor) ResolvePackage.resolveToDescriptor((JetFunction) element);
if (element instanceof JetFunction || element instanceof JetProperty) {
currentCallableDescriptor = (CallableDescriptor) ResolvePackage.resolveToDescriptor((JetDeclaration) element);
}
else if (element instanceof JetClass) {
currentFunctionDescriptor = ((ClassDescriptor) ResolvePackage.resolveToDescriptor((JetClass) element)).getUnsubstitutedPrimaryConstructor();
currentCallableDescriptor = ((ClassDescriptor) ResolvePackage.resolveToDescriptor((JetClass) element)).getUnsubstitutedPrimaryConstructor();
}
else if (element instanceof PsiMethod) {
currentFunctionDescriptor = ResolvePackage.getJavaMethodDescriptor((PsiMethod) element);
currentCallableDescriptor = ResolvePackage.getJavaMethodDescriptor((PsiMethod) element);
}
}
return currentFunctionDescriptor;
return currentCallableDescriptor;
}
@Override
public boolean processUsage(JetChangeInfo changeInfo, PsiElement element) {
JetParameterList parameterList;
if (!(element instanceof JetNamedDeclaration)) return true;
JetPsiFactory psiFactory = JetPsiFactory(element.getProject());
if (element instanceof JetFunction) {
JetFunction function = (JetFunction) element;
parameterList = function.getValueParameterList();
if (changeInfo.isNameChanged()) {
PsiElement identifier = function.getNameIdentifier();
if (changeInfo.isNameChanged()) {
PsiElement identifier = ((JetCallableDeclaration) element).getNameIdentifier();
if (identifier != null) {
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
);
}
if (identifier != null) {
identifier.replace(psiFactory.createIdentifier(changeInfo.getNewName()));
}
}
else {
parameterList = ((JetClass) element).getPrimaryConstructorParameterList();
}
changeReturnTypeIfNeeded(changeInfo, element);
JetParameterList parameterList = PsiUtilPackage.getValueParameterList((JetNamedDeclaration) element);
if (changeInfo.isParameterSetOrOrderChanged()) {
processParameterListWithStructuralChanges(changeInfo, element, parameterList, psiFactory);
}
else if (parameterList != null) {
int paramIndex = originalFunctionDescriptor.getExtensionReceiverParameter() != null ? 1 : 0;
int paramIndex = originalCallableDescriptor.getExtensionReceiverParameter() != null ? 1 : 0;
for (JetParameter parameter : parameterList.getParameters()) {
JetParameterInfo parameterInfo = changeInfo.getNewParameters()[paramIndex];
@@ -215,11 +197,11 @@ public class JetFunctionDefinitionUsage<T extends PsiElement> extends JetUsageIn
ShortenPackage.addToShorteningWaitSet(parameterList, Options.DEFAULT);
}
if (element instanceof JetFunction && changeInfo.isReceiverTypeChanged()) {
if (element instanceof JetCallableDeclaration && changeInfo.isReceiverTypeChanged()) {
//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 newReceiverTypeRef = TypeRefHelpersPackage.setReceiverTypeReference((JetFunction) element, receiverTypeRef);
JetTypeReference newReceiverTypeRef = TypeRefHelpersPackage.setReceiverTypeReference((JetCallableDeclaration) element, receiverTypeRef);
if (newReceiverTypeRef != null) {
ShortenPackage.addToShorteningWaitSet(newReceiverTypeRef, ShortenReferences.Options.DEFAULT);
}
@@ -232,6 +214,36 @@ public class JetFunctionDefinitionUsage<T extends PsiElement> extends JetUsageIn
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(
JetChangeInfo changeInfo,
PsiElement element,
@@ -256,14 +268,14 @@ public class JetFunctionDefinitionUsage<T extends PsiElement> extends JetUsageIn
}
else {
newParameterList = psiFactory.createFunctionLiteralParameterList(changeInfo.getNewParametersSignature(
(JetFunctionDefinitionUsage<PsiElement>) this)
(JetCallableDefinitionUsage<PsiElement>) this)
);
canReplaceEntireList = true;
}
}
else {
else if (!(element instanceof JetProperty)) {
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) {
JetModifierKeywordToken newVisibilityToken = JetRefactoringUtil.getVisibilityToken(changeInfo.getNewVisibility());
if (element instanceof JetFunction) {
((JetFunction)element).addModifier(newVisibilityToken);
if (element instanceof JetCallableDeclaration) {
((JetCallableDeclaration)element).addModifier(newVisibilityToken);
}
else {
else if (element instanceof JetClass) {
JetPrimaryConstructor constructor = ((JetClass) element).getPrimaryConstructor();
assert constructor != null : "Primary constructor should be created before changing visibility";
constructor.addModifier(newVisibilityToken);
}
else throw new AssertionError("Invalid element: " + PsiUtilPackage.getElementTextWithContext(element));
}
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) {
PsiElement firstChild = parameter.getFirstChild();
//noinspection ConstantConditions
parameter.addBefore(valOrVar.createKeyword(psiFactory), firstChild);
parameter.addBefore(psiFactory.createWhiteSpace(), firstChild);
}
@@ -378,7 +392,7 @@ public class JetFunctionDefinitionUsage<T extends PsiElement> extends JetUsageIn
if (identifier != null) {
//noinspection unchecked
String newName = parameterInfo.getInheritedName((JetFunctionDefinitionUsage<PsiElement>) this);
String newName = parameterInfo.getInheritedName(this);
identifier.replace(psiFactory.createIdentifier(newName));
}
}
@@ -25,7 +25,7 @@ public class JetConstructorDelegationCallUsage(
call: JetConstructorDelegationCall,
changeInfo: JetChangeInfo
) : 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 {
val isThisCall = element.isCallToThis()
@@ -35,7 +35,7 @@ public class JetEnumEntryWithoutSuperCallUsage(enumEntry: JetEnumEntry) : JetUsa
) as JetDelegatorToSuperCall
element.addBefore(psiFactory.createColon(), delegatorToSuperCall)
return JetFunctionCallUsage(delegatorToSuperCall, changeInfo.methodDescriptor.originalPrimaryFunction)
return JetFunctionCallUsage(delegatorToSuperCall, changeInfo.methodDescriptor.originalPrimaryCallable)
.processUsage(changeInfo, delegatorToSuperCall)
}
@@ -29,6 +29,7 @@ import kotlin.Unit;
import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.codegen.PropertyCodegen;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage;
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.introduceVariable.KotlinIntroduceVariableHandler;
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.resolve.BindingContext;
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 final JetFunctionDefinitionUsage<?> callee;
private final JetCallableDefinitionUsage<?> callee;
private final BindingContext context;
private final ResolvedCall<? extends CallableDescriptor> resolvedCall;
public JetFunctionCallUsage(@NotNull JetCallElement element, JetFunctionDefinitionUsage callee) {
public JetFunctionCallUsage(@NotNull JetCallElement element, JetCallableDefinitionUsage callee) {
super(element);
this.callee = callee;
this.context = ResolvePackage.analyze(element, BodyResolveMode.FULL);
@@ -88,13 +92,7 @@ public class JetFunctionCallUsage extends JetUsageInfo<JetCallElement> {
@Override
public boolean processUsage(JetChangeInfo changeInfo, JetCallElement element) {
if (changeInfo.isNameChanged()) {
JetExpression callee = element.getCalleeExpression();
if (callee instanceof JetSimpleNameExpression) {
callee.replace(JetPsiFactory(getProject()).createSimpleName(changeInfo.getNewName()));
}
}
changeNameIfNeeded(changeInfo, element);
if (element.getValueArgumentList() != null) {
if (changeInfo.isParameterSetOrOrderChanged()) {
@@ -118,6 +116,27 @@ public class JetFunctionCallUsage extends JetUsageInfo<JetCallElement> {
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
private JetExpression getReceiverExpressionIfMatched(
@NotNull ReceiverValue receiverValue,
@@ -288,6 +307,11 @@ public class JetFunctionCallUsage extends JetUsageInfo<JetCallElement> {
assert arguments != null : "Argument list is expected: " + element.getText();
List<? extends ValueArgument> oldArguments = element.getValueArguments();
if (isPropertyJavaUsage()) {
updateJavaPropertyCall(changeInfo, element);
return;
}
boolean isNamedCall = oldArguments.size() > 1 && oldArguments.get(0).isNamed();
StringBuilder parametersBuilder = new StringBuilder("(");
boolean isFirst = true;
@@ -388,7 +412,8 @@ public class JetFunctionCallUsage extends JetUsageInfo<JetCallElement> {
//TODO: this is not correct!
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);
@@ -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
private static JetExpression getReceiverExpression(@NotNull ReceiverValue receiver, @NotNull JetPsiFactory psiFactory) {
if (receiver instanceof ExpressionReceiver) {
@@ -44,9 +44,9 @@ public abstract class JetImplicitReceiverUsage(callElement: JetElement): JetUsag
public class JetImplicitThisToParameterUsage(
callElement: JetElement,
val parameterInfo: JetParameterInfo,
val containingFunction: JetFunctionDefinitionUsage<*>
val containingCallable: JetCallableDefinitionUsage<*>
): JetImplicitReceiverUsage(callElement) {
override fun getNewReceiverText(): String = parameterInfo.getInheritedName(containingFunction)
override fun getNewReceiverText(): String = parameterInfo.getInheritedName(containingCallable)
override fun processReplacedElement(element: JetElement) {
element.addToShorteningWaitSet(Options(removeThisLabels = true))
@@ -46,7 +46,7 @@ public abstract class JetExplicitReferenceUsage<T: JetElement>(element: T) : Jet
public class JetParameterUsage(
element: JetElement,
private val parameterInfo: JetParameterInfo,
val containingFunction: JetFunctionDefinitionUsage<*>
val containingCallable: JetCallableDefinitionUsage<*>
) : JetExplicitReferenceUsage<JetElement>(element) {
override fun processReplacedElement(element: JetElement) {
val qualifiedExpression = element.getParent() as? JetQualifiedExpression
@@ -56,7 +56,7 @@ public class JetParameterUsage(
override fun getReplacementText(changeInfo: JetChangeInfo): String =
if (changeInfo.receiverParameterInfo != parameterInfo) {
parameterInfo.getInheritedName(containingFunction)
parameterInfo.getInheritedName(containingCallable)
} 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
import com.intellij.psi.PsiElement
import com.intellij.refactoring.changeSignature.JavaChangeInfo
import com.intellij.usageView.UsageInfo
public class KotlinWrapperForJavaUsageInfos(
val javaChangeInfo: JavaChangeInfo,
val javaUsageInfos: Array<UsageInfo>,
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.core.refactoring.isMultiLine
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.KotlinParameterTablePanel
import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.*
@@ -233,18 +234,9 @@ public class KotlinIntroduceParameterDialog private constructor(
override fun createCenterPanel() = null
override fun canRun() {
fun validateElement(e: PsiElement, errorMessage: String) {
try {
AnalyzingUtils.checkForSyntacticErrors(e)
}
catch(e: Exception) {
throw ConfigurationException(errorMessage)
}
}
val psiFactory = JetPsiFactory(myProject)
validateElement(psiFactory.createType(nameField.getEnteredName()), "Invalid parameter name")
validateElement(psiFactory.createType(typeField.getEnteredName()), "Invalid parameter type")
psiFactory.createSimpleName(nameField.getEnteredName()).validateElement("Invalid parameter name")
psiFactory.createType(typeField.getEnteredName()).validateElement("Invalid parameter type")
}
override fun doAction() {
@@ -142,7 +142,7 @@ fun IntroduceParameterDescriptor.performRefactoring() {
.forEach { methodDescriptor.removeParameter(it) }
}
val parameterInfo = JetParameterInfo(functionDescriptor = callableDescriptor,
val parameterInfo = JetParameterInfo(callableDescriptor = callableDescriptor,
name = newParameterName,
defaultValueForCall = if (withDefaultValue) null else newArgumentValue,
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
val defaultValueForCall = (data.getParameterInitializer().getExpression()!! as? PsiExpression)?.let { it.j2k() }
changeInfo.addParameter(JetParameterInfo(functionDescriptor = psiMethodDescriptor,
changeInfo.addParameter(JetParameterInfo(callableDescriptor = psiMethodDescriptor,
name = data.getParameterName(),
type = KotlinBuiltIns.getInstance().getAnyType(),
defaultValueForCall = defaultValueForCall))
@@ -100,7 +100,7 @@ public class KotlinIntroduceParameterMethodUsageProcessor : IntroduceParameterMe
.map { it.unwrapped }
.filterIsInstance<JetFunction>()
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>)
}
else {
JetFunctionCallUsage(callElement, changeInfo.methodDescriptor.originalPrimaryFunction)
JetFunctionCallUsage(callElement, changeInfo.methodDescriptor.originalPrimaryCallable)
}
return delegateUsage.processUsage(changeInfo, callElement)
}
@@ -78,6 +78,7 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
import com.intellij.lang.java.JavaLanguage
import com.intellij.codeInsight.daemon.impl.quickfix.CreateFromUsageUtils
import com.intellij.openapi.options.ConfigurationException
import com.intellij.psi.*
import com.intellij.refactoring.listeners.RefactoringEventData
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.JavaToKotlinConverter
import org.jetbrains.kotlin.psi.psiUtil.*
import org.jetbrains.kotlin.resolve.AnalyzingUtils
fun <T: Any> PsiElement.getAndRemoveCopyableUserData(key: Key<T>): T? {
val data = getCopyableUserData(key)
@@ -604,4 +606,14 @@ public fun (() -> Any).runRefactoringWithPostprocessing(
}
})
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.Nullable;
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.idea.caches.resolve.ResolvePackage;
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
@Override
protected String getTestDataPath() {
@@ -1039,11 +1100,11 @@ public class JetChangeSignatureTest extends KotlinCodeInsightTestCase {
PsiElement context = file.findElementAt(editor.getCaretModel().getOffset());
assertNotNull(context);
FunctionDescriptor functionDescriptor = JetChangeSignatureHandler.findDescriptor(element, project, editor, bindingContext);
assertNotNull(functionDescriptor);
CallableDescriptor callableDescriptor = JetChangeSignatureHandler.findDescriptor(element, project, editor, bindingContext);
assertNotNull(callableDescriptor);
return ChangeSignaturePackage.createChangeInfo(
project, functionDescriptor, JetChangeSignatureHandler.getConfiguration(), bindingContext, context);
project, callableDescriptor, JetChangeSignatureHandler.getConfiguration(), bindingContext, context);
}
private class JavaRefactoringProvider {