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 61d18657747..2e797e1e24a 100644 --- a/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/DeclaredHeaderMarker.kt +++ b/idea/src/org/jetbrains/kotlin/idea/highlighter/markers/DeclaredHeaderMarker.kt @@ -68,7 +68,7 @@ internal fun KtDeclaration.headerDeclarationIfAny(): KtDeclaration? { internal fun KtDeclaration.isHeaderOrHeaderClassMember() = hasModifier(KtTokens.HEADER_KEYWORD) || (containingClassOrObject?.hasModifier(KtTokens.HEADER_KEYWORD) ?: false) -private fun DeclarationDescriptor.liftToHeader(): DeclarationDescriptor? { +internal fun DeclarationDescriptor.liftToHeader(): DeclarationDescriptor? { if (this is MemberDescriptor) { return when { isHeader -> this diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertParameterToReceiverIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertParameterToReceiverIntention.kt index 7bb69f1db4c..29c714c4f99 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertParameterToReceiverIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertParameterToReceiverIntention.kt @@ -19,15 +19,14 @@ package org.jetbrains.kotlin.idea.intentions import com.intellij.openapi.editor.Editor import com.intellij.psi.PsiElement import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.refactoring.changeSignature.KotlinChangeSignatureConfiguration import org.jetbrains.kotlin.idea.refactoring.changeSignature.KotlinMethodDescriptor import org.jetbrains.kotlin.idea.refactoring.changeSignature.modify import org.jetbrains.kotlin.idea.refactoring.changeSignature.runChangeSignature +import org.jetbrains.kotlin.idea.refactoring.resolveToHeaderDescriptorIfPossible import org.jetbrains.kotlin.psi.KtNamedFunction import org.jetbrains.kotlin.psi.KtParameter import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType -import org.jetbrains.kotlin.resolve.BindingContext class ConvertParameterToReceiverIntention : SelfTargetingIntention(KtParameter::class.java, "Convert parameter to receiver") { override fun isApplicableTo(element: KtParameter, caretOffset: Int): Boolean { @@ -53,8 +52,7 @@ class ConvertParameterToReceiverIntention : SelfTargetingIntention( override fun applyTo(element: KtParameter, editor: Editor?) { val function = element.getStrictParentOfType() ?: return val parameterIndex = function.valueParameters.indexOf(element) - val context = function.analyze() - val descriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, function] as? FunctionDescriptor ?: return + val descriptor = function.resolveToHeaderDescriptorIfPossible() as? FunctionDescriptor ?: return runChangeSignature(element.project, descriptor, configureChangeSignature(parameterIndex), element, text) } } diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertReceiverToParameterIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertReceiverToParameterIntention.kt index 1e47e5c2fd7..ca5262c8ab4 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertReceiverToParameterIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/ConvertReceiverToParameterIntention.kt @@ -26,9 +26,9 @@ import com.intellij.openapi.editor.Editor import com.intellij.psi.PsiDocumentManager import com.intellij.psi.PsiElement import org.jetbrains.kotlin.descriptors.FunctionDescriptor -import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor import org.jetbrains.kotlin.idea.core.getOrCreateValueParameterList import org.jetbrains.kotlin.idea.refactoring.changeSignature.* +import org.jetbrains.kotlin.idea.refactoring.resolveToHeaderDescriptorIfPossible import org.jetbrains.kotlin.idea.util.application.executeWriteCommand import org.jetbrains.kotlin.idea.util.application.runWriteAction import org.jetbrains.kotlin.psi.KtNamedFunction @@ -61,7 +61,7 @@ class ConvertReceiverToParameterIntention : SelfTargetingOffsetIndependentIntent override fun applyTo(element: KtTypeReference, editor: Editor?) { val function = element.parent as? KtNamedFunction ?: return - val descriptor = function.resolveToDescriptor() as FunctionDescriptor + val descriptor = function.resolveToHeaderDescriptorIfPossible() as FunctionDescriptor val project = function.project @@ -102,7 +102,7 @@ class ConvertReceiverToParameterIntention : SelfTargetingOffsetIndependentIntent if (!brokenOff) { runChangeSignature( element.project, - function.resolveToDescriptor() as FunctionDescriptor, + function.resolveToHeaderDescriptorIfPossible() as FunctionDescriptor, configureChangeSignature(newName), function.receiverTypeReference!!, text diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/kotlinRefactoringUtil.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/kotlinRefactoringUtil.kt index 6e0f0e8cfeb..e844e081bc2 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/kotlinRefactoringUtil.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/kotlinRefactoringUtil.kt @@ -970,4 +970,9 @@ internal fun KtDeclaration.withHeaderImplementations(): List { val header = liftToHeader() ?: return listOf(this) val implementations = header.headerImplementations() ?: emptySet() return listOf(header) + implementations +} + +internal fun KtDeclaration.resolveToHeaderDescriptorIfPossible(): DeclarationDescriptor { + val descriptor = resolveToDescriptor() + return descriptor.liftToHeader() ?: descriptor } \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByHeader/header/header.kt b/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByHeader/header/header.kt new file mode 100644 index 00000000000..551339bfc3d --- /dev/null +++ b/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByHeader/header/header.kt @@ -0,0 +1,9 @@ +// "Convert parameter to receiver" "true" + +header class Foo { + fun foo(n: Int, s: String) +} + +fun Foo.test() { + foo(1, "2") +} \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByHeader/header/header.kt.after b/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByHeader/header/header.kt.after new file mode 100644 index 00000000000..0f1663ee8f5 --- /dev/null +++ b/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByHeader/header/header.kt.after @@ -0,0 +1,9 @@ +// "Convert parameter to receiver" "true" + +header class Foo { + fun String.foo(n: Int) +} + +fun Foo.test() { + "2".foo(1) +} \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByHeader/js/js.kt b/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByHeader/js/js.kt new file mode 100644 index 00000000000..ff202ccc8e3 --- /dev/null +++ b/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByHeader/js/js.kt @@ -0,0 +1,9 @@ +impl class Foo { + impl fun foo(n: Int, s: String) { + + } +} + +fun Foo.test() { + foo(1, "2") +} \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByHeader/js/js.kt.after b/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByHeader/js/js.kt.after new file mode 100644 index 00000000000..8f105199635 --- /dev/null +++ b/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByHeader/js/js.kt.after @@ -0,0 +1,9 @@ +impl class Foo { + impl fun String.foo(n: Int) { + + } +} + +fun Foo.test() { + "2".foo(1) +} \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByHeader/jvm/jvm.kt b/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByHeader/jvm/jvm.kt new file mode 100644 index 00000000000..ff202ccc8e3 --- /dev/null +++ b/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByHeader/jvm/jvm.kt @@ -0,0 +1,9 @@ +impl class Foo { + impl fun foo(n: Int, s: String) { + + } +} + +fun Foo.test() { + foo(1, "2") +} \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByHeader/jvm/jvm.kt.after b/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByHeader/jvm/jvm.kt.after new file mode 100644 index 00000000000..8f105199635 --- /dev/null +++ b/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByHeader/jvm/jvm.kt.after @@ -0,0 +1,9 @@ +impl class Foo { + impl fun String.foo(n: Int) { + + } +} + +fun Foo.test() { + "2".foo(1) +} \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByImpl/header/header.kt b/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByImpl/header/header.kt new file mode 100644 index 00000000000..31f3189a7e2 --- /dev/null +++ b/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByImpl/header/header.kt @@ -0,0 +1,7 @@ +header class Foo { + fun foo(n: Int, s: String) +} + +fun Foo.test() { + foo(1, "2") +} \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByImpl/header/header.kt.after b/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByImpl/header/header.kt.after new file mode 100644 index 00000000000..35793393242 --- /dev/null +++ b/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByImpl/header/header.kt.after @@ -0,0 +1,7 @@ +header class Foo { + fun String.foo(n: Int) +} + +fun Foo.test() { + "2".foo(1) +} \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByImpl/js/js.kt b/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByImpl/js/js.kt new file mode 100644 index 00000000000..5c58a5506d8 --- /dev/null +++ b/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByImpl/js/js.kt @@ -0,0 +1,11 @@ +// "Convert parameter to receiver" "true" + +impl class Foo { + impl fun foo(n: Int, s: String) { + + } +} + +fun Foo.test() { + foo(1, "2") +} \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByImpl/js/js.kt.after b/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByImpl/js/js.kt.after new file mode 100644 index 00000000000..863897a494f --- /dev/null +++ b/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByImpl/js/js.kt.after @@ -0,0 +1,11 @@ +// "Convert parameter to receiver" "true" + +impl class Foo { + impl fun String.foo(n: Int) { + + } +} + +fun Foo.test() { + "2".foo(1) +} \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByImpl/jvm/jvm.kt b/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByImpl/jvm/jvm.kt new file mode 100644 index 00000000000..ff202ccc8e3 --- /dev/null +++ b/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByImpl/jvm/jvm.kt @@ -0,0 +1,9 @@ +impl class Foo { + impl fun foo(n: Int, s: String) { + + } +} + +fun Foo.test() { + foo(1, "2") +} \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByImpl/jvm/jvm.kt.after b/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByImpl/jvm/jvm.kt.after new file mode 100644 index 00000000000..8f105199635 --- /dev/null +++ b/idea/testData/multiModuleQuickFix/memberFunParameterToReceiverByImpl/jvm/jvm.kt.after @@ -0,0 +1,9 @@ +impl class Foo { + impl fun String.foo(n: Int) { + + } +} + +fun Foo.test() { + "2".foo(1) +} \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByHeader/header/header.kt b/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByHeader/header/header.kt new file mode 100644 index 00000000000..1faacbbc2b9 --- /dev/null +++ b/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByHeader/header/header.kt @@ -0,0 +1,9 @@ +// "Convert receiver to parameter" "true" + +header class Foo { + fun String.foo(n: Int) +} + +fun Foo.test() { + "1".foo(2) +} \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByHeader/header/header.kt.after b/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByHeader/header/header.kt.after new file mode 100644 index 00000000000..92381d3bd51 --- /dev/null +++ b/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByHeader/header/header.kt.after @@ -0,0 +1,9 @@ +// "Convert receiver to parameter" "true" + +header class Foo { + fun foo(s: String, n: Int) +} + +fun Foo.test() { + foo("1", 2) +} \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByHeader/js/js.kt b/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByHeader/js/js.kt new file mode 100644 index 00000000000..e8d9c8ef812 --- /dev/null +++ b/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByHeader/js/js.kt @@ -0,0 +1,9 @@ +impl class Foo { + impl fun String.foo(n: Int) { + + } +} + +fun Foo.test() { + "1".foo(2) +} \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByHeader/js/js.kt.after b/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByHeader/js/js.kt.after new file mode 100644 index 00000000000..2ee10e93455 --- /dev/null +++ b/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByHeader/js/js.kt.after @@ -0,0 +1,9 @@ +impl class Foo { + impl fun foo(s: String, n: Int) { + + } +} + +fun Foo.test() { + foo("1", 2) +} \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByHeader/jvm/jvm.kt b/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByHeader/jvm/jvm.kt new file mode 100644 index 00000000000..e8d9c8ef812 --- /dev/null +++ b/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByHeader/jvm/jvm.kt @@ -0,0 +1,9 @@ +impl class Foo { + impl fun String.foo(n: Int) { + + } +} + +fun Foo.test() { + "1".foo(2) +} \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByHeader/jvm/jvm.kt.after b/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByHeader/jvm/jvm.kt.after new file mode 100644 index 00000000000..2ee10e93455 --- /dev/null +++ b/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByHeader/jvm/jvm.kt.after @@ -0,0 +1,9 @@ +impl class Foo { + impl fun foo(s: String, n: Int) { + + } +} + +fun Foo.test() { + foo("1", 2) +} \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByImpl/header/header.kt b/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByImpl/header/header.kt new file mode 100644 index 00000000000..607c3e385cf --- /dev/null +++ b/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByImpl/header/header.kt @@ -0,0 +1,7 @@ +header class Foo { + fun String.foo(n: Int) +} + +fun Foo.test() { + "1".foo(2) +} \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByImpl/header/header.kt.after b/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByImpl/header/header.kt.after new file mode 100644 index 00000000000..f0246e39cb8 --- /dev/null +++ b/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByImpl/header/header.kt.after @@ -0,0 +1,7 @@ +header class Foo { + fun foo(s: String, n: Int) +} + +fun Foo.test() { + foo("1", 2) +} \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByImpl/js/js.kt b/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByImpl/js/js.kt new file mode 100644 index 00000000000..e20bc5ed03e --- /dev/null +++ b/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByImpl/js/js.kt @@ -0,0 +1,11 @@ +// "Convert receiver to parameter" "true" + +impl class Foo { + impl fun String.foo(n: Int) { + + } +} + +fun Foo.test() { + "1".foo(2) +} \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByImpl/js/js.kt.after b/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByImpl/js/js.kt.after new file mode 100644 index 00000000000..68c97c89a98 --- /dev/null +++ b/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByImpl/js/js.kt.after @@ -0,0 +1,11 @@ +// "Convert receiver to parameter" "true" + +impl class Foo { + impl fun foo(s: String, n: Int) { + + } +} + +fun Foo.test() { + foo("1", 2) +} \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByImpl/jvm/jvm.kt b/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByImpl/jvm/jvm.kt new file mode 100644 index 00000000000..e8d9c8ef812 --- /dev/null +++ b/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByImpl/jvm/jvm.kt @@ -0,0 +1,9 @@ +impl class Foo { + impl fun String.foo(n: Int) { + + } +} + +fun Foo.test() { + "1".foo(2) +} \ No newline at end of file diff --git a/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByImpl/jvm/jvm.kt.after b/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByImpl/jvm/jvm.kt.after new file mode 100644 index 00000000000..2ee10e93455 --- /dev/null +++ b/idea/testData/multiModuleQuickFix/memberFunReceiverToParameterByImpl/jvm/jvm.kt.after @@ -0,0 +1,9 @@ +impl class Foo { + impl fun foo(s: String, n: Int) { + + } +} + +fun Foo.test() { + foo("1", 2) +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiModuleTest.kt b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiModuleTest.kt index 11977aa94f9..93186790190 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiModuleTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiModuleTest.kt @@ -129,4 +129,16 @@ class QuickFixMultiModuleTest : AbstractQuickFixMultiModuleTest() { @Test fun testAddOperatorByImpl() = doTestHeaderWithJvmAndJs() + + @Test + fun testMemberFunReceiverToParameterByHeader() = doTestHeaderWithJvmAndJs() + + @Test + fun testMemberFunReceiverToParameterByImpl() = doTestHeaderWithJvmAndJs() + + @Test + fun testMemberFunParameterToReceiverByHeader() = doTestHeaderWithJvmAndJs() + + @Test + fun testMemberFunParameterToReceiverByImpl() = doTestHeaderWithJvmAndJs() } \ No newline at end of file