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-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-8817](https://youtrack.jetbrains.com/issue/KT-8817) Fixed rename of Java getters/setters through synthetic property references in Kotlin
|
||||
|
||||
#### Debugger
|
||||
|
||||
|
||||
+7
-3
@@ -51,6 +51,12 @@ sealed class SyntheticPropertyAccessorReference(expression: KtNameReferenceExpre
|
||||
|
||||
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? {
|
||||
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
|
||||
|
||||
val nameIdentifier = KtPsiFactory(expression).createNameIdentifier(newName.identifier)
|
||||
expression.getReferencedNameElement().replace(nameIdentifier)
|
||||
return expression
|
||||
return renameByPropertyName(newName.identifier)
|
||||
}
|
||||
|
||||
class Getter(expression: KtNameReferenceExpression) : SyntheticPropertyAccessorReference(expression, true)
|
||||
|
||||
@@ -411,9 +411,12 @@
|
||||
<renamePsiElementProcessor implementation="org.jetbrains.kotlin.idea.refactoring.rename.RenameKotlinFileProcessor"
|
||||
id="KotlinFile"
|
||||
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.RenameDynamicMemberHandler"/>
|
||||
<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.AutomaticVariableRenamerFactoryForJavaClass"/>
|
||||
<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.RefactoringDescriptionLocation
|
||||
import com.intellij.usageView.UsageViewLongNameLocation
|
||||
import com.intellij.usageView.UsageViewTypeLocation
|
||||
import org.jetbrains.kotlin.asJava.unwrapped
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
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.psi.*
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
@@ -44,6 +47,7 @@ class KotlinElementDescriptionProvider : ElementDescriptionProvider {
|
||||
is KtTypeParameter -> "type parameter"
|
||||
is KtParameter -> "parameter"
|
||||
is KtDestructuringDeclarationEntry -> "variable"
|
||||
is RenameJavaSyntheticPropertyHandler.SyntheticPropertyWrapper -> "property"
|
||||
else -> null
|
||||
}
|
||||
|
||||
@@ -55,9 +59,9 @@ class KotlinElementDescriptionProvider : ElementDescriptionProvider {
|
||||
return descriptor
|
||||
}
|
||||
|
||||
if (targetElement !is PsiNamedElement || targetElement !is KtElement) return null
|
||||
|
||||
if (targetElement !is PsiNamedElement || targetElement.language != KotlinLanguage.INSTANCE) return null
|
||||
return when(location) {
|
||||
is UsageViewTypeLocation -> elementKind()
|
||||
is UsageViewLongNameLocation -> targetElement.getName()
|
||||
is RefactoringDescriptionLocation -> {
|
||||
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 org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
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.jsonUtils.getNullableString
|
||||
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.search.allScope
|
||||
import org.jetbrains.kotlin.idea.test.*
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.name.*
|
||||
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.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
import org.jetbrains.kotlin.serialization.deserialization.findClassAcrossModuleDependencies
|
||||
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
|
||||
import org.junit.Assert
|
||||
import java.io.File
|
||||
|
||||
@@ -68,7 +74,8 @@ private enum class RenameType {
|
||||
KOTLIN_PACKAGE,
|
||||
MARKED_ELEMENT,
|
||||
FILE,
|
||||
BUNDLE_PROPERTY
|
||||
BUNDLE_PROPERTY,
|
||||
SYNTHETIC_PROPERTY
|
||||
}
|
||||
|
||||
abstract class AbstractRenameTest : KotlinMultiFileTestCase() {
|
||||
@@ -109,6 +116,7 @@ abstract class AbstractRenameTest : KotlinMultiFileTestCase() {
|
||||
RenameType.MARKED_ELEMENT -> renameMarkedElement(renameObject, context)
|
||||
RenameType.FILE -> renameFile(renameObject, context)
|
||||
RenameType.BUNDLE_PROPERTY -> renameBundleProperty(renameObject, context)
|
||||
RenameType.SYNTHETIC_PROPERTY -> renameSyntheticProperty(renameObject, context)
|
||||
}
|
||||
|
||||
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(
|
||||
context: TestContext,
|
||||
newName: String,
|
||||
|
||||
@@ -215,6 +215,30 @@ public class RenameTestGenerated extends AbstractRenameTest {
|
||||
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")
|
||||
public void testRenameKotlinBaseMethod_JavaWrapperForBaseFunction() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/rename/renameKotlinBaseMethod/javaWrapperForBaseFunction.test");
|
||||
|
||||
Reference in New Issue
Block a user