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 3d3671f26d4..ddb78045f7f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/KotlinTypeMapper.java @@ -1676,13 +1676,21 @@ public class KotlinTypeMapper { } @Nullable - public static String internalNameWithoutModuleSuffix(@NotNull String name) { + public static String demangleInternalName(@NotNull String name) { int indexOfDollar = name.indexOf('$'); - if (indexOfDollar == -1) { - return null; - } + return indexOfDollar >= 0 ? name.substring(0, indexOfDollar) : null; + } - return name.substring(0, indexOfDollar) + '$'; + @Nullable + public static String getModuleNameSuffix(@NotNull String name) { + int indexOfDollar = name.indexOf('$'); + return indexOfDollar >=0 ? name.substring(indexOfDollar + 1) : null; + } + + @Nullable + public static String internalNameWithoutModuleSuffix(@NotNull String name) { + String demangledName = demangleInternalName(name); + return demangledName != null ? demangledName + '$' : null; } } } diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightElements.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightElements.kt index eb2902e50a9..49beb6ba892 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightElements.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightElements.kt @@ -44,4 +44,6 @@ interface KtLightMethod : PsiAnnotationMethod, KtLightMember { val isDelegated: Boolean get() = lightMemberOrigin?.originKind == JvmDeclarationOriginKind.DELEGATION || lightMemberOrigin?.originKind == JvmDeclarationOriginKind.CLASS_MEMBER_DELEGATION_TO_DEFAULT_IMPL + + val isMangled: Boolean } \ No newline at end of file diff --git a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMethodImpl.kt b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMethodImpl.kt index 39de7ac4fad..6b6c390356b 100644 --- a/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMethodImpl.kt +++ b/compiler/light-classes/src/org/jetbrains/kotlin/asJava/elements/KtLightMethodImpl.kt @@ -30,6 +30,7 @@ import org.jetbrains.kotlin.asJava.classes.cannotModify import org.jetbrains.kotlin.asJava.classes.lazyPub import org.jetbrains.kotlin.asJava.propertyNameByAccessor import org.jetbrains.kotlin.asJava.unwrapped +import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.resolve.DescriptorUtils @@ -84,9 +85,17 @@ class KtLightMethodImpl private constructor( } } + override val isMangled: Boolean + get() { + val demangledName = KotlinTypeMapper.InternalNameMapper.demangleInternalName(name) ?: return false + val originalName = propertyNameByAccessor(demangledName, this) ?: demangledName + return originalName == kotlinOrigin?.name + } + override fun setName(name: String): PsiElement? { val jvmNameAnnotation = modifierList.findAnnotation(DescriptorUtils.JVM_NAME.asString()) - val newNameForOrigin = propertyNameByAccessor(name, this) ?: name + val demangledName = (if (isMangled) KotlinTypeMapper.InternalNameMapper.demangleInternalName(name) else null) ?: name + val newNameForOrigin = propertyNameByAccessor(demangledName, this) ?: demangledName if (newNameForOrigin == kotlinOrigin?.name) { jvmNameAnnotation?.delete() return this diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinReferencesSearcher.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinReferencesSearcher.kt index 22781b4dfc3..45bcb52626a 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinReferencesSearcher.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinReferencesSearcher.kt @@ -227,6 +227,9 @@ class KotlinReferencesSearcher : QueryExecutorBase SearchScope)? = null + ) { if (name != null && element != null) { - val scope = queryParameters.effectiveSearchScope(element) + val baseScope = queryParameters.effectiveSearchScope(element) + val scope = if (modifyScope != null) modifyScope(baseScope) else baseScope val context = UsageSearchContext.IN_CODE + UsageSearchContext.IN_FOREIGN_LANGUAGES + UsageSearchContext.IN_COMMENTS val resultProcessor = KotlinRequestResultProcessor(element, queryParameters.elementToSearch.namedUnwrappedElement ?: element, diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinClassifierProcessor.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinClassifierProcessor.kt index 5eb65ea3d24..ea53ab3ec57 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinClassifierProcessor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinClassifierProcessor.kt @@ -121,7 +121,7 @@ class RenameKotlinClassifierProcessor : RenameKotlinPsiProcessor() { else -> null } - override fun renameElement(element: PsiElement, newName: String, usages: Array, listener: RefactoringElementListener?) { + override fun renameElement(element: PsiElement, newName: String, usages: Array, listener: RefactoringElementListener?) { val simpleUsages = ArrayList(usages.size) val ambiguousImportUsages = com.intellij.util.SmartList() for (usage in usages) { 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 e5622404417..e85686d878a 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinFunctionProcessor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinFunctionProcessor.kt @@ -35,6 +35,8 @@ 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.descriptors.FunctionDescriptor import org.jetbrains.kotlin.idea.caches.resolve.unsafeResolveToDescriptor import org.jetbrains.kotlin.idea.refactoring.Pass @@ -181,6 +183,8 @@ 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 } } @@ -190,22 +194,22 @@ class RenameKotlinFunctionProcessor : RenameKotlinPsiProcessor() { 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 if (psiMethod.containingClass != null) { - psiMethod.forEachOverridingMethod { it -> + psiMethod.forEachOverridingMethod(scope) { it -> val overrider = (it as? PsiMirrorElement)?.prototype as? PsiMethod ?: it if (overrider is SyntheticElement) return@forEachOverridingMethod true val overriderName = overrider.name - val baseName = psiMethod.name - val newOverriderName = RefactoringUtil.suggestNewOverriderName(overriderName, baseName, newName) + val newOverriderName = RefactoringUtil.suggestNewOverriderName(overriderName, baseName, newBaseName) if (newOverriderName != null) { RenameProcessor.assertNonCompileElement(overrider) allRenames.put(overrider, newOverriderName) } return@forEachOverridingMethod true } - javaMethodProcessorInstance.prepareRenaming(psiMethod, newName, allRenames, scope) } } } @@ -223,7 +227,9 @@ class RenameKotlinFunctionProcessor : RenameKotlinPsiProcessor() { ambiguousImportUsages += usage } else { - simpleUsages += usage + if (!renameUsageIfPossible(usage, element, newName)) { + simpleUsages += usage + } } } element.ambiguousImportUsages = ambiguousImportUsages diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinParameterProcessor.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinParameterProcessor.kt index 69f24550b5f..9dcfe817b15 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinParameterProcessor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinParameterProcessor.kt @@ -53,7 +53,7 @@ class RenameKotlinParameterProcessor : RenameKotlinPsiProcessor() { result += collisions } - override fun renameElement(element: PsiElement, newName: String, usages: Array, listener: RefactoringElementListener?) { + override fun renameElement(element: PsiElement, newName: String, usages: Array, listener: RefactoringElementListener?) { super.renameElement(element, newName, usages, listener) usages.forEach { (it as? KtResolvableCollisionUsageInfo)?.apply() } diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinPropertyProcessor.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinPropertyProcessor.kt index b30984cbeee..7d4d871568f 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinPropertyProcessor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinPropertyProcessor.kt @@ -36,6 +36,9 @@ import org.jetbrains.kotlin.asJava.* import org.jetbrains.kotlin.asJava.classes.KtLightClass import org.jetbrains.kotlin.asJava.elements.KtLightDeclaration import org.jetbrains.kotlin.asJava.elements.KtLightMethod +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.mangleInternalName import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor @@ -323,16 +326,21 @@ class RenameKotlinPropertyProcessor : RenameKotlinPsiProcessor() { } for (propertyMethod in propertyMethods) { - if (element is KtDeclaration && newPropertyName != null) { + val mangledPropertyName = if (propertyMethod is KtLightMethod && propertyMethod.isMangled) { + val suffix = getModuleNameSuffix(propertyMethod.name) + if (suffix != null && newPropertyName != null) mangleInternalName(newPropertyName, suffix) else null + } else null + val adjustedPropertyName = mangledPropertyName ?: newPropertyName + if (element is KtDeclaration && adjustedPropertyName != null) { val wrapper = PropertyMethodWrapper(propertyMethod) when { JvmAbi.isGetterName(propertyMethod.name) && getterJvmName == null -> - allRenames[wrapper] = JvmAbi.getterName(newPropertyName) + allRenames[wrapper] = JvmAbi.getterName(adjustedPropertyName) JvmAbi.isSetterName(propertyMethod.name) && setterJvmName == null -> - allRenames[wrapper] = JvmAbi.setterName(newPropertyName) + allRenames[wrapper] = JvmAbi.setterName(adjustedPropertyName) } } - addRenameElements(propertyMethod, (element as PsiNamedElement).name, newPropertyName, allRenames, scope) + addRenameElements(propertyMethod, (element as PsiNamedElement).name, adjustedPropertyName, allRenames, scope) } } @@ -389,7 +397,10 @@ class RenameKotlinPropertyProcessor : RenameKotlinPsiProcessor() { val refKindUsages = adjustedUsages.groupBy { usage: UsageInfo -> val refElement = usage.reference?.resolve() if (refElement is PsiMethod) { - when (refElement.name) { + val refElementName = refElement.name + val refElementNameToCheck = + (if (usage is MangledJavaRefUsageInfo) demangleInternalName(refElementName) else null) ?: refElementName + when (refElementNameToCheck) { oldGetterName -> UsageKind.GETTER_USAGE oldSetterName -> UsageKind.SETTER_USAGE else -> UsageKind.SIMPLE_PROPERTY_USAGE @@ -441,7 +452,9 @@ class RenameKotlinPropertyProcessor : RenameKotlinPsiProcessor() { } } else { - val newOverriderName = RefactoringUtil.suggestNewOverriderName(overriderName, oldName, newName) + val demangledName = if (newName != null && overrider is KtLightMethod && overrider.isMangled) demangleInternalName(newName) else null + val adjustedName = demangledName ?: newName + val newOverriderName = RefactoringUtil.suggestNewOverriderName(overriderName, oldName, adjustedName) if (newOverriderName != null) { allRenames[overriderElement] = newOverriderName } 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 1d7cd9d489d..58942c79534 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinPsiProcessor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinPsiProcessor.kt @@ -24,10 +24,15 @@ import com.intellij.psi.search.searches.ReferencesSearch import com.intellij.psi.util.PsiUtilCore import com.intellij.refactoring.listeners.RefactoringElementListener import com.intellij.refactoring.rename.RenamePsiElementProcessor +import com.intellij.refactoring.rename.RenameUtil +import com.intellij.refactoring.util.MoveRenameUsageInfo import com.intellij.usageView.UsageInfo +import org.jetbrains.kotlin.asJava.elements.KtLightMethod import org.jetbrains.kotlin.asJava.namedUnwrappedElement import org.jetbrains.kotlin.asJava.toLightMethods import org.jetbrains.kotlin.asJava.unwrapped +import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper +import org.jetbrains.kotlin.idea.references.KtReference import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchOptions import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchParameters import org.jetbrains.kotlin.idea.search.projectScope @@ -40,15 +45,43 @@ import org.jetbrains.kotlin.psi.psiUtil.isIdentifier 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 abstract class RenameKotlinPsiProcessor : RenamePsiElementProcessor() { + class MangledJavaRefUsageInfo( + val manglingSuffix: String, + element: PsiElement, + ref: PsiReference, + referenceElement: PsiElement + ) : MoveRenameUsageInfo( + referenceElement, + ref, + ref.getRangeInElement().getStartOffset(), + ref.getRangeInElement().getEndOffset(), + element, + false + ) + override fun canProcessElement(element: PsiElement): Boolean = element is KtNamedDeclaration override fun findReferences(element: PsiElement): Collection { val searchParameters = KotlinReferencesSearchParameters( - element, - element.project.projectScope(), - kotlinOptions = KotlinReferencesSearchOptions(searchForComponentConventions = false) + element, + element.project.projectScope(), + kotlinOptions = KotlinReferencesSearchOptions(searchForComponentConventions = false) ) val references = ReferencesSearch.search(searchParameters).toMutableList() if (element is KtNamedFunction @@ -59,6 +92,23 @@ abstract class RenameKotlinPsiProcessor : RenamePsiElementProcessor() { return references } + override fun createUsageInfo(element: PsiElement, ref: PsiReference, referenceElement: PsiElement): UsageInfo { + if (ref !is KtReference) { + val targetElement = ref.resolve() + if (targetElement is KtLightMethod && targetElement.isMangled) { + KotlinTypeMapper.InternalNameMapper.getModuleNameSuffix(targetElement.name)?.let { + return MangledJavaRefUsageInfo( + it, + element, + ref, + referenceElement + ) + } + } + } + return super.createUsageInfo(element, ref, referenceElement) + } + override fun getElementToSearchInStringsAndComments(element: PsiElement): PsiElement? { val unwrapped = element?.unwrapped ?: return null if ((unwrapped is KtDeclaration) && KtPsiUtil.isLocal(unwrapped as KtDeclaration)) return null @@ -101,12 +151,44 @@ 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) + } else { + val reference = usage.reference + if (reference is KtReference) { + chosenName = (if (element is KtLightMethod && element.isMangled) KotlinTypeMapper.InternalNameMapper.demangleInternalName(newName) else null) ?: newName + } + } + if (chosenName == null) return false + usage.reference?.handleElementRename(chosenName) + return true + } + + override fun renameElement( + element: PsiElement, + newName: String, + usages: Array, + listener: RefactoringElementListener? + ) { + val simpleUsages = ArrayList(usages.size) + for (usage in usages) { + if (renameUsageIfPossible(usage, element, newName)) continue + simpleUsages += usage + } + + RenameUtil.doRenameGenericNamedElement(element, newName, simpleUsages.toTypedArray(), listener) + } + override fun getPostRenameCallback(element: PsiElement, newName: String, elementListener: RefactoringElementListener): Runnable? { return Runnable { element.ambiguousImportUsages?.forEach { val ref = it.reference as? PsiPolyVariantReference ?: return@forEach if (ref.multiResolve(false).isEmpty()) { - ref.handleElementRename(newName) + if (!renameUsageIfPossible(it, element, newName)) { + ref.handleElementRename(newName) + } } else { ref.element?.getStrictParentOfType()?.let { importDirective -> 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 01b3444da62..e50bc41e25a 100644 --- a/idea/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinOverridingMethodReferenceSearcher.kt +++ b/idea/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinOverridingMethodReferenceSearcher.kt @@ -24,6 +24,7 @@ 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 @@ -31,8 +32,10 @@ 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 @@ -47,6 +50,26 @@ 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) diff --git a/idea/testData/refactoring/rename/internalFunWithOverrides/after/J.java b/idea/testData/refactoring/rename/internalFunWithOverrides/after/J.java new file mode 100644 index 00000000000..e068d64ee0e --- /dev/null +++ b/idea/testData/refactoring/rename/internalFunWithOverrides/after/J.java @@ -0,0 +1,6 @@ +class J extends X.Y { + @Override + public int newOverridableMethod$production_sources_for_module_light_idea_test_case(int x) { + return super.newOverridableMethod$production_sources_for_module_light_idea_test_case(x); + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/internalFunWithOverrides/after/test.kt b/idea/testData/refactoring/rename/internalFunWithOverrides/after/test.kt new file mode 100644 index 00000000000..5f91341fcaf --- /dev/null +++ b/idea/testData/refactoring/rename/internalFunWithOverrides/after/test.kt @@ -0,0 +1,21 @@ +sealed class X { + internal abstract fun newOverridableMethod(x: Int): Int + + abstract class Y : X() { + override fun newOverridableMethod(x: Int): Int = 1 + } + + class Z : Y() { + override fun newOverridableMethod(x: Int): Int = + if (x > 0) x + else super.newOverridableMethod(x) + } +} + +fun get() : X? { + return X.Z() +} + +fun test() { + get()?.newOverridableMethod(2) +} diff --git a/idea/testData/refactoring/rename/internalFunWithOverrides/before/J.java b/idea/testData/refactoring/rename/internalFunWithOverrides/before/J.java new file mode 100644 index 00000000000..8ef83c80828 --- /dev/null +++ b/idea/testData/refactoring/rename/internalFunWithOverrides/before/J.java @@ -0,0 +1,6 @@ +class J extends X.Y { + @Override + public int overridableMethod$production_sources_for_module_light_idea_test_case(int x) { + return super.overridableMethod$production_sources_for_module_light_idea_test_case(x); + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/internalFunWithOverrides/before/test.kt b/idea/testData/refactoring/rename/internalFunWithOverrides/before/test.kt new file mode 100644 index 00000000000..fb09850cce2 --- /dev/null +++ b/idea/testData/refactoring/rename/internalFunWithOverrides/before/test.kt @@ -0,0 +1,21 @@ +sealed class X { + internal abstract fun /*rename*/overridableMethod(x: Int): Int + + abstract class Y : X() { + override fun overridableMethod(x: Int): Int = 1 + } + + class Z : Y() { + override fun overridableMethod(x: Int): Int = + if (x > 0) x + else super.overridableMethod(x) + } +} + +fun get() : X? { + return X.Z() +} + +fun test() { + get()?.overridableMethod(2) +} diff --git a/idea/testData/refactoring/rename/internalFunWithOverrides/internalFunWithOverrides.test b/idea/testData/refactoring/rename/internalFunWithOverrides/internalFunWithOverrides.test new file mode 100644 index 00000000000..eaf15b1ef73 --- /dev/null +++ b/idea/testData/refactoring/rename/internalFunWithOverrides/internalFunWithOverrides.test @@ -0,0 +1,5 @@ +{ + "type": "MARKED_ELEMENT", + "mainFile": "test.kt", + "newName": "newOverridableMethod" +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/internalVarWithOverrides/after/J.java b/idea/testData/refactoring/rename/internalVarWithOverrides/after/J.java new file mode 100644 index 00000000000..2022758dd30 --- /dev/null +++ b/idea/testData/refactoring/rename/internalVarWithOverrides/after/J.java @@ -0,0 +1,11 @@ +class J extends X.Y { + @Override + public int getNewOverridableVar$production_sources_for_module_light_idea_test_case() { + return super.getNewOverridableVar$production_sources_for_module_light_idea_test_case(); + } + + @Override + public void setNewOverridableVar$production_sources_for_module_light_idea_test_case(int value) { + super.setNewOverridableVar$production_sources_for_module_light_idea_test_case(value); + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/internalVarWithOverrides/after/test.kt b/idea/testData/refactoring/rename/internalVarWithOverrides/after/test.kt new file mode 100644 index 00000000000..f5bd890a8c7 --- /dev/null +++ b/idea/testData/refactoring/rename/internalVarWithOverrides/after/test.kt @@ -0,0 +1,24 @@ +sealed class X { + internal abstract var newOverridableVar: Int + + abstract class Y : X() { + override var newOverridableVar: Int + get() = 1 + set(value) {} + } + + class Z : Y() { + override var newOverridableVar: Int + get() = super.newOverridableVar + set(value) { super.newOverridableVar = value } + } +} + +fun get() : X? { + return X.Z() +} + +fun test() { + get()?.newOverridableVar + get()?.newOverridableVar = 3 +} diff --git a/idea/testData/refactoring/rename/internalVarWithOverrides/before/J.java b/idea/testData/refactoring/rename/internalVarWithOverrides/before/J.java new file mode 100644 index 00000000000..eb75f56b21c --- /dev/null +++ b/idea/testData/refactoring/rename/internalVarWithOverrides/before/J.java @@ -0,0 +1,11 @@ +class J extends X.Y { + @Override + public int getOverridableVar$production_sources_for_module_light_idea_test_case() { + return super.getOverridableVar$production_sources_for_module_light_idea_test_case(); + } + + @Override + public void setOverridableVar$production_sources_for_module_light_idea_test_case(int value) { + super.setOverridableVar$production_sources_for_module_light_idea_test_case(value); + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/rename/internalVarWithOverrides/before/test.kt b/idea/testData/refactoring/rename/internalVarWithOverrides/before/test.kt new file mode 100644 index 00000000000..976cef711fd --- /dev/null +++ b/idea/testData/refactoring/rename/internalVarWithOverrides/before/test.kt @@ -0,0 +1,24 @@ +sealed class X { + internal abstract var /*rename*/overridableVar: Int + + abstract class Y : X() { + override var overridableVar: Int + get() = 1 + set(value) {} + } + + class Z : Y() { + override var overridableVar: Int + get() = super.overridableVar + set(value) { super.overridableVar = value } + } +} + +fun get() : X? { + return X.Z() +} + +fun test() { + get()?.overridableVar + get()?.overridableVar = 3 +} diff --git a/idea/testData/refactoring/rename/internalVarWithOverrides/internalFunWithOverrides.test b/idea/testData/refactoring/rename/internalVarWithOverrides/internalFunWithOverrides.test new file mode 100644 index 00000000000..0d430d00874 --- /dev/null +++ b/idea/testData/refactoring/rename/internalVarWithOverrides/internalFunWithOverrides.test @@ -0,0 +1,5 @@ +{ + "type": "MARKED_ELEMENT", + "mainFile": "test.kt", + "newName": "newOverridableVar" +} \ 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 d579d4aee4e..11c71643cc0 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/rename/RenameTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/rename/RenameTestGenerated.java @@ -214,6 +214,16 @@ public class RenameTestGenerated extends AbstractRenameTest { runTest("idea/testData/refactoring/rename/importAliasByRef/importAliasByRef.test"); } + @TestMetadata("internalFunWithOverrides/internalFunWithOverrides.test") + public void testInternalFunWithOverrides_InternalFunWithOverrides() throws Exception { + runTest("idea/testData/refactoring/rename/internalFunWithOverrides/internalFunWithOverrides.test"); + } + + @TestMetadata("internalVarWithOverrides/internalFunWithOverrides.test") + public void testInternalVarWithOverrides_InternalFunWithOverrides() throws Exception { + runTest("idea/testData/refactoring/rename/internalVarWithOverrides/internalFunWithOverrides.test"); + } + @TestMetadata("javaClassImportAliasByRef/javaClassImportAliasByRef.test") public void testJavaClassImportAliasByRef_JavaClassImportAliasByRef() throws Exception { runTest("idea/testData/refactoring/rename/javaClassImportAliasByRef/javaClassImportAliasByRef.test");