From fecfc93e63fa36f4919aeb5e41338915f9ddfeed Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Thu, 22 Jan 2015 16:17:44 +0300 Subject: [PATCH] Change Signature: Support conversion between extension and non-extension functions (UI) --- .../JetCallableParameterTableModel.java | 70 ++++++++++++++ .../JetChangeSignatureDialog.java | 65 +++++++++---- .../JetConstructorParameterTableModel.java | 4 +- .../JetFunctionParameterTableModel.java | 96 +++++++++++-------- 4 files changed, 179 insertions(+), 56 deletions(-) create mode 100644 idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetCallableParameterTableModel.java diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetCallableParameterTableModel.java b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetCallableParameterTableModel.java new file mode 100644 index 00000000000..3e58f251d79 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetCallableParameterTableModel.java @@ -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> { + 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 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(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; + } +} diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeSignatureDialog.java b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeSignatureDialog.java index 3d1c587e898..75b6797f267 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeSignatureDialog.java +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeSignatureDialog.java @@ -74,7 +74,7 @@ public class JetChangeSignatureDialog extends ChangeSignatureDialogBase< Visibility, JetMethodDescriptor, ParameterTableModelItemBase, - 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 item) { + JetParameterInfo parameter = item.parameter; + if (parameter == null) return null; + if (parameter == myParametersTableModel.getReceiver()) return ""; + return parameter.getName(); + } + private int getColumnTextMaxLength(Function, String> nameFunction) { int len = 0; for (ParameterTableModelItemBase item : myParametersTableModel.getItems()) { @@ -178,7 +185,7 @@ public class JetChangeSignatureDialog extends ChangeSignatureDialogBase< return getColumnTextMaxLength(new Function, String>() { @Override public String fun(ParameterTableModelItemBase 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 item) { return new JBTableRowEditor() { private final List components = new ArrayList(); - 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 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 ); } diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetConstructorParameterTableModel.java b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetConstructorParameterTableModel.java index 9863b7d5f40..bd770fe6d4c 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetConstructorParameterTableModel.java +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetConstructorParameterTableModel.java @@ -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(), diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetFunctionParameterTableModel.java b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetFunctionParameterTableModel.java index 91ce91099f9..c00eea6c495 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetFunctionParameterTableModel.java +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetFunctionParameterTableModel.java @@ -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> { - 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>(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>(context.getProject(), + JetFileType.INSTANCE), + new ReceiverColumn(context.getProject(), methodDescriptor)); } @Override - protected ParameterTableModelItemBase 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> + extends ColumnInfoBase { + 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(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); + } } }