Skip to content

Commit

Permalink
Do not suggest to update usages on renaming duplicated method or prop…
Browse files Browse the repository at this point in the history
…erty

(cherry picked from commit e95d1c1)
  • Loading branch information
valentinkip authored and Alefas committed Mar 20, 2020
1 parent bcdb934 commit 05c3366
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@ import com.intellij.refactoring.suggested.SuggestedRefactoringSupport.Parameter
import com.intellij.refactoring.suggested.SuggestedRefactoringSupport.Signature
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtCallableDeclaration
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.children

class KotlinSuggestedRefactoringStateChanges(refactoringSupport: SuggestedRefactoringSupport) :
Expand All @@ -22,7 +19,41 @@ class KotlinSuggestedRefactoringStateChanges(refactoringSupport: SuggestedRefact
declaration as KtDeclaration
if (declaration.hasModifier(KtTokens.OVERRIDE_KEYWORD)) return null // currently not supported
if (declaration.hasModifier(KtTokens.ACTUAL_KEYWORD)) return null // currently not supported
return super.createInitialState(declaration)
val state = super.createInitialState(declaration) ?: return null
if (isDuplicate(declaration, state.oldSignature)) return null
return state
}

private fun isDuplicate(declaration: KtDeclaration, signature: Signature): Boolean {
val container = declaration.parent as? KtDeclarationContainer ?: return false
if (container !is KtFile && container !is KtClassBody) return false
val name = declaration.name ?: return false
return when (declaration) {
is KtFunction -> {
container.declarations
.filter { it != declaration && it.name == name }
.any {
val otherSignature = signature(it, null) ?: return@any false
areDuplicateSignatures(otherSignature, signature)
}
}

is KtProperty -> {
container.declarations.any { it != declaration && it is KtProperty && it.name == name }
}

else -> false
}
}

// we can't compare signatures by equals here because it takes into account parameter id's and they will be different in our case
private fun areDuplicateSignatures(signature1: Signature, signature2: Signature): Boolean {
if (signature1.name != signature2.name) return false
if (signature1.type != signature2.type) return false
if (signature1.parameters.size != signature2.parameters.size) return false
return signature1.parameters.zip(signature2.parameters).all { (p1, p2) ->
p1.type == p2.type && p1.name == p2.name
}
}

override fun signature(declaration: PsiElement, prevState: SuggestedRefactoringState?): Signature? {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.jetbrains.kotlin.idea.refactoring.suggested

import com.intellij.openapi.actionSystem.IdeActions
import com.intellij.openapi.fileTypes.LanguageFileType
import com.intellij.refactoring.suggested.BaseSuggestedRefactoringAvailabilityTest
import org.jetbrains.kotlin.idea.KotlinFileType
Expand Down Expand Up @@ -361,6 +362,53 @@ class KotlinSuggestedRefactoringAvailabilityTest : BaseSuggestedRefactoringAvail
)
}

fun testDuplicateProperty() {
doTest(
"""
const val <caret>CONST1 = 1
""".trimIndent(),
{
myFixture.performEditorAction(IdeActions.ACTION_EDITOR_DUPLICATE)
},
{
replaceTextAtCaret("CONST1", "CONST2")
},
expectedAvailability = Availability.NotAvailable
)
}

fun testDuplicateMethod() {
doTest(
"""
class Test {
fun <caret>foo(p: Int) {}
}
""".trimIndent(),
{
myFixture.performEditorAction(IdeActions.ACTION_EDITOR_DUPLICATE)
},
{
replaceTextAtCaret("foo", "bar")
},
expectedAvailability = Availability.NotAvailable
)
}

fun testNotDuplicateMethod() {
doTest(
"""
class Test {
fun <caret>foo(p: Int) {}
fun foo(p: String) {}
}
""".trimIndent(),
{
replaceTextAtCaret("foo", "bar")
},
expectedAvailability = Availability.Available(renameAvailableTooltip("foo", "bar"))
)
}

private fun addImport(fqName: String) {
(file as KtFile).importList!!.add(KtPsiFactory(project).createImportDirective(ImportPath.fromString(fqName)))
}
Expand Down

0 comments on commit 05c3366

Please sign in to comment.