diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/move/moveMembers/MoveMembersProcessor.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/move/moveMembers/MoveMembersProcessor.java index 70cc72711..5632344c6 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/move/moveMembers/MoveMembersProcessor.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/move/moveMembers/MoveMembersProcessor.java @@ -82,8 +82,8 @@ public MoveMembersProcessor(Project project, @Nullable MoveCallback moveCallback @Nonnull @Override - protected String getCommandName() { - return myCommandName.get(); + protected LocalizeValue getCommandName() { + return myCommandName; } private void setOptions(MoveMembersOptions dialog) { diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/rename/ClassHidesUnqualifiableClassUsageInfo.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/rename/ClassHidesUnqualifiableClassUsageInfo.java index 5768a1e82..eaf26dd56 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/rename/ClassHidesUnqualifiableClassUsageInfo.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/rename/ClassHidesUnqualifiableClassUsageInfo.java @@ -22,23 +22,27 @@ import consulo.language.editor.refactoring.rename.UnresolvableCollisionUsageInfo; import consulo.language.editor.refactoring.ui.RefactoringUIUtil; import consulo.language.psi.PsiElement; +import consulo.localize.LocalizeValue; +import jakarta.annotation.Nonnull; /** * @author dsl */ public class ClassHidesUnqualifiableClassUsageInfo extends UnresolvableCollisionUsageInfo { - private final PsiClass myHiddenClass; + private final PsiClass myHiddenClass; - public ClassHidesUnqualifiableClassUsageInfo(PsiJavaCodeReferenceElement element, PsiClass renamedClass, PsiClass hiddenClass) { - super(element, renamedClass); - myHiddenClass = hiddenClass; - } + public ClassHidesUnqualifiableClassUsageInfo(PsiJavaCodeReferenceElement element, PsiClass renamedClass, PsiClass hiddenClass) { + super(element, renamedClass); + myHiddenClass = hiddenClass; + } - public String getDescription() { - PsiElement container = ConflictsUtil.getContainer(myHiddenClass); - return RefactoringLocalize.renamedClassWillHide0In1( - RefactoringUIUtil.getDescription(myHiddenClass, false), - RefactoringUIUtil.getDescription(container, false) - ).get(); - } + @Nonnull + @Override + public LocalizeValue getDescription() { + PsiElement container = ConflictsUtil.getContainer(myHiddenClass); + return RefactoringLocalize.renamedClassWillHide0In1( + RefactoringUIUtil.getDescription(myHiddenClass, false), + RefactoringUIUtil.getDescription(container, false) + ); + } } diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/rename/DirectoryAsPackageRenameHandler.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/rename/DirectoryAsPackageRenameHandler.java index 4be7056f7..9d999c796 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/rename/DirectoryAsPackageRenameHandler.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/rename/DirectoryAsPackageRenameHandler.java @@ -19,63 +19,70 @@ import com.intellij.java.language.psi.JavaDirectoryService; import com.intellij.java.language.psi.PsiJavaPackage; import com.intellij.java.language.psi.PsiNameHelper; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; import consulo.language.editor.refactoring.BaseRefactoringProcessor; import consulo.language.editor.refactoring.localize.RefactoringLocalize; import consulo.language.editor.refactoring.rename.DirectoryAsPackageRenameHandlerBase; import consulo.language.psi.PsiDirectory; +import consulo.localize.LocalizeValue; import consulo.project.Project; import consulo.util.lang.StringUtil; import consulo.virtualFileSystem.VirtualFile; +import jakarta.annotation.Nonnull; /** * @author yole */ @ExtensionImpl public class DirectoryAsPackageRenameHandler extends DirectoryAsPackageRenameHandlerBase { + @Override + protected VirtualFile[] occursInPackagePrefixes(PsiJavaPackage aPackage) { + return aPackage.occursInPackagePrefixes(); + } - @Override - protected VirtualFile[] occursInPackagePrefixes(PsiJavaPackage aPackage) { - return aPackage.occursInPackagePrefixes(); - } + @Override + protected boolean isIdentifier(String name, Project project) { + return PsiNameHelper.getInstance(project).isIdentifier(name); + } - @Override - protected boolean isIdentifier(String name, Project project) { - return PsiNameHelper.getInstance(project).isIdentifier(name); - } + @Override + protected String getQualifiedName(PsiJavaPackage aPackage) { + return aPackage.getQualifiedName(); + } - @Override - protected String getQualifiedName(PsiJavaPackage aPackage) { - return aPackage.getQualifiedName(); - } + @Override + protected PsiJavaPackage getPackage(PsiDirectory psiDirectory) { + return JavaDirectoryService.getInstance().getPackage(psiDirectory); + } - @Override - protected PsiJavaPackage getPackage(PsiDirectory psiDirectory) { - return JavaDirectoryService.getInstance().getPackage(psiDirectory); - } + @Override + @RequiredReadAction + protected BaseRefactoringProcessor createProcessor( + final String newQName, + Project project, + final PsiDirectory[] dirsToRename, + boolean searchInComments, + boolean searchInNonJavaFiles + ) { + return new MoveDirectoryWithClassesProcessor(project, dirsToRename, null, searchInComments, searchInNonJavaFiles, false, null) { + @Override + public TargetDirectoryWrapper getTargetDirectory(PsiDirectory dir) { + return new TargetDirectoryWrapper(dir.getParentDirectory(), StringUtil.getShortName(newQName)); + } - @Override - protected BaseRefactoringProcessor createProcessor(final String newQName, - Project project, - final PsiDirectory[] dirsToRename, - boolean searchInComments, boolean searchInNonJavaFiles) { - return new MoveDirectoryWithClassesProcessor(project, dirsToRename, null, searchInComments, searchInNonJavaFiles, false, null) { - @Override - public TargetDirectoryWrapper getTargetDirectory(PsiDirectory dir) { - return new TargetDirectoryWrapper(dir.getParentDirectory(), StringUtil.getShortName(newQName)); - } + @Override + protected String getTargetName() { + return newQName; + } - @Override - protected String getTargetName() { - return newQName; - } - - @Override - protected String getCommandName() { - return dirsToRename.length == 1 - ? RefactoringLocalize.renameDirectoryCommandName().get() - : RefactoringLocalize.renameDirectoriesCommandName().get(); - } - }; - } + @Nonnull + @Override + protected LocalizeValue getCommandName() { + return dirsToRename.length == 1 + ? RefactoringLocalize.renameDirectoryCommandName() + : RefactoringLocalize.renameDirectoriesCommandName(); + } + }; + } } diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/rename/LocalHidesRenamedLocalUsageInfo.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/rename/LocalHidesRenamedLocalUsageInfo.java index e79323765..3347d3536 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/rename/LocalHidesRenamedLocalUsageInfo.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/rename/LocalHidesRenamedLocalUsageInfo.java @@ -13,38 +13,36 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -/* - * Created by IntelliJ IDEA. - * User: dsl - * Date: 05.06.2002 - * Time: 13:38:29 - * To change template for new class use - * Code Style | Class Templates options (Tools | IDE Options). - */ package com.intellij.java.impl.refactoring.rename; +import consulo.annotation.access.RequiredReadAction; import consulo.language.editor.refactoring.localize.RefactoringLocalize; import consulo.language.editor.refactoring.rename.UnresolvableCollisionUsageInfo; import consulo.language.editor.refactoring.ui.RefactoringUIUtil; -import consulo.language.editor.refactoring.util.CommonRefactoringUtil; import consulo.language.psi.PsiElement; import consulo.localize.LocalizeValue; import consulo.usage.UsageViewUtil; +import jakarta.annotation.Nonnull; +/* + * @author dsl + * @since 2002-06-05 + */ public class LocalHidesRenamedLocalUsageInfo extends UnresolvableCollisionUsageInfo { - private final PsiElement myConflictingElement; + private final PsiElement myConflictingElement; - public LocalHidesRenamedLocalUsageInfo(PsiElement element, PsiElement conflictingElement) { - super(element, null); - myConflictingElement = conflictingElement; - } + public LocalHidesRenamedLocalUsageInfo(PsiElement element, PsiElement conflictingElement) { + super(element, null); + myConflictingElement = conflictingElement; + } - public String getDescription() { - PsiElement element = getElement(); - String type = element == null ? "element" : UsageViewUtil.getType(element); - String elemDescr = RefactoringUIUtil.getDescription(myConflictingElement, true); - LocalizeValue descr = RefactoringLocalize.thereIsAlreadyA0ItWillConflictWithTheRenamed1(elemDescr, type); - return CommonRefactoringUtil.capitalize(descr.get()); - } + @Nonnull + @Override + @RequiredReadAction + public LocalizeValue getDescription() { + PsiElement element = getElement(); + String type = element == null ? "element" : UsageViewUtil.getType(element); + String elemDescr = RefactoringUIUtil.getDescription(myConflictingElement, true); + return RefactoringLocalize.thereIsAlreadyA0ItWillConflictWithTheRenamed1(elemDescr, type); + } } diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/rename/RenameJavaClassProcessor.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/rename/RenameJavaClassProcessor.java index b1c3f77af..1f84424c5 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/rename/RenameJavaClassProcessor.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/rename/RenameJavaClassProcessor.java @@ -196,10 +196,13 @@ public void findCollisions( for (PsiTypeParameter typeParameter : owner.getTypeParameters()) { if (Comparing.equal(newName, typeParameter.getName())) { result.add(new UnresolvableCollisionUsageInfo(typeParam, typeParameter) { + @Nonnull @Override - public String getDescription() { - return "There is already type parameter in " + - RefactoringUIUtil.getDescription(typeParam, false) + " with name " + newName; + public LocalizeValue getDescription() { + return LocalizeValue.localizeTODO( + "There is already type parameter in " + + RefactoringUIUtil.getDescription(typeParam, false) + " with name " + newName + ); } }); } @@ -231,7 +234,7 @@ else if (aClass instanceof PsiTypeParameter typeParam) { if (typeParam.getOwner() instanceof PsiClass ownerClass) { for (PsiClass superClass : ownerClass.getSupers()) { if (newName.equals(superClass.getName())) { - ClassCollisionsDetector classCollisionsDetector = new ClassCollisionsDetector(aClass); + ClassCollisionsDetector classCollisionsDetector = new ClassCollisionsDetector(typeParam); for (PsiReference reference : ReferencesSearch.search(superClass, new LocalSearchScope(superClass))) { classCollisionsDetector.addClassCollisions(reference.getElement(), newName, result); } @@ -244,7 +247,7 @@ else if (aClass instanceof PsiTypeParameter typeParam) { if (refElement instanceof PsiReferenceExpression refExpr && refExpr.isQualified()) { return true; } - MemberHidesOuterMemberUsageInfo info = new MemberHidesOuterMemberUsageInfo(refElement, aClass); + MemberHidesOuterMemberUsageInfo info = new MemberHidesOuterMemberUsageInfo(refElement, typeParam); result.add(info); return true; }); diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/rename/RenameJavaMethodProcessor.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/rename/RenameJavaMethodProcessor.java index 1cf4a38bc..c3ba40a76 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/rename/RenameJavaMethodProcessor.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/rename/RenameJavaMethodProcessor.java @@ -94,13 +94,7 @@ else if (usage instanceof MemberHidesOuterMemberUsageInfo) { outerHides.add(new MemberHidesOuterMemberUsageInfo(element, resolved)); } else if (!(element instanceof PsiMethod)) { - PsiReference ref; - if (usage instanceof MoveRenameUsageInfo) { - ref = usage.getReference(); - } - else { - ref = element.getReference(); - } + PsiReference ref = usage instanceof MoveRenameUsageInfo ? usage.getReference() : element.getReference(); if (ref instanceof PsiImportStaticReferenceElement importStaticRef && importStaticRef.multiResolve(false).length > 1) { continue; } @@ -202,10 +196,13 @@ public void findCollisions( final PsiMethod methodInBaseClass = containingClass.findMethodBySignature(patternMethod, true); if (methodInBaseClass != null && methodInBaseClass.getContainingClass() != containingClass && methodInBaseClass.isFinal()) { result.add(new UnresolvableCollisionUsageInfo(methodInBaseClass, methodToRename) { + @Nonnull @Override - public String getDescription() { - return "Renaming method will override final " + - "\"" + RefactoringUIUtil.getDescription(methodInBaseClass, true) + "\""; + public LocalizeValue getDescription() { + return LocalizeValue.localizeTODO( + "Renaming method will override final " + + "\"" + RefactoringUIUtil.getDescription(methodInBaseClass, true) + "\"" + ); } }); } @@ -240,10 +237,13 @@ private void findHidingMethodWithOtherSignature(final PsiMethod methodToRename, final PsiMember resolveResultElement = (PsiMember) resolveResult.getElement(); if (resolveResult.isValidResult() && resolveResultElement != null) { result.add(new UnresolvableCollisionUsageInfo(refExpr, methodToRename) { + @Nonnull @Override - public String getDescription() { - return "Method call would be linked to " + - "\"" + RefactoringUIUtil.getDescription(resolveResultElement, true) + "\" after rename"; + public LocalizeValue getDescription() { + return LocalizeValue.localizeTODO( + "Method call would be linked to " + + "\"" + RefactoringUIUtil.getDescription(resolveResultElement, true) + "\" after rename" + ); } }); break; diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/rename/SubmemberHidesMemberUsageInfo.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/rename/SubmemberHidesMemberUsageInfo.java index 504c4a7c3..eb83d1d95 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/rename/SubmemberHidesMemberUsageInfo.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/rename/SubmemberHidesMemberUsageInfo.java @@ -13,42 +13,35 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -/* - * Created by IntelliJ IDEA. - * User: dsl - * Date: 05.06.2002 - * Time: 12:43:27 - * To change template for new class use - * Code Style | Class Templates options (Tools | IDE Options). - */ package com.intellij.java.impl.refactoring.rename; import com.intellij.java.language.psi.PsiMethod; +import consulo.annotation.access.RequiredReadAction; import consulo.language.editor.refactoring.localize.RefactoringLocalize; import consulo.language.editor.refactoring.rename.UnresolvableCollisionUsageInfo; import consulo.language.editor.refactoring.ui.RefactoringUIUtil; -import consulo.language.editor.refactoring.util.CommonRefactoringUtil; import consulo.language.psi.PsiElement; import consulo.localize.LocalizeValue; import consulo.usage.UsageViewUtil; +import jakarta.annotation.Nonnull; +/** + * @author dsl + * @since 2002-06-05 + */ public class SubmemberHidesMemberUsageInfo extends UnresolvableCollisionUsageInfo { - public SubmemberHidesMemberUsageInfo(PsiElement element, PsiElement referencedElement) { - super(element, referencedElement); - } + public SubmemberHidesMemberUsageInfo(PsiElement element, PsiElement referencedElement) { + super(element, referencedElement); + } - public String getDescription() { - PsiElement element = getElement(); - LocalizeValue descr = element instanceof PsiMethod - ? RefactoringLocalize.zeroWillOverrideRenamed1( - RefactoringUIUtil.getDescription(element, true), - UsageViewUtil.getType(element) - ) - : RefactoringLocalize.zeroWillHideRenamed1( - RefactoringUIUtil.getDescription(element, true), - UsageViewUtil.getType(element) - ); - return CommonRefactoringUtil.capitalize(descr.get()); - } + @Nonnull + @Override + @RequiredReadAction + public LocalizeValue getDescription() { + PsiElement element = getElement(); + LocalizeValue descr = element instanceof PsiMethod method + ? RefactoringLocalize.zeroWillOverrideRenamed1(RefactoringUIUtil.getDescription(element, true), UsageViewUtil.getType(element)) + : RefactoringLocalize.zeroWillHideRenamed1(RefactoringUIUtil.getDescription(element, true), UsageViewUtil.getType(element)); + return descr.capitalize(); + } } diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderDialog.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderDialog.java index 8cf5d8dbf..878d1c198 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderDialog.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderDialog.java @@ -37,6 +37,7 @@ import consulo.logging.Logger; import consulo.platform.base.icon.PlatformIconGroup; import consulo.project.Project; +import consulo.ui.annotation.RequiredUIAccess; import consulo.ui.ex.awt.*; import consulo.ui.ex.awt.event.DocumentAdapter; import consulo.ui.ex.awt.util.TableUtil; @@ -48,306 +49,333 @@ import javax.swing.table.AbstractTableModel; import javax.swing.table.TableColumnModel; import java.awt.*; -import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyEvent; import java.util.ArrayList; import java.util.LinkedHashMap; +import java.util.Map; public class ReplaceConstructorWithBuilderDialog extends RefactoringDialog { - private final PsiMethod[] myConstructors; - - private JRadioButton myCreateBuilderClassRadioButton; - private JRadioButton myExistingBuilderClassRadioButton; - - private JPanel myWholePanel; - private JTextField myNewClassName; - private ReferenceEditorComboWithBrowseButton myPackageTextField; - private ReferenceEditorComboWithBrowseButton myExistentClassTF; - private ComboboxWithBrowseButton myDestinationCb; - private JPanel myCreateNewPanel; - - private static final Logger LOG = Logger.getInstance(ReplaceConstructorWithBuilderDialog.class); - private final LinkedHashMap myParametersMap; - private MyTableModel myTableModel; - private Table myTable; - private static final String RECENT_KEYS = "ReplaceConstructorWithBuilder.RECENT_KEYS"; - - - protected ReplaceConstructorWithBuilderDialog(@Nonnull Project project, PsiMethod[] constructors) { - super(project, false); - myConstructors = constructors; - myParametersMap = new LinkedHashMap(); - for (PsiMethod constructor : constructors) { - ParameterData.createFromConstructor(constructor, myParametersMap); - } - init(); - setTitle(ReplaceConstructorWithBuilderProcessor.REFACTORING_NAME); - } - - @Override - protected String getHelpId() { - return "replace_constructor_with_builder_dialog"; - } - - protected void doAction() { - TableUtil.stopEditing(myTable); - - String className; - String packageName; - if (myCreateBuilderClassRadioButton.isSelected()) { - className = myNewClassName.getText().trim(); - packageName = myPackageTextField.getText().trim(); - } else { - String fqName = myExistentClassTF.getText().trim(); - className = StringUtil.getShortName(fqName); - packageName = StringUtil.getPackageName(fqName); - PsiClass builderClass = JavaPsiFacade.getInstance(myProject).findClass(StringUtil.getQualifiedName(packageName, className), GlobalSearchScope.projectScope(myProject)); - if (builderClass != null && !CommonRefactoringUtil.checkReadOnlyStatus(myProject, builderClass)) return; - } - invokeRefactoring(new ReplaceConstructorWithBuilderProcessor(getProject(), myConstructors, myParametersMap, className, packageName, - ((DestinationFolderComboBox) myDestinationCb).selectDirectory(new PackageWrapper(myConstructors[0].getManager(), packageName), false), - myCreateBuilderClassRadioButton.isSelected())); - } - - - protected JComponent createCenterPanel() { - Splitter splitter = new Splitter(true); - splitter.setFirstComponent(createTablePanel()); - splitter.setSecondComponent(myWholePanel); - ActionListener enableDisableListener = new ActionListener() { - public void actionPerformed(ActionEvent e) { - setEnabled(myCreateBuilderClassRadioButton.isSelected()); - ApplicationIdeFocusManager.getInstance().getInstanceForProject(myProject).requestFocus( - myCreateBuilderClassRadioButton.isSelected() ? myNewClassName : myExistentClassTF.getChildComponent(), true); - validateButtons(); - } - }; - myCreateBuilderClassRadioButton.addActionListener(enableDisableListener); - myExistingBuilderClassRadioButton.addActionListener(enableDisableListener); - myCreateBuilderClassRadioButton.setSelected(true); - setEnabled(true); - - DocumentAdapter validateButtonsListener = new DocumentAdapter() { - @Override - protected void textChanged(DocumentEvent e) { - validateButtons(); - } - }; - myNewClassName.getDocument().addDocumentListener(validateButtonsListener); - PsiClass psiClass = myConstructors[0].getContainingClass(); - LOG.assertTrue(psiClass != null); - myNewClassName.setText(psiClass.getName() + "Builder"); - - return splitter; - } - - private void setEnabled(boolean createNew) { - UIUtil.setEnabled(myCreateNewPanel, createNew, true); - myExistentClassTF.setEnabled(!createNew); - } - - @Override - public JComponent getPreferredFocusedComponent() { - return myNewClassName; - } - - @Override - protected void canRun() throws ConfigurationException { - PsiNameHelper nameHelper = PsiNameHelper.getInstance(myProject); - for (ParameterData parameterData : myParametersMap.values()) { - if (!nameHelper.isIdentifier(parameterData.getFieldName())) - throw new ConfigurationException("\'" + parameterData.getFieldName() + "\' is not a valid field name"); - if (!nameHelper.isIdentifier(parameterData.getSetterName())) - throw new ConfigurationException("\'" + parameterData.getSetterName() + "\' is not a valid setter name"); + private final PsiMethod[] myConstructors; + + private JRadioButton myCreateBuilderClassRadioButton; + private JRadioButton myExistingBuilderClassRadioButton; + + private JPanel myWholePanel; + private JTextField myNewClassName; + private ReferenceEditorComboWithBrowseButton myPackageTextField; + private ReferenceEditorComboWithBrowseButton myExistentClassTF; + private ComboboxWithBrowseButton myDestinationCb; + private JPanel myCreateNewPanel; + + private static final Logger LOG = Logger.getInstance(ReplaceConstructorWithBuilderDialog.class); + private final Map myParametersMap = new LinkedHashMap<>(); + private MyTableModel myTableModel; + private Table myTable; + private static final String RECENT_KEYS = "ReplaceConstructorWithBuilder.RECENT_KEYS"; + + protected ReplaceConstructorWithBuilderDialog(@Nonnull Project project, PsiMethod[] constructors) { + super(project, false); + myConstructors = constructors; + for (PsiMethod constructor : constructors) { + ParameterData.createFromConstructor(constructor, myParametersMap); + } + init(); + setTitle(ReplaceConstructorWithBuilderProcessor.REFACTORING_NAME); } - if (myCreateBuilderClassRadioButton.isSelected()) { - String className = myNewClassName.getText().trim(); - if (className.length() == 0 || !nameHelper.isQualifiedName(className)) - throw new ConfigurationException("\'" + className + "\' is invalid builder class name"); - String packageName = myPackageTextField.getText().trim(); - if (packageName.length() > 0 && !nameHelper.isQualifiedName(packageName)) - throw new ConfigurationException("\'" + packageName + "\' is invalid builder package name"); - } else { - String qualifiedName = myExistentClassTF.getText().trim(); - if (qualifiedName.length() == 0 || !nameHelper.isQualifiedName(qualifiedName)) - throw new ConfigurationException("\'" + qualifiedName + "\' is invalid builder qualified class name"); + + @Override + protected String getHelpId() { + return "replace_constructor_with_builder_dialog"; } - } - - private JScrollPane createTablePanel() { - myTableModel = new MyTableModel(); - myTable = new Table(myTableModel); - myTable.setSurrendersFocusOnKeystroke(true); - myTable.getTableHeader().setReorderingAllowed(false); - - TableColumnModel columnModel = myTable.getColumnModel(); - columnModel.getColumn(SKIP_SETTER).setCellRenderer(new BooleanTableCellRenderer()); - - myTable.registerKeyboardAction( - new ActionListener() { - public void actionPerformed(ActionEvent e) { - int[] selectedRows = myTable.getSelectedRows(); - for (int selectedRow : selectedRows) { - ParameterData parameterData = myTableModel.getParamData(selectedRow); - if (parameterData.getDefaultValue() != null) { - parameterData.setInsertSetter(!parameterData.isInsertSetter()); - } - } - TableUtil.selectRows(myTable, selectedRows); - } - }, - KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), - JComponent.WHEN_FOCUSED - ); - - myTable.setPreferredScrollableViewportSize(new Dimension(550, myTable.getRowHeight() * 12)); - myTable.getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); - - JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myTable); - //final Border titledBorder = IdeBorderFactory.createBoldTitledBorder("Parameters to Pass to the Builder"); - //final Border emptyBorder = BorderFactory.createEmptyBorder(0, 5, 5, 5); - //final Border border = BorderFactory.createCompoundBorder(titledBorder, emptyBorder); - //scrollPane.setBorder(border); - - return scrollPane; - } - - private static final int PARAM = 0; - private static final int FIELD = 1; - private static final int SETTER = 2; - private static final int DEFAULT_VALUE = 3; - private static final int SKIP_SETTER = 4; - - private void createUIComponents() { - consulo.document.event.DocumentAdapter adapter = new consulo.document.event.DocumentAdapter() { - @Override - public void documentChanged(consulo.document.event.DocumentEvent e) { - validateButtons(); - } - }; - - myPackageTextField = new PackageNameReferenceEditorCombo( - ((PsiJavaFile) myConstructors[0].getContainingFile()).getPackageName(), - myProject, - RECENT_KEYS, - RefactoringLocalize.chooseDestinationPackage().get() - ); - myPackageTextField.getChildComponent().getDocument().addDocumentListener(adapter); - - myDestinationCb = new DestinationFolderComboBox() { - @Override - public String getTargetPackage() { - return myPackageTextField.getText().trim(); - } - }; - ((DestinationFolderComboBox) myDestinationCb).setData(myProject, myConstructors[0].getContainingFile().getContainingDirectory(), myPackageTextField.getChildComponent()); - - myExistentClassTF = new ReferenceEditorComboWithBrowseButton(new ActionListener() { - public void actionPerformed(ActionEvent e) { - TreeClassChooser chooser = TreeClassChooserFactory.getInstance(getProject()) - .createWithInnerClassesScopeChooser("Select Builder Class", GlobalSearchScope.projectScope(myProject), null, null); - String classText = myExistentClassTF.getText(); - PsiClass currentClass = JavaPsiFacade.getInstance(myProject).findClass(classText, GlobalSearchScope.allScope(myProject)); - if (currentClass != null) { - chooser.select(currentClass); + + @Override + @RequiredUIAccess + protected void doAction() { + TableUtil.stopEditing(myTable); + + String className; + String packageName; + if (myCreateBuilderClassRadioButton.isSelected()) { + className = myNewClassName.getText().trim(); + packageName = myPackageTextField.getText().trim(); } - chooser.showDialog(); - PsiClass selectedClass = chooser.getSelected(); - if (selectedClass != null) { - myExistentClassTF.setText(selectedClass.getQualifiedName()); + else { + String fqName = myExistentClassTF.getText().trim(); + className = StringUtil.getShortName(fqName); + packageName = StringUtil.getPackageName(fqName); + PsiClass builderClass = JavaPsiFacade.getInstance(myProject) + .findClass(StringUtil.getQualifiedName(packageName, className), GlobalSearchScope.projectScope(myProject)); + if (builderClass != null && !CommonRefactoringUtil.checkReadOnlyStatus(myProject, builderClass)) { + return; + } } - } - }, "", myProject, true, RECENT_KEYS); - myExistentClassTF.setButtonIcon(PlatformIconGroup.nodesClass()); - myExistentClassTF.getChildComponent().getDocument().addDocumentListener(adapter); - } - - private class MyTableModel extends AbstractTableModel { - - public Class getColumnClass(int columnIndex) { - if (columnIndex == SKIP_SETTER) { - return Boolean.class; - } - return String.class; + invokeRefactoring(new ReplaceConstructorWithBuilderProcessor( + getProject(), + myConstructors, + myParametersMap, + className, + packageName, + ((DestinationFolderComboBox) myDestinationCb).selectDirectory( + new PackageWrapper(myConstructors[0].getManager(), packageName), + false + ), + myCreateBuilderClassRadioButton.isSelected() + )); } - public int getRowCount() { - return myParametersMap.size(); - } + @Override + @RequiredUIAccess + protected JComponent createCenterPanel() { + Splitter splitter = new Splitter(true); + splitter.setFirstComponent(createTablePanel()); + splitter.setSecondComponent(myWholePanel); + ActionListener enableDisableListener = e -> { + setEnabled(myCreateBuilderClassRadioButton.isSelected()); + ApplicationIdeFocusManager.getInstance().getInstanceForProject(myProject).requestFocus( + myCreateBuilderClassRadioButton.isSelected() ? myNewClassName : myExistentClassTF.getChildComponent(), true); + validateButtons(); + }; + myCreateBuilderClassRadioButton.addActionListener(enableDisableListener); + myExistingBuilderClassRadioButton.addActionListener(enableDisableListener); + myCreateBuilderClassRadioButton.setSelected(true); + setEnabled(true); + + DocumentAdapter validateButtonsListener = new DocumentAdapter() { + @Override + protected void textChanged(DocumentEvent e) { + validateButtons(); + } + }; + myNewClassName.getDocument().addDocumentListener(validateButtonsListener); + PsiClass psiClass = myConstructors[0].getContainingClass(); + LOG.assertTrue(psiClass != null); + myNewClassName.setText(psiClass.getName() + "Builder"); - public int getColumnCount() { - return 5; + return splitter; } - public Object getValueAt(int rowIndex, int columnIndex) { - ParameterData data = getParamData(rowIndex); - switch (columnIndex) { - case PARAM: - return data.getType().getCanonicalText() + " " + data.getParamName(); - case FIELD: - return data.getFieldName(); - case SETTER: - return data.getSetterName(); - case DEFAULT_VALUE: - return data.getDefaultValue(); - case SKIP_SETTER: - return !data.isInsertSetter(); - } - return null; + private void setEnabled(boolean createNew) { + UIUtil.setEnabled(myCreateNewPanel, createNew, true); + myExistentClassTF.setEnabled(!createNew); } - private ParameterData getParamData(int rowIndex) { - return myParametersMap.get(new ArrayList(myParametersMap.keySet()).get(rowIndex)); + @Override + @RequiredUIAccess + public JComponent getPreferredFocusedComponent() { + return myNewClassName; } @Override - public void setValueAt(Object aValue, int rowIndex, int columnIndex) { - ParameterData data = getParamData(rowIndex); - switch (columnIndex) { - case FIELD: - data.setFieldName((String) aValue); - break; - case SETTER: - data.setSetterName((String) aValue); - break; - case DEFAULT_VALUE: - data.setDefaultValue((String) aValue); - break; - case SKIP_SETTER: - data.setInsertSetter(!((Boolean) aValue).booleanValue()); - break; - default: - assert false; - } + protected void canRun() throws ConfigurationException { + PsiNameHelper nameHelper = PsiNameHelper.getInstance(myProject); + for (ParameterData parameterData : myParametersMap.values()) { + if (!nameHelper.isIdentifier(parameterData.getFieldName())) { + throw new ConfigurationException("\'" + parameterData.getFieldName() + "\' is not a valid field name"); + } + if (!nameHelper.isIdentifier(parameterData.getSetterName())) { + throw new ConfigurationException("\'" + parameterData.getSetterName() + "\' is not a valid setter name"); + } + } + if (myCreateBuilderClassRadioButton.isSelected()) { + String className = myNewClassName.getText().trim(); + if (className.length() == 0 || !nameHelper.isQualifiedName(className)) { + throw new ConfigurationException("\'" + className + "\' is invalid builder class name"); + } + String packageName = myPackageTextField.getText().trim(); + if (packageName.length() > 0 && !nameHelper.isQualifiedName(packageName)) { + throw new ConfigurationException("\'" + packageName + "\' is invalid builder package name"); + } + } + else { + String qualifiedName = myExistentClassTF.getText().trim(); + if (qualifiedName.length() == 0 || !nameHelper.isQualifiedName(qualifiedName)) { + throw new ConfigurationException("\'" + qualifiedName + "\' is invalid builder qualified class name"); + } + } } - @Override - public boolean isCellEditable(int rowIndex, int columnIndex) { - if (columnIndex == PARAM) return false; - if (columnIndex == SKIP_SETTER) { - ParameterData data = getParamData(rowIndex); - if (data.getDefaultValue() == null) return false; - } - return true; + private JScrollPane createTablePanel() { + myTableModel = new MyTableModel(); + myTable = new Table(myTableModel); + myTable.setSurrendersFocusOnKeystroke(true); + myTable.getTableHeader().setReorderingAllowed(false); + + TableColumnModel columnModel = myTable.getColumnModel(); + columnModel.getColumn(SKIP_SETTER).setCellRenderer(new BooleanTableCellRenderer()); + + myTable.registerKeyboardAction( + e -> { + int[] selectedRows = myTable.getSelectedRows(); + for (int selectedRow : selectedRows) { + ParameterData parameterData = myTableModel.getParamData(selectedRow); + if (parameterData.getDefaultValue() != null) { + parameterData.setInsertSetter(!parameterData.isInsertSetter()); + } + } + TableUtil.selectRows(myTable, selectedRows); + }, + KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), + JComponent.WHEN_FOCUSED + ); + + myTable.setPreferredScrollableViewportSize(new Dimension(550, myTable.getRowHeight() * 12)); + myTable.getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); + + JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myTable); + //final Border titledBorder = IdeBorderFactory.createBoldTitledBorder("Parameters to Pass to the Builder"); + //final Border emptyBorder = BorderFactory.createEmptyBorder(0, 5, 5, 5); + //final Border border = BorderFactory.createCompoundBorder(titledBorder, emptyBorder); + //scrollPane.setBorder(border); + + return scrollPane; } - @Override - public String getColumnName(int column) { - switch (column) { - case PARAM: - return "Parameter"; - case FIELD: - return "Field Name"; - case SETTER: - return "Setter Name"; - case DEFAULT_VALUE: - return "Default Value"; - case SKIP_SETTER: - return "Optional Setter"; - } - assert false : "unknown column " + column; - return null; + private static final int PARAM = 0; + private static final int FIELD = 1; + private static final int SETTER = 2; + private static final int DEFAULT_VALUE = 3; + private static final int SKIP_SETTER = 4; + + private void createUIComponents() { + consulo.document.event.DocumentAdapter adapter = new consulo.document.event.DocumentAdapter() { + @Override + public void documentChanged(consulo.document.event.DocumentEvent e) { + validateButtons(); + } + }; + + myPackageTextField = new PackageNameReferenceEditorCombo( + ((PsiJavaFile) myConstructors[0].getContainingFile()).getPackageName(), + myProject, + RECENT_KEYS, + RefactoringLocalize.chooseDestinationPackage().get() + ); + myPackageTextField.getChildComponent().getDocument().addDocumentListener(adapter); + + myDestinationCb = new DestinationFolderComboBox() { + @Override + public String getTargetPackage() { + return myPackageTextField.getText().trim(); + } + }; + ((DestinationFolderComboBox) myDestinationCb).setData( + myProject, + myConstructors[0].getContainingFile().getContainingDirectory(), + myPackageTextField.getChildComponent() + ); + + myExistentClassTF = new ReferenceEditorComboWithBrowseButton( + e -> { + TreeClassChooser chooser = TreeClassChooserFactory.getInstance(getProject()) + .createWithInnerClassesScopeChooser("Select Builder Class", GlobalSearchScope.projectScope(myProject), null, null); + String classText = myExistentClassTF.getText(); + PsiClass currentClass = JavaPsiFacade.getInstance(myProject).findClass(classText, GlobalSearchScope.allScope(myProject)); + if (currentClass != null) { + chooser.select(currentClass); + } + chooser.showDialog(); + PsiClass selectedClass = chooser.getSelected(); + if (selectedClass != null) { + myExistentClassTF.setText(selectedClass.getQualifiedName()); + } + }, + "", + myProject, + true, + RECENT_KEYS + ); + myExistentClassTF.setButtonIcon(PlatformIconGroup.nodesClass()); + myExistentClassTF.getChildComponent().getDocument().addDocumentListener(adapter); + } + + private class MyTableModel extends AbstractTableModel { + @Override + public Class getColumnClass(int columnIndex) { + if (columnIndex == SKIP_SETTER) { + return Boolean.class; + } + return String.class; + } + + @Override + public int getRowCount() { + return myParametersMap.size(); + } + + @Override + public int getColumnCount() { + return 5; + } + + @Override + public Object getValueAt(int rowIndex, int columnIndex) { + ParameterData data = getParamData(rowIndex); + return switch (columnIndex) { + case PARAM -> data.getType().getCanonicalText() + " " + data.getParamName(); + case FIELD -> data.getFieldName(); + case SETTER -> data.getSetterName(); + case DEFAULT_VALUE -> data.getDefaultValue(); + case SKIP_SETTER -> !data.isInsertSetter(); + default -> null; + }; + } + + private ParameterData getParamData(int rowIndex) { + return myParametersMap.get(new ArrayList<>(myParametersMap.keySet()).get(rowIndex)); + } + + @Override + public void setValueAt(Object aValue, int rowIndex, int columnIndex) { + ParameterData data = getParamData(rowIndex); + switch (columnIndex) { + case FIELD: + data.setFieldName((String) aValue); + break; + case SETTER: + data.setSetterName((String) aValue); + break; + case DEFAULT_VALUE: + data.setDefaultValue((String) aValue); + break; + case SKIP_SETTER: + data.setInsertSetter(!(Boolean) aValue); + break; + default: + assert false; + } + } + + @Override + public boolean isCellEditable(int rowIndex, int columnIndex) { + if (columnIndex == PARAM) { + return false; + } + if (columnIndex == SKIP_SETTER) { + ParameterData data = getParamData(rowIndex); + if (data.getDefaultValue() == null) { + return false; + } + } + return true; + } + + @Override + public String getColumnName(int column) { + switch (column) { + case PARAM: + return "Parameter"; + case FIELD: + return "Field Name"; + case SETTER: + return "Setter Name"; + case DEFAULT_VALUE: + return "Default Value"; + case SKIP_SETTER: + return "Optional Setter"; + } + assert false : "unknown column " + column; + return null; + } } - } } diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderHandler.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderHandler.java index ecfd83a86..796a43f9f 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderHandler.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderHandler.java @@ -24,57 +24,80 @@ import com.intellij.java.language.psi.PsiClass; import com.intellij.java.language.psi.PsiJavaCodeReferenceElement; import com.intellij.java.language.psi.PsiMethod; +import consulo.annotation.access.RequiredReadAction; import consulo.dataContext.DataContext; import consulo.codeEditor.Editor; +import consulo.localize.LocalizeValue; import consulo.project.Project; import consulo.language.psi.*; import consulo.language.psi.util.PsiTreeUtil; import com.intellij.java.impl.refactoring.HelpID; import consulo.language.editor.refactoring.action.RefactoringActionHandler; import consulo.language.editor.refactoring.util.CommonRefactoringUtil; +import consulo.ui.annotation.RequiredUIAccess; import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; public class ReplaceConstructorWithBuilderHandler implements RefactoringActionHandler { - public void invoke(@Nonnull Project project, Editor editor, PsiFile file, DataContext dataContext) { - int offset = editor.getCaretModel().getOffset(); - PsiElement element = file.findElementAt(offset); - PsiClass psiClass = getParentNamedClass(element); - if (psiClass == null) { - showErrorMessage("The caret should be positioned inside a class which constructors are to be replaced with builder.", project, editor); - return; - } - - PsiMethod[] constructors = psiClass.getConstructors(); - if (constructors.length == 0) { - showErrorMessage("Current class doesn't have constructors to replace with builder.", project, editor); - return; - } + @Override + @RequiredUIAccess + public void invoke(@Nonnull Project project, Editor editor, PsiFile file, DataContext dataContext) { + int offset = editor.getCaretModel().getOffset(); + PsiElement element = file.findElementAt(offset); + PsiClass psiClass = getParentNamedClass(element); + if (psiClass == null) { + showErrorMessage( + LocalizeValue.localizeTODO( + "The caret should be positioned inside a class which constructors are to be replaced with builder." + ), + project, + editor + ); + return; + } - new ReplaceConstructorWithBuilderDialog(project, constructors).show(); - } + PsiMethod[] constructors = psiClass.getConstructors(); + if (constructors.length == 0) { + showErrorMessage( + LocalizeValue.localizeTODO("Current class doesn't have constructors to replace with builder."), + project, + editor + ); + return; + } - @Nullable - public static PsiClass getParentNamedClass(PsiElement element) { - if (element != null) { - PsiElement parent = element.getParent(); - if (parent instanceof PsiJavaCodeReferenceElement) { - PsiElement resolve = ((PsiJavaCodeReferenceElement)parent).resolve(); - if (resolve instanceof PsiClass) return (PsiClass)resolve; - } + new ReplaceConstructorWithBuilderDialog(project, constructors).show(); } - PsiClass psiClass = PsiTreeUtil.getParentOfType(element, PsiClass.class); - if (psiClass instanceof PsiAnonymousClass) { - return getParentNamedClass(psiClass); + + @Nullable + @RequiredReadAction + public static PsiClass getParentNamedClass(PsiElement element) { + if (element != null + && element.getParent() instanceof PsiJavaCodeReferenceElement codeRef + && codeRef.resolve() instanceof PsiClass psiClass) { + return psiClass; + } + PsiClass psiClass = PsiTreeUtil.getParentOfType(element, PsiClass.class); + if (psiClass instanceof PsiAnonymousClass) { + return getParentNamedClass(psiClass); + } + return psiClass; } - return psiClass; - } - public void invoke(@Nonnull Project project, @Nonnull PsiElement[] elements, DataContext dataContext) { - throw new UnsupportedOperationException(); - } + @Override + @RequiredUIAccess + public void invoke(@Nonnull Project project, @Nonnull PsiElement[] elements, DataContext dataContext) { + throw new UnsupportedOperationException(); + } - private static void showErrorMessage(String message, Project project, Editor editor) { - CommonRefactoringUtil.showErrorHint(project, editor, message, ReplaceConstructorWithBuilderProcessor.REFACTORING_NAME, HelpID.REPLACE_CONSTRUCTOR_WITH_BUILDER); - } + @RequiredUIAccess + private static void showErrorMessage(@Nonnull LocalizeValue message, Project project, Editor editor) { + CommonRefactoringUtil.showErrorHint( + project, + editor, + message, + ReplaceConstructorWithBuilderProcessor.REFACTORING_NAME, + HelpID.REPLACE_CONSTRUCTOR_WITH_BUILDER + ); + } } diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderProcessor.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderProcessor.java index 4fd299859..94c6adfb3 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderProcessor.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/replaceConstructorWithBuilder/ReplaceConstructorWithBuilderProcessor.java @@ -60,7 +60,7 @@ * @since 2008-09-04 */ public class ReplaceConstructorWithBuilderProcessor extends FixableUsagesRefactoringProcessor { - public static final String REFACTORING_NAME = "Replace Constructor with Builder"; + public static final LocalizeValue REFACTORING_NAME = LocalizeValue.localizeTODO("Replace Constructor with Builder"); private final PsiMethod[] myConstructors; private final Map myParametersMap; private final String myClassName; @@ -69,7 +69,6 @@ public class ReplaceConstructorWithBuilderProcessor extends FixableUsagesRefacto private final PsiElementFactory myElementFactory; private MoveDestination myMoveDestination; - public ReplaceConstructorWithBuilderProcessor( Project project, PsiMethod[] constructors, @@ -348,7 +347,7 @@ else if (myCreateNewBuilderClass) { @Nonnull @Override - protected String getCommandName() { + protected LocalizeValue getCommandName() { return REFACTORING_NAME; } } diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/replaceConstructorWithFactory/ReplaceConstructorWithFactoryProcessor.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/replaceConstructorWithFactory/ReplaceConstructorWithFactoryProcessor.java index 80e42ba5d..d53679a53 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/replaceConstructorWithFactory/ReplaceConstructorWithFactoryProcessor.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/replaceConstructorWithFactory/ReplaceConstructorWithFactoryProcessor.java @@ -128,15 +128,18 @@ else if (element instanceof PsiClass) { } //if (myConstructor != null && myConstructor.getParameterList().getParametersCount() == 0) { - // RefactoringUtil.visitImplicitConstructorUsages(getConstructorContainingClass(), new RefactoringUtil.ImplicitConstructorUsageVisitor() { - // @Override public void visitConstructor(PsiMethod constructor, PsiMethod baseConstructor) { - // myNonNewConstructorUsages.add(constructor); - // } + // RefactoringUtil.visitImplicitConstructorUsages( + // getConstructorContainingClass(), + // new RefactoringUtil.ImplicitConstructorUsageVisitor() { + // @Override public void visitConstructor(PsiMethod constructor, PsiMethod baseConstructor) { + // myNonNewConstructorUsages.add(constructor); + // } // - // @Override public void visitClassWithoutConstructors(PsiClass aClass) { - // myNonNewConstructorUsages.add(aClass); + // @Override public void visitClassWithoutConstructors(PsiClass aClass) { + // myNonNewConstructorUsages.add(aClass); + // } // } - // }); + // ); //} return usages.toArray(new UsageInfo[usages.size()]); @@ -195,12 +198,7 @@ protected boolean preprocessUsages(@Nonnull SimpleReference refUsag } private PsiClass getConstructorContainingClass() { - if (myConstructor != null) { - return myConstructor.getContainingClass(); - } - else { - return myOriginalClass; - } + return myConstructor != null ? myConstructor.getContainingClass() : myOriginalClass; } @Override @@ -308,28 +306,17 @@ private PsiMethod createFactoryMethod() throws IncorrectOperationException { @PsiModifier.ModifierConstant private String getDefaultFactoryVisibility() { - PsiModifierList modifierList; - if (myConstructor != null) { - modifierList = myConstructor.getModifierList(); - } - else { - modifierList = myOriginalClass.getModifierList(); - } + PsiModifierList modifierList = myConstructor != null ? myConstructor.getModifierList() : myOriginalClass.getModifierList(); return VisibilityUtil.getVisibilityModifier(modifierList); } @Nonnull @Override @RequiredReadAction - protected String getCommandName() { - if (myConstructor != null) { - return RefactoringLocalize.replaceConstructor0WithAFactoryMethod(DescriptiveNameUtil.getDescriptiveName(myConstructor)).get(); - } - else { - return RefactoringLocalize.replaceDefaultConstructorOf0WithAFactoryMethod( - DescriptiveNameUtil.getDescriptiveName(myOriginalClass) - ).get(); - } + protected LocalizeValue getCommandName() { + return myConstructor != null + ? RefactoringLocalize.replaceConstructor0WithAFactoryMethod(DescriptiveNameUtil.getDescriptiveName(myConstructor)) + : RefactoringLocalize.replaceDefaultConstructorOf0WithAFactoryMethod(DescriptiveNameUtil.getDescriptiveName(myOriginalClass)); } public PsiClass getOriginalClass() { diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/turnRefsToSuper/TurnRefsToSuperDialog.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/turnRefsToSuper/TurnRefsToSuperDialog.java index 464745a0c..da1868e4f 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/turnRefsToSuper/TurnRefsToSuperDialog.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/turnRefsToSuper/TurnRefsToSuperDialog.java @@ -15,113 +15,120 @@ */ package com.intellij.java.impl.refactoring.turnRefsToSuper; -import consulo.application.HelpManager; -import consulo.language.editor.refactoring.localize.RefactoringLocalize; -import consulo.project.Project; -import com.intellij.java.language.psi.PsiClass; import com.intellij.java.impl.refactoring.HelpID; import com.intellij.java.impl.refactoring.JavaRefactoringSettings; -import consulo.language.editor.refactoring.RefactoringBundle; import com.intellij.java.impl.refactoring.ui.ClassCellRenderer; -import consulo.language.editor.refactoring.ui.RefactoringDialog; import com.intellij.java.impl.refactoring.util.RefactoringHierarchyUtil; +import com.intellij.java.language.psi.PsiClass; +import consulo.annotation.access.RequiredReadAction; +import consulo.application.HelpManager; +import consulo.language.editor.refactoring.localize.RefactoringLocalize; +import consulo.language.editor.refactoring.ui.RefactoringDialog; +import consulo.project.Project; +import consulo.ui.annotation.RequiredUIAccess; import consulo.ui.ex.awt.JBList; import consulo.ui.ex.awt.ScrollPaneFactory; import consulo.ui.ex.awt.UIUtil; - import jakarta.annotation.Nonnull; - import jakarta.annotation.Nullable; + import javax.swing.*; import java.awt.*; import java.util.List; /** * @author dsl - * Date: 06.06.2002 + * @since 2002-06-06 */ public class TurnRefsToSuperDialog extends RefactoringDialog { - @Nonnull - private final PsiClass mySubClass; - private final List mySuperClasses; - - private JList mySuperClassesList = null; - private final JCheckBox myCbReplaceInstanceOf = new JCheckBox(); + @Nonnull + private final PsiClass mySubClass; + private final List mySuperClasses; - TurnRefsToSuperDialog(Project project, @Nonnull PsiClass subClass, List superClasses) { - super(project, true); + private JList mySuperClassesList = null; + private final JCheckBox myCbReplaceInstanceOf = new JCheckBox(); - mySubClass = subClass; - mySuperClasses = superClasses; + TurnRefsToSuperDialog(Project project, @Nonnull PsiClass subClass, List superClasses) { + super(project, true); - setTitle(TurnRefsToSuperHandler.REFACTORING_NAME); - init(); - } + mySubClass = subClass; + mySuperClasses = superClasses; - @Nullable - public PsiClass getSuperClass() { - if(mySuperClassesList != null) { - return (PsiClass) mySuperClassesList.getSelectedValue(); - } - else { - return null; + setTitle(TurnRefsToSuperHandler.REFACTORING_NAME); + init(); } - } - public boolean isUseInInstanceOf() { - return myCbReplaceInstanceOf.isSelected(); - } - - protected void doHelpAction() { - HelpManager.getInstance().invokeHelp(HelpID.TURN_REFS_TO_SUPER); - } - - public JComponent getPreferredFocusedComponent() { - return mySuperClassesList; - } + @Nullable + public PsiClass getSuperClass() { + if (mySuperClassesList != null) { + return (PsiClass) mySuperClassesList.getSelectedValue(); + } + else { + return null; + } + } + public boolean isUseInInstanceOf() { + return myCbReplaceInstanceOf.isSelected(); + } - protected JComponent createCenterPanel() { - JPanel panel = new JPanel(); - panel.setLayout(new BorderLayout(UIUtil.DEFAULT_HGAP, UIUtil.DEFAULT_VGAP)); + @Override + @RequiredUIAccess + protected void doHelpAction() { + HelpManager.getInstance().invokeHelp(HelpID.TURN_REFS_TO_SUPER); + } - JLabel classListLabel = new JLabel(); - panel.add(classListLabel, BorderLayout.NORTH); + @Override + @RequiredUIAccess + public JComponent getPreferredFocusedComponent() { + return mySuperClassesList; + } - mySuperClassesList = new JBList(mySuperClasses.toArray()); - mySuperClassesList.setCellRenderer(new ClassCellRenderer(mySuperClassesList.getCellRenderer())); - mySuperClassesList.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - classListLabel.setText(RefactoringLocalize.turnrefstosuperChangeUsagesTo(mySubClass.getQualifiedName()).get()); + @Override + protected JComponent createCenterPanel() { + JPanel panel = new JPanel(); + panel.setLayout(new BorderLayout(UIUtil.DEFAULT_HGAP, UIUtil.DEFAULT_VGAP)); + + JLabel classListLabel = new JLabel(); + panel.add(classListLabel, BorderLayout.NORTH); + + mySuperClassesList = new JBList(mySuperClasses.toArray()); + mySuperClassesList.setCellRenderer(new ClassCellRenderer(mySuperClassesList.getCellRenderer())); + mySuperClassesList.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + classListLabel.setText(RefactoringLocalize.turnrefstosuperChangeUsagesTo(mySubClass.getQualifiedName()).get()); + + PsiClass nearestBase = RefactoringHierarchyUtil.getNearestBaseClass(mySubClass, true); + int indexToSelect = 0; + if (nearestBase != null) { + indexToSelect = mySuperClasses.indexOf(nearestBase); + } + mySuperClassesList.setSelectedIndex(indexToSelect); + panel.add(ScrollPaneFactory.createScrollPane(mySuperClassesList), BorderLayout.CENTER); + + myCbReplaceInstanceOf.setText(RefactoringLocalize.turnrefstosuperUseSuperclassInInstanceof().get()); + myCbReplaceInstanceOf.setSelected(false); + myCbReplaceInstanceOf.setFocusable(false); + panel.add(myCbReplaceInstanceOf, BorderLayout.SOUTH); + + return panel; + } - PsiClass nearestBase = RefactoringHierarchyUtil.getNearestBaseClass(mySubClass, true); - int indexToSelect = 0; - if(nearestBase != null) { - indexToSelect = mySuperClasses.indexOf(nearestBase); + @Override + protected String getDimensionServiceKey() { + return "#com.intellij.refactoring.turnRefsToSuper.TurnRefsToSuperDialog"; } - mySuperClassesList.setSelectedIndex(indexToSelect); - panel.add(ScrollPaneFactory.createScrollPane(mySuperClassesList), BorderLayout.CENTER); - - myCbReplaceInstanceOf.setText(RefactoringLocalize.turnrefstosuperUseSuperclassInInstanceof().get()); - myCbReplaceInstanceOf.setSelected(false); - myCbReplaceInstanceOf.setFocusable(false); - panel.add(myCbReplaceInstanceOf, BorderLayout.SOUTH); - - return panel; - } - - protected String getDimensionServiceKey() { - return "#com.intellij.refactoring.turnRefsToSuper.TurnRefsToSuperDialog"; - } - - protected void doAction() { - JavaRefactoringSettings.getInstance().TURN_REFS_TO_SUPER_PREVIEW_USAGES = isPreviewUsages(); - PsiClass superClass = getSuperClass(); - if (superClass != null) { - invokeRefactoring(new TurnRefsToSuperProcessor(getProject(), mySubClass, superClass, isUseInInstanceOf())); + + @Override + protected void doAction() { + JavaRefactoringSettings.getInstance().TURN_REFS_TO_SUPER_PREVIEW_USAGES = isPreviewUsages(); + PsiClass superClass = getSuperClass(); + if (superClass != null) { + invokeRefactoring(new TurnRefsToSuperProcessor(getProject(), mySubClass, superClass, isUseInInstanceOf())); + } } - } - protected JComponent createNorthPanel() { - return null; - } + @Override + protected JComponent createNorthPanel() { + return null; + } } diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/turnRefsToSuper/TurnRefsToSuperHandler.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/turnRefsToSuper/TurnRefsToSuperHandler.java index e9adbd789..eb570a6c4 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/turnRefsToSuper/TurnRefsToSuperHandler.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/turnRefsToSuper/TurnRefsToSuperHandler.java @@ -13,11 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -/** - * created at Oct 25, 2001 - * @author Jeka - */ package com.intellij.java.impl.refactoring.turnRefsToSuper; import com.intellij.java.impl.refactoring.HelpID; @@ -27,7 +22,6 @@ import consulo.codeEditor.Editor; import consulo.codeEditor.ScrollType; import consulo.dataContext.DataContext; -import consulo.language.editor.refactoring.RefactoringBundle; import consulo.language.editor.refactoring.action.RefactoringActionHandler; import consulo.language.editor.refactoring.localize.RefactoringLocalize; import consulo.language.editor.refactoring.util.CommonRefactoringUtil; @@ -38,47 +32,56 @@ import consulo.ui.annotation.RequiredUIAccess; import jakarta.annotation.Nonnull; -import java.util.ArrayList; +import java.util.List; +/** + * @author Jeka + * @since 2001-10-25 + */ public class TurnRefsToSuperHandler implements RefactoringActionHandler { - public static final String REFACTORING_NAME = RefactoringBundle.message("use.interface.where.possible.title"); + public static final LocalizeValue REFACTORING_NAME = RefactoringLocalize.useInterfaceWherePossibleTitle(); - @RequiredUIAccess - public void invoke(@Nonnull Project project, Editor editor, PsiFile file, DataContext dataContext) { - int offset = editor.getCaretModel().getOffset(); - editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); - PsiElement element = file.findElementAt(offset); - while (true) { - if (element == null || element instanceof PsiFile) { - LocalizeValue message = RefactoringLocalize.cannotPerformRefactoringWithReason(RefactoringLocalize.errorWrongCaretPositionClass()); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME, HelpID.TURN_REFS_TO_SUPER); - return; - } - if (element instanceof PsiClass && !(element instanceof PsiAnonymousClass)) { - invoke(project, new PsiElement[]{element}, dataContext); - return; - } - element = element.getParent(); + @Override + @RequiredUIAccess + public void invoke(@Nonnull Project project, Editor editor, PsiFile file, DataContext dataContext) { + int offset = editor.getCaretModel().getOffset(); + editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE); + PsiElement element = file.findElementAt(offset); + while (true) { + if (element == null || element instanceof PsiFile) { + LocalizeValue message = + RefactoringLocalize.cannotPerformRefactoringWithReason(RefactoringLocalize.errorWrongCaretPositionClass()); + CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.TURN_REFS_TO_SUPER); + return; + } + if (element instanceof PsiClass psiClass && !(psiClass instanceof PsiAnonymousClass)) { + invoke(project, new PsiElement[]{psiClass}, dataContext); + return; + } + element = element.getParent(); + } } - } - public void invoke(@Nonnull Project project, @Nonnull PsiElement[] elements, DataContext dataContext) { - if (elements.length != 1) { - return; - } + @Override + @RequiredUIAccess + public void invoke(@Nonnull Project project, @Nonnull PsiElement[] elements, DataContext dataContext) { + if (elements.length != 1) { + return; + } - PsiClass subClass = (PsiClass) elements[0]; + PsiClass subClass = (PsiClass) elements[0]; - ArrayList basesList = RefactoringHierarchyUtil.createBasesList(subClass, true, true); + List basesList = RefactoringHierarchyUtil.createBasesList(subClass, true, true); - if (basesList.isEmpty()) { - LocalizeValue message = - RefactoringLocalize.cannotPerformRefactoringWithReason(RefactoringLocalize.interfaceDoesNotHaveBaseInterfaces(subClass.getQualifiedName())); - Editor editor = dataContext.getData(Editor.KEY); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME, HelpID.TURN_REFS_TO_SUPER); - return; - } + if (basesList.isEmpty()) { + LocalizeValue message = RefactoringLocalize.cannotPerformRefactoringWithReason( + RefactoringLocalize.interfaceDoesNotHaveBaseInterfaces(subClass.getQualifiedName()) + ); + Editor editor = dataContext.getData(Editor.KEY); + CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.TURN_REFS_TO_SUPER); + return; + } - new TurnRefsToSuperDialog(project, subClass, basesList).show(); - } + new TurnRefsToSuperDialog(project, subClass, basesList).show(); + } } diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/turnRefsToSuper/TurnRefsToSuperProcessor.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/turnRefsToSuper/TurnRefsToSuperProcessor.java index be0824acd..59d013f4e 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/turnRefsToSuper/TurnRefsToSuperProcessor.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/turnRefsToSuper/TurnRefsToSuperProcessor.java @@ -20,6 +20,7 @@ import com.intellij.java.language.psi.util.InheritanceUtil; import com.intellij.java.language.psi.util.PsiUtil; import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.language.editor.refactoring.localize.RefactoringLocalize; import consulo.language.findUsage.DescriptiveNameUtil; import consulo.language.psi.PsiElement; @@ -64,11 +65,11 @@ public TurnRefsToSuperProcessor( @Nonnull @Override @RequiredReadAction - protected String getCommandName() { + protected LocalizeValue getCommandName() { return RefactoringLocalize.turnRefsToSuperCommand( DescriptiveNameUtil.getDescriptiveName(myClass), DescriptiveNameUtil.getDescriptiveName(mySuper) - ).get(); + ); } @Nonnull @@ -106,7 +107,7 @@ protected void refreshElements(PsiElement[] elements) { protected boolean preprocessUsages(@Nonnull SimpleReference refUsages) { if (!myProject.getApplication().isUnitTestMode() && refUsages.get().length == 0) { LocalizeValue message = RefactoringLocalize.noUsagesCanBeReplaced(myClass.getQualifiedName(), mySuper.getQualifiedName()); - Messages.showInfoMessage(myProject, message.get(), TurnRefsToSuperHandler.REFACTORING_NAME); + Messages.showInfoMessage(myProject, message.get(), TurnRefsToSuperHandler.REFACTORING_NAME.get()); return false; } @@ -120,11 +121,11 @@ protected boolean canTurnToSuper(PsiElement refElement) { } @Override + @RequiredWriteAction protected void performRefactoring(@Nonnull UsageInfo[] usages) { try { PsiClass aSuper = mySuper; processTurnToSuperRefs(usages, aSuper); - } catch (IncorrectOperationException e) { LOG.error(e); @@ -146,7 +147,7 @@ protected boolean isInSuper(PsiElement member) { if (member instanceof PsiField field) { PsiClass containingClass = field.getContainingClass(); - LanguageLevel languageLevel = PsiUtil.getLanguageLevel(member); + LanguageLevel languageLevel = PsiUtil.getLanguageLevel(field); if (manager.areElementsEquivalent( containingClass, JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().getArrayClass(languageLevel) diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/turnRefsToSuper/TurnRefsToSuperProcessorBase.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/turnRefsToSuper/TurnRefsToSuperProcessorBase.java index f841e3ae3..bf454ca41 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/turnRefsToSuper/TurnRefsToSuperProcessorBase.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/turnRefsToSuper/TurnRefsToSuperProcessorBase.java @@ -100,7 +100,7 @@ protected boolean preprocessUsages(@Nonnull SimpleReference refUsag Runnable runnable = () -> myVariableRenamer.findUsages(myVariablesUsages, false, false); if (!ProgressManager.getInstance() - .runProcessWithProgressSynchronously(runnable, RefactoringLocalize.searchingForVariables().get(), true, myProject)) { + .runProcessWithProgressSynchronously(runnable, RefactoringLocalize.searchingForVariables(), true, myProject)) { return false; } } @@ -153,7 +153,7 @@ protected TurnRefsToSuperProcessorBase(Project project, boolean replaceInstanceO } @RequiredReadAction - protected ArrayList detectTurnToSuperRefs(PsiReference[] refs, ArrayList result) { + protected List detectTurnToSuperRefs(PsiReference[] refs, List result) { buildGraph(refs); for (PsiReference ref : refs) { @@ -188,6 +188,7 @@ protected static void processTurnToSuperRefs(UsageInfo[] usages, PsiClass aSuper } } + @RequiredWriteAction private static void fixPossiblyRedundantCast(PsiTypeCastExpression cast) throws IncorrectOperationException { PsiTypeElement castTypeElement = cast.getCastType(); if (castTypeElement == null) { @@ -213,8 +214,8 @@ private static void fixPossiblyRedundantCast(PsiTypeCastExpression cast) throws } // OK, cast is redundant PsiExpression exprToReplace = cast; - while (exprToReplace.getParent() instanceof PsiParenthesizedExpression) { - exprToReplace = (PsiExpression)exprToReplace.getParent(); + while (exprToReplace.getParent() instanceof PsiParenthesizedExpression parenthesized) { + exprToReplace = parenthesized; } exprToReplace.replace(operand); } @@ -235,6 +236,7 @@ private void buildGraph(PsiReference[] refs) { spreadMarks(); } + @RequiredReadAction private void processUsage(PsiElement ref) { if (ref instanceof PsiReferenceExpression) { if (ref.getParent() instanceof PsiReferenceExpression refExpr && !isInSuper(refExpr.resolve())) { @@ -245,35 +247,35 @@ private void processUsage(PsiElement ref) { PsiElement parent = ref.getParent(); if (parent instanceof PsiTypeElement) { - PsiElement pparent = parent.getParent(); - while (pparent instanceof PsiTypeElement) { - addLink(pparent, parent); - addLink(parent, pparent); - parent = pparent; - pparent = parent.getParent(); + PsiElement grandparent = parent.getParent(); + while (grandparent instanceof PsiTypeElement) { + addLink(grandparent, parent); + addLink(parent, grandparent); + parent = grandparent; + grandparent = parent.getParent(); } PsiTypeElement typeElement = (PsiTypeElement)parent; addLink(typeElement, ref); addLink(ref, typeElement); - if (pparent instanceof PsiVariable variable) { + if (grandparent instanceof PsiVariable variable) { processVariableType(variable); } - else if (pparent instanceof PsiMethod method) { + else if (grandparent instanceof PsiMethod method) { processMethodReturnType(method); } - else if (pparent instanceof PsiTypeCastExpression) { - addLink(pparent, typeElement); - addLink(typeElement, pparent); + else if (grandparent instanceof PsiTypeCastExpression) { + addLink(grandparent, typeElement); + addLink(typeElement, grandparent); } - else if (pparent instanceof PsiReferenceParameterList refParameterList) { - PsiElement ppparent = pparent.getParent(); - if (ppparent instanceof PsiJavaCodeReferenceElement classReference) { + else if (grandparent instanceof PsiReferenceParameterList refParameterList) { + if (grandparent.getParent() instanceof PsiJavaCodeReferenceElement classReference) { if (classReference.getParent() instanceof PsiReferenceList referenceList) { PsiClass parentClass = PsiTreeUtil.getParentOfType(ref, PsiClass.class); if (parentClass != null) { - if (referenceList.equals(parentClass.getExtendsList()) || referenceList.equals(parentClass.getImplementsList())) { + if (referenceList.equals(parentClass.getExtendsList()) + || referenceList.equals(parentClass.getImplementsList())) { PsiTypeElement[] typeParameterElements = refParameterList.getTypeParameterElements(); for (int i = 0; i < typeParameterElements.length; i++) { if (typeParameterElements[i] == typeElement @@ -337,8 +339,7 @@ private void linkTypeParameterInstantiations( PsiTypeElement instantiation, PsiClass inheritingClass ) { - PsiTypeParameterListOwner owner = typeParameter.getOwner(); - if (owner instanceof PsiClass ownerClass) { + if (typeParameter.getOwner() instanceof PsiClass ownerClass) { LocalSearchScope derivedScope = new LocalSearchScope(inheritingClass); PsiSubstitutor substitutor = TypeConversionUtil.getClassSubstitutor(ownerClass, inheritingClass, PsiSubstitutor.EMPTY); if (substitutor == null) { @@ -347,8 +348,8 @@ private void linkTypeParameterInstantiations( LocalSearchScope baseScope = new LocalSearchScope(ownerClass); ReferencesSearch.search(typeParameter, baseScope).forEach(ref -> { if (ref.getElement().getParent() instanceof PsiTypeElement typeElem) { - PsiElement pparent = typeElem.getParent(); - if (pparent instanceof PsiMethod method && typeElem.equals(method.getReturnTypeElement())) { + PsiElement grandparent = typeElem.getParent(); + if (grandparent instanceof PsiMethod method && typeElem.equals(method.getReturnTypeElement())) { MethodSignature signature = method.getSignature(substitutor); if (PsiUtil.isAccessible(method, inheritingClass, null)) { PsiMethod inInheritor = MethodSignatureUtil.findMethodBySignature(inheritingClass, signature, false); @@ -358,7 +359,7 @@ private void linkTypeParameterInstantiations( } } } - else if (pparent instanceof PsiParameter parameter + else if (grandparent instanceof PsiParameter parameter && parameter.getDeclarationScope() instanceof PsiMethod method) { int index = ((PsiParameterList)parameter.getParent()).getParameterIndex(parameter); MethodSignature signature = method.getSignature(substitutor); @@ -422,6 +423,7 @@ private void checkToArray(PsiElement ref, PsiNewExpression newExpression) { } } + @RequiredReadAction private void processVariableType(PsiVariable variable) { final PsiTypeElement type = variable.getTypeElement(); PsiExpression initializer = variable.getInitializer(); @@ -547,6 +549,7 @@ private void checkConstrainingType(PsiElement element, @Nullable PsiType constra } } + @RequiredReadAction private void processMethodReturnType(PsiMethod method) { final PsiTypeElement returnType = method.getReturnTypeElement(); for (PsiReference call : ReferencesSearch.search(method)) { @@ -626,6 +629,7 @@ else if (parent instanceof PsiExpressionList expressionList) { } } + @RequiredReadAction protected void markNodes() { //for (Iterator iterator = myDependencyMap.keySet().getSectionsIterator(); getSectionsIterator.hasNext();) { for (PsiElement element : myElementToNode.keySet()) { @@ -648,14 +652,14 @@ else if (element instanceof PsiParameter parameter) { PsiType type = TypeConversionUtil.erasure(parameter.getType()); PsiClass aClass = PsiUtil.resolveClassInType(type); if (aClass != null) { - if (!myManager.isInProject(element) || !myManager.areElementsEquivalent(aClass, myClass)) { + if (!myManager.isInProject(parameter) || !myManager.areElementsEquivalent(aClass, myClass)) { if (!isSuperInheritor(aClass)) { - markNode(element); + markNode(parameter); } } } else { // unresolvable class - markNode(element); + markNode(parameter); } } } diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/typeCook/TypeCookProcessor.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/typeCook/TypeCookProcessor.java index 738ec4cbe..38a5c5246 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/typeCook/TypeCookProcessor.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/typeCook/TypeCookProcessor.java @@ -21,103 +21,112 @@ import com.intellij.java.impl.refactoring.typeCook.deductive.resolver.Binding; import com.intellij.java.impl.refactoring.typeCook.deductive.resolver.ResolverTree; import com.intellij.java.language.psi.PsiTypeCastExpression; +import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.language.editor.refactoring.BaseRefactoringProcessor; import consulo.language.editor.refactoring.localize.RefactoringLocalize; import consulo.language.psi.PsiElement; +import consulo.localize.LocalizeValue; import consulo.project.Project; import consulo.usage.UsageInfo; import consulo.usage.UsageViewDescriptor; import jakarta.annotation.Nonnull; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; +import java.util.*; public class TypeCookProcessor extends BaseRefactoringProcessor { - private PsiElement[] myElements; - private final Settings mySettings; - private Result myResult; + private PsiElement[] myElements; + private final Settings mySettings; + private Result myResult; - public TypeCookProcessor(Project project, PsiElement[] elements, Settings settings) { - super(project); + public TypeCookProcessor(Project project, PsiElement[] elements, Settings settings) { + super(project); - myElements = elements; - mySettings = settings; - } + myElements = elements; + mySettings = settings; + } - @Nonnull - protected UsageViewDescriptor createUsageViewDescriptor(UsageInfo[] usages) { - return new TypeCookViewDescriptor(myElements); - } + @Nonnull + @Override + protected UsageViewDescriptor createUsageViewDescriptor(@Nonnull UsageInfo[] usages) { + return new TypeCookViewDescriptor(myElements); + } - @Nonnull - protected UsageInfo[] findUsages() { - SystemBuilder systemBuilder = new SystemBuilder(myProject, mySettings); + @Nonnull + @Override + @RequiredReadAction + protected UsageInfo[] findUsages() { + SystemBuilder systemBuilder = new SystemBuilder(myProject, mySettings); - ReductionSystem commonSystem = systemBuilder.build(myElements); - myResult = new Result(commonSystem); + ReductionSystem commonSystem = systemBuilder.build(myElements); + myResult = new Result(commonSystem); - ReductionSystem[] systems = commonSystem.isolate(); + ReductionSystem[] systems = commonSystem.isolate(); - for (ReductionSystem system : systems) { - if (system != null) { - ResolverTree tree = new ResolverTree(system); + for (ReductionSystem system : systems) { + if (system != null) { + ResolverTree tree = new ResolverTree(system); - tree.resolve(); + tree.resolve(); - Binding solution = tree.getBestSolution(); + Binding solution = tree.getBestSolution(); - if (solution != null) { - myResult.incorporateSolution(solution); + if (solution != null) { + myResult.incorporateSolution(solution); + } + } } - } - } - HashSet changedItems = myResult.getCookedElements(); - UsageInfo[] usages = new UsageInfo[changedItems.size()]; - - int i = 0; - for (final PsiElement element : changedItems) { - if (!(element instanceof PsiTypeCastExpression)) { - usages[i++] = new UsageInfo(element) { - public String getTooltipText() { - return myResult.getCookedType(element).getCanonicalText(); - } - }; - } - else { - usages[i++] = new UsageInfo(element); - } + Set changedItems = myResult.getCookedElements(); + UsageInfo[] usages = new UsageInfo[changedItems.size()]; + + int i = 0; + for (final PsiElement element : changedItems) { + if (!(element instanceof PsiTypeCastExpression)) { + usages[i++] = new UsageInfo(element) { + @Override + public String getTooltipText() { + return myResult.getCookedType(element).getCanonicalText(); + } + }; + } + else { + usages[i++] = new UsageInfo(element); + } + } + + return usages; } - return usages; - } + @Override + protected void refreshElements(@Nonnull PsiElement[] elements) { + myElements = elements; + } - protected void refreshElements(PsiElement[] elements) { - myElements = elements; - } + @Override + @RequiredWriteAction + protected void performRefactoring(UsageInfo[] usages) { + Set victims = new HashSet<>(); - protected void performRefactoring(UsageInfo[] usages) { - HashSet victims = new HashSet(); + for (UsageInfo usage : usages) { + victims.add(usage.getElement()); + } - for (UsageInfo usage : usages) { - victims.add(usage.getElement()); + myResult.apply(victims); } - myResult.apply (victims); - } - - @Override - protected boolean isGlobalUndoAction() { - return true; - } + @Override + protected boolean isGlobalUndoAction() { + return true; + } - protected String getCommandName() { - return RefactoringLocalize.typeCookCommand().get(); - } + @Nonnull + @Override + protected LocalizeValue getCommandName() { + return RefactoringLocalize.typeCookCommand(); + } - public List getElements() { - return Collections.unmodifiableList(Arrays.asList(myElements)); - } + public List getElements() { + return Collections.unmodifiableList(Arrays.asList(myElements)); + } } diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/typeCook/deductive/builder/Result.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/typeCook/deductive/builder/Result.java index 6fd519913..34095ac94 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/typeCook/deductive/builder/Result.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/typeCook/deductive/builder/Result.java @@ -18,152 +18,159 @@ import com.intellij.java.impl.refactoring.typeCook.Settings; import com.intellij.java.impl.refactoring.typeCook.Util; import com.intellij.java.impl.refactoring.typeCook.deductive.resolver.Binding; -import com.intellij.java.language.psi.Bottom; -import com.intellij.java.language.psi.PsiTypeVariable; import com.intellij.java.language.psi.*; import com.intellij.java.language.psi.util.PsiUtil; +import consulo.annotation.access.RequiredWriteAction; import consulo.language.editor.refactoring.RefactoringBundle; import consulo.language.editor.refactoring.localize.RefactoringLocalize; import consulo.language.psi.PsiElement; import consulo.language.util.IncorrectOperationException; import consulo.logging.Logger; -import java.util.HashMap; import java.util.HashSet; import java.util.Map; +import java.util.Set; /** * @author db */ public class Result { - private static final Logger LOG = Logger.getInstance(Result.class); - - private final HashSet myVictims; - private final HashMap myTypes; - private final Settings mySettings; - private final HashMap myCastToOperandType; - - private int myCookedNumber = -1; - private int myCastsRemoved = -1; - private final int myCastsNumber; - - private Binding myBinding; - - public Result(ReductionSystem system) { - myVictims = system.myElements; - myTypes = system.myTypes; - mySettings = system.mySettings; - myCastToOperandType = system.myCastToOperandType; - myCastsNumber = myCastToOperandType.size(); - } - - public void incorporateSolution(Binding binding) { - if (myBinding == null) { - myBinding = binding; + private static final Logger LOG = Logger.getInstance(Result.class); + + private final Set myVictims; + private final Map myTypes; + private final Settings mySettings; + private final Map myCastToOperandType; + + private int myCookedNumber = -1; + private int myCastsRemoved = -1; + private final int myCastsNumber; + + private Binding myBinding; + + public Result(ReductionSystem system) { + myVictims = system.myElements; + myTypes = system.myTypes; + mySettings = system.mySettings; + myCastToOperandType = system.myCastToOperandType; + myCastsNumber = myCastToOperandType.size(); } - else { - myBinding.merge(binding, mySettings.leaveObjectParameterizedTypesRaw()); + + public void incorporateSolution(Binding binding) { + if (myBinding == null) { + myBinding = binding; + } + else { + myBinding.merge(binding, mySettings.leaveObjectParameterizedTypesRaw()); + } } - } - public PsiType getCookedType(PsiElement element) { - PsiType originalType = Util.getType(element); + public PsiType getCookedType(PsiElement element) { + PsiType originalType = Util.getType(element); - if (myBinding != null) { - PsiType type = myBinding.substitute(myTypes.get(element)); + if (myBinding != null) { + PsiType type = myBinding.substitute(myTypes.get(element)); - String objectFQName = CommonClassNames.JAVA_LANG_OBJECT; - if (originalType.getCanonicalText().equals(objectFQName)) { - if (type == null) { - return originalType; - } + String objectFQName = CommonClassNames.JAVA_LANG_OBJECT; + if (originalType.getCanonicalText().equals(objectFQName)) { + if (type == null) { + return originalType; + } + + if (type instanceof PsiWildcardType wildcardType) { + PsiType bound = wildcardType.getBound(); - if (type instanceof PsiWildcardType){ - PsiType bound = ((PsiWildcardType)type).getBound(); + if (bound != null) { + return bound; + } - if (bound != null){ - return bound; - } + return originalType; + } + } - return originalType; + return type; } - } - return type; + return originalType; } - return originalType; - } + public Set getCookedElements() { + myCookedNumber = 0; - public HashSet getCookedElements() { - myCookedNumber = 0; + Set set = new HashSet<>(); - HashSet set = new HashSet(); + for (PsiElement element : myVictims) { + PsiType originalType = Util.getType(element); - for (PsiElement element : myVictims) { - PsiType originalType = Util.getType(element); + PsiType cookedType = getCookedType(element); + if (cookedType != null && !originalType.equals(cookedType)) { + set.add(element); + myCookedNumber++; + } + } + + if (mySettings.dropObsoleteCasts()) { + myCastsRemoved = 0; + if (myBinding != null) { + for (Map.Entry entry : myCastToOperandType.entrySet()) { + PsiTypeCastExpression cast = entry.getKey(); + PsiType operandType = myBinding.apply(entry.getValue()); + PsiType castType = cast.getType(); + if (!(operandType instanceof PsiTypeVariable) + && castType != null + && !isBottomArgument(operandType) + && castType.isAssignableFrom(operandType)) { + set.add(cast); + } + } + } + } - PsiType cookedType = getCookedType(element); - if (cookedType != null && !originalType.equals(cookedType)) { - set.add(element); - myCookedNumber++; - } + return set; } - if (mySettings.dropObsoleteCasts()) { - myCastsRemoved = 0; - if (myBinding != null) { - for (Map.Entry entry : myCastToOperandType.entrySet()) { - PsiTypeCastExpression cast = entry.getKey(); - PsiType operandType = myBinding.apply(entry.getValue()); - PsiType castType = cast.getType(); - if (!(operandType instanceof PsiTypeVariable) && castType != null && !isBottomArgument(operandType) && castType.isAssignableFrom(operandType)) { - set.add(cast); - } + private static boolean isBottomArgument(PsiType type) { + PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(type); + PsiClass clazz = resolveResult.getElement(); + if (clazz != null) { + for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable(clazz)) { + PsiType t = resolveResult.getSubstitutor().substitute(typeParameter); + if (t == Bottom.BOTTOM) { + return true; + } + } } - } - } - return set; - } - - private static boolean isBottomArgument(PsiType type) { - PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(type); - PsiClass clazz = resolveResult.getElement(); - if (clazz != null) { - for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable(clazz)) { - PsiType t = resolveResult.getSubstitutor().substitute(typeParameter); - if (t == Bottom.BOTTOM) return true; - } + return false; } - return false; - } - - public void apply(HashSet victims) { - for (PsiElement element : victims) { - if (element instanceof PsiTypeCastExpression && myCastToOperandType.containsKey(element)) { - PsiTypeCastExpression cast = ((PsiTypeCastExpression)element); - try { - cast.replace(cast.getOperand()); - myCastsRemoved++; + @RequiredWriteAction + public void apply(Set victims) { + for (PsiElement element : victims) { + if (element instanceof PsiTypeCastExpression cast && myCastToOperandType.containsKey(cast)) { + try { + cast.replace(cast.getOperand()); + myCastsRemoved++; + } + catch (IncorrectOperationException e1) { + LOG.error(e1); + } + } + else { + Util.changeType(element, getCookedType(element)); + } } - catch (IncorrectOperationException e1) { - LOG.error(e1); - } - - } else { - Util.changeType(element, getCookedType(element)); - } } - } - private String getRatio(int x, int y) { - String ratio = RefactoringBundle.message("type.cook.ratio.generified", x, y); - return ratio + (y != 0 ? " (" + (x * 100 / y) + "%)" : ""); - } + private String getRatio(int x, int y) { + String ratio = RefactoringBundle.message("type.cook.ratio.generified", x, y); + return ratio + (y != 0 ? " (" + (x * 100 / y) + "%)" : ""); + } - public String getReport() { - return RefactoringLocalize.typeCookReport(getRatio(myCookedNumber, myVictims.size()), getRatio(myCastsRemoved, myCastsNumber)).get(); - } + public String getReport() { + return RefactoringLocalize.typeCookReport( + getRatio(myCookedNumber, myVictims.size()), + getRatio(myCastsRemoved, myCastsNumber) + ).get(); + } } diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/typeMigration/TypeMigrationProcessor.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/typeMigration/TypeMigrationProcessor.java index 0fbf34221..0b79a41df 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/typeMigration/TypeMigrationProcessor.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/typeMigration/TypeMigrationProcessor.java @@ -28,6 +28,7 @@ import consulo.language.editor.refactoring.BaseRefactoringProcessor; import consulo.language.psi.*; import consulo.language.util.IncorrectOperationException; +import consulo.localize.LocalizeValue; import consulo.project.Project; import consulo.project.ui.wm.ToolWindowId; import consulo.project.ui.wm.ToolWindowManager; @@ -330,7 +331,7 @@ public TypeMigrationLabeler getLabeler() { @Nonnull @Override - protected String getCommandName() { - return "TypeMigration"; + protected LocalizeValue getCommandName() { + return LocalizeValue.localizeTODO("TypeMigration"); } } diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/util/duplicates/MethodDuplicatesHandler.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/util/duplicates/MethodDuplicatesHandler.java index ad297134f..abcad92a4 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/util/duplicates/MethodDuplicatesHandler.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/util/duplicates/MethodDuplicatesHandler.java @@ -22,18 +22,17 @@ import com.intellij.java.analysis.impl.refactoring.util.duplicates.VariableReturnValue; import com.intellij.java.impl.refactoring.HelpID; import com.intellij.java.language.psi.*; +import consulo.annotation.access.RequiredReadAction; import consulo.application.Application; -import consulo.application.ApplicationManager; +import consulo.application.ReadAction; import consulo.application.progress.ProgressIndicator; import consulo.application.progress.ProgressManager; import consulo.application.progress.Task; -import consulo.application.util.function.Computable; import consulo.codeEditor.Editor; import consulo.dataContext.DataContext; import consulo.ide.impl.idea.openapi.project.ProjectUtil; import consulo.language.codeStyle.PostprocessReformattingAspect; import consulo.language.editor.refactoring.ContextAwareActionHandler; -import consulo.language.editor.refactoring.RefactoringBundle; import consulo.language.editor.refactoring.action.RefactoringActionHandler; import consulo.language.editor.refactoring.localize.RefactoringLocalize; import consulo.language.editor.refactoring.util.CommonRefactoringUtil; @@ -45,14 +44,13 @@ import consulo.language.psi.PsiRecursiveElementVisitor; import consulo.language.psi.scope.LocalSearchScope; import consulo.language.psi.util.PsiTreeUtil; -import consulo.language.util.ModuleUtilCore; import consulo.localHistory.LocalHistory; import consulo.localHistory.LocalHistoryAction; import consulo.localize.LocalizeValue; import consulo.logging.Logger; import consulo.module.Module; +import consulo.module.content.util.ModuleContentUtil; import consulo.project.Project; -import consulo.project.ui.wm.WindowManager; import consulo.ui.annotation.RequiredUIAccess; import consulo.ui.ex.awt.Messages; import consulo.undoRedo.CommandProcessor; @@ -66,277 +64,285 @@ * @author dsl */ public class MethodDuplicatesHandler implements RefactoringActionHandler, ContextAwareActionHandler { - public static final String REFACTORING_NAME = RefactoringBundle.message("replace.method.code.duplicates.title"); - private static final Logger LOG = Logger.getInstance(MethodDuplicatesHandler.class); + public static final LocalizeValue REFACTORING_NAME = RefactoringLocalize.replaceMethodCodeDuplicatesTitle(); + private static final Logger LOG = Logger.getInstance(MethodDuplicatesHandler.class); - @Override - public boolean isAvailableForQuickList(@Nonnull Editor editor, @Nonnull PsiFile file, @Nonnull DataContext dataContext) { - PsiElement element = file.findElementAt(editor.getCaretModel().getOffset()); - return getCannotRefactorMessage(PsiTreeUtil.getParentOfType(element, PsiMember.class)) == null; - } - - @Override - @RequiredUIAccess - public void invoke(@Nonnull final Project project, Editor editor, PsiFile file, DataContext dataContext) { - int offset = editor.getCaretModel().getOffset(); - PsiElement element = file.findElementAt(offset); - final PsiMember member = PsiTreeUtil.getParentOfType(element, PsiMember.class); - String cannotRefactorMessage = getCannotRefactorMessage(member); - if (cannotRefactorMessage != null) { - String message = RefactoringLocalize.cannotPerformRefactoringWithReason(cannotRefactorMessage).get(); - showErrorMessage(message, project, editor); - return; + @Override + @RequiredReadAction + public boolean isAvailableForQuickList(@Nonnull Editor editor, @Nonnull PsiFile file, @Nonnull DataContext dataContext) { + PsiElement element = file.findElementAt(editor.getCaretModel().getOffset()); + return getCannotRefactorMessage(PsiTreeUtil.getParentOfType(element, PsiMember.class)) == null; } - final AnalysisScope scope = new AnalysisScope(file); - Module module = ModuleUtilCore.findModuleForPsiElement(file); - final BaseAnalysisActionDialog dlg = new BaseAnalysisActionDialog( - RefactoringLocalize.replaceMethodDuplicatesScopeChooserTitle(REFACTORING_NAME).get(), - RefactoringLocalize.replaceMethodDuplicatesScopeChooserMessage().get(), - project, - scope, - module != null ? module.getName() : null, - false, - AnalysisUIOptions.getInstance(project), - element - ); - if (dlg.showAndGet()) { - ProgressManager.getInstance().run(new Task.Backgroundable(project, "Locate duplicates", true) { - @Override - public void run(@Nonnull ProgressIndicator indicator) { - indicator.setIndeterminate(true); - invokeOnScope(project, member, dlg.getScope(scope)); + @Override + @RequiredUIAccess + public void invoke(@Nonnull final Project project, Editor editor, PsiFile file, DataContext dataContext) { + int offset = editor.getCaretModel().getOffset(); + PsiElement element = file.findElementAt(offset); + final PsiMember member = PsiTreeUtil.getParentOfType(element, PsiMember.class); + String cannotRefactorMessage = getCannotRefactorMessage(member); + if (cannotRefactorMessage != null) { + LocalizeValue message = RefactoringLocalize.cannotPerformRefactoringWithReason(cannotRefactorMessage); + showErrorMessage(message, project, editor); + return; } - }); - } - } - - @Nullable - private static String getCannotRefactorMessage(PsiMember member) { - if (member == null) { - return RefactoringLocalize.locateCaretInsideAMethod().get(); - } - if (member instanceof PsiMethod method) { - if (method.isConstructor()) { - return RefactoringLocalize.replaceWithMethodCallDoesNotWorkForConstructors().get(); - } - PsiCodeBlock body = method.getBody(); - if (body == null) { - return RefactoringLocalize.methodDoesNotHaveABody(member.getName()).get(); - } - PsiStatement[] statements = body.getStatements(); - if (statements.length == 0) { - return RefactoringLocalize.methodHasAnEmptyBody(member.getName()).get(); - } - } else if (member instanceof PsiField field) { - if (field.getInitializer() == null) { - return "Field " + member.getName() + " doesn't have initializer"; - } - PsiClass containingClass = field.getContainingClass(); - if (!field.hasModifierProperty(PsiModifier.FINAL) || !field.hasModifierProperty(PsiModifier.STATIC) || - containingClass == null || containingClass.getQualifiedName() == null) { - return "Replace Duplicates works with constants only"; - } - } else { - return "Caret should be inside method or constant"; - } - return null; - } - - public static void invokeOnScope(Project project, PsiMember member, AnalysisScope scope) { - invokeOnScope(project, Collections.singleton(member), scope, false); - } - public static void invokeOnScope(final Project project, final Set members, AnalysisScope scope, boolean silent) { - final Map> duplicates = new HashMap>(); - final int fileCount = scope.getFileCount(); - final ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator(); - if (progressIndicator != null) { - progressIndicator.setIndeterminate(false); + final AnalysisScope scope = new AnalysisScope(file); + Module module = file.getModule(); + final BaseAnalysisActionDialog dlg = new BaseAnalysisActionDialog( + RefactoringLocalize.replaceMethodDuplicatesScopeChooserTitle(REFACTORING_NAME).get(), + RefactoringLocalize.replaceMethodDuplicatesScopeChooserMessage().get(), + project, + scope, + module != null ? module.getName() : null, + false, + AnalysisUIOptions.getInstance(project), + element + ); + if (dlg.showAndGet()) { + ProgressManager.getInstance().run(new Task.Backgroundable(project, "Locate duplicates", true) { + @Override + public void run(@Nonnull ProgressIndicator indicator) { + indicator.setIndeterminate(true); + invokeOnScope(project, member, dlg.getScope(scope)); + } + }); + } } - final Map> memberWithModulesMap = new HashMap>(); - for (final PsiMember member : members) { - final Module module = ApplicationManager.getApplication().runReadAction(new Computable() { - @Override - public Module compute() { - return ModuleUtilCore.findModuleForPsiElement(member); + @Nullable + private static String getCannotRefactorMessage(PsiMember member) { + if (member == null) { + return RefactoringLocalize.locateCaretInsideAMethod().get(); } - }); - if (module != null) { - final HashSet dependencies = new HashSet(); - ApplicationManager.getApplication().runReadAction(new Runnable() { - public void run() { - ModuleUtilCore.collectModulesDependsOn(module, dependencies); - } - }); - memberWithModulesMap.put(member, dependencies); - } + if (member instanceof PsiMethod method) { + if (method.isConstructor()) { + return RefactoringLocalize.replaceWithMethodCallDoesNotWorkForConstructors().get(); + } + PsiCodeBlock body = method.getBody(); + if (body == null) { + return RefactoringLocalize.methodDoesNotHaveABody(member.getName()).get(); + } + PsiStatement[] statements = body.getStatements(); + if (statements.length == 0) { + return RefactoringLocalize.methodHasAnEmptyBody(member.getName()).get(); + } + } + else if (member instanceof PsiField field) { + if (field.getInitializer() == null) { + return "Field " + member.getName() + " doesn't have initializer"; + } + PsiClass containingClass = field.getContainingClass(); + if (!field.isFinal() || !field.isStatic() || containingClass == null || containingClass.getQualifiedName() == null) { + return "Replace Duplicates works with constants only"; + } + } + else { + return "Caret should be inside method or constant"; + } + return null; } - scope.accept(new PsiRecursiveElementVisitor() { - private int myFileCount = 0; + public static void invokeOnScope(Project project, PsiMember member, AnalysisScope scope) { + invokeOnScope(project, Collections.singleton(member), scope, false); + } - @Override - public void visitFile(PsiFile file) { + public static void invokeOnScope(final Project project, final Set members, AnalysisScope scope, boolean silent) { + final Map> duplicates = new HashMap<>(); + final int fileCount = scope.getFileCount(); + final ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator(); if (progressIndicator != null) { - if (progressIndicator.isCanceled()) { - return; - } - progressIndicator.setFraction(((double) myFileCount++) / fileCount); - VirtualFile virtualFile = file.getVirtualFile(); - if (virtualFile != null) { - progressIndicator.setText2(ProjectUtil.calcRelativeToProjectPath(virtualFile, project)); - } + progressIndicator.setIndeterminate(false); } - Module targetModule = ModuleUtilCore.findModuleForPsiElement(file); - if (targetModule == null) { - return; + + final Map> memberWithModulesMap = new HashMap<>(); + for (PsiMember member : members) { + Module module = ReadAction.compute(member::getModule); + if (module != null) { + Set dependencies = new HashSet<>(); + ReadAction.run(() -> ModuleContentUtil.collectModulesDependsOn(module, dependencies)); + memberWithModulesMap.put(member, dependencies); + } } - for (Map.Entry> entry : memberWithModulesMap.entrySet()) { - Set dependencies = entry.getValue(); - if (dependencies == null || !dependencies.contains(targetModule)) { - continue; - } - PsiMember method = entry.getKey(); - List matchList = hasDuplicates(file, method); - for (Iterator iterator = matchList.iterator(); iterator.hasNext(); ) { - Match match = iterator.next(); - PsiElement matchStart = match.getMatchStart(); - PsiElement matchEnd = match.getMatchEnd(); - for (PsiMember psiMember : members) { - if (PsiTreeUtil.isAncestor(psiMember, matchStart, false) || PsiTreeUtil.isAncestor(psiMember, matchEnd, false)) { - iterator.remove(); - break; - } + scope.accept(new PsiRecursiveElementVisitor() { + private int myFileCount = 0; + + @Override + @RequiredReadAction + public void visitFile(PsiFile file) { + if (progressIndicator != null) { + if (progressIndicator.isCanceled()) { + return; + } + progressIndicator.setFraction(((double) myFileCount++) / fileCount); + VirtualFile virtualFile = file.getVirtualFile(); + if (virtualFile != null) { + progressIndicator.setText2(ProjectUtil.calcRelativeToProjectPath(virtualFile, project)); + } + } + Module targetModule = file.getModule(); + if (targetModule == null) { + return; + } + for (Map.Entry> entry : memberWithModulesMap.entrySet()) { + Set dependencies = entry.getValue(); + if (dependencies == null || !dependencies.contains(targetModule)) { + continue; + } + + PsiMember method = entry.getKey(); + List matchList = hasDuplicates(file, method); + for (Iterator iterator = matchList.iterator(); iterator.hasNext(); ) { + Match match = iterator.next(); + PsiElement matchStart = match.getMatchStart(); + PsiElement matchEnd = match.getMatchEnd(); + for (PsiMember psiMember : members) { + if (PsiTreeUtil.isAncestor(psiMember, matchStart, false) || PsiTreeUtil.isAncestor( + psiMember, + matchEnd, + false + )) { + iterator.remove(); + break; + } + } + } + if (!matchList.isEmpty()) { + List matches = duplicates.get(method); + if (matches == null) { + matches = new ArrayList<>(); + duplicates.put(method, matches); + } + matches.addAll(matchList); + } + } } - } - if (!matchList.isEmpty()) { - List matches = duplicates.get(method); - if (matches == null) { - matches = new ArrayList(); - duplicates.put(method, matches); + }); + if (duplicates.isEmpty()) { + if (!silent) { + Application application = Application.get(); + Runnable nothingFoundRunnable = () -> { + LocalizeValue message = + RefactoringLocalize.ideaHasNotFoundAnyCodeThatCanBeReplacedWithMethodCall(application.getName()); + Messages.showInfoMessage(project, message.get(), REFACTORING_NAME.get()); + }; + if (application.isUnitTestMode()) { + nothingFoundRunnable.run(); + } + else { + application.invokeLater(nothingFoundRunnable, application.getNoneModalityState()); + } } - matches.addAll(matchList); - } } - } - }); - if (duplicates.isEmpty()) { - if (!silent) { - Runnable nothingFoundRunnable = () -> { - LocalizeValue message = RefactoringLocalize.ideaHasNotFoundAnyCodeThatCanBeReplacedWithMethodCall(Application.get().getName()); - Messages.showInfoMessage(project, message.get(), REFACTORING_NAME); - }; - if (ApplicationManager.getApplication().isUnitTestMode()) { - nothingFoundRunnable.run(); - } else { - ApplicationManager.getApplication().invokeLater(nothingFoundRunnable, Application.get().getNoneModalityState()); + else { + replaceDuplicate(project, duplicates, members); } - } - } else { - replaceDuplicate(project, duplicates, members); } - } - private static void replaceDuplicate(final Project project, final Map> duplicates, final Set methods) { - ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator(); - if (progressIndicator != null && progressIndicator.isCanceled()) { - return; - } + private static void replaceDuplicate(Project project, Map> duplicates, Set methods) { + ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator(); + if (progressIndicator != null && progressIndicator.isCanceled()) { + return; + } - Runnable replaceRunnable = new Runnable() { - @Override - public void run() { - LocalHistoryAction a = LocalHistory.getInstance().startAction(REFACTORING_NAME); - try { - for (final PsiMember member : methods) { - final List matches = duplicates.get(member); - if (matches == null) { - continue; + Runnable replaceRunnable = () -> { + LocalHistoryAction a = LocalHistory.getInstance().startAction(REFACTORING_NAME); + try { + for (PsiMember member : methods) { + List matches = duplicates.get(member); + if (matches == null) { + continue; + } + int duplicatesNo = matches.size(); + CommandProcessor.getInstance().newCommand() + .project(project) + .name(REFACTORING_NAME) + .groupId(REFACTORING_NAME) + .run(() -> PostprocessReformattingAspect.getInstance(project).postponeFormattingInside(() -> { + MatchProvider matchProvider = member instanceof PsiMethod method + ? new MethodDuplicatesMatchProvider(method, matches) + : new ConstantMatchProvider(member, project, matches); + DuplicatesImpl.invoke(project, matchProvider); + })); + } } - int duplicatesNo = matches.size(); - CommandProcessor.getInstance().executeCommand(project, new Runnable() { - @Override - public void run() { - PostprocessReformattingAspect.getInstance(project).postponeFormattingInside(new Runnable() { - @Override - public void run() { - MatchProvider matchProvider = member instanceof PsiMethod ? new MethodDuplicatesMatchProvider((PsiMethod) member, - matches) : new ConstantMatchProvider(member, project, matches); - DuplicatesImpl.invoke(project, matchProvider); - } - }); - } - }, REFACTORING_NAME, REFACTORING_NAME); - } - } finally { - a.finish(); + finally { + a.finish(); + } + }; + Application application = Application.get(); + application.invokeLater(replaceRunnable, application.getNoneModalityState()); + } + + @RequiredReadAction + public static List hasDuplicates(PsiFile file, PsiMember member) { + DuplicatesFinder duplicatesFinder = createDuplicatesFinder(member); + if (duplicatesFinder == null) { + return Collections.emptyList(); } - } - }; - ApplicationManager.getApplication().invokeLater(replaceRunnable, Application.get().getNoneModalityState()); - } - public static List hasDuplicates(PsiFile file, PsiMember member) { - DuplicatesFinder duplicatesFinder = createDuplicatesFinder(member); - if (duplicatesFinder == null) { - return Collections.emptyList(); + return duplicatesFinder.findDuplicates(file); } - return duplicatesFinder.findDuplicates(file); - } - - @Nullable - public static DuplicatesFinder createDuplicatesFinder(PsiMember member) { - PsiElement[] pattern; - ReturnValue matchedReturnValue = null; - if (member instanceof PsiMethod) { - PsiCodeBlock body = ((PsiMethod) member).getBody(); - LOG.assertTrue(body != null); - PsiStatement[] statements = body.getStatements(); - pattern = statements; - matchedReturnValue = null; - if (statements.length != 1 || !(statements[0] instanceof PsiReturnStatement)) { - PsiStatement lastStatement = statements.length > 0 ? statements[statements.length - 1] : null; - if (lastStatement instanceof PsiReturnStatement) { - PsiExpression returnValue = ((PsiReturnStatement) lastStatement).getReturnValue(); - if (returnValue instanceof PsiReferenceExpression) { - PsiElement resolved = ((PsiReferenceExpression) returnValue).resolve(); - if (resolved instanceof PsiVariable) { - pattern = new PsiElement[statements.length - 1]; - System.arraycopy(statements, 0, pattern, 0, statements.length - 1); - matchedReturnValue = new VariableReturnValue((PsiVariable) resolved); + @Nullable + @RequiredReadAction + public static DuplicatesFinder createDuplicatesFinder(PsiMember member) { + PsiElement[] pattern; + ReturnValue matchedReturnValue = null; + if (member instanceof PsiMethod method) { + PsiCodeBlock body = method.getBody(); + LOG.assertTrue(body != null); + PsiStatement[] statements = body.getStatements(); + pattern = statements; + matchedReturnValue = null; + if (statements.length != 1 || !(statements[0] instanceof PsiReturnStatement)) { + if (statements.length > 0 + && statements[statements.length - 1] instanceof PsiReturnStatement returnStmt + && returnStmt.getReturnValue() instanceof PsiReferenceExpression returnRef + && returnRef.resolve() instanceof PsiVariable variable) { + pattern = new PsiElement[statements.length - 1]; + System.arraycopy(statements, 0, pattern, 0, statements.length - 1); + matchedReturnValue = new VariableReturnValue(variable); + } + } + else { + PsiExpression returnValue = ((PsiReturnStatement) statements[0]).getReturnValue(); + if (returnValue != null) { + pattern = new PsiElement[]{returnValue}; + } } - } } - } else { - PsiExpression returnValue = ((PsiReturnStatement) statements[0]).getReturnValue(); - if (returnValue != null) { - pattern = new PsiElement[]{returnValue}; + else { + pattern = new PsiElement[]{((PsiField) member).getInitializer()}; } - } - } else { - pattern = new PsiElement[]{((PsiField) member).getInitializer()}; - } - if (pattern.length == 0) { - return null; + if (pattern.length == 0) { + return null; + } + + List inputVariables = member instanceof PsiMethod method + ? Arrays.asList(method.getParameterList().getParameters()) + : new ArrayList<>(); + return new DuplicatesFinder( + pattern, + new InputVariables(inputVariables, member.getProject(), new LocalSearchScope(pattern), false), + matchedReturnValue, + new ArrayList<>() + ); } - List inputVariables = member instanceof PsiMethod ? Arrays.asList(((PsiMethod) member).getParameterList().getParameters()) : new ArrayList(); - return new DuplicatesFinder(pattern, new InputVariables(inputVariables, member.getProject(), new LocalSearchScope(pattern), false), matchedReturnValue, new ArrayList()); - } - static String getStatusMessage(int duplicatesNo) { - return RefactoringLocalize.methodDuplicatesFoundMessage(duplicatesNo).get(); - } + static LocalizeValue getStatusMessage(int duplicatesNo) { + return RefactoringLocalize.methodDuplicatesFoundMessage(duplicatesNo); + } - private static void showErrorMessage(String message, Project project, Editor editor) { - CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.METHOD_DUPLICATES); - } + @RequiredUIAccess + private static void showErrorMessage(@Nonnull LocalizeValue message, Project project, Editor editor) { + CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.METHOD_DUPLICATES); + } - @Override - public void invoke(@Nonnull Project project, @Nonnull PsiElement[] elements, DataContext dataContext) { - throw new UnsupportedOperationException(); - } + @Override + @RequiredUIAccess + public void invoke(@Nonnull Project project, @Nonnull PsiElement[] elements, DataContext dataContext) { + throw new UnsupportedOperationException(); + } } diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/wrapreturnvalue/WrapReturnValueProcessor.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/wrapreturnvalue/WrapReturnValueProcessor.java index 5bfca68e1..29358377e 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/wrapreturnvalue/WrapReturnValueProcessor.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/wrapreturnvalue/WrapReturnValueProcessor.java @@ -59,7 +59,7 @@ import java.util.Set; public class WrapReturnValueProcessor extends FixableUsagesRefactoringProcessor { - private static final Logger LOG = Logger.getInstance("com.siyeh.rpp.wrapreturnvalue.WrapReturnValueProcessor"); + private static final Logger LOG = Logger.getInstance(WrapReturnValueProcessor.class); private MoveDestination myMoveDestination; private final PsiMethod method; @@ -140,8 +140,7 @@ public void findUsages(@Nonnull List usages) { @RequiredReadAction private void findUsagesForMethod(PsiMethod psiMethod, List usages) { for (PsiReference reference : ReferencesSearch.search(psiMethod, psiMethod.getUseScope())) { - PsiElement referenceElement = reference.getElement(); - if (referenceElement.getParent() instanceof PsiCallExpression callExpr) { + if (reference.getElement().getParent() instanceof PsiCallExpression callExpr) { usages.add(new UnwrapCall(callExpr, unwrapMethodName)); } } @@ -333,9 +332,9 @@ private boolean buildClass() { @Nonnull @Override @RequiredReadAction - protected String getCommandName() { + protected LocalizeValue getCommandName() { PsiClass containingClass = method.getContainingClass(); - return JavaRefactoringLocalize.wrappedReturnCommandName(className, containingClass.getName(), '.', method.getName()).get(); + return JavaRefactoringLocalize.wrappedReturnCommandName(className, containingClass.getName(), '.', method.getName()); } private class ReturnSearchVisitor extends JavaRecursiveElementWalkingVisitor {