diff --git a/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/DeclaredHeaderMarker.kt b/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/DeclaredHeaderMarker.kt index 7348f79654d..02b2f5106c7 100644 --- a/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/DeclaredHeaderMarker.kt +++ b/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/DeclaredHeaderMarker.kt @@ -80,4 +80,4 @@ internal fun KtDeclaration.liftToHeader(): KtDeclaration? { hasModifier(KtTokens.IMPL_KEYWORD) -> headerDeclarationIfAny() else -> null } -} +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeSignatureData.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeSignatureData.kt index fad4f9432dc..d33010a1e6c 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeSignatureData.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinChangeSignatureData.kt @@ -28,12 +28,12 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde +import org.jetbrains.kotlin.idea.highlighter.markers.headerImplementations +import org.jetbrains.kotlin.idea.highlighter.markers.liftToHeader import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.KotlinCallableDefinitionUsage import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers -import org.jetbrains.kotlin.psi.KtCallableDeclaration -import org.jetbrains.kotlin.psi.KtClass -import org.jetbrains.kotlin.psi.KtFunction -import org.jetbrains.kotlin.psi.KtNamedDeclaration +import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.DescriptorUtils import java.util.* @@ -86,7 +86,9 @@ class KotlinChangeSignatureData( override val primaryCallables: Collection> by lazy { descriptorsForSignatureChange.map { - val declaration = DescriptorToSourceUtilsIde.getAnyDeclaration(baseDeclaration.project, it) + val declaration = DescriptorToSourceUtilsIde.getAnyDeclaration(baseDeclaration.project, it)?.let { + (it as? KtDeclaration)?.liftToHeader() ?: it + } assert(declaration != null) { "No declaration found for " + baseDescriptor } KotlinCallableDefinitionUsage(declaration!!, it, null, null) } @@ -98,9 +100,15 @@ class KotlinChangeSignatureData( override val affectedCallables: Collection by lazy { primaryCallables + primaryCallables.flatMapTo(HashSet()) { primaryFunction -> - val primaryDeclaration = primaryFunction.declaration as? KtCallableDeclaration - val lightMethods = primaryDeclaration?.toLightMethods() ?: Collections.emptyList() - lightMethods.flatMap { baseMethod -> + val primaryDeclaration = primaryFunction.declaration as? KtCallableDeclaration ?: return@flatMapTo emptyList() + + if (primaryDeclaration.hasModifier(KtTokens.HEADER_KEYWORD)) { + return@flatMapTo primaryDeclaration.headerImplementations().map { + KotlinCallableDefinitionUsage(it, it.resolveToDescriptor() as CallableDescriptor, primaryFunction, null) + } + } + + primaryDeclaration.toLightMethods().flatMap { baseMethod -> OverridingMethodsSearch .search(baseMethod) .mapNotNullTo(HashSet()) { overridingMethod -> 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 73a10810a04..b6b3c84568d 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinPsiProcessor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/rename/RenameKotlinPsiProcessor.kt @@ -31,12 +31,11 @@ import org.jetbrains.kotlin.asJava.namedUnwrappedElement import org.jetbrains.kotlin.asJava.toLightMethods import org.jetbrains.kotlin.idea.core.KotlinNameSuggester import org.jetbrains.kotlin.idea.core.quoteIfNeeded -import org.jetbrains.kotlin.idea.highlighter.markers.headerDeclarationIfAny import org.jetbrains.kotlin.idea.highlighter.markers.headerImplementations +import org.jetbrains.kotlin.idea.highlighter.markers.liftToHeader import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchOptions import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchParameters import org.jetbrains.kotlin.idea.search.projectScope -import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType @@ -72,11 +71,7 @@ abstract class RenameKotlinPsiProcessor : RenamePsiElementProcessor() { val declaration = element.namedUnwrappedElement as? KtNamedDeclaration if (declaration != null) { - when { - declaration.hasModifier(KtTokens.HEADER_KEYWORD) -> declaration - declaration.hasModifier(KtTokens.IMPL_KEYWORD) -> declaration.headerDeclarationIfAny() - else -> null - }?.let { headerDeclaration -> + declaration.liftToHeader()?.let { headerDeclaration -> allRenames[headerDeclaration] = safeNewName headerDeclaration.headerImplementations().forEach { allRenames[it] = safeNewName } } diff --git a/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/after/Common/Common.iml b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/after/Common/Common.iml new file mode 100644 index 00000000000..0ecf9949f6c --- /dev/null +++ b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/after/Common/Common.iml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/after/Common/src/test/test.kt b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/after/Common/src/test/test.kt new file mode 100644 index 00000000000..0cb659d2ac2 --- /dev/null +++ b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/after/Common/src/test/test.kt @@ -0,0 +1,11 @@ +package test + +header fun foo() +header fun baz(n: Int) +header fun bar(n: Int) + +fun test() { + foo() + baz(1) + bar(1) +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/after/JS/JS.iml b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/after/JS/JS.iml new file mode 100644 index 00000000000..82d3e6bdf49 --- /dev/null +++ b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/after/JS/JS.iml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/after/JS/src/test/test.kt b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/after/JS/src/test/test.kt new file mode 100644 index 00000000000..02bcd27d7cb --- /dev/null +++ b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/after/JS/src/test/test.kt @@ -0,0 +1,11 @@ +package test + +impl fun foo() { } +impl fun baz(n: Int) { } +impl fun bar(n: Int) { } + +fun test() { + foo() + baz(1) + bar(1) +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/after/JVM/JVM.iml b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/after/JVM/JVM.iml new file mode 100644 index 00000000000..c3173af9ec7 --- /dev/null +++ b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/after/JVM/JVM.iml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/after/JVM/src/test/test.kt b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/after/JVM/src/test/test.kt new file mode 100644 index 00000000000..02bcd27d7cb --- /dev/null +++ b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/after/JVM/src/test/test.kt @@ -0,0 +1,11 @@ +package test + +impl fun foo() { } +impl fun baz(n: Int) { } +impl fun bar(n: Int) { } + +fun test() { + foo() + baz(1) + bar(1) +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/before/Common/Common.iml b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/before/Common/Common.iml new file mode 100644 index 00000000000..0ecf9949f6c --- /dev/null +++ b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/before/Common/Common.iml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/before/Common/src/test/test.kt b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/before/Common/src/test/test.kt new file mode 100644 index 00000000000..532afd023ee --- /dev/null +++ b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/before/Common/src/test/test.kt @@ -0,0 +1,11 @@ +package test + +header fun foo() +header fun foo(n: Int) +header fun bar(n: Int) + +fun test() { + foo() + foo(1) + bar(1) +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/before/JS/JS.iml b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/before/JS/JS.iml new file mode 100644 index 00000000000..82d3e6bdf49 --- /dev/null +++ b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/before/JS/JS.iml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/before/JS/src/test/test.kt b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/before/JS/src/test/test.kt new file mode 100644 index 00000000000..f2b7f613043 --- /dev/null +++ b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/before/JS/src/test/test.kt @@ -0,0 +1,11 @@ +package test + +impl fun foo() { } +impl fun foo(n: Int) { } +impl fun bar(n: Int) { } + +fun test() { + foo() + foo(1) + bar(1) +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/before/JVM/JVM.iml b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/before/JVM/JVM.iml new file mode 100644 index 00000000000..c3173af9ec7 --- /dev/null +++ b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/before/JVM/JVM.iml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/before/JVM/src/test/test.kt b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/before/JVM/src/test/test.kt new file mode 100644 index 00000000000..f2b7f613043 --- /dev/null +++ b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByHeaderFun/before/JVM/src/test/test.kt @@ -0,0 +1,11 @@ +package test + +impl fun foo() { } +impl fun foo(n: Int) { } +impl fun bar(n: Int) { } + +fun test() { + foo() + foo(1) + bar(1) +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/after/Common/Common.iml b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/after/Common/Common.iml new file mode 100644 index 00000000000..0ecf9949f6c --- /dev/null +++ b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/after/Common/Common.iml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/after/Common/src/test/test.kt b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/after/Common/src/test/test.kt new file mode 100644 index 00000000000..0cb659d2ac2 --- /dev/null +++ b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/after/Common/src/test/test.kt @@ -0,0 +1,11 @@ +package test + +header fun foo() +header fun baz(n: Int) +header fun bar(n: Int) + +fun test() { + foo() + baz(1) + bar(1) +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/after/JS/JS.iml b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/after/JS/JS.iml new file mode 100644 index 00000000000..82d3e6bdf49 --- /dev/null +++ b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/after/JS/JS.iml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/after/JS/src/test/test.kt b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/after/JS/src/test/test.kt new file mode 100644 index 00000000000..02bcd27d7cb --- /dev/null +++ b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/after/JS/src/test/test.kt @@ -0,0 +1,11 @@ +package test + +impl fun foo() { } +impl fun baz(n: Int) { } +impl fun bar(n: Int) { } + +fun test() { + foo() + baz(1) + bar(1) +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/after/JVM/JVM.iml b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/after/JVM/JVM.iml new file mode 100644 index 00000000000..c3173af9ec7 --- /dev/null +++ b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/after/JVM/JVM.iml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/after/JVM/src/test/test.kt b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/after/JVM/src/test/test.kt new file mode 100644 index 00000000000..02bcd27d7cb --- /dev/null +++ b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/after/JVM/src/test/test.kt @@ -0,0 +1,11 @@ +package test + +impl fun foo() { } +impl fun baz(n: Int) { } +impl fun bar(n: Int) { } + +fun test() { + foo() + baz(1) + bar(1) +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/before/Common/Common.iml b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/before/Common/Common.iml new file mode 100644 index 00000000000..0ecf9949f6c --- /dev/null +++ b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/before/Common/Common.iml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/before/Common/src/test/test.kt b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/before/Common/src/test/test.kt new file mode 100644 index 00000000000..922453b2613 --- /dev/null +++ b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/before/Common/src/test/test.kt @@ -0,0 +1,11 @@ +package test + +header fun foo() +header fun foo(n: Int) +header fun bar(n: Int) + +fun test() { + foo() + foo(1) + bar(1) +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/before/JS/JS.iml b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/before/JS/JS.iml new file mode 100644 index 00000000000..82d3e6bdf49 --- /dev/null +++ b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/before/JS/JS.iml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/before/JS/src/test/test.kt b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/before/JS/src/test/test.kt new file mode 100644 index 00000000000..7a82ea2bb0c --- /dev/null +++ b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/before/JS/src/test/test.kt @@ -0,0 +1,11 @@ +package test + +impl fun foo() { } +impl fun foo(n: Int) { } +impl fun bar(n: Int) { } + +fun test() { + foo() + foo(1) + bar(1) +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/before/JVM/JVM.iml b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/before/JVM/JVM.iml new file mode 100644 index 00000000000..c3173af9ec7 --- /dev/null +++ b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/before/JVM/JVM.iml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/before/JVM/src/test/test.kt b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/before/JVM/src/test/test.kt new file mode 100644 index 00000000000..f2b7f613043 --- /dev/null +++ b/idea/testData/refactoring/changeSignatureMultiModule/headersAndImplsByImplFun/before/JVM/src/test/test.kt @@ -0,0 +1,11 @@ +package test + +impl fun foo() { } +impl fun foo(n: Int) { } +impl fun bar(n: Int) { } + +fun test() { + foo() + foo(1) + bar(1) +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinMultiModuleChangeSignatureTest.kt b/idea/tests/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinMultiModuleChangeSignatureTest.kt new file mode 100644 index 00000000000..ccd6e40bdc2 --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/changeSignature/KotlinMultiModuleChangeSignatureTest.kt @@ -0,0 +1,58 @@ +/* + * Copyright 2010-2017 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.changeSignature + +import com.intellij.psi.PsiDocumentManager +import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.refactoring.toPsiFile +import org.jetbrains.kotlin.idea.test.KotlinMultiFileTestCase +import org.jetbrains.kotlin.idea.test.PluginTestCaseBase +import org.jetbrains.kotlin.idea.test.extractMarkerOffset +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode + +class KotlinMultiModuleChangeSignatureTest : KotlinMultiFileTestCase() { + init { + isMultiModule = true + } + + override fun getTestRoot(): String = "/refactoring/changeSignatureMultiModule/" + + override fun getTestDataPath(): String = PluginTestCaseBase.getTestDataPathBase() + + private fun doTest(filePath: String, configure: KotlinChangeInfo.() -> Unit) { + doTestCommittingDocuments { rootDir, _ -> + val psiFile = rootDir.findFileByRelativePath(filePath)!!.toPsiFile(project)!! + val doc = PsiDocumentManager.getInstance(project).getDocument(psiFile)!! + val marker = doc.extractMarkerOffset(project) + assert(marker != -1) + val element = KotlinChangeSignatureHandler().findTargetMember(psiFile.findElementAt(marker)!!) as KtElement + val bindingContext = element.analyze(BodyResolveMode.FULL) + val callableDescriptor = KotlinChangeSignatureHandler.findDescriptor(element, project, editor, bindingContext)!! + val changeInfo = createChangeInfo(project, callableDescriptor, KotlinChangeSignatureConfiguration.Empty, element)!! + KotlinChangeSignatureProcessor(project, changeInfo.apply { configure() }, "Change signature").run() + } + } + + fun testHeadersAndImplsByHeaderFun() = doTest("Common/src/test/test.kt") { + newName = "baz" + } + + fun testHeadersAndImplsByImplFun() = doTest("JS/src/test/test.kt") { + newName = "baz" + } +}