Extract Function: Show possible types for receiver in Extract Function/Introduce Lambda Parameter dialogs

#KT-7578 Fixed
This commit is contained in:
Alexey Sedunov
2015-05-22 14:15:07 +03:00
parent cb9b1019b2
commit 72205540d6
6 changed files with 78 additions and 14 deletions
@@ -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<KotlinParameterTablePanel.ParameterInfo> newParameterInfos
) {
Map<Parameter, Parameter> oldToNewParameters = ContainerUtil.newLinkedHashMap();
for (KotlinParameterTablePanel.ParameterInfo parameterInfo : newParameterInfos) {
oldToNewParameters.put(parameterInfo.getOriginalParameter(), parameterInfo.toParameter());
}
ArrayList<Parameter> 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<OutputValue> outputValues = new ArrayList<OutputValue>(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
@@ -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 ? "<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<Parameter> parameters) {
parameterInfos = KotlinPackage.map(
public void init(@Nullable Parameter receiver, @NotNull List<Parameter> parameters) {
parameterInfos = KotlinPackage.mapTo(
parameters,
receiver != null ? KotlinPackage.arrayListOf(new ParameterInfo(receiver, true)) : new ArrayList<ParameterInfo>(),
new Function1<Parameter, ParameterInfo>() {
@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<ParameterInfo, Boolean>() {
@Override
public Boolean invoke(ParameterInfo info) {
return info.isEnabled() && info.isReceiver();
}
}
);
}
@NotNull
public List<ParameterInfo> getParameterInfos() {
return KotlinPackage.filter(
parameterInfos,
new Function1<ParameterInfo, Boolean>() {
@Override
public Boolean invoke(ParameterInfo info) {
return info.isEnabled();
return info.isEnabled() && !info.isReceiver();
}
}
);
@@ -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(
@@ -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() {
<selection>toString()</selection>
}
@@ -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()
}
@@ -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");