Change Signature: Support conversion between extension and non-extension functions (UI)

This commit is contained in:
Alexey Sedunov
2015-01-22 16:17:44 +03:00
parent 96866a108f
commit fecfc93e63
4 changed files with 179 additions and 56 deletions
@@ -0,0 +1,70 @@
/*
* 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.changeSignature;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiCodeFragment;
import com.intellij.psi.PsiElement;
import com.intellij.refactoring.changeSignature.ParameterTableModelBase;
import com.intellij.refactoring.changeSignature.ParameterTableModelItemBase;
import com.intellij.util.ui.ColumnInfo;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.psi.JetPsiFactory;
import static org.jetbrains.kotlin.psi.PsiPackage.JetPsiFactory;
public abstract class JetCallableParameterTableModel extends ParameterTableModelBase<JetParameterInfo, ParameterTableModelItemBase<JetParameterInfo>> {
private final Project project;
protected JetCallableParameterTableModel(PsiElement context, ColumnInfo... columnInfos) {
super(context, context, columnInfos);
project = context.getProject();
}
@Nullable
public JetParameterInfo getReceiver() {
return null;
}
@Override
protected ParameterTableModelItemBase<JetParameterInfo> createRowItem(@Nullable JetParameterInfo parameterInfo) {
if (parameterInfo == null) {
parameterInfo = new JetParameterInfo(-1, "", null, null, "", null, null);
}
JetPsiFactory psiFactory = JetPsiFactory(project);
PsiCodeFragment paramTypeCodeFragment = psiFactory.createTypeCodeFragment(parameterInfo.getTypeText(), myTypeContext);
PsiCodeFragment defaultValueCodeFragment = psiFactory.createExpressionCodeFragment(parameterInfo.getDefaultValueForCall(), myDefaultValueContext);
return new ParameterTableModelItemBase<JetParameterInfo>(parameterInfo, paramTypeCodeFragment, defaultValueCodeFragment) {
@Override
public boolean isEllipsisType() {
return false;
}
};
}
public static boolean isTypeColumn(ColumnInfo column) {
return column instanceof TypeColumn;
}
public static boolean isNameColumn(ColumnInfo column) {
return column instanceof NameColumn;
}
public static boolean isDefaultValueColumn(ColumnInfo column) {
return column instanceof DefaultValueColumn;
}
}
@@ -74,7 +74,7 @@ public class JetChangeSignatureDialog extends ChangeSignatureDialogBase<
Visibility,
JetMethodDescriptor,
ParameterTableModelItemBase<JetParameterInfo>,
JetFunctionParameterTableModel
JetCallableParameterTableModel
>
{
private final String commandName;
@@ -90,11 +90,11 @@ public class JetChangeSignatureDialog extends ChangeSignatureDialogBase<
}
@Override
protected JetFunctionParameterTableModel createParametersInfoModel(JetMethodDescriptor descriptor) {
protected JetCallableParameterTableModel createParametersInfoModel(JetMethodDescriptor descriptor) {
if (ChangeSignaturePackage.getIsConstructor(descriptor))
return new JetConstructorParameterTableModel(myDefaultValueContext);
else
return new JetFunctionParameterTableModel(myDefaultValueContext);
return new JetFunctionParameterTableModel(descriptor, myDefaultValueContext);
}
@Override
@@ -132,7 +132,7 @@ public class JetChangeSignatureDialog extends ChangeSignatureDialogBase<
}
}
String parameterName = item.parameter.getName();
String parameterName = getPresentationName(item);
String typeText = item.typeCodeFragment.getText();
String defaultValue = item.defaultValueCodeFragment.getText();
String separator = StringUtil.repeatSymbol(' ', getParamNamesMaxLength() - parameterName.length() + 1);
@@ -165,6 +165,13 @@ public class JetChangeSignatureDialog extends ChangeSignatureDialogBase<
return panel;
}
private String getPresentationName(ParameterTableModelItemBase<JetParameterInfo> item) {
JetParameterInfo parameter = item.parameter;
if (parameter == null) return null;
if (parameter == myParametersTableModel.getReceiver()) return "<receiver>";
return parameter.getName();
}
private int getColumnTextMaxLength(Function<ParameterTableModelItemBase<JetParameterInfo>, String> nameFunction) {
int len = 0;
for (ParameterTableModelItemBase<JetParameterInfo> item : myParametersTableModel.getItems()) {
@@ -178,7 +185,7 @@ public class JetChangeSignatureDialog extends ChangeSignatureDialogBase<
return getColumnTextMaxLength(new Function<ParameterTableModelItemBase<JetParameterInfo>, String>() {
@Override
public String fun(ParameterTableModelItemBase<JetParameterInfo> item) {
return item.parameter == null ? null : item.parameter.getName();
return getPresentationName(item);
}
});
}
@@ -223,7 +230,15 @@ public class JetChangeSignatureDialog extends ChangeSignatureDialogBase<
protected JBTableRowEditor getTableEditor(final JTable t, final ParameterTableModelItemBase<JetParameterInfo> item) {
return new JBTableRowEditor() {
private final List<JComponent> components = new ArrayList<JComponent>();
private final boolean defaultValueColumnEnabled = item.parameter.getIsNewParameter();
private final EditorTextField nameEditor = new EditorTextField(item.parameter.getName(), getProject(), getFileType());;
private void updateNameEditor() {
nameEditor.setEnabled(item.parameter != myParametersTableModel.getReceiver());
}
private boolean isDefaultColumnEnabled() {
return item.parameter.getIsNewParameter() && item.parameter != myMethod.getReceiver();
}
@Override
public void prepareEditor(JTable table, final int row) {
@@ -236,13 +251,15 @@ public class JetChangeSignatureDialog extends ChangeSignatureDialogBase<
JComponent component;
final int columnFinal = column;
if (JetFunctionParameterTableModel.isTypeColumn(columnInfo)) {
if (JetCallableParameterTableModel.isTypeColumn(columnInfo)) {
Document document = PsiDocumentManager.getInstance(getProject()).getDocument(item.typeCodeFragment);
component = editor = new EditorTextField(document, getProject(), getFileType());
}
else if (JetFunctionParameterTableModel.isNameColumn(columnInfo))
component = editor = new EditorTextField((String)columnInfo.valueOf(item), getProject(), getFileType());
else if (JetFunctionParameterTableModel.isDefaultValueColumn(columnInfo) && defaultValueColumnEnabled) {
else if (JetCallableParameterTableModel.isNameColumn(columnInfo)) {
component = editor = nameEditor;
updateNameEditor();
}
else if (JetCallableParameterTableModel.isDefaultValueColumn(columnInfo) && isDefaultColumnEnabled()) {
Document document = PsiDocumentManager.getInstance(getProject()).getDocument(item.defaultValueCodeFragment);
component = editor = new EditorTextField(document, getProject(), getFileType());
}
@@ -258,6 +275,21 @@ public class JetChangeSignatureDialog extends ChangeSignatureDialogBase<
});
component = comboBox;
}
else if (JetFunctionParameterTableModel.isReceiverColumn(columnInfo)) {
JCheckBox checkBox = new JCheckBox();
checkBox.setSelected(myParametersTableModel.getReceiver() == item.parameter);
checkBox.addItemListener(
new ItemListener() {
@Override
public void itemStateChanged(@NotNull ItemEvent e) {
((JetFunctionParameterTableModel)myParametersTableModel).setReceiver(item.parameter);
updateSignature();
updateNameEditor();
}
}
);
component = checkBox;
}
else
continue;
@@ -291,11 +323,11 @@ public class JetChangeSignatureDialog extends ChangeSignatureDialogBase<
if (JetConstructorParameterTableModel.isValVarColumn(columnInfo))
return ((JComboBox) components.get(column)).getSelectedItem();
else if (JetFunctionParameterTableModel.isTypeColumn(columnInfo))
else if (JetCallableParameterTableModel.isTypeColumn(columnInfo))
return item.typeCodeFragment;
else if (JetFunctionParameterTableModel.isNameColumn(columnInfo))
else if (JetCallableParameterTableModel.isNameColumn(columnInfo))
return ((EditorTextField) components.get(column)).getText();
else if (JetFunctionParameterTableModel.isDefaultValueColumn(columnInfo))
else if (JetCallableParameterTableModel.isDefaultValueColumn(columnInfo))
return item.defaultValueCodeFragment;
else
return null;
@@ -310,7 +342,7 @@ public class JetChangeSignatureDialog extends ChangeSignatureDialogBase<
}
private int getEditorIndex(int x) {
int[] columnLetters = defaultValueColumnEnabled ?
int[] columnLetters = isDefaultColumnEnabled() ?
new int[] { 4, getParamNamesMaxLength(), getTypesMaxLength(), getDefaultValuesMaxLength() } :
new int[] { 4, getParamNamesMaxLength(), getTypesMaxLength() };
int columnIndex = 0;
@@ -391,7 +423,8 @@ public class JetChangeSignatureDialog extends ChangeSignatureDialogBase<
for (ParameterTableModelItemBase<JetParameterInfo> item : parameterInfos) {
String parameterName = item.parameter.getName();
if (!JavaPsiFacade.getInstance(myProject).getNameHelper().isIdentifier(parameterName))
if (item.parameter != myParametersTableModel.getReceiver()
&& !JavaPsiFacade.getInstance(myProject).getNameHelper().isIdentifier(parameterName))
throw new ConfigurationException(JetRefactoringBundle.message("parameter.name.is.invalid", parameterName));
if (getType((JetTypeCodeFragment) item.typeCodeFragment) == null)
throw new ConfigurationException(JetRefactoringBundle.message("parameter.type.is.invalid", item.typeCodeFragment.getText()));
@@ -420,7 +453,7 @@ public class JetChangeSignatureDialog extends ChangeSignatureDialogBase<
String returnTypeText = myReturnTypeCodeFragment != null ? myReturnTypeCodeFragment.getText().trim() : "";
return new JetChangeInfo(myMethod, getMethodName(), getReturnType(), returnTypeText,
getVisibility(), parameters, null, myDefaultValueContext
getVisibility(), parameters, myParametersTableModel.getReceiver(), myDefaultValueContext
);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
* Copyright 2010-2013 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.
@@ -28,7 +28,7 @@ import javax.swing.*;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
public class JetConstructorParameterTableModel extends JetFunctionParameterTableModel {
public class JetConstructorParameterTableModel extends JetCallableParameterTableModel {
public JetConstructorParameterTableModel(PsiElement context) {
super(context,
new ValVarColumn(),
@@ -17,57 +17,77 @@
package org.jetbrains.kotlin.idea.refactoring.changeSignature;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiCodeFragment;
import com.intellij.psi.PsiElement;
import com.intellij.refactoring.changeSignature.ParameterTableModelBase;
import com.intellij.refactoring.changeSignature.ParameterTableModelItemBase;
import com.intellij.refactoring.ui.StringTableCellEditor;
import com.intellij.ui.BooleanTableCellRenderer;
import com.intellij.util.ui.ColumnInfo;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.idea.JetFileType;
import org.jetbrains.kotlin.psi.JetPsiFactory;
import static org.jetbrains.kotlin.psi.PsiPackage.JetPsiFactory;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
public class JetFunctionParameterTableModel extends ParameterTableModelBase<JetParameterInfo, ParameterTableModelItemBase<JetParameterInfo>> {
private final Project project;
protected JetFunctionParameterTableModel(PsiElement context, ColumnInfo... columnInfos) {
super(context, context, columnInfos);
project = context.getProject();
}
public JetFunctionParameterTableModel(PsiElement context) {
this(context,
new NameColumn(context.getProject()),
new TypeColumn(context.getProject(), JetFileType.INSTANCE),
new DefaultValueColumn<JetParameterInfo, ParameterTableModelItemBase<JetParameterInfo>>(context.getProject(), JetFileType.INSTANCE));
public class JetFunctionParameterTableModel extends JetCallableParameterTableModel {
public JetFunctionParameterTableModel(JetMethodDescriptor methodDescriptor, PsiElement context) {
super(context,
new NameColumn(context.getProject()),
new TypeColumn(context.getProject(), JetFileType.INSTANCE),
new DefaultValueColumn<JetParameterInfo, ParameterTableModelItemBase<JetParameterInfo>>(context.getProject(),
JetFileType.INSTANCE),
new ReceiverColumn(context.getProject(), methodDescriptor));
}
@Override
protected ParameterTableModelItemBase<JetParameterInfo> createRowItem(@Nullable JetParameterInfo parameterInfo) {
if (parameterInfo == null) {
parameterInfo = new JetParameterInfo(-1, "", null, null, "", null, null);
@Nullable
public JetParameterInfo getReceiver() {
return ((ReceiverColumn)getColumnInfos()[getColumnCount() - 1]).receiver;
}
public void setReceiver(@Nullable JetParameterInfo receiver) {
((ReceiverColumn)getColumnInfos()[getColumnCount() - 1]).receiver = receiver;
}
public static boolean isReceiverColumn(ColumnInfo column) {
return column instanceof ReceiverColumn;
}
protected static class ReceiverColumn<TableItem extends ParameterTableModelItemBase<JetParameterInfo>>
extends ColumnInfoBase<JetParameterInfo, TableItem, Boolean> {
private final Project project;
@Nullable
private JetParameterInfo receiver;
public ReceiverColumn(Project project, @Nullable JetMethodDescriptor methodDescriptor) {
super("Receiver:");
this.project = project;
this.receiver = methodDescriptor != null ? methodDescriptor.getReceiver() : null;
}
JetPsiFactory psiFactory = JetPsiFactory(project);
PsiCodeFragment paramTypeCodeFragment = psiFactory.createTypeCodeFragment(parameterInfo.getTypeText(), myTypeContext);
PsiCodeFragment defaultValueCodeFragment = psiFactory.createExpressionCodeFragment(parameterInfo.getDefaultValueForCall(), myDefaultValueContext);
return new ParameterTableModelItemBase<JetParameterInfo>(parameterInfo, paramTypeCodeFragment, defaultValueCodeFragment) {
@Override
public boolean isEllipsisType() {
return false;
}
};
}
public static boolean isTypeColumn(ColumnInfo column) {
return column instanceof TypeColumn;
}
@Override
public Boolean valueOf(TableItem item) {
return item.parameter == receiver;
}
public static boolean isNameColumn(ColumnInfo column) {
return column instanceof NameColumn;
}
@Override
public void setValue(TableItem item, Boolean value) {
if (value == null) return;
receiver = value ? item.parameter : null;
}
public static boolean isDefaultValueColumn(ColumnInfo column) {
return column instanceof DefaultValueColumn;
@Override
public boolean isCellEditable(TableItem pParameterTableModelItemBase) {
return true;
}
@Override
public TableCellRenderer doCreateRenderer(TableItem item) {
return new BooleanTableCellRenderer();
}
@Override
public TableCellEditor doCreateEditor(TableItem o) {
return new StringTableCellEditor(project);
}
}
}