diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index 47866545ecb..b470d601b60 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -307,6 +307,7 @@
+
diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/AutomaticOverloadsRenamer.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/AutomaticOverloadsRenamer.kt
new file mode 100644
index 00000000000..0abb3648761
--- /dev/null
+++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/AutomaticOverloadsRenamer.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2010-2015 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.module.ModuleUtilCore
+import com.intellij.openapi.roots.ProjectFileIndex
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiMethod
+import com.intellij.psi.search.GlobalSearchScope
+import com.intellij.refactoring.JavaRefactoringSettings
+import com.intellij.refactoring.RefactoringBundle
+import com.intellij.refactoring.rename.naming.AutomaticRenamer
+import com.intellij.refactoring.rename.naming.AutomaticRenamerFactory
+import com.intellij.usageView.UsageInfo
+import org.jetbrains.kotlin.idea.stubindex.JetTopLevelFunctionByPackageIndex
+import org.jetbrains.kotlin.idea.stubindex.JetTopLevelFunctionFqnNameIndex
+import org.jetbrains.kotlin.psi.JetFile
+import org.jetbrains.kotlin.psi.JetNamedFunction
+
+public class AutomaticOverloadsRenamer(function: JetNamedFunction, newName: String) : AutomaticRenamer() {
+ init {
+ val project = function.getProject()
+ val module = ProjectFileIndex.SERVICE.getInstance(project).getModuleForFile(function.getContainingFile().getVirtualFile())
+ if (module != null) {
+ val searchScope = GlobalSearchScope.moduleScope(module)
+ val overloads = JetTopLevelFunctionFqnNameIndex.getInstance().get(function.getFqName()!!.asString(), project, searchScope)
+ for (overload in overloads) {
+ if (overload != function) {
+ myElements.add(overload)
+ }
+ }
+ }
+ suggestAllNames(function.getName(), newName)
+ }
+
+ override fun getDialogTitle() = "Rename Overloads"
+ override fun getDialogDescription() = "Rename overloads to:"
+ override fun entityName() = "Overload"
+ override fun isSelectedByDefault(): Boolean = true
+}
+
+
+public class AutomaticOverloadsRenamerFactory : AutomaticRenamerFactory {
+ override fun isApplicable(element: PsiElement): Boolean {
+ return element is JetNamedFunction && element.getName() != null && element.getParent() is JetFile
+ }
+
+ override fun getOptionName() = RefactoringBundle.message("rename.overloads")
+ override fun isEnabled() = JavaRefactoringSettings.getInstance().isRenameOverloads()
+ override fun setEnabled(enabled: Boolean) = JavaRefactoringSettings.getInstance().setRenameOverloads(enabled)
+ override fun createRenamer(element: PsiElement, newName: String, usages: Collection)
+ = AutomaticOverloadsRenamer(element as JetNamedFunction, newName)
+}
\ No newline at end of file
diff --git a/idea/testData/refactoring/rename/automaticRenamerOverloads/after/package.kt b/idea/testData/refactoring/rename/automaticRenamerOverloads/after/package.kt
new file mode 100644
index 00000000000..2361ed25b9a
--- /dev/null
+++ b/idea/testData/refactoring/rename/automaticRenamerOverloads/after/package.kt
@@ -0,0 +1,16 @@
+package testing
+
+fun bar() {
+}
+
+fun bar(a: Int) {
+}
+
+fun String.bar() {
+}
+
+fun main(args: Array) {
+ bar()
+ bar(1)
+ "".bar()
+}
\ No newline at end of file
diff --git a/idea/testData/refactoring/rename/automaticRenamerOverloads/after/packageExtra.kt b/idea/testData/refactoring/rename/automaticRenamerOverloads/after/packageExtra.kt
new file mode 100644
index 00000000000..3c4c0557d34
--- /dev/null
+++ b/idea/testData/refactoring/rename/automaticRenamerOverloads/after/packageExtra.kt
@@ -0,0 +1,4 @@
+package testing
+
+fun bar(x: Int, y: Int) {
+}
diff --git a/idea/testData/refactoring/rename/automaticRenamerOverloads/before/package.kt b/idea/testData/refactoring/rename/automaticRenamerOverloads/before/package.kt
new file mode 100644
index 00000000000..7d5847cdae4
--- /dev/null
+++ b/idea/testData/refactoring/rename/automaticRenamerOverloads/before/package.kt
@@ -0,0 +1,16 @@
+package testing
+
+fun foo() {
+}
+
+fun foo(a: Int) {
+}
+
+fun String.foo() {
+}
+
+fun main(args: Array) {
+ foo()
+ foo(1)
+ "".foo()
+}
\ No newline at end of file
diff --git a/idea/testData/refactoring/rename/automaticRenamerOverloads/before/packageExtra.kt b/idea/testData/refactoring/rename/automaticRenamerOverloads/before/packageExtra.kt
new file mode 100644
index 00000000000..e9f673869f9
--- /dev/null
+++ b/idea/testData/refactoring/rename/automaticRenamerOverloads/before/packageExtra.kt
@@ -0,0 +1,4 @@
+package testing
+
+fun foo(x: Int, y: Int) {
+}
diff --git a/idea/testData/refactoring/rename/automaticRenamerOverloads/package.test b/idea/testData/refactoring/rename/automaticRenamerOverloads/package.test
new file mode 100644
index 00000000000..889d5c9d1cb
--- /dev/null
+++ b/idea/testData/refactoring/rename/automaticRenamerOverloads/package.test
@@ -0,0 +1,7 @@
+{
+ "type": "KOTLIN_FUNCTION",
+ "packageFqn": "testing",
+ "oldName": "foo",
+ "newName": "bar",
+ "mainFile": "package.kt"
+}
\ No newline at end of file
diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/rename/AbstractRenameTest.kt b/idea/tests/org/jetbrains/kotlin/idea/refactoring/rename/AbstractRenameTest.kt
index 995aa7ee85e..59be89555c9 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/rename/AbstractRenameTest.kt
+++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/rename/AbstractRenameTest.kt
@@ -45,10 +45,10 @@ import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
import org.jetbrains.kotlin.name.*
import org.jetbrains.kotlin.psi.JetFile
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
+import org.jetbrains.kotlin.resolve.scopes.JetScope
import org.jetbrains.kotlin.serialization.deserialization.findClassAcrossModuleDependencies
import org.junit.Assert
import java.io.File
-import java.util.Collections
private enum class RenameType {
JAVA_CLASS
@@ -137,23 +137,19 @@ public abstract class AbstractRenameTest : KotlinMultiFileTestCase() {
private fun renameKotlinFunctionTest(renameParamsObject: JsonObject, context: TestContext) {
val oldMethodName = Name.identifier(renameParamsObject.getString("oldName"))
- doRenameInKotlinClass(renameParamsObject, context) { classDescriptor ->
- val scope = classDescriptor.getMemberScope(Collections.emptyList())
- scope.getFunctions(oldMethodName).first()
- }
+ doRenameInKotlinClassOrPackage(renameParamsObject, context) { it.getFunctions(oldMethodName).first() }
}
private fun renameKotlinPropertyTest(renameParamsObject: JsonObject, context: TestContext) {
val oldPropertyName = Name.identifier(renameParamsObject.getString("oldName"))
- doRenameInKotlinClass(renameParamsObject, context) { classDescriptor ->
- val scope = classDescriptor.getMemberScope(Collections.emptyList())
- scope.getProperties(oldPropertyName).first()
- }
+ doRenameInKotlinClassOrPackage(renameParamsObject, context) { it.getProperties(oldPropertyName).first() }
}
private fun renameKotlinClassTest(renameParamsObject: JsonObject, context: TestContext) {
- doRenameInKotlinClass(renameParamsObject, context) { classDescriptor -> classDescriptor }
+ renameParamsObject.getString("classId") //assertion
+
+ doRenameInKotlinClassOrPackage(renameParamsObject, context) { scope -> scope.getContainingDeclaration() as ClassDescriptor }
}
private fun renameKotlinPackageTest(renameParamsObject: JsonObject, context: TestContext) {
@@ -179,10 +175,18 @@ public abstract class AbstractRenameTest : KotlinMultiFileTestCase() {
}
}
- private fun doRenameInKotlinClass(
- renameParamsObject: JsonObject, context: TestContext, findDescriptorToRename: (ClassDescriptor) -> DeclarationDescriptor
+ private fun doRenameInKotlinClassOrPackage(
+ renameParamsObject: JsonObject, context: TestContext, findDescriptorToRename: (JetScope) -> DeclarationDescriptor
) {
- val classId = renameParamsObject.getString("classId").toClassId()
+ val classIdStr = renameParamsObject.getNullableString("classId")
+ val packageFqnStr = renameParamsObject.getNullableString("packageFqn")
+ if (classIdStr != null && packageFqnStr != null) {
+ throw AssertionError("Both classId and packageFqn are defined. Where should I search: in class or in package?")
+ }
+ else if (classIdStr == null && packageFqnStr == null) {
+ throw AssertionError("Define classId or packageFqn")
+ }
+
val newName = renameParamsObject.getString("newName")
val mainFilePath = renameParamsObject.getNullableString("mainFile") ?: "${getTestDirName(false)}.kt"
@@ -192,9 +196,14 @@ public abstract class AbstractRenameTest : KotlinMultiFileTestCase() {
val jetFile = PsiDocumentManager.getInstance(context.project).getPsiFile(document) as JetFile
val module = jetFile.analyzeFullyAndGetResult().moduleDescriptor
- val classDescriptor = module.findClassAcrossModuleDependencies(classId)!!
- val psiElement = DescriptorToSourceUtils.descriptorToDeclaration(findDescriptorToRename(classDescriptor))!!
+ val scopeToSearch = if (classIdStr != null) {
+ module.findClassAcrossModuleDependencies(classIdStr.toClassId())!!.getDefaultType().getMemberScope()
+ } else {
+ module.getPackage(FqName(packageFqnStr!!))!!.getMemberScope()
+ }
+
+ val psiElement = DescriptorToSourceUtils.descriptorToDeclaration(findDescriptorToRename(scopeToSearch))!!
val substitution = RenamePsiElementProcessor.forElement(psiElement).substituteElementToRename(psiElement, null)
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 ffaf511cdfa..b9704e8c2f8 100644
--- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/rename/RenameTestGenerated.java
+++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/rename/RenameTestGenerated.java
@@ -47,6 +47,12 @@ public class RenameTestGenerated extends AbstractRenameTest {
doTest(fileName);
}
+ @TestMetadata("automaticRenamerOverloads/package.test")
+ public void testAutomaticRenamerOverloads_Package() throws Exception {
+ String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/rename/automaticRenamerOverloads/package.test");
+ doTest(fileName);
+ }
+
@TestMetadata("defaultObject/defaultObject.test")
public void testDefaultObject_DefaultObject() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/rename/defaultObject/defaultObject.test");