From 8978c4b9e82c242c158cf77e4d8a34522af024a9 Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Mon, 5 Mar 2018 13:54:14 +0300 Subject: [PATCH] Rename: Fix processing of references to synthetic Java properties #KT-17742 Fixed --- .../codegen/state/KotlinTypeMapper.java | 2 +- .../SyntheticPropertyAccessorReference.kt | 123 ++++++++++++++++-- idea/src/META-INF/plugin.xml | 3 + .../KotlinAwareJavaGetterRenameProcessor.kt | 39 ++++++ .../rename/RenameKotlinFunctionProcessor.kt | 12 +- .../rename/RenameKotlinPsiProcessor.kt | 31 ++--- ...KotlinOverridingMethodReferenceSearcher.kt | 31 +---- .../after/SyntheticProperty.java | 4 + .../after/synthesize.kt | 12 ++ .../before/SyntheticProperty.java | 4 + .../before/synthesize.kt | 8 ++ .../javaGetterToOrdinaryMethod.test | 6 + .../after/SyntheticProperty.java | 4 + .../after/synthesize.kt | 12 ++ .../before/SyntheticProperty.java | 4 + .../before/synthesize.kt | 8 ++ .../javaSetterToOrdinaryMethod.test | 6 + .../syntheticPropertyUsages1/after/Usages.kt | 2 +- .../rename/RenameTestGenerated.java | 10 ++ 19 files changed, 256 insertions(+), 65 deletions(-) create mode 100644 idea/src/org/jetbrains/kotlin/idea/refactoring/rename/KotlinAwareJavaGetterRenameProcessor.kt create mode 100644 idea/testData/refactoring/rename/javaGetterToOrdinaryMethod/after/SyntheticProperty.java create mode 100644 idea/testData/refactoring/rename/javaGetterToOrdinaryMethod/after/synthesize.kt create mode 100644 idea/testData/refactoring/rename/javaGetterToOrdinaryMethod/before/SyntheticProperty.java create mode 100644 idea/testData/refactoring/rename/javaGetterToOrdinaryMethod/before/synthesize.kt create mode 100644 idea/testData/refactoring/rename/javaGetterToOrdinaryMethod/javaGetterToOrdinaryMethod.test create mode 100644 idea/testData/refactoring/rename/javaSetterToOrdinaryMethod/after/SyntheticProperty.java create mode 100644 idea/testData/refactoring/rename/javaSetterToOrdinaryMethod/after/synthesize.kt create mode 100644 idea/testData/refactoring/rename/javaSetterToOrdinaryMethod/before/SyntheticProperty.java create mode 100644 idea/testData/refactoring/rename/javaSetterToOrdinaryMethod/before/synthesize.kt create mode 100644 idea/testData/refactoring/rename/javaSetterToOrdinaryMethod/javaSetterToOrdinaryMethod.test diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java index ddb78045f7f..60fc9b2ac59 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java @@ -1684,7 +1684,7 @@ public class KotlinTypeMapper { @Nullable public static String getModuleNameSuffix(@NotNull String name) { int indexOfDollar = name.indexOf('$'); - return indexOfDollar >=0 ? name.substring(indexOfDollar + 1) : null; + return indexOfDollar >= 0 ? name.substring(indexOfDollar + 1) : null; } @Nullable diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/SyntheticPropertyAccessorReference.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/SyntheticPropertyAccessorReference.kt index 59228d2f728..75e615ef535 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/SyntheticPropertyAccessorReference.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/references/SyntheticPropertyAccessorReference.kt @@ -22,14 +22,23 @@ import com.intellij.psi.PsiMethod import com.intellij.util.SmartList import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.core.KotlinNameSuggester +import org.jetbrains.kotlin.idea.core.NewDeclarationNameValidator +import org.jetbrains.kotlin.idea.core.copied +import org.jetbrains.kotlin.idea.core.replaced +import org.jetbrains.kotlin.lexer.KtSingleValueToken +import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.psi.KtNameReferenceExpression -import org.jetbrains.kotlin.psi.KtPsiFactory +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.* import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor +import org.jetbrains.kotlin.types.expressions.OperatorConventions import org.jetbrains.kotlin.utils.addIfNotNull -sealed class SyntheticPropertyAccessorReference(expression: KtNameReferenceExpression, private val getter: Boolean) : KtSimpleReference(expression) { +sealed class SyntheticPropertyAccessorReference(expression: KtNameReferenceExpression, private val getter: Boolean) : + KtSimpleReference(expression) { override fun getTargetDescriptors(context: BindingContext): Collection { val descriptors = super.getTargetDescriptors(context) if (descriptors.none { it is SyntheticJavaPropertyDescriptor }) return emptyList() @@ -39,8 +48,7 @@ sealed class SyntheticPropertyAccessorReference(expression: KtNameReferenceExpre if (descriptor is SyntheticJavaPropertyDescriptor) { if (getter) { result.add(descriptor.getMethod) - } - else { + } else { result.addIfNotNull(descriptor.setMethod) } } @@ -50,6 +58,7 @@ sealed class SyntheticPropertyAccessorReference(expression: KtNameReferenceExpre override fun isReferenceTo(element: PsiElement?): Boolean { if (element !is PsiMethod || !isAccessorName(element.name)) return false + if (!getter && expression.readWriteAccess(true) == ReferenceAccess.READ) return false return super.isReferenceTo(element) } @@ -70,19 +79,115 @@ sealed class SyntheticPropertyAccessorReference(expression: KtNameReferenceExpre return expression } + private fun KtExpression.createCall( + psiFactory: KtPsiFactory, + newName: String? = null, + argument: KtExpression? = null + ): KtExpression { + return if (this is KtQualifiedExpression) { + copied().also { + val selector = it.getQualifiedElementSelector() as? KtExpression + selector?.replace(selector.createCall(psiFactory, newName, argument)) + } + } else { + psiFactory.buildExpression { + if (newName != null) { + appendFixedText(newName) + } else { + appendExpression(this@createCall) + } + appendFixedText("(") + if (argument != null) { + appendExpression(argument) + } + appendFixedText(")") + } + } + } + override fun handleElementRename(newElementName: String?): PsiElement? { if (!Name.isValidIdentifier(newElementName!!)) return expression val newNameAsName = Name.identifier(newElementName) val newName = if (getter) { SyntheticJavaPropertyDescriptor.propertyNameByGetMethodName(newNameAsName) - } - else { + } else { //TODO: it's not correct //TODO: setIsY -> setIsIsY bug - SyntheticJavaPropertyDescriptor.propertyNameBySetMethodName(newNameAsName, withIsPrefix = expression.getReferencedNameAsName().asString().startsWith("is")) + SyntheticJavaPropertyDescriptor.propertyNameBySetMethodName( + newNameAsName, + withIsPrefix = expression.getReferencedNameAsName().asString().startsWith( + "is" + ) + ) + } + // get/set becomes ordinary method + if (newName == null) { + val psiFactory = KtPsiFactory(expression) + + val newGetterName = if (getter) newElementName else JvmAbi.getterName(expression.getReferencedName()) + + if (expression.readWriteAccess(false) == ReferenceAccess.READ) { + return expression.replaced(expression.createCall(psiFactory, newGetterName)) + } + + val newSetterName = if (getter) JvmAbi.setterName(expression.getReferencedName()) else newElementName + + val fullExpression = expression.getQualifiedExpressionForSelectorOrThis() + fullExpression.getAssignmentByLHS()?.let { assignment -> + val rhs = assignment.right ?: return expression + val operationToken = assignment.operationToken as? KtSingleValueToken + val counterpartOp = OperatorConventions.ASSIGNMENT_OPERATION_COUNTERPARTS[operationToken] + val setterArgument = if (counterpartOp != null) { + val getterCall = if (getter) fullExpression.createCall(psiFactory, newGetterName) else fullExpression + psiFactory.createExpressionByPattern("$0 ${counterpartOp.value} $1", getterCall, rhs) + } else { + rhs + } + val newSetterCall = fullExpression.createCall(psiFactory, newSetterName, setterArgument) + return assignment.replaced(newSetterCall).getQualifiedElementSelector() + } + + fullExpression.getStrictParentOfType()?.let { unaryExpr -> + val operationToken = unaryExpr.operationToken as? KtSingleValueToken ?: return expression + if (operationToken !in OperatorConventions.INCREMENT_OPERATIONS) return expression + val operationName = OperatorConventions.getNameForOperationSymbol(operationToken) + val originalValue = if (getter) fullExpression.createCall(psiFactory, newGetterName) else fullExpression + val incDecValue = psiFactory.createExpressionByPattern("$0.$operationName()", originalValue) + val parent = unaryExpr.parent + val context = parent.parentsWithSelf.firstOrNull { it is KtBlockExpression || it is KtDeclarationContainer } + if (context == parent || context == null) { + val newSetterCall = fullExpression.createCall(psiFactory, newSetterName, incDecValue) + return unaryExpr.replaced(newSetterCall).getQualifiedElementSelector() + } else { + val anchor = parent.parentsWithSelf.firstOrNull { it.parent == context } + val validator = NewDeclarationNameValidator( + context, + anchor, + NewDeclarationNameValidator.Target.VARIABLES + ) + val varName = KotlinNameSuggester.suggestNamesByExpressionAndType( + unaryExpr, + null, + unaryExpr.analyze(), + validator, + "p" + ).first() + val isPrefix = unaryExpr is KtPrefixExpression + val varInitializer = if (isPrefix) incDecValue else originalValue + val newVar = psiFactory.createDeclarationByPattern("val $varName = $0", varInitializer) + val setterArgument = psiFactory.createExpression(if (isPrefix) varName else "$varName.$operationName()") + val newSetterCall = fullExpression.createCall(psiFactory, newSetterName, setterArgument) + val newLine = psiFactory.createNewLine() + context.addBefore(newVar, anchor) + context.addBefore(newLine, anchor) + context.addBefore(newSetterCall, anchor) + return unaryExpr.replaced(psiFactory.createExpression(varName)) + } + } + + return expression } - if (newName == null) return expression //TODO: handle the case when get/set becomes ordinary method return renameByPropertyName(newName.identifier) } diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 34dbaf135e1..f106da5296e 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -512,6 +512,9 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio. + diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/KotlinAwareJavaGetterRenameProcessor.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/KotlinAwareJavaGetterRenameProcessor.kt new file mode 100644 index 00000000000..dbc21f4763e --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/KotlinAwareJavaGetterRenameProcessor.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.refactoring.rename + +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiMethod +import com.intellij.psi.PsiReference +import com.intellij.psi.PsiType +import com.intellij.refactoring.rename.RenameJavaMethodProcessor +import org.jetbrains.kotlin.asJava.elements.KtLightMethod +import org.jetbrains.kotlin.idea.references.SyntheticPropertyAccessorReference +import org.jetbrains.kotlin.load.java.JvmAbi +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor +import org.jetbrains.kotlin.utils.ifEmpty + +class KotlinAwareJavaGetterRenameProcessor : RenameJavaMethodProcessor() { + override fun canProcessElement(element: PsiElement) = element is PsiMethod && element !is KtLightMethod && JvmAbi.isGetterName(element.name) + + override fun findReferences(element: PsiElement): MutableCollection { + val getterReferences = super.findReferences(element) + val getter = element as? PsiMethod ?: return getterReferences + val propertyName = SyntheticJavaPropertyDescriptor.propertyNameByGetMethodName(Name.identifier(getter.name)) ?: return getterReferences + val setterName = JvmAbi.setterName(propertyName.asString()) + val containingClass = getter.containingClass ?: return getterReferences + val setterReferences = containingClass + .findMethodsByName(setterName, true) + .filter { it.parameters.size == 1 && it.returnType == PsiType.VOID } + .flatMap { super.findReferences(it).filterIsInstance() } + .ifEmpty { return getterReferences } + return ArrayList(getterReferences.size + setterReferences.size).apply { + addAll(getterReferences) + setterReferences.mapTo(this) { SyntheticPropertyAccessorReference.Getter(it.expression) } + } + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinFunctionProcessor.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinFunctionProcessor.kt index e85686d878a..16ad9a98338 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinFunctionProcessor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinFunctionProcessor.kt @@ -35,8 +35,7 @@ import org.jetbrains.kotlin.asJava.elements.KtLightElement import org.jetbrains.kotlin.asJava.elements.KtLightMethod import org.jetbrains.kotlin.asJava.namedUnwrappedElement import org.jetbrains.kotlin.asJava.unwrapped -import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper.InternalNameMapper.demangleInternalName -import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper.InternalNameMapper.getModuleNameSuffix +import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper.InternalNameMapper.* import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor import org.jetbrains.kotlin.idea.refactoring.Pass @@ -183,19 +182,20 @@ class RenameKotlinFunctionProcessor : RenameKotlinPsiProcessor() { override fun prepareRenaming(element: PsiElement, newName: String, allRenames: MutableMap, scope: SearchScope) { super.prepareRenaming(element, newName, allRenames, scope) - val originalName = (element.unwrapped as? KtNamedFunction)?.name ?: "" - if (element is KtLightMethod && getJvmName(element) == null) { (element.kotlinOrigin as? KtNamedFunction)?.let { allRenames[it] = newName } } if (element is FunctionWithSupersWrapper) { allRenames.remove(element) } + val originalName = (element.unwrapped as? KtNamedFunction)?.name ?: return for (declaration in ((element as? FunctionWithSupersWrapper)?.supers ?: listOf(element))) { val psiMethod = wrapPsiMethod(declaration) ?: continue allRenames[declaration] = newName val baseName = psiMethod.name - val newBaseName = if (demangleInternalName(baseName) == originalName) "$newName$${getModuleNameSuffix(baseName)}" else newName + val newBaseName = if (demangleInternalName(baseName) == originalName) { + mangleInternalName(newName, getModuleNameSuffix(baseName)!!) + } else newName if (psiMethod.containingClass != null) { psiMethod.forEachOverridingMethod(scope) { it -> val overrider = (it as? PsiMirrorElement)?.prototype as? PsiMethod ?: it @@ -227,7 +227,7 @@ class RenameKotlinFunctionProcessor : RenameKotlinPsiProcessor() { ambiguousImportUsages += usage } else { - if (!renameUsageIfPossible(usage, element, newName)) { + if (!renameMangledUsageIfPossible(usage, element, newName)) { simpleUsages += usage } } diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinPsiProcessor.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinPsiProcessor.kt index 58942c79534..f0f6f7512c0 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinPsiProcessor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinPsiProcessor.kt @@ -46,19 +46,7 @@ import org.jetbrains.kotlin.psi.psiUtil.parents import org.jetbrains.kotlin.psi.psiUtil.quoteIfNeeded import org.jetbrains.kotlin.resolve.ImportPath import java.util.ArrayList -import kotlin.collections.Collection -import kotlin.collections.HashSet -import kotlin.collections.List -import kotlin.collections.MutableMap -import kotlin.collections.flatMapTo -import kotlin.collections.forEach -import kotlin.collections.isEmpty -import kotlin.collections.mapNotNullTo -import kotlin.collections.none -import kotlin.collections.plusAssign -import kotlin.collections.set -import kotlin.collections.toMutableList -import kotlin.collections.toTypedArray +import kotlin.collections.* abstract class RenameKotlinPsiProcessor : RenamePsiElementProcessor() { class MangledJavaRefUsageInfo( @@ -151,15 +139,16 @@ abstract class RenameKotlinPsiProcessor : RenamePsiElementProcessor() { && ref.multiResolve(false).mapNotNullTo(HashSet()) { it.element?.unwrapped }.size > 1 } - protected fun renameUsageIfPossible(usage: UsageInfo, element: PsiElement, newName: String): Boolean { - var chosenName: String? = null - if (usage is MangledJavaRefUsageInfo) { - chosenName = KotlinTypeMapper.InternalNameMapper.mangleInternalName(newName, usage.manglingSuffix) + protected fun renameMangledUsageIfPossible(usage: UsageInfo, element: PsiElement, newName: String): Boolean { + val chosenName = if (usage is MangledJavaRefUsageInfo) { + KotlinTypeMapper.InternalNameMapper.mangleInternalName(newName, usage.manglingSuffix) } else { val reference = usage.reference if (reference is KtReference) { - chosenName = (if (element is KtLightMethod && element.isMangled) KotlinTypeMapper.InternalNameMapper.demangleInternalName(newName) else null) ?: newName - } + if (element is KtLightMethod && element.isMangled) { + KotlinTypeMapper.InternalNameMapper.demangleInternalName(newName) + } else null + } else null } if (chosenName == null) return false usage.reference?.handleElementRename(chosenName) @@ -174,7 +163,7 @@ abstract class RenameKotlinPsiProcessor : RenamePsiElementProcessor() { ) { val simpleUsages = ArrayList(usages.size) for (usage in usages) { - if (renameUsageIfPossible(usage, element, newName)) continue + if (renameMangledUsageIfPossible(usage, element, newName)) continue simpleUsages += usage } @@ -186,7 +175,7 @@ abstract class RenameKotlinPsiProcessor : RenamePsiElementProcessor() { element.ambiguousImportUsages?.forEach { val ref = it.reference as? PsiPolyVariantReference ?: return@forEach if (ref.multiResolve(false).isEmpty()) { - if (!renameUsageIfPossible(it, element, newName)) { + if (!renameMangledUsageIfPossible(it, element, newName)) { ref.handleElementRename(newName) } } diff --git a/idea/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinOverridingMethodReferenceSearcher.kt b/idea/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinOverridingMethodReferenceSearcher.kt index e50bc41e25a..44759bd332c 100644 --- a/idea/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinOverridingMethodReferenceSearcher.kt +++ b/idea/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinOverridingMethodReferenceSearcher.kt @@ -24,7 +24,6 @@ import com.intellij.psi.search.UsageSearchContext import com.intellij.psi.search.searches.MethodReferencesSearch import com.intellij.psi.util.MethodSignatureUtil import com.intellij.psi.util.TypeConversionUtil -import org.jetbrains.kotlin.asJava.elements.KtLightMethod import org.jetbrains.kotlin.asJava.toLightMethods import org.jetbrains.kotlin.compatibility.ExecutorProcessor import org.jetbrains.kotlin.idea.references.KtSimpleNameReference @@ -32,10 +31,8 @@ import org.jetbrains.kotlin.idea.references.SyntheticPropertyAccessorReference import org.jetbrains.kotlin.idea.references.readWriteAccess import org.jetbrains.kotlin.idea.search.restrictToKotlinSources import org.jetbrains.kotlin.idea.util.runReadActionInSmartMode -import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.java.getPropertyNamesCandidatesByAccessorName -import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper.InternalNameMapper.demangleInternalName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtCallableDeclaration import org.jetbrains.kotlin.psi.KtNamedFunction @@ -50,30 +47,10 @@ class KotlinOverridingMethodReferenceSearcher : MethodUsagesSearcher() { return } - if (method is KtLightMethod) { - method.kotlinOrigin?.let { ktElement -> - val (mayBeMangled, name) = p.project.runReadActionInSmartMode { - ktElement.hasModifier(KtTokens.PRIVATE_KEYWORD) || ktElement.hasModifier(KtTokens.INTERNAL_KEYWORD) - } to method.name - if (mayBeMangled && name != null) { - val demangledName = demangleInternalName(name) - if (demangledName != null) { - val wrappedMethod = object : KtLightMethod by method { - override fun getName(): String = demangledName - } - processQuery( - MethodReferencesSearch.SearchParameters(wrappedMethod, p.scopeDeterminedByUser, p.isStrictSignatureSearch, p.optimizer), - consumer - ) - } - } - } - } - val searchScope = p.project.runReadActionInSmartMode { p.effectiveSearchScope - .intersectWith(method.useScope) - .restrictToKotlinSources() + .intersectWith(method.useScope) + .restrictToKotlinSources() } if (searchScope === GlobalSearchScope.EMPTY_SCOPE) return @@ -133,8 +110,8 @@ class KotlinOverridingMethodReferenceSearcher : MethodUsagesSearcher() { } fun countNonFinalLightMethods() = refElement - .toLightMethods() - .filterNot { it.hasModifierProperty(PsiModifier.FINAL) } + .toLightMethods() + .filterNot { it.hasModifierProperty(PsiModifier.FINAL) } val lightMethods = when (refElement) { is KtProperty, is KtParameter -> { diff --git a/idea/testData/refactoring/rename/javaGetterToOrdinaryMethod/after/SyntheticProperty.java b/idea/testData/refactoring/rename/javaGetterToOrdinaryMethod/after/SyntheticProperty.java new file mode 100644 index 00000000000..14832ca3d63 --- /dev/null +++ b/idea/testData/refactoring/rename/javaGetterToOrdinaryMethod/after/SyntheticProperty.java @@ -0,0 +1,4 @@ +public class SyntheticProperty { + public int foo() { return 1; } + public void setSyntheticA(int x) { } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/javaGetterToOrdinaryMethod/after/synthesize.kt b/idea/testData/refactoring/rename/javaGetterToOrdinaryMethod/after/synthesize.kt new file mode 100644 index 00000000000..c9e058a1c55 --- /dev/null +++ b/idea/testData/refactoring/rename/javaGetterToOrdinaryMethod/after/synthesize.kt @@ -0,0 +1,12 @@ +fun synthesize(p: SyntheticProperty) { + val v1 = p.foo() + p.setSyntheticA(1) + p.setSyntheticA(p.foo() + 2) + p.setSyntheticA(p.foo().inc()) + val syntheticA = p.foo() + p.setSyntheticA(syntheticA.inc()) + val x = syntheticA + val i = p.foo().inc() + p.setSyntheticA(i) + val y = i +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/javaGetterToOrdinaryMethod/before/SyntheticProperty.java b/idea/testData/refactoring/rename/javaGetterToOrdinaryMethod/before/SyntheticProperty.java new file mode 100644 index 00000000000..3866351e2ef --- /dev/null +++ b/idea/testData/refactoring/rename/javaGetterToOrdinaryMethod/before/SyntheticProperty.java @@ -0,0 +1,4 @@ +public class SyntheticProperty { + public int /*rename*/getSyntheticA() { return 1; } + public void setSyntheticA(int x) { } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/javaGetterToOrdinaryMethod/before/synthesize.kt b/idea/testData/refactoring/rename/javaGetterToOrdinaryMethod/before/synthesize.kt new file mode 100644 index 00000000000..9c7901e93e5 --- /dev/null +++ b/idea/testData/refactoring/rename/javaGetterToOrdinaryMethod/before/synthesize.kt @@ -0,0 +1,8 @@ +fun synthesize(p: SyntheticProperty) { + val v1 = p.syntheticA + p.syntheticA = 1 + p.syntheticA += 2 + p.syntheticA++ + val x = p.syntheticA++ + val y = ++p.syntheticA +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/javaGetterToOrdinaryMethod/javaGetterToOrdinaryMethod.test b/idea/testData/refactoring/rename/javaGetterToOrdinaryMethod/javaGetterToOrdinaryMethod.test new file mode 100644 index 00000000000..24b4fcfe461 --- /dev/null +++ b/idea/testData/refactoring/rename/javaGetterToOrdinaryMethod/javaGetterToOrdinaryMethod.test @@ -0,0 +1,6 @@ +{ + "type": "AUTO_DETECT", + "mainFile": "SyntheticProperty.java", + "newName": "foo", + "withRuntime": "true" +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/javaSetterToOrdinaryMethod/after/SyntheticProperty.java b/idea/testData/refactoring/rename/javaSetterToOrdinaryMethod/after/SyntheticProperty.java new file mode 100644 index 00000000000..1a07475f3bf --- /dev/null +++ b/idea/testData/refactoring/rename/javaSetterToOrdinaryMethod/after/SyntheticProperty.java @@ -0,0 +1,4 @@ +public class SyntheticProperty { + public int getSyntheticA() { return 1; } + public void foo(int x) { } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/javaSetterToOrdinaryMethod/after/synthesize.kt b/idea/testData/refactoring/rename/javaSetterToOrdinaryMethod/after/synthesize.kt new file mode 100644 index 00000000000..6fb01f218db --- /dev/null +++ b/idea/testData/refactoring/rename/javaSetterToOrdinaryMethod/after/synthesize.kt @@ -0,0 +1,12 @@ +fun synthesize(p: SyntheticProperty) { + val v1 = p.syntheticA + p.foo(1) + p.foo(p.syntheticA + 2) + p.foo(p.syntheticA.inc()) + val syntheticA = p.syntheticA + p.foo(syntheticA.inc()) + val x = syntheticA + val i = p.syntheticA.inc() + p.foo(i) + val y = i +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/javaSetterToOrdinaryMethod/before/SyntheticProperty.java b/idea/testData/refactoring/rename/javaSetterToOrdinaryMethod/before/SyntheticProperty.java new file mode 100644 index 00000000000..4166ad3126d --- /dev/null +++ b/idea/testData/refactoring/rename/javaSetterToOrdinaryMethod/before/SyntheticProperty.java @@ -0,0 +1,4 @@ +public class SyntheticProperty { + public int getSyntheticA() { return 1; } + public void /*rename*/setSyntheticA(int x) { } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/javaSetterToOrdinaryMethod/before/synthesize.kt b/idea/testData/refactoring/rename/javaSetterToOrdinaryMethod/before/synthesize.kt new file mode 100644 index 00000000000..9c7901e93e5 --- /dev/null +++ b/idea/testData/refactoring/rename/javaSetterToOrdinaryMethod/before/synthesize.kt @@ -0,0 +1,8 @@ +fun synthesize(p: SyntheticProperty) { + val v1 = p.syntheticA + p.syntheticA = 1 + p.syntheticA += 2 + p.syntheticA++ + val x = p.syntheticA++ + val y = ++p.syntheticA +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/javaSetterToOrdinaryMethod/javaSetterToOrdinaryMethod.test b/idea/testData/refactoring/rename/javaSetterToOrdinaryMethod/javaSetterToOrdinaryMethod.test new file mode 100644 index 00000000000..24b4fcfe461 --- /dev/null +++ b/idea/testData/refactoring/rename/javaSetterToOrdinaryMethod/javaSetterToOrdinaryMethod.test @@ -0,0 +1,6 @@ +{ + "type": "AUTO_DETECT", + "mainFile": "SyntheticProperty.java", + "newName": "foo", + "withRuntime": "true" +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/syntheticPropertyUsages1/after/Usages.kt b/idea/testData/refactoring/rename/syntheticPropertyUsages1/after/Usages.kt index c9635f4e917..87f9e780d2a 100644 --- a/idea/testData/refactoring/rename/syntheticPropertyUsages1/after/Usages.kt +++ b/idea/testData/refactoring/rename/syntheticPropertyUsages1/after/Usages.kt @@ -1,6 +1,6 @@ import testing.JavaClass fun usages(javaClass: JavaClass) { - javaClass.something = javaClass.somethingNew + 1 + javaClass.somethingNew = javaClass.somethingNew + 1 javaClass.somethingNew++ } \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/rename/RenameTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/refactoring/rename/RenameTestGenerated.java index 11c71643cc0..fd5a82a2cc4 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/rename/RenameTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/rename/RenameTestGenerated.java @@ -234,6 +234,16 @@ public class RenameTestGenerated extends AbstractRenameTest { runTest("idea/testData/refactoring/rename/javaEnumValueOf/javaEnumValueOf.test"); } + @TestMetadata("javaGetterToOrdinaryMethod/javaGetterToOrdinaryMethod.test") + public void testJavaGetterToOrdinaryMethod_JavaGetterToOrdinaryMethod() throws Exception { + runTest("idea/testData/refactoring/rename/javaGetterToOrdinaryMethod/javaGetterToOrdinaryMethod.test"); + } + + @TestMetadata("javaSetterToOrdinaryMethod/javaSetterToOrdinaryMethod.test") + public void testJavaSetterToOrdinaryMethod_JavaSetterToOrdinaryMethod() throws Exception { + runTest("idea/testData/refactoring/rename/javaSetterToOrdinaryMethod/javaSetterToOrdinaryMethod.test"); + } + @TestMetadata("labeledAnonymousFunByLabel/labeledLambdaByLabel.test") public void testLabeledAnonymousFunByLabel_LabeledLambdaByLabel() throws Exception { runTest("idea/testData/refactoring/rename/labeledAnonymousFunByLabel/labeledLambdaByLabel.test");