diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractFunction/ui/KotlinExtractFunctionDialog.java b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractFunction/ui/KotlinExtractFunctionDialog.java index 01870cc63e0..0223100f434 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractFunction/ui/KotlinExtractFunctionDialog.java +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractFunction/ui/KotlinExtractFunctionDialog.java @@ -28,6 +28,7 @@ import kotlin.Unit; import kotlin.jvm.functions.Function0; import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.idea.JetFileType; import org.jetbrains.kotlin.idea.core.refactoring.JetNameSuggester; import org.jetbrains.kotlin.idea.core.refactoring.RefactoringPackage; @@ -120,8 +121,10 @@ public class KotlinExtractFunctionDialog extends DialogWrapper { protected void init() { super.init(); + ExtractableCodeDescriptor extractableCodeDescriptor = originalDescriptor.getDescriptor(); + functionNameField = new NameSuggestionsField( - ArrayUtil.toStringArray(originalDescriptor.getDescriptor().getSuggestedNames()), + ArrayUtil.toStringArray(extractableCodeDescriptor.getSuggestedNames()), project, JetFileType.INSTANCE ); @@ -139,7 +142,7 @@ public class KotlinExtractFunctionDialog extends DialogWrapper { boolean enableVisibility = isVisibilitySectionAvailable(); visibilityBox.setEnabled(enableVisibility); if (enableVisibility) { - visibilityBox.setSelectedItem(originalDescriptor.getDescriptor().getVisibility()); + visibilityBox.setSelectedItem(extractableCodeDescriptor.getVisibility()); } visibilityBox.addItemListener( new ItemListener() { @@ -166,7 +169,7 @@ public class KotlinExtractFunctionDialog extends DialogWrapper { doCancelAction(); } }; - parameterTablePanel.init(originalDescriptor.getDescriptor().getParameters()); + parameterTablePanel.init(extractableCodeDescriptor.getReceiverParameter(), extractableCodeDescriptor.getParameters()); inputParametersPanel.setText("&Parameters"); inputParametersPanel.setLabelFor(parameterTablePanel.getTable()); @@ -213,6 +216,7 @@ public class KotlinExtractFunctionDialog extends DialogWrapper { return createNewDescriptor(originalDescriptor.getDescriptor(), getFunctionName(), getVisibility(), + parameterTablePanel.getReceiverInfo(), parameterTablePanel.getParameterInfos()); } @@ -225,12 +229,20 @@ public class KotlinExtractFunctionDialog extends DialogWrapper { @NotNull ExtractableCodeDescriptor originalDescriptor, @NotNull String newName, @NotNull String newVisibility, + @Nullable KotlinParameterTablePanel.ParameterInfo newReceiverInfo, @NotNull List newParameterInfos ) { Map oldToNewParameters = ContainerUtil.newLinkedHashMap(); for (KotlinParameterTablePanel.ParameterInfo parameterInfo : newParameterInfos) { oldToNewParameters.put(parameterInfo.getOriginalParameter(), parameterInfo.toParameter()); } + ArrayList newParameters = ContainerUtil.newArrayList(oldToNewParameters.values()); + + Parameter originalReceiver = originalDescriptor.getReceiverParameter(); + Parameter newReceiver = newReceiverInfo != null ? newReceiverInfo.toParameter() : null; + if (originalReceiver != null && newReceiver != null) { + oldToNewParameters.put(originalReceiver, newReceiver); + } ControlFlow controlFlow = originalDescriptor.getControlFlow(); List outputValues = new ArrayList(controlFlow.getOutputValues()); @@ -267,8 +279,8 @@ public class KotlinExtractFunctionDialog extends DialogWrapper { originalDescriptor.getOriginalContext(), Collections.singletonList(newName), newVisibility, - ContainerUtil.newArrayList(oldToNewParameters.values()), - originalDescriptor.getReceiverParameter(), + newParameters, + newReceiver, originalDescriptor.getTypeParameters(), replacementMap, controlFlow diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractFunction/ui/KotlinParameterTablePanel.java b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractFunction/ui/KotlinParameterTablePanel.java index b806c451751..cb5295bfa7e 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractFunction/ui/KotlinParameterTablePanel.java +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/extractFunction/ui/KotlinParameterTablePanel.java @@ -43,18 +43,21 @@ import javax.swing.table.TableColumn; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; +import java.util.ArrayList; import java.util.List; public class KotlinParameterTablePanel extends JPanel { public static class ParameterInfo { private final Parameter originalParameter; + private final boolean receiver; private String name; private JetType type; private boolean enabled = true; - public ParameterInfo(Parameter originalParameter) { + public ParameterInfo(Parameter originalParameter, boolean receiver) { this.originalParameter = originalParameter; - this.name = originalParameter.getName(); + this.receiver = receiver; + this.name = receiver ? "" : originalParameter.getName(); this.type = originalParameter.getParameterType(false); } @@ -62,6 +65,10 @@ public class KotlinParameterTablePanel extends JPanel { return originalParameter; } + public boolean isReceiver() { + return receiver; + } + public boolean isEnabled() { return enabled; } @@ -100,13 +107,14 @@ public class KotlinParameterTablePanel extends JPanel { super(new BorderLayout()); } - public void init(List parameters) { - parameterInfos = KotlinPackage.map( + public void init(@Nullable Parameter receiver, @NotNull List parameters) { + parameterInfos = KotlinPackage.mapTo( parameters, + receiver != null ? KotlinPackage.arrayListOf(new ParameterInfo(receiver, true)) : new ArrayList(), new Function1() { @Override public ParameterInfo invoke(Parameter parameter) { - return new ParameterInfo(parameter); + return new ParameterInfo(parameter, false); } } ); @@ -358,7 +366,7 @@ public class KotlinParameterTablePanel extends JPanel { case CHECKMARK_COLUMN: return isEnabled(); case PARAMETER_NAME_COLUMN: - return isEnabled() && info.isEnabled(); + return isEnabled() && info.isEnabled() && !info.isReceiver(); case PARAMETER_TYPE_COLUMN: return isEnabled() && info.isEnabled() && info.getOriginalParameter().getParameterTypeCandidates(false).size() > 1; default: @@ -376,13 +384,27 @@ public class KotlinParameterTablePanel extends JPanel { } } + @Nullable + public ParameterInfo getReceiverInfo() { + return KotlinPackage.singleOrNull( + parameterInfos, + new Function1() { + @Override + public Boolean invoke(ParameterInfo info) { + return info.isEnabled() && info.isReceiver(); + } + } + ); + } + + @NotNull public List getParameterInfos() { return KotlinPackage.filter( parameterInfos, new Function1() { @Override public Boolean invoke(ParameterInfo info) { - return info.isEnabled(); + return info.isEnabled() && !info.isReceiver(); } } ); diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceParameter/KotlinIntroduceParameterDialog.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceParameter/KotlinIntroduceParameterDialog.kt index fd7f0f183ac..14d0c94a461 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceParameter/KotlinIntroduceParameterDialog.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceParameter/KotlinIntroduceParameterDialog.kt @@ -150,7 +150,8 @@ public class KotlinIntroduceParameterDialog private ( gbConstraints.fill = GridBagConstraints.BOTH panel.add(typeField, gbConstraints) - if (lambdaExtractionDescriptor != null && lambdaExtractionDescriptor.parameters.isNotEmpty()) { + if (lambdaExtractionDescriptor != null + && (lambdaExtractionDescriptor.parameters.isNotEmpty() || lambdaExtractionDescriptor.receiverParameter != null)) { val parameterTablePanel = object : KotlinParameterTablePanel() { override fun onEnterAction() { doOKAction() @@ -160,7 +161,7 @@ public class KotlinIntroduceParameterDialog private ( doCancelAction() } } - parameterTablePanel.init(lambdaExtractionDescriptor!!.parameters) + parameterTablePanel.init(lambdaExtractionDescriptor!!.receiverParameter, lambdaExtractionDescriptor.parameters) gbConstraints.insets = Insets(4, 4, 4, 8) gbConstraints.gridwidth = 1 @@ -273,6 +274,7 @@ public class KotlinIntroduceParameterDialog private ( oldDescriptor, chosenName, "", + parameterTablePanel?.getReceiverInfo(), parameterTablePanel?.getParameterInfos() ?: listOf() ) val options = ExtractionGeneratorOptions.DEFAULT.copy( diff --git a/idea/testData/refactoring/extractFunction/parameters/candidateTypes/receiverCandidateTypes.kt b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/receiverCandidateTypes.kt new file mode 100644 index 00000000000..858338234d7 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/receiverCandidateTypes.kt @@ -0,0 +1,9 @@ +// PARAM_DESCRIPTOR: internal fun Bar.foo(): kotlin.Unit defined in root package +// PARAM_TYPES: Bar, Foo, kotlin.Any + +open class Foo +class Bar : Foo() + +fun Bar.foo() { + toString() +} \ No newline at end of file diff --git a/idea/testData/refactoring/extractFunction/parameters/candidateTypes/receiverCandidateTypes.kt.after b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/receiverCandidateTypes.kt.after new file mode 100644 index 00000000000..88bf1101481 --- /dev/null +++ b/idea/testData/refactoring/extractFunction/parameters/candidateTypes/receiverCandidateTypes.kt.after @@ -0,0 +1,13 @@ +// PARAM_DESCRIPTOR: internal fun Bar.foo(): kotlin.Unit defined in root package +// PARAM_TYPES: Bar, Foo, kotlin.Any + +open class Foo +class Bar : Foo() + +fun Bar.foo() { + __dummyTestFun__() +} + +private fun Bar.__dummyTestFun__() { + toString() +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/JetExtractionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/JetExtractionTestGenerated.java index 23147634fdb..a5d6c7c3188 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/JetExtractionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/JetExtractionTestGenerated.java @@ -1571,6 +1571,12 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest { doExtractFunctionTest(fileName); } + @TestMetadata("receiverCandidateTypes.kt") + public void testReceiverCandidateTypes() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/extractFunction/parameters/candidateTypes/receiverCandidateTypes.kt"); + doExtractFunctionTest(fileName); + } + @TestMetadata("typeHierarchy1.kt") public void testTypeHierarchy1() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/extractFunction/parameters/candidateTypes/typeHierarchy1.kt");