Rename: Fixed rename of Java getters/setters through synthetic property references in Kotlin
#KT-8817 Fixed
This commit is contained in:
@@ -31,6 +31,7 @@ Issues fixed:
|
|||||||
- [KT-11908](https://youtrack.jetbrains.com/issue/KT-11866) Allow properties with custom setters to be used in generated equals/hashCode/toString
|
- [KT-11908](https://youtrack.jetbrains.com/issue/KT-11866) Allow properties with custom setters to be used in generated equals/hashCode/toString
|
||||||
- [KT-11845](https://youtrack.jetbrains.com/issue/KT-11845) Fixed exception on attempt to find derived classes
|
- [KT-11845](https://youtrack.jetbrains.com/issue/KT-11845) Fixed exception on attempt to find derived classes
|
||||||
- [KT-11736](https://youtrack.jetbrains.com/issue/KT-11736) Fixed searching of Java usages for @JvmStatic properties and @JvmStatic @JvmOverloads functions
|
- [KT-11736](https://youtrack.jetbrains.com/issue/KT-11736) Fixed searching of Java usages for @JvmStatic properties and @JvmStatic @JvmOverloads functions
|
||||||
|
- [KT-8817](https://youtrack.jetbrains.com/issue/KT-8817) Fixed rename of Java getters/setters through synthetic property references in Kotlin
|
||||||
|
|
||||||
#### Debugger
|
#### Debugger
|
||||||
|
|
||||||
|
|||||||
+7
-3
@@ -51,6 +51,12 @@ sealed class SyntheticPropertyAccessorReference(expression: KtNameReferenceExpre
|
|||||||
|
|
||||||
override fun canRename() = true
|
override fun canRename() = true
|
||||||
|
|
||||||
|
fun renameByPropertyName(newName: String): PsiElement? {
|
||||||
|
val nameIdentifier = KtPsiFactory(expression).createNameIdentifier(newName)
|
||||||
|
expression.getReferencedNameElement().replace(nameIdentifier)
|
||||||
|
return expression
|
||||||
|
}
|
||||||
|
|
||||||
override fun handleElementRename(newElementName: String?): PsiElement? {
|
override fun handleElementRename(newElementName: String?): PsiElement? {
|
||||||
if (!Name.isValidIdentifier(newElementName!!)) return expression
|
if (!Name.isValidIdentifier(newElementName!!)) return expression
|
||||||
|
|
||||||
@@ -65,9 +71,7 @@ sealed class SyntheticPropertyAccessorReference(expression: KtNameReferenceExpre
|
|||||||
}
|
}
|
||||||
if (newName == null) return expression //TODO: handle the case when get/set becomes ordinary method
|
if (newName == null) return expression //TODO: handle the case when get/set becomes ordinary method
|
||||||
|
|
||||||
val nameIdentifier = KtPsiFactory(expression).createNameIdentifier(newName.identifier)
|
return renameByPropertyName(newName.identifier)
|
||||||
expression.getReferencedNameElement().replace(nameIdentifier)
|
|
||||||
return expression
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class Getter(expression: KtNameReferenceExpression) : SyntheticPropertyAccessorReference(expression, true)
|
class Getter(expression: KtNameReferenceExpression) : SyntheticPropertyAccessorReference(expression, true)
|
||||||
|
|||||||
@@ -411,9 +411,12 @@
|
|||||||
<renamePsiElementProcessor implementation="org.jetbrains.kotlin.idea.refactoring.rename.RenameKotlinFileProcessor"
|
<renamePsiElementProcessor implementation="org.jetbrains.kotlin.idea.refactoring.rename.RenameKotlinFileProcessor"
|
||||||
id="KotlinFile"
|
id="KotlinFile"
|
||||||
order="first"/>
|
order="first"/>
|
||||||
|
<renamePsiElementProcessor implementation="org.jetbrains.kotlin.idea.refactoring.rename.RenameJavaSyntheticPropertyHandler$Processor"
|
||||||
|
id="JavaSyntheticPropertyFromKotlin"/>
|
||||||
<renameHandler implementation="org.jetbrains.kotlin.idea.refactoring.rename.RenameKotlinImplicitLambdaParameter"/>
|
<renameHandler implementation="org.jetbrains.kotlin.idea.refactoring.rename.RenameKotlinImplicitLambdaParameter"/>
|
||||||
<renameHandler implementation="org.jetbrains.kotlin.idea.refactoring.rename.RenameDynamicMemberHandler"/>
|
<renameHandler implementation="org.jetbrains.kotlin.idea.refactoring.rename.RenameDynamicMemberHandler"/>
|
||||||
<renameHandler implementation="org.jetbrains.kotlin.idea.refactoring.rename.RenameOnSecondaryConstructorHandler"/>
|
<renameHandler implementation="org.jetbrains.kotlin.idea.refactoring.rename.RenameOnSecondaryConstructorHandler"/>
|
||||||
|
<renameHandler implementation="org.jetbrains.kotlin.idea.refactoring.rename.RenameJavaSyntheticPropertyHandler"/>
|
||||||
<automaticRenamerFactory implementation="org.jetbrains.kotlin.idea.refactoring.rename.AutomaticVariableRenamerFactory"/>
|
<automaticRenamerFactory implementation="org.jetbrains.kotlin.idea.refactoring.rename.AutomaticVariableRenamerFactory"/>
|
||||||
<automaticRenamerFactory implementation="org.jetbrains.kotlin.idea.refactoring.rename.AutomaticVariableRenamerFactoryForJavaClass"/>
|
<automaticRenamerFactory implementation="org.jetbrains.kotlin.idea.refactoring.rename.AutomaticVariableRenamerFactoryForJavaClass"/>
|
||||||
<automaticRenamerFactory implementation="org.jetbrains.kotlin.idea.refactoring.rename.AutomaticVariableInJavaRenamerFactory"/>
|
<automaticRenamerFactory implementation="org.jetbrains.kotlin.idea.refactoring.rename.AutomaticVariableInJavaRenamerFactory"/>
|
||||||
|
|||||||
@@ -24,9 +24,12 @@ import com.intellij.psi.PsiNamedElement
|
|||||||
import com.intellij.refactoring.util.CommonRefactoringUtil
|
import com.intellij.refactoring.util.CommonRefactoringUtil
|
||||||
import com.intellij.refactoring.util.RefactoringDescriptionLocation
|
import com.intellij.refactoring.util.RefactoringDescriptionLocation
|
||||||
import com.intellij.usageView.UsageViewLongNameLocation
|
import com.intellij.usageView.UsageViewLongNameLocation
|
||||||
|
import com.intellij.usageView.UsageViewTypeLocation
|
||||||
import org.jetbrains.kotlin.asJava.unwrapped
|
import org.jetbrains.kotlin.asJava.unwrapped
|
||||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.rename.RenameJavaSyntheticPropertyHandler
|
||||||
import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
|
import org.jetbrains.kotlin.idea.search.usagesSearch.descriptor
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
@@ -44,6 +47,7 @@ class KotlinElementDescriptionProvider : ElementDescriptionProvider {
|
|||||||
is KtTypeParameter -> "type parameter"
|
is KtTypeParameter -> "type parameter"
|
||||||
is KtParameter -> "parameter"
|
is KtParameter -> "parameter"
|
||||||
is KtDestructuringDeclarationEntry -> "variable"
|
is KtDestructuringDeclarationEntry -> "variable"
|
||||||
|
is RenameJavaSyntheticPropertyHandler.SyntheticPropertyWrapper -> "property"
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,9 +59,9 @@ class KotlinElementDescriptionProvider : ElementDescriptionProvider {
|
|||||||
return descriptor
|
return descriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetElement !is PsiNamedElement || targetElement !is KtElement) return null
|
if (targetElement !is PsiNamedElement || targetElement.language != KotlinLanguage.INSTANCE) return null
|
||||||
|
|
||||||
return when(location) {
|
return when(location) {
|
||||||
|
is UsageViewTypeLocation -> elementKind()
|
||||||
is UsageViewLongNameLocation -> targetElement.getName()
|
is UsageViewLongNameLocation -> targetElement.getName()
|
||||||
is RefactoringDescriptionLocation -> {
|
is RefactoringDescriptionLocation -> {
|
||||||
val kind = elementKind() ?: return null
|
val kind = elementKind() ?: return null
|
||||||
|
|||||||
+99
@@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 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.rename
|
||||||
|
|
||||||
|
import com.intellij.openapi.actionSystem.CommonDataKeys
|
||||||
|
import com.intellij.openapi.actionSystem.DataContext
|
||||||
|
import com.intellij.openapi.editor.Editor
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.psi.*
|
||||||
|
import com.intellij.psi.impl.light.LightElement
|
||||||
|
import com.intellij.psi.search.SearchScope
|
||||||
|
import com.intellij.refactoring.rename.PsiElementRenameHandler
|
||||||
|
import com.intellij.refactoring.rename.RenamePsiElementProcessor
|
||||||
|
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
|
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||||
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
|
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||||
|
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
|
||||||
|
|
||||||
|
class RenameJavaSyntheticPropertyHandler : PsiElementRenameHandler() {
|
||||||
|
class Processor : RenamePsiElementProcessor() {
|
||||||
|
override fun prepareRenaming(element: PsiElement, newName: String, allRenames: MutableMap<PsiElement, String>, scope: SearchScope) {
|
||||||
|
val propertyWrapper = element as? SyntheticPropertyWrapper ?: return
|
||||||
|
propertyWrapper.getter?.let { allRenames[it] = JvmAbi.getterName(newName) }
|
||||||
|
propertyWrapper.setter?.let { allRenames[it] = JvmAbi.setterName(newName) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canProcessElement(element: PsiElement) = element is SyntheticPropertyWrapper
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class SyntheticPropertyWrapper(
|
||||||
|
manager: PsiManager,
|
||||||
|
val descriptor: SyntheticJavaPropertyDescriptor
|
||||||
|
): LightElement(manager, KotlinLanguage.INSTANCE), PsiNamedElement {
|
||||||
|
val getter: PsiMethod? get() = descriptor.getMethod.source.getPsi() as? PsiMethod
|
||||||
|
val setter: PsiMethod? get() = descriptor.setMethod?.source?.getPsi() as? PsiMethod
|
||||||
|
|
||||||
|
override fun getContainingFile() = getter?.containingFile
|
||||||
|
|
||||||
|
override fun getName() = descriptor.name.asString()
|
||||||
|
|
||||||
|
override fun setName(name: String): PsiElement? {
|
||||||
|
getter?.name = JvmAbi.getterName(name)
|
||||||
|
setter?.name = JvmAbi.setterName(name)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
val renderer = IdeDescriptorRenderers.SOURCE_CODE
|
||||||
|
return "${renderer.render(descriptor.getMethod)}|${descriptor.setMethod?.let { renderer.render(it) }}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getTargetDescriptor(dataContext: DataContext): SyntheticJavaPropertyDescriptor? {
|
||||||
|
val caret = CommonDataKeys.CARET.getData(dataContext) ?: return null
|
||||||
|
val ktFile = CommonDataKeys.PSI_FILE.getData(dataContext) as? KtFile ?: return null
|
||||||
|
val refExpr = ktFile.findElementAt(caret.offset)?.getNonStrictParentOfType<KtSimpleNameExpression>() ?: return null
|
||||||
|
return refExpr.analyze(BodyResolveMode.PARTIAL)[BindingContext.REFERENCE_TARGET, refExpr] as? SyntheticJavaPropertyDescriptor
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isAvailableOnDataContext(dataContext: DataContext): Boolean {
|
||||||
|
return CommonDataKeys.EDITOR.getData(dataContext) != null && getTargetDescriptor(dataContext) != null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun invoke(project: Project, editor: Editor?, file: PsiFile?, dataContext: DataContext) {
|
||||||
|
val descriptor = getTargetDescriptor(dataContext) ?: return
|
||||||
|
val wrappingContext = DataContext { id ->
|
||||||
|
if (CommonDataKeys.PSI_ELEMENT.`is`(id)) {
|
||||||
|
return@DataContext SyntheticPropertyWrapper(PsiManager.getInstance(project), descriptor)
|
||||||
|
}
|
||||||
|
dataContext.getData(id)
|
||||||
|
}
|
||||||
|
super.invoke(project, editor, file, wrappingContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun invoke(project: Project, elements: Array<out PsiElement>, dataContext: DataContext) {
|
||||||
|
// Can't be invoked outside of a text editor
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
public class Bean {
|
||||||
|
private boolean prop;
|
||||||
|
public boolean isProp2() { return prop; }
|
||||||
|
public void setProp2(boolean prop) { this.prop = prop; }
|
||||||
|
|
||||||
|
void test() {
|
||||||
|
isProp2();
|
||||||
|
setProp2(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
fun test(bean: Bean) {
|
||||||
|
bean.isProp2 = true
|
||||||
|
println(bean.isProp2)
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
public class Bean {
|
||||||
|
private boolean prop;
|
||||||
|
public boolean isProp() { return prop; }
|
||||||
|
public void setProp(boolean prop) { this.prop = prop; }
|
||||||
|
|
||||||
|
void test() {
|
||||||
|
isProp();
|
||||||
|
setProp(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
@@ -0,0 +1,4 @@
|
|||||||
|
fun test(bean: Bean) {
|
||||||
|
bean.isProp = true
|
||||||
|
println(bean./*rename*/isProp)
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"type": "SYNTHETIC_PROPERTY",
|
||||||
|
"mainFile": "test.kt",
|
||||||
|
"newName": "isProp2"
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
public class Bean {
|
||||||
|
private String prop = "value";
|
||||||
|
public String getProp2() { return prop; }
|
||||||
|
public void setProp2(String prop) { this.prop = prop; }
|
||||||
|
|
||||||
|
void test() {
|
||||||
|
getProp2();
|
||||||
|
setProp2("");
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
fun test(bean: Bean) {
|
||||||
|
bean.prop2 = "a"
|
||||||
|
println(bean.prop2)
|
||||||
|
bean.prop2 += "a"
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
public class Bean {
|
||||||
|
private String prop = "value";
|
||||||
|
public String getProp() { return prop; }
|
||||||
|
public void setProp(String prop) { this.prop = prop; }
|
||||||
|
|
||||||
|
void test() {
|
||||||
|
getProp();
|
||||||
|
setProp("");
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
fun test(bean: Bean) {
|
||||||
|
bean.prop = "a"
|
||||||
|
println(bean./*rename*/prop)
|
||||||
|
bean.prop += "a"
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"type": "SYNTHETIC_PROPERTY",
|
||||||
|
"mainFile": "test.kt",
|
||||||
|
"newName": "prop2"
|
||||||
|
}
|
||||||
Vendored
+10
@@ -0,0 +1,10 @@
|
|||||||
|
public class Bean {
|
||||||
|
private String prop = "value";
|
||||||
|
public String getProp2() { return prop; }
|
||||||
|
public void setProp2(String prop) { this.prop = prop; }
|
||||||
|
|
||||||
|
void test() {
|
||||||
|
getProp2();
|
||||||
|
setProp2("");
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+5
@@ -0,0 +1,5 @@
|
|||||||
|
fun test(bean: Bean) {
|
||||||
|
bean.prop2 = "a"
|
||||||
|
println(bean.prop2)
|
||||||
|
bean.prop2 += "a"
|
||||||
|
}
|
||||||
Vendored
+10
@@ -0,0 +1,10 @@
|
|||||||
|
public class Bean {
|
||||||
|
private String prop = "value";
|
||||||
|
public String getProp() { return prop; }
|
||||||
|
public void setProp(String prop) { this.prop = prop; }
|
||||||
|
|
||||||
|
void test() {
|
||||||
|
getProp();
|
||||||
|
setProp("");
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+5
@@ -0,0 +1,5 @@
|
|||||||
|
fun test(bean: Bean) {
|
||||||
|
bean.prop = "a"
|
||||||
|
println(bean.prop)
|
||||||
|
bean./*rename*/prop += "a"
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"type": "SYNTHETIC_PROPERTY",
|
||||||
|
"mainFile": "test.kt",
|
||||||
|
"newName": "prop2"
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
public class Bean {
|
||||||
|
private String prop = "value";
|
||||||
|
public String getProp2() { return prop; }
|
||||||
|
public void setProp2(String prop) { this.prop = prop; }
|
||||||
|
|
||||||
|
void test() {
|
||||||
|
getProp2();
|
||||||
|
setProp2("");
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
fun test(bean: Bean) {
|
||||||
|
bean.prop2 = "a"
|
||||||
|
println(bean.prop2)
|
||||||
|
bean.prop2 += "a"
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
public class Bean {
|
||||||
|
private String prop = "value";
|
||||||
|
public String getProp() { return prop; }
|
||||||
|
public void setProp(String prop) { this.prop = prop; }
|
||||||
|
|
||||||
|
void test() {
|
||||||
|
getProp();
|
||||||
|
setProp("");
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
fun test(bean: Bean) {
|
||||||
|
bean./*rename*/prop = "a"
|
||||||
|
println(bean.prop)
|
||||||
|
bean.prop += "a"
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"type": "SYNTHETIC_PROPERTY",
|
||||||
|
"mainFile": "test.kt",
|
||||||
|
"newName": "prop2"
|
||||||
|
}
|
||||||
@@ -43,19 +43,25 @@ import com.intellij.refactoring.rename.naming.AutomaticRenamerFactory
|
|||||||
import com.intellij.refactoring.util.CommonRefactoringUtil.RefactoringErrorHintException
|
import com.intellij.refactoring.util.CommonRefactoringUtil.RefactoringErrorHintException
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFullyAndGetResult
|
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFullyAndGetResult
|
||||||
import org.jetbrains.kotlin.idea.jsonUtils.getNullableString
|
import org.jetbrains.kotlin.idea.jsonUtils.getNullableString
|
||||||
import org.jetbrains.kotlin.idea.jsonUtils.getString
|
import org.jetbrains.kotlin.idea.jsonUtils.getString
|
||||||
|
import org.jetbrains.kotlin.idea.refactoring.toPsiFile
|
||||||
import org.jetbrains.kotlin.idea.references.mainReference
|
import org.jetbrains.kotlin.idea.references.mainReference
|
||||||
import org.jetbrains.kotlin.idea.search.allScope
|
import org.jetbrains.kotlin.idea.search.allScope
|
||||||
import org.jetbrains.kotlin.idea.test.*
|
import org.jetbrains.kotlin.idea.test.*
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.name.*
|
import org.jetbrains.kotlin.name.*
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||||
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
import org.jetbrains.kotlin.serialization.deserialization.findClassAcrossModuleDependencies
|
import org.jetbrains.kotlin.serialization.deserialization.findClassAcrossModuleDependencies
|
||||||
|
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@@ -68,7 +74,8 @@ private enum class RenameType {
|
|||||||
KOTLIN_PACKAGE,
|
KOTLIN_PACKAGE,
|
||||||
MARKED_ELEMENT,
|
MARKED_ELEMENT,
|
||||||
FILE,
|
FILE,
|
||||||
BUNDLE_PROPERTY
|
BUNDLE_PROPERTY,
|
||||||
|
SYNTHETIC_PROPERTY
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class AbstractRenameTest : KotlinMultiFileTestCase() {
|
abstract class AbstractRenameTest : KotlinMultiFileTestCase() {
|
||||||
@@ -109,6 +116,7 @@ abstract class AbstractRenameTest : KotlinMultiFileTestCase() {
|
|||||||
RenameType.MARKED_ELEMENT -> renameMarkedElement(renameObject, context)
|
RenameType.MARKED_ELEMENT -> renameMarkedElement(renameObject, context)
|
||||||
RenameType.FILE -> renameFile(renameObject, context)
|
RenameType.FILE -> renameFile(renameObject, context)
|
||||||
RenameType.BUNDLE_PROPERTY -> renameBundleProperty(renameObject, context)
|
RenameType.BUNDLE_PROPERTY -> renameBundleProperty(renameObject, context)
|
||||||
|
RenameType.SYNTHETIC_PROPERTY -> renameSyntheticProperty(renameObject, context)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hintDirective != null) {
|
if (hintDirective != null) {
|
||||||
@@ -323,6 +331,30 @@ abstract class AbstractRenameTest : KotlinMultiFileTestCase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun renameSyntheticProperty(renameParamsObject: JsonObject, context: TestContext) {
|
||||||
|
val mainFilePath = renameParamsObject.getString("mainFile")
|
||||||
|
val newName = renameParamsObject.getString("newName")
|
||||||
|
|
||||||
|
doTestCommittingDocuments { rootDir, rootAfter ->
|
||||||
|
configExtra(rootDir, renameParamsObject)
|
||||||
|
|
||||||
|
val psiFile = rootDir.findFileByRelativePath(mainFilePath)!!.toPsiFile(project)!!
|
||||||
|
|
||||||
|
val doc = PsiDocumentManager.getInstance(project).getDocument(psiFile)!!
|
||||||
|
val marker = doc.extractMarkerOffset(project, "/*rename*/")
|
||||||
|
assert(marker != -1)
|
||||||
|
|
||||||
|
val refExpr = psiFile.findElementAt(marker)!!.getNonStrictParentOfType<KtSimpleNameExpression>()!!
|
||||||
|
val descriptor = refExpr.analyze(BodyResolveMode.PARTIAL)[BindingContext.REFERENCE_TARGET, refExpr]
|
||||||
|
as SyntheticJavaPropertyDescriptor
|
||||||
|
val propertyWrapper = RenameJavaSyntheticPropertyHandler.SyntheticPropertyWrapper(psiFile.manager, descriptor)
|
||||||
|
|
||||||
|
val substitution = RenamePsiElementProcessor.forElement(propertyWrapper).substituteElementToRename(propertyWrapper, null)
|
||||||
|
|
||||||
|
runRenameProcessor(context, newName, substitution, true, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun runRenameProcessor(
|
private fun runRenameProcessor(
|
||||||
context: TestContext,
|
context: TestContext,
|
||||||
newName: String,
|
newName: String,
|
||||||
|
|||||||
@@ -215,6 +215,30 @@ public class RenameTestGenerated extends AbstractRenameTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("renameJavaSyntheticIsPropertyByGetterRef/renameJavaSyntheticIsPropertyByGetterRef.test")
|
||||||
|
public void testRenameJavaSyntheticIsPropertyByGetterRef_RenameJavaSyntheticIsPropertyByGetterRef() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/renameJavaSyntheticIsPropertyByGetterRef/renameJavaSyntheticIsPropertyByGetterRef.test");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("renameJavaSyntheticPropertyByGetterRef/renameJavaSyntheticPropertyByGetterRef.test")
|
||||||
|
public void testRenameJavaSyntheticPropertyByGetterRef_RenameJavaSyntheticPropertyByGetterRef() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/renameJavaSyntheticPropertyByGetterRef/renameJavaSyntheticPropertyByGetterRef.test");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("renameJavaSyntheticPropertyByGetterSetterRef/renameJavaSyntheticPropertyByGetterSetterRef.test")
|
||||||
|
public void testRenameJavaSyntheticPropertyByGetterSetterRef_RenameJavaSyntheticPropertyByGetterSetterRef() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/renameJavaSyntheticPropertyByGetterSetterRef/renameJavaSyntheticPropertyByGetterSetterRef.test");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("renameJavaSyntheticPropertyBySetterRef/renameJavaSyntheticPropertyBySetterRef.test")
|
||||||
|
public void testRenameJavaSyntheticPropertyBySetterRef_RenameJavaSyntheticPropertyBySetterRef() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/renameJavaSyntheticPropertyBySetterRef/renameJavaSyntheticPropertyBySetterRef.test");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("renameKotlinBaseMethod/javaWrapperForBaseFunction.test")
|
@TestMetadata("renameKotlinBaseMethod/javaWrapperForBaseFunction.test")
|
||||||
public void testRenameKotlinBaseMethod_JavaWrapperForBaseFunction() throws Exception {
|
public void testRenameKotlinBaseMethod_JavaWrapperForBaseFunction() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/renameKotlinBaseMethod/javaWrapperForBaseFunction.test");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/renameKotlinBaseMethod/javaWrapperForBaseFunction.test");
|
||||||
|
|||||||
Reference in New Issue
Block a user