Change Signature: Avoid creating parameters from scratch
#KT-15519 Fixed
This commit is contained in:
@@ -24,13 +24,26 @@ import org.jetbrains.kotlin.lexer.KtTokens.*
|
|||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.siblings
|
import org.jetbrains.kotlin.psi.psiUtil.siblings
|
||||||
|
|
||||||
private fun createModifierList(text: String, owner: KtModifierListOwner): KtModifierList {
|
private fun KtModifierListOwner.addModifierList(newModifierList: KtModifierList): KtModifierList {
|
||||||
val newModifierList = KtPsiFactory(owner).createModifierList(text)
|
val anchor = firstChild!!
|
||||||
val anchor = owner.firstChild!!
|
|
||||||
.siblings(forward = true)
|
.siblings(forward = true)
|
||||||
.dropWhile { it is PsiComment || it is PsiWhiteSpace }
|
.dropWhile { it is PsiComment || it is PsiWhiteSpace }
|
||||||
.first()
|
.first()
|
||||||
return owner.addBefore(newModifierList, anchor) as KtModifierList
|
return addBefore(newModifierList, anchor) as KtModifierList
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createModifierList(text: String, owner: KtModifierListOwner): KtModifierList {
|
||||||
|
return owner.addModifierList(KtPsiFactory(owner).createModifierList(text))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun KtModifierListOwner.setModifierList(newModifierList: KtModifierList) {
|
||||||
|
val currentModifierList = modifierList
|
||||||
|
if (currentModifierList != null) {
|
||||||
|
currentModifierList.replace(newModifierList)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
addModifierList(newModifierList)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addModifier(owner: KtModifierListOwner, modifier: KtModifierKeywordToken) {
|
fun addModifier(owner: KtModifierListOwner, modifier: KtModifierKeywordToken) {
|
||||||
|
|||||||
@@ -313,3 +313,10 @@ fun KtCallableDeclaration.setReceiverType(type: KotlinType) {
|
|||||||
ShortenReferences.DEFAULT.process(receiverTypeReference!!)
|
ShortenReferences.DEFAULT.process(receiverTypeReference!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun KtParameter.setDefaultValue(newDefaultValue: KtExpression): PsiElement? {
|
||||||
|
defaultValue?.let { return it.replaced(newDefaultValue) }
|
||||||
|
|
||||||
|
val psiFactory = KtPsiFactory(this)
|
||||||
|
val eq = equalsToken ?: add(psiFactory.createEQ())
|
||||||
|
return addAfter(newDefaultValue, eq) as KtExpression
|
||||||
|
}
|
||||||
|
|||||||
@@ -284,11 +284,11 @@ open class KotlinChangeInfo(
|
|||||||
|
|
||||||
val isLambda = inheritedCallable.declaration is KtFunctionLiteral
|
val isLambda = inheritedCallable.declaration is KtFunctionLiteral
|
||||||
if (isLambda && signatureParameters.size == 1 && !signatureParameters[0].requiresExplicitType(inheritedCallable)) {
|
if (isLambda && signatureParameters.size == 1 && !signatureParameters[0].requiresExplicitType(inheritedCallable)) {
|
||||||
return signatureParameters[0].getDeclarationSignature(0, inheritedCallable)
|
return signatureParameters[0].getDeclarationSignature(0, inheritedCallable).text
|
||||||
}
|
}
|
||||||
|
|
||||||
return signatureParameters.indices
|
return signatureParameters.indices
|
||||||
.map { i -> signatureParameters[i].getDeclarationSignature(i, inheritedCallable) }
|
.map { i -> signatureParameters[i].getDeclarationSignature(i, inheritedCallable).text }
|
||||||
.joinToString(separator = ", ")
|
.joinToString(separator = ", ")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-2
@@ -65,8 +65,7 @@ class KotlinChangeSignatureData(
|
|||||||
name = parameterDescriptor.name.asString(),
|
name = parameterDescriptor.name.asString(),
|
||||||
originalTypeInfo = KotlinTypeInfo(false, parameterType, parameterTypeText),
|
originalTypeInfo = KotlinTypeInfo(false, parameterType, parameterTypeText),
|
||||||
defaultValueForParameter = jetParameter?.defaultValue,
|
defaultValueForParameter = jetParameter?.defaultValue,
|
||||||
valOrVar = jetParameter?.valOrVarKeyword.toValVar(),
|
valOrVar = jetParameter?.valOrVarKeyword.toValVar()
|
||||||
modifierList = jetParameter?.modifierList
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+42
-2
@@ -22,11 +22,14 @@ import org.jetbrains.kotlin.descriptors.*
|
|||||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
import org.jetbrains.kotlin.idea.core.compareDescriptors
|
import org.jetbrains.kotlin.idea.core.compareDescriptors
|
||||||
|
import org.jetbrains.kotlin.idea.core.copied
|
||||||
import org.jetbrains.kotlin.idea.core.quoteIfNeeded
|
import org.jetbrains.kotlin.idea.core.quoteIfNeeded
|
||||||
|
import org.jetbrains.kotlin.idea.core.setDefaultValue
|
||||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.KotlinCallableDefinitionUsage
|
import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.KotlinCallableDefinitionUsage
|
||||||
import org.jetbrains.kotlin.idea.references.KtReference
|
import org.jetbrains.kotlin.idea.references.KtReference
|
||||||
import org.jetbrains.kotlin.idea.references.mainReference
|
import org.jetbrains.kotlin.idea.references.mainReference
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
|
import org.jetbrains.kotlin.psi.addRemoveModifier.setModifierList
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||||
@@ -186,7 +189,15 @@ class KotlinParameterInfo @JvmOverloads constructor (
|
|||||||
return parameter.typeReference != null
|
return parameter.typeReference != null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getDeclarationSignature(parameterIndex: Int, inheritedCallable: KotlinCallableDefinitionUsage<*>): String {
|
private fun getOriginalParameter(inheritedCallable: KotlinCallableDefinitionUsage<*>): KtParameter? {
|
||||||
|
val currentFunction = inheritedCallable.declaration as? KtFunction ?: return null
|
||||||
|
val originalParameterIndex = if (currentFunction.receiverTypeReference == null) originalIndex else originalIndex - 1
|
||||||
|
return currentFunction.valueParameters.getOrNull(originalParameterIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildNewParameter(inheritedCallable: KotlinCallableDefinitionUsage<*>, parameterIndex: Int): KtParameter {
|
||||||
|
val psiFactory = KtPsiFactory(inheritedCallable.project)
|
||||||
|
|
||||||
val buffer = StringBuilder()
|
val buffer = StringBuilder()
|
||||||
|
|
||||||
if (modifierList != null) {
|
if (modifierList != null) {
|
||||||
@@ -207,6 +218,35 @@ class KotlinParameterInfo @JvmOverloads constructor (
|
|||||||
defaultValueForParameter?.let { buffer.append(" = ").append(it.text) }
|
defaultValueForParameter?.let { buffer.append(" = ").append(it.text) }
|
||||||
}
|
}
|
||||||
|
|
||||||
return buffer.toString()
|
return psiFactory.createParameter(buffer.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getDeclarationSignature(parameterIndex: Int, inheritedCallable: KotlinCallableDefinitionUsage<*>): KtParameter {
|
||||||
|
val originalParameter = getOriginalParameter(inheritedCallable)
|
||||||
|
?: return buildNewParameter(inheritedCallable, parameterIndex)
|
||||||
|
|
||||||
|
val psiFactory = KtPsiFactory(originalParameter)
|
||||||
|
val newParameter = originalParameter.copied()
|
||||||
|
|
||||||
|
modifierList?.let { newParameter.setModifierList(it) }
|
||||||
|
|
||||||
|
if (valOrVar != newParameter.valOrVarKeyword.toValVar()) {
|
||||||
|
newParameter.setValOrVar(valOrVar)
|
||||||
|
}
|
||||||
|
|
||||||
|
val newName = getInheritedName(inheritedCallable)
|
||||||
|
if (newParameter.name != newName) {
|
||||||
|
newParameter.setName(newName.quoteIfNeeded())
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newParameter.typeReference != null || requiresExplicitType(inheritedCallable)) {
|
||||||
|
newParameter.typeReference = psiFactory.createType(renderType(parameterIndex, inheritedCallable))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!inheritedCallable.isInherited) {
|
||||||
|
defaultValueForParameter?.let { newParameter.setDefaultValue(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
return newParameter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.idea.refactoring.changeSignature
|
|||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
|
import org.jetbrains.kotlin.psi.KtParameter
|
||||||
import org.jetbrains.kotlin.psi.KtPsiFactory
|
import org.jetbrains.kotlin.psi.KtPsiFactory
|
||||||
|
|
||||||
enum class KotlinValVar(val keywordName: String) {
|
enum class KotlinValVar(val keywordName: String) {
|
||||||
@@ -44,3 +45,24 @@ fun PsiElement?.toValVar(): KotlinValVar {
|
|||||||
else -> throw IllegalArgumentException("Unknown val/var token: " + text)
|
else -> throw IllegalArgumentException("Unknown val/var token: " + text)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun KtParameter.setValOrVar(valOrVar: KotlinValVar): PsiElement? {
|
||||||
|
val newKeyword = valOrVar.createKeyword(KtPsiFactory(this))
|
||||||
|
val currentKeyword = valOrVarKeyword
|
||||||
|
|
||||||
|
if (currentKeyword != null) {
|
||||||
|
return if (newKeyword == null) {
|
||||||
|
currentKeyword.delete()
|
||||||
|
null
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
currentKeyword.replace(newKeyword)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newKeyword == null) return null
|
||||||
|
|
||||||
|
nameIdentifier?.let { return addBefore(newKeyword, it) }
|
||||||
|
modifierList?.let { return addAfter(newKeyword, it) }
|
||||||
|
return addAfter(newKeyword, null)
|
||||||
|
}
|
||||||
+2
-21
@@ -28,14 +28,11 @@ import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
|||||||
import org.jetbrains.kotlin.idea.codeInsight.shorten.addToShorteningWaitSet
|
import org.jetbrains.kotlin.idea.codeInsight.shorten.addToShorteningWaitSet
|
||||||
import org.jetbrains.kotlin.idea.core.setVisibility
|
import org.jetbrains.kotlin.idea.core.setVisibility
|
||||||
import org.jetbrains.kotlin.idea.core.toKeywordToken
|
import org.jetbrains.kotlin.idea.core.toKeywordToken
|
||||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.KotlinChangeInfo
|
|
||||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.KotlinParameterInfo
|
|
||||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.KotlinValVar
|
|
||||||
import org.jetbrains.kotlin.idea.refactoring.changeSignature.getCallableSubstitutor
|
|
||||||
import org.jetbrains.kotlin.idea.refactoring.dropOverrideKeywordIfNecessary
|
import org.jetbrains.kotlin.idea.refactoring.dropOverrideKeywordIfNecessary
|
||||||
import org.jetbrains.kotlin.idea.refactoring.replaceListPsiAndKeepDelimiters
|
import org.jetbrains.kotlin.idea.refactoring.replaceListPsiAndKeepDelimiters
|
||||||
import org.jetbrains.kotlin.idea.core.ShortenReferences
|
import org.jetbrains.kotlin.idea.core.ShortenReferences
|
||||||
import org.jetbrains.kotlin.idea.core.ShortenReferences.Options
|
import org.jetbrains.kotlin.idea.core.ShortenReferences.Options
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.changeSignature.*
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
|
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
|
||||||
@@ -237,31 +234,15 @@ class KotlinCallableDefinitionUsage<T : PsiElement>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun changeParameter(parameterIndex: Int, parameter: KtParameter, parameterInfo: KotlinParameterInfo) {
|
private fun changeParameter(parameterIndex: Int, parameter: KtParameter, parameterInfo: KotlinParameterInfo) {
|
||||||
val valOrVarKeyword = parameter.valOrVarKeyword
|
parameter.setValOrVar(parameterInfo.valOrVar)
|
||||||
val valOrVar = parameterInfo.valOrVar
|
|
||||||
|
|
||||||
val psiFactory = KtPsiFactory(project)
|
val psiFactory = KtPsiFactory(project)
|
||||||
val newKeyword = valOrVar.createKeyword(psiFactory)
|
|
||||||
if (valOrVarKeyword != null) {
|
|
||||||
if (newKeyword != null) {
|
|
||||||
valOrVarKeyword.replace(newKeyword)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
valOrVarKeyword.delete()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (valOrVar != KotlinValVar.None && newKeyword != null) {
|
|
||||||
val firstChild = parameter.firstChild
|
|
||||||
parameter.addBefore(newKeyword, firstChild)
|
|
||||||
parameter.addBefore(psiFactory.createWhiteSpace(), firstChild)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parameterInfo.isTypeChanged && parameter.typeReference != null) {
|
if (parameterInfo.isTypeChanged && parameter.typeReference != null) {
|
||||||
val renderedType = parameterInfo.renderType(parameterIndex, this)
|
val renderedType = parameterInfo.renderType(parameterIndex, this)
|
||||||
parameter.typeReference = psiFactory.createType(renderedType)
|
parameter.typeReference = psiFactory.createType(renderedType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
val inheritedName = parameterInfo.getInheritedName(this)
|
val inheritedName = parameterInfo.getInheritedName(this)
|
||||||
if (Name.isValidIdentifier(inheritedName)) {
|
if (Name.isValidIdentifier(inheritedName)) {
|
||||||
val newIdentifier = psiFactory.createIdentifier(inheritedName)
|
val newIdentifier = psiFactory.createIdentifier(inheritedName)
|
||||||
|
|||||||
+2
-5
@@ -34,15 +34,12 @@ class KotlinCallerUsage(element: KtNamedDeclaration): KotlinUsageInfo<KtNamedDec
|
|||||||
is KtClass -> element.createPrimaryConstructorParameterListIfAbsent()
|
is KtClass -> element.createPrimaryConstructorParameterListIfAbsent()
|
||||||
else -> null
|
else -> null
|
||||||
} ?: return true
|
} ?: return true
|
||||||
val psiFactory = KtPsiFactory(project)
|
|
||||||
changeInfo.getNonReceiverParameters()
|
changeInfo.getNonReceiverParameters()
|
||||||
.withIndex()
|
.withIndex()
|
||||||
.filter { it.value.isNewParameter }
|
.filter { it.value.isNewParameter }
|
||||||
.forEach {
|
.forEach {
|
||||||
val parameterText = it.value.getDeclarationSignature(it.index, changeInfo.methodDescriptor.originalPrimaryCallable)
|
val newParameter = it.value.getDeclarationSignature(it.index, changeInfo.methodDescriptor.originalPrimaryCallable)
|
||||||
parameterList
|
parameterList.addParameter(newParameter).addToShorteningWaitSet()
|
||||||
.addParameter(psiFactory.createParameter(parameterText))
|
|
||||||
.addToShorteningWaitSet()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
|
|||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
data class <caret>VertexAttribute(
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of components this attribute has.
|
||||||
|
**/
|
||||||
|
val numComponents: Int
|
||||||
|
) {}
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
data class <caret>VertexAttribute(
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of components this attribute has.
|
||||||
|
**/
|
||||||
|
val numComponents: Int,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If true and [type] is not [Gl20.FLOAT], the data will be mapped to the range -1 to 1 for signed types and
|
||||||
|
* the range 0 to 1 for unsigned types.
|
||||||
|
*/
|
||||||
|
val normalized: Boolean
|
||||||
|
) {}
|
||||||
+2
@@ -942,4 +942,6 @@ class KotlinChangeSignatureTest : KotlinLightCodeInsightFixtureTestCase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun testReceiverInSafeCall() = doTestConflict { receiverParameterInfo = null }
|
fun testReceiverInSafeCall() = doTestConflict { receiverParameterInfo = null }
|
||||||
|
|
||||||
|
fun testRemoveParameterKeepOtherComments() = doTest { removeParameter(1) }
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user