From 955ab2e7d365f8324a3ab71934acdb8d7a811e1f Mon Sep 17 00:00:00 2001 From: UNV Date: Fri, 14 Nov 2025 02:58:05 +0300 Subject: [PATCH 1/2] Localizing inline inspections/refactorings. --- .../java/impl/ig/fixes/InlineCallFix.java | 45 +- .../CallToSimpleGetterInClassInspection.java | 269 +++++---- .../CallToSimpleSetterInClassInspection.java | 279 ++++----- .../inline/InlineConstantFieldHandler.java | 120 ++-- .../inline/InlineConstantFieldProcessor.java | 45 +- .../refactoring/inline/InlineFieldDialog.java | 174 +++--- .../inline/InlineLocalHandler.java | 550 +++++++++--------- .../inline/InlineMethodDialog.java | 219 +++---- .../inline/InlineMethodHandler.java | 270 +++++---- .../inline/InlineMethodProcessor.java | 32 +- .../inline/InlineParameterDialog.java | 99 ++-- .../InlineParameterExpressionProcessor.java | 2 +- .../inline/InlineParameterHandler.java | 459 ++++++++------- .../impl/refactoring/psi/MutationUtils.java | 155 +++-- .../usageInfo/InlineDelegatingCall.java | 82 +-- .../consulo.java.JavaRefactoringLocalize.yaml | 12 + 16 files changed, 1451 insertions(+), 1361 deletions(-) diff --git a/plugin/src/main/java/com/intellij/java/impl/ig/fixes/InlineCallFix.java b/plugin/src/main/java/com/intellij/java/impl/ig/fixes/InlineCallFix.java index d33d6798f8..98ae1bcd3a 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ig/fixes/InlineCallFix.java +++ b/plugin/src/main/java/com/intellij/java/impl/ig/fixes/InlineCallFix.java @@ -20,7 +20,7 @@ import com.intellij.java.language.psi.PsiReferenceExpression; import com.siyeh.ig.InspectionGadgetsFix; import com.siyeh.localize.InspectionGadgetsLocalize; -import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.application.Application; import consulo.language.editor.inspection.ProblemDescriptor; import consulo.language.editor.refactoring.action.RefactoringActionHandler; @@ -30,27 +30,28 @@ import jakarta.annotation.Nonnull; public class InlineCallFix extends InspectionGadgetsFix { - - @Nonnull - public LocalizeValue getName() { - return InspectionGadgetsLocalize.inlineCallQuickfix(); - } - - @RequiredReadAction - public void doFix(final Project project, ProblemDescriptor descriptor) { - final PsiElement nameElement = descriptor.getPsiElement(); - final PsiReferenceExpression methodExpression = (PsiReferenceExpression)nameElement.getParent(); - assert methodExpression != null; - final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)methodExpression.getParent(); - final JavaRefactoringActionHandlerFactory factory = JavaRefactoringActionHandlerFactory.getInstance(); - final RefactoringActionHandler inlineHandler = factory.createInlineHandler(); - final Runnable runnable = () -> inlineHandler.invoke(project, new PsiElement[]{methodCallExpression}, null); - final Application application = project.getApplication(); - if (application.isUnitTestMode()) { - runnable.run(); + @Nonnull + @Override + public LocalizeValue getName() { + return InspectionGadgetsLocalize.inlineCallQuickfix(); } - else { - application.invokeLater(runnable, project.getDisposed()); + + @Override + @RequiredWriteAction + public void doFix(Project project, ProblemDescriptor descriptor) { + PsiElement nameElement = descriptor.getPsiElement(); + PsiReferenceExpression methodExpression = (PsiReferenceExpression) nameElement.getParent(); + assert methodExpression != null; + PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression) methodExpression.getParent(); + JavaRefactoringActionHandlerFactory factory = JavaRefactoringActionHandlerFactory.getInstance(); + RefactoringActionHandler inlineHandler = factory.createInlineHandler(); + Runnable runnable = () -> inlineHandler.invoke(project, new PsiElement[]{methodCallExpression}, null); + Application application = project.getApplication(); + if (application.isUnitTestMode()) { + runnable.run(); + } + else { + application.invokeLater(runnable, project.getDisposed()); + } } - } } diff --git a/plugin/src/main/java/com/intellij/java/impl/ig/performance/CallToSimpleGetterInClassInspection.java b/plugin/src/main/java/com/intellij/java/impl/ig/performance/CallToSimpleGetterInClassInspection.java index c692c02bb3..6f47b3eec8 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ig/performance/CallToSimpleGetterInClassInspection.java +++ b/plugin/src/main/java/com/intellij/java/impl/ig/performance/CallToSimpleGetterInClassInspection.java @@ -23,6 +23,7 @@ import com.siyeh.ig.InspectionGadgetsFix; import com.siyeh.ig.psiutils.ClassUtils; import com.siyeh.localize.InspectionGadgetsLocalize; +import consulo.annotation.access.RequiredWriteAction; import consulo.annotation.component.ExtensionImpl; import consulo.application.util.query.Query; import consulo.deadCodeNotWorking.impl.MultipleCheckboxOptionsPanel; @@ -38,157 +39,149 @@ @ExtensionImpl public class CallToSimpleGetterInClassInspection extends BaseInspection { + @SuppressWarnings("UnusedDeclaration") + public boolean ignoreGetterCallsOnOtherObjects = false; - @SuppressWarnings("UnusedDeclaration") - public boolean ignoreGetterCallsOnOtherObjects = false; + @SuppressWarnings("UnusedDeclaration") + public boolean onlyReportPrivateGetter = false; - @SuppressWarnings("UnusedDeclaration") - public boolean onlyReportPrivateGetter = false; - - @Override - @Nonnull - public String getID() { - return "CallToSimpleGetterFromWithinClass"; - } - - @Override - @Nonnull - public LocalizeValue getDisplayName() { - return InspectionGadgetsLocalize.callToSimpleGetterInClassDisplayName(); - } - - @Override - @Nonnull - public String buildErrorString(Object... infos) { - return InspectionGadgetsLocalize.callToSimpleGetterInClassProblemDescriptor().get(); - } - - @Override - @Nullable - public JComponent createOptionsPanel() { - final MultipleCheckboxOptionsPanel optionsPanel = new MultipleCheckboxOptionsPanel(this); - optionsPanel.addCheckbox( - InspectionGadgetsLocalize.callToSimpleGetterInClassIgnoreOption().get(), - "ignoreGetterCallsOnOtherObjects" - ); - optionsPanel.addCheckbox(InspectionGadgetsLocalize.callToPrivateSimpleGetterInClassOption().get(), "onlyReportPrivateGetter"); - return optionsPanel; - } - - @Override - public InspectionGadgetsFix buildFix(Object... infos) { - return new InlineCallFix(); - } + @Override + @Nonnull + public String getID() { + return "CallToSimpleGetterFromWithinClass"; + } - private static class InlineCallFix extends InspectionGadgetsFix { + @Override @Nonnull - public LocalizeValue getName() { - return InspectionGadgetsLocalize.callToSimpleGetterInClassInlineQuickfix(); + public LocalizeValue getDisplayName() { + return InspectionGadgetsLocalize.callToSimpleGetterInClassDisplayName(); } @Override - public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException { - final PsiElement methodIdentifier = descriptor.getPsiElement(); - final PsiReferenceExpression methodExpression = (PsiReferenceExpression)methodIdentifier.getParent(); - if (methodExpression == null) { - return; - } - final PsiMethodCallExpression call = (PsiMethodCallExpression)methodExpression.getParent(); - if (call == null) { - return; - } - final PsiMethod method = call.resolveMethod(); - if (method == null) { - return; - } - final PsiCodeBlock body = method.getBody(); - if (body == null) { - return; - } - final PsiStatement[] statements = body.getStatements(); - final PsiReturnStatement returnStatement = (PsiReturnStatement)statements[0]; - final PsiExpression returnValue = returnStatement.getReturnValue(); - if (!(returnValue instanceof PsiReferenceExpression)) { - return; - } - final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)returnValue; - final PsiField field = (PsiField)referenceExpression.resolve(); - if (field == null) { - return; - } - final String fieldName = field.getName(); - if (fieldName == null) { - return; - } - final PsiExpression qualifier = methodExpression.getQualifierExpression(); - if (qualifier == null) { - final JavaPsiFacade facade = JavaPsiFacade.getInstance(call.getProject()); - final PsiResolveHelper resolveHelper = facade.getResolveHelper(); - final PsiVariable variable = resolveHelper.resolveReferencedVariable(fieldName, call); - if (variable == null) { - return; - } - if (variable.equals(field)) { - replaceExpression(call, fieldName); - } - else { - replaceExpression(call, "this." + fieldName); - } - } - else { - replaceExpression(call, qualifier.getText() + '.' + fieldName); - } + @Nonnull + public String buildErrorString(Object... infos) { + return InspectionGadgetsLocalize.callToSimpleGetterInClassProblemDescriptor().get(); } - } - @Override - public BaseInspectionVisitor buildVisitor() { - return new CallToSimpleGetterInClassVisitor(); - } + @Override + @Nullable + public JComponent createOptionsPanel() { + MultipleCheckboxOptionsPanel optionsPanel = new MultipleCheckboxOptionsPanel(this); + optionsPanel.addCheckbox( + InspectionGadgetsLocalize.callToSimpleGetterInClassIgnoreOption().get(), + "ignoreGetterCallsOnOtherObjects" + ); + optionsPanel.addCheckbox(InspectionGadgetsLocalize.callToPrivateSimpleGetterInClassOption().get(), "onlyReportPrivateGetter"); + return optionsPanel; + } - private class CallToSimpleGetterInClassVisitor extends BaseInspectionVisitor { @Override - public void visitMethodCallExpression(@Nonnull PsiMethodCallExpression call) { - super.visitMethodCallExpression(call); - final PsiClass containingClass = ClassUtils.getContainingClass(call); - if (containingClass == null) { - return; - } - final PsiMethod method = call.resolveMethod(); - if (method == null) { - return; - } - if (!containingClass.equals(method.getContainingClass())) { - return; - } - final PsiReferenceExpression methodExpression = call.getMethodExpression(); - final PsiExpression qualifier = methodExpression.getQualifierExpression(); - if (qualifier != null && !(qualifier instanceof PsiThisExpression)) { - if (ignoreGetterCallsOnOtherObjects) { - return; + public InspectionGadgetsFix buildFix(Object... infos) { + return new InlineCallFix(); + } + + private static class InlineCallFix extends InspectionGadgetsFix { + @Nonnull + @Override + public LocalizeValue getName() { + return InspectionGadgetsLocalize.callToSimpleGetterInClassInlineQuickfix(); } - final PsiType type = qualifier.getType(); - if (!(type instanceof PsiClassType)) { - return; + + @Override + @RequiredWriteAction + public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException { + PsiElement methodIdentifier = descriptor.getPsiElement(); + PsiReferenceExpression methodExpression = (PsiReferenceExpression) methodIdentifier.getParent(); + if (methodExpression == null) { + return; + } + PsiMethodCallExpression call = (PsiMethodCallExpression) methodExpression.getParent(); + if (call == null) { + return; + } + PsiMethod method = call.resolveMethod(); + if (method == null) { + return; + } + PsiCodeBlock body = method.getBody(); + if (body == null) { + return; + } + PsiStatement[] statements = body.getStatements(); + PsiReturnStatement returnStatement = (PsiReturnStatement) statements[0]; + if (!(returnStatement.getReturnValue() instanceof PsiReferenceExpression refExpr + && refExpr.resolve() instanceof PsiField field)) { + return; + } + String fieldName = field.getName(); + if (fieldName == null) { + return; + } + PsiExpression qualifier = methodExpression.getQualifierExpression(); + if (qualifier == null) { + JavaPsiFacade facade = JavaPsiFacade.getInstance(call.getProject()); + PsiResolveHelper resolveHelper = facade.getResolveHelper(); + PsiVariable variable = resolveHelper.resolveReferencedVariable(fieldName, call); + if (variable == null) { + return; + } + if (variable.equals(field)) { + replaceExpression(call, fieldName); + } + else { + replaceExpression(call, "this." + fieldName); + } + } + else { + replaceExpression(call, qualifier.getText() + '.' + fieldName); + } } - final PsiClassType classType = (PsiClassType)type; - final PsiClass qualifierClass = classType.resolve(); - if (!containingClass.equals(qualifierClass)) { - return; + } + + @Override + public BaseInspectionVisitor buildVisitor() { + return new CallToSimpleGetterInClassVisitor(); + } + + private class CallToSimpleGetterInClassVisitor extends BaseInspectionVisitor { + @Override + public void visitMethodCallExpression(@Nonnull PsiMethodCallExpression call) { + super.visitMethodCallExpression(call); + PsiClass containingClass = ClassUtils.getContainingClass(call); + if (containingClass == null) { + return; + } + PsiMethod method = call.resolveMethod(); + if (method == null) { + return; + } + if (!containingClass.equals(method.getContainingClass())) { + return; + } + PsiReferenceExpression methodExpression = call.getMethodExpression(); + PsiExpression qualifier = methodExpression.getQualifierExpression(); + if (qualifier != null && !(qualifier instanceof PsiThisExpression)) { + if (ignoreGetterCallsOnOtherObjects + || !(qualifier.getType() instanceof PsiClassType classType)) { + return; + } + PsiClass qualifierClass = classType.resolve(); + if (!containingClass.equals(qualifierClass)) { + return; + } + } + if (!PropertyUtil.isSimpleGetter(method)) { + return; + } + if (onlyReportPrivateGetter && !method.isPrivate()) { + return; + } + Query query = OverridingMethodsSearch.search(method, true); + PsiMethod overridingMethod = query.findFirst(); + if (overridingMethod != null) { + return; + } + registerMethodCallError(call); } - } - if (!PropertyUtil.isSimpleGetter(method)) { - return; - } - if (onlyReportPrivateGetter && !method.hasModifierProperty(PsiModifier.PRIVATE)) { - return; - } - final Query query = OverridingMethodsSearch.search(method, true); - final PsiMethod overridingMethod = query.findFirst(); - if (overridingMethod != null) { - return; - } - registerMethodCallError(call); } - } } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/java/impl/ig/performance/CallToSimpleSetterInClassInspection.java b/plugin/src/main/java/com/intellij/java/impl/ig/performance/CallToSimpleSetterInClassInspection.java index 20dcf60b13..7f15dcdfd4 100644 --- a/plugin/src/main/java/com/intellij/java/impl/ig/performance/CallToSimpleSetterInClassInspection.java +++ b/plugin/src/main/java/com/intellij/java/impl/ig/performance/CallToSimpleSetterInClassInspection.java @@ -23,6 +23,7 @@ import com.siyeh.ig.InspectionGadgetsFix; import com.siyeh.ig.psiutils.ClassUtils; import com.siyeh.localize.InspectionGadgetsLocalize; +import consulo.annotation.access.RequiredWriteAction; import consulo.annotation.component.ExtensionImpl; import consulo.application.util.query.Query; import consulo.deadCodeNotWorking.impl.MultipleCheckboxOptionsPanel; @@ -33,162 +34,164 @@ import consulo.project.Project; import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; -import org.jetbrains.annotations.NonNls; import javax.swing.*; @ExtensionImpl public class CallToSimpleSetterInClassInspection extends BaseInspection { + @SuppressWarnings("UnusedDeclaration") + public boolean ignoreSetterCallsOnOtherObjects = false; - @SuppressWarnings("UnusedDeclaration") - public boolean ignoreSetterCallsOnOtherObjects = false; + @SuppressWarnings("UnusedDeclaration") + public boolean onlyReportPrivateSetter = false; - @SuppressWarnings("UnusedDeclaration") - public boolean onlyReportPrivateSetter = false; - - @Nonnull - public String getID() { - return "CallToSimpleSetterFromWithinClass"; - } - - @Nonnull - public LocalizeValue getDisplayName() { - return InspectionGadgetsLocalize.callToSimpleSetterInClassDisplayName(); - } - - @Nonnull - public String buildErrorString(Object... infos) { - return InspectionGadgetsLocalize.callToSimpleSetterInClassProblemDescriptor().get(); - } + @Nonnull + @Override + public String getID() { + return "CallToSimpleSetterFromWithinClass"; + } - @Nullable - public JComponent createOptionsPanel() { - final MultipleCheckboxOptionsPanel optionsPanel = new MultipleCheckboxOptionsPanel(this); - optionsPanel.addCheckbox( - InspectionGadgetsLocalize.callToSimpleSetterInClassIgnoreOption().get(), - "ignoreSetterCallsOnOtherObjects" - ); - optionsPanel.addCheckbox( - InspectionGadgetsLocalize.callToPrivateSetterInClassOption().get(), - "onlyReportPrivateSetter" - ); - return optionsPanel; - } + @Nonnull + @Override + public LocalizeValue getDisplayName() { + return InspectionGadgetsLocalize.callToSimpleSetterInClassDisplayName(); + } - public InspectionGadgetsFix buildFix(Object... infos) { - return new InlineCallFix(); - } + @Nonnull + @Override + public String buildErrorString(Object... infos) { + return InspectionGadgetsLocalize.callToSimpleSetterInClassProblemDescriptor().get(); + } - private static class InlineCallFix extends InspectionGadgetsFix { + @Nullable + @Override + public JComponent createOptionsPanel() { + MultipleCheckboxOptionsPanel optionsPanel = new MultipleCheckboxOptionsPanel(this); + optionsPanel.addCheckbox( + InspectionGadgetsLocalize.callToSimpleSetterInClassIgnoreOption().get(), + "ignoreSetterCallsOnOtherObjects" + ); + optionsPanel.addCheckbox( + InspectionGadgetsLocalize.callToPrivateSetterInClassOption().get(), + "onlyReportPrivateSetter" + ); + return optionsPanel; + } - @Nonnull - public LocalizeValue getName() { - return InspectionGadgetsLocalize.callToSimpleSetterInClassInlineQuickfix(); + @Override + public InspectionGadgetsFix buildFix(Object... infos) { + return new InlineCallFix(); } - public void doFix(Project project, ProblemDescriptor descriptor) - throws IncorrectOperationException { - final PsiElement methodIdentifier = descriptor.getPsiElement(); - final PsiReferenceExpression methodExpression = (PsiReferenceExpression)methodIdentifier.getParent(); - if (methodExpression == null) { - return; - } - final PsiMethodCallExpression call = (PsiMethodCallExpression)methodExpression.getParent(); - if (call == null) { - return; - } - final PsiExpressionList argumentList = call.getArgumentList(); - final PsiExpression[] arguments = argumentList.getExpressions(); - final PsiExpression argument = arguments[0]; - final PsiMethod method = call.resolveMethod(); - if (method == null) { - return; - } - final PsiCodeBlock body = method.getBody(); - if (body == null) { - return; - } - final PsiStatement[] statements = body.getStatements(); - final PsiExpressionStatement assignmentStatement = (PsiExpressionStatement)statements[0]; - final PsiAssignmentExpression assignment = (PsiAssignmentExpression)assignmentStatement.getExpression(); - final PsiExpression qualifier = methodExpression.getQualifierExpression(); - final PsiReferenceExpression lhs = (PsiReferenceExpression)assignment.getLExpression(); - final PsiField field = (PsiField)lhs.resolve(); - if (field == null) { - return; - } - final String fieldName = field.getName(); - if (qualifier == null) { - final JavaPsiFacade manager = JavaPsiFacade.getInstance(call.getProject()); - final PsiResolveHelper resolveHelper = manager.getResolveHelper(); - final PsiVariable variable = resolveHelper.resolveReferencedVariable(fieldName, call); - if (variable == null) { - return; - } - @NonNls final String newExpression; - if (variable.equals(field)) { - newExpression = fieldName + " = " + argument.getText(); + private static class InlineCallFix extends InspectionGadgetsFix { + @Nonnull + @Override + public LocalizeValue getName() { + return InspectionGadgetsLocalize.callToSimpleSetterInClassInlineQuickfix(); } - else { - newExpression = "this." + fieldName + " = " + argument.getText(); + + @Override + @RequiredWriteAction + public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException { + PsiElement methodIdentifier = descriptor.getPsiElement(); + PsiReferenceExpression methodExpression = (PsiReferenceExpression) methodIdentifier.getParent(); + if (methodExpression == null) { + return; + } + PsiMethodCallExpression call = (PsiMethodCallExpression) methodExpression.getParent(); + if (call == null) { + return; + } + PsiExpressionList argumentList = call.getArgumentList(); + PsiExpression[] arguments = argumentList.getExpressions(); + PsiExpression argument = arguments[0]; + PsiMethod method = call.resolveMethod(); + if (method == null) { + return; + } + PsiCodeBlock body = method.getBody(); + if (body == null) { + return; + } + PsiStatement[] statements = body.getStatements(); + PsiExpressionStatement assignmentStatement = (PsiExpressionStatement) statements[0]; + PsiAssignmentExpression assignment = (PsiAssignmentExpression) assignmentStatement.getExpression(); + PsiExpression qualifier = methodExpression.getQualifierExpression(); + PsiReferenceExpression lhs = (PsiReferenceExpression) assignment.getLExpression(); + PsiField field = (PsiField) lhs.resolve(); + if (field == null) { + return; + } + String fieldName = field.getName(); + if (qualifier == null) { + PsiResolveHelper resolveHelper = PsiResolveHelper.getInstance(call.getProject()); + PsiVariable variable = resolveHelper.resolveReferencedVariable(fieldName, call); + if (variable == null) { + return; + } + String newExpression; + if (variable.equals(field)) { + newExpression = fieldName + " = " + argument.getText(); + } + else { + newExpression = "this." + fieldName + " = " + argument.getText(); + } + replaceExpression(call, newExpression); + } + else { + String newExpression = qualifier.getText() + '.' + fieldName + " = " + argument.getText(); + replaceExpression(call, newExpression); + } } - replaceExpression(call, newExpression); - } - else { - final String newExpression = qualifier.getText() + '.' + fieldName + " = " + argument.getText(); - replaceExpression(call, newExpression); - } } - } - - public BaseInspectionVisitor buildVisitor() { - return new CallToSimpleSetterInClassVisitor(); - } - - private class CallToSimpleSetterInClassVisitor extends BaseInspectionVisitor { @Override - public void visitMethodCallExpression(@Nonnull PsiMethodCallExpression call) { - super.visitMethodCallExpression(call); - final PsiClass containingClass = ClassUtils.getContainingClass(call); - if (containingClass == null) { - return; - } - final PsiMethod method = call.resolveMethod(); - if (method == null) { - return; - } - if (!containingClass.equals(method.getContainingClass())) { - return; - } - final PsiReferenceExpression methodExpression = call.getMethodExpression(); - final PsiExpression qualifier = methodExpression.getQualifierExpression(); - if (qualifier != null && !(qualifier instanceof PsiThisExpression)) { - if (ignoreSetterCallsOnOtherObjects) { - return; - } - final PsiType type = qualifier.getType(); - if (!(type instanceof PsiClassType)) { - return; - } - final PsiClassType classType = (PsiClassType)type; - final PsiClass qualifierClass = classType.resolve(); - if (!containingClass.equals(qualifierClass)) { - return; + public BaseInspectionVisitor buildVisitor() { + return new CallToSimpleSetterInClassVisitor(); + } + + private class CallToSimpleSetterInClassVisitor extends BaseInspectionVisitor { + @Override + public void visitMethodCallExpression(@Nonnull PsiMethodCallExpression call) { + super.visitMethodCallExpression(call); + PsiClass containingClass = ClassUtils.getContainingClass(call); + if (containingClass == null) { + return; + } + PsiMethod method = call.resolveMethod(); + if (method == null) { + return; + } + if (!containingClass.equals(method.getContainingClass())) { + return; + } + PsiReferenceExpression methodExpression = call.getMethodExpression(); + PsiExpression qualifier = methodExpression.getQualifierExpression(); + if (qualifier != null && !(qualifier instanceof PsiThisExpression)) { + if (ignoreSetterCallsOnOtherObjects) { + return; + } + PsiType type = qualifier.getType(); + if (!(type instanceof PsiClassType classType)) { + return; + } + PsiClass qualifierClass = classType.resolve(); + if (!containingClass.equals(qualifierClass)) { + return; + } + } + if (!PropertyUtil.isSimpleSetter(method)) { + return; + } + if (onlyReportPrivateSetter && !method.isPrivate()) { + return; + } + Query query = OverridingMethodsSearch.search(method, true); + PsiMethod overridingMethod = query.findFirst(); + if (overridingMethod != null) { + return; + } + registerMethodCallError(call); } - } - if (!PropertyUtil.isSimpleSetter(method)) { - return; - } - if (onlyReportPrivateSetter && !method.hasModifierProperty(PsiModifier.PRIVATE)) { - return; - } - final Query query = OverridingMethodsSearch.search(method, true); - final PsiMethod overridingMethod = query.findFirst(); - if (overridingMethod != null) { - return; - } - registerMethodCallError(call); } - } } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineConstantFieldHandler.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineConstantFieldHandler.java index 6fa5dc29bd..58eda46a28 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineConstantFieldHandler.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineConstantFieldHandler.java @@ -19,11 +19,12 @@ import com.intellij.java.language.JavaLanguage; import com.intellij.java.language.psi.*; import com.intellij.java.language.psi.util.PsiUtil; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; import consulo.application.progress.ProgressManager; import consulo.codeEditor.Editor; +import consulo.java.localize.JavaRefactoringLocalize; import consulo.language.editor.TargetElementUtil; -import consulo.language.editor.refactoring.RefactoringBundle; import consulo.language.editor.refactoring.localize.RefactoringLocalize; import consulo.language.editor.refactoring.util.CommonRefactoringUtil; import consulo.language.psi.PsiCompiledElement; @@ -33,75 +34,82 @@ import consulo.localize.LocalizeValue; import consulo.project.Project; import consulo.project.content.scope.ProjectScopes; -import consulo.util.lang.ref.Ref; +import consulo.ui.annotation.RequiredUIAccess; +import consulo.util.lang.ref.SimpleReference; /** * @author ven */ @ExtensionImpl public class InlineConstantFieldHandler extends JavaInlineActionHandler { - private static final String REFACTORING_NAME = RefactoringBundle.message("inline.field.title"); + private static final LocalizeValue REFACTORING_NAME = RefactoringLocalize.inlineFieldTitle(); - public boolean canInlineElement(PsiElement element) { - return element instanceof PsiField && JavaLanguage.INSTANCE.equals(element.getLanguage()); - } + @Override + @RequiredReadAction + public boolean canInlineElement(PsiElement element) { + return element instanceof PsiField && JavaLanguage.INSTANCE.equals(element.getLanguage()); + } - public void inlineElement(Project project, Editor editor, PsiElement element) { - final PsiElement navigationElement = element.getNavigationElement(); - final PsiField field = (PsiField)(navigationElement instanceof PsiField ? navigationElement : element); + @Override + @RequiredUIAccess + public void inlineElement(Project project, Editor editor, PsiElement element) { + PsiField field = element.getNavigationElement() instanceof PsiField psiField ? psiField : (PsiField) element; - if (!field.hasInitializer()) { - LocalizeValue message = RefactoringLocalize.noInitializerPresentForTheField(); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME, HelpID.INLINE_FIELD); - return; - } + if (!field.hasInitializer()) { + LocalizeValue message = RefactoringLocalize.noInitializerPresentForTheField(); + CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME.get(), HelpID.INLINE_FIELD); + return; + } - if (field instanceof PsiEnumConstant) { - String message = REFACTORING_NAME + " is not supported for enum constants"; - CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.INLINE_FIELD); - return; - } + if (field instanceof PsiEnumConstant) { + LocalizeValue message = JavaRefactoringLocalize.inlineConstantFieldNotSupportedForEnumConstants(REFACTORING_NAME); + CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME.get(), HelpID.INLINE_FIELD); + return; + } - if (ReferencesSearch.search(field, ProjectScopes.getProjectScope(project), false).findFirst() == null) { - LocalizeValue message = RefactoringLocalize.field0IsNeverUsed(field.getName()); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME, HelpID.INLINE_FIELD); - return; - } + if (ReferencesSearch.search(field, ProjectScopes.getProjectScope(project), false).findFirst() == null) { + LocalizeValue message = RefactoringLocalize.field0IsNeverUsed(field.getName()); + CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME.get(), HelpID.INLINE_FIELD); + return; + } - if (!field.hasModifierProperty(PsiModifier.FINAL)) { - final Ref hasWriteUsages = new Ref(false); - if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() { - @Override - public void run() { - for (PsiReference reference : ReferencesSearch.search(field)) { - final PsiElement referenceElement = reference.getElement(); - if (!(referenceElement instanceof PsiExpression && PsiUtil.isAccessedForReading((PsiExpression)referenceElement))) { - hasWriteUsages.set(true); - break; + if (!field.isFinal()) { + SimpleReference hasWriteUsages = new SimpleReference(false); + if (!ProgressManager.getInstance().runProcessWithProgressSynchronously( + () -> { + for (PsiReference reference : ReferencesSearch.search(field)) { + if (!(reference.getElement() instanceof PsiExpression expr && PsiUtil.isAccessedForReading(expr))) { + hasWriteUsages.set(true); + break; + } + } + }, + JavaRefactoringLocalize.inlineConflictsProgress(), + true, + project + )) { + return; + } + if (hasWriteUsages.get()) { + LocalizeValue message = RefactoringLocalize.zeroRefactoringIsSupportedOnlyForFinalFields(REFACTORING_NAME); + CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME.get(), HelpID.INLINE_FIELD); + return; } - } } - }, "Check if inline is possible...", true, project)) { - return; - } - if (hasWriteUsages.get()) { - LocalizeValue message = RefactoringLocalize.zeroRefactoringIsSupportedOnlyForFinalFields(REFACTORING_NAME); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME, HelpID.INLINE_FIELD); - return; - } - } - PsiReference reference = editor != null ? TargetElementUtil.findReference(editor, editor.getCaretModel().getOffset()) : null; - if (reference != null) { - final PsiElement resolve = reference.resolve(); - if (resolve != null && !field.equals(resolve.getNavigationElement())) { - reference = null; - } - } + PsiReference reference = editor != null ? TargetElementUtil.findReference(editor, editor.getCaretModel().getOffset()) : null; + if (reference != null) { + PsiElement resolve = reference.resolve(); + if (resolve != null && !field.equals(resolve.getNavigationElement())) { + reference = null; + } + } - if ((!(element instanceof PsiCompiledElement) || reference == null) && !CommonRefactoringUtil.checkReadOnlyStatus(project, field)) return; - PsiReferenceExpression refExpression = reference instanceof PsiReferenceExpression ? (PsiReferenceExpression)reference : null; - InlineFieldDialog dialog = new InlineFieldDialog(project, field, refExpression); - dialog.show(); - } + if ((!(element instanceof PsiCompiledElement) || reference == null) && !CommonRefactoringUtil.checkReadOnlyStatus(project, field)) { + return; + } + PsiReferenceExpression refExpression = reference instanceof PsiReferenceExpression refExpr ? refExpr : null; + InlineFieldDialog dialog = new InlineFieldDialog(project, field, refExpression); + dialog.show(); + } } diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineConstantFieldProcessor.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineConstantFieldProcessor.java index b8c6c5312e..5cf8c96f95 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineConstantFieldProcessor.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineConstantFieldProcessor.java @@ -15,12 +15,15 @@ */ package com.intellij.java.impl.refactoring.inline; +import com.intellij.java.impl.psi.impl.source.resolve.reference.impl.JavaLangClassMemberReference; import com.intellij.java.impl.refactoring.util.ConflictsUtil; import com.intellij.java.impl.refactoring.util.InlineUtil; import com.intellij.java.language.impl.psi.impl.source.javadoc.PsiDocMethodOrFieldRef; import com.intellij.java.language.psi.*; import com.intellij.java.language.psi.util.PsiUtil; import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; +import consulo.java.localize.JavaRefactoringLocalize; import consulo.language.editor.refactoring.BaseRefactoringProcessor; import consulo.language.editor.refactoring.localize.RefactoringLocalize; import consulo.language.editor.refactoring.rename.NonCodeUsageInfoFactory; @@ -43,6 +46,7 @@ import consulo.usage.UsageInfo; import consulo.usage.UsageInfoFactory; import consulo.usage.UsageViewDescriptor; +import consulo.util.collection.ContainerUtil; import consulo.util.collection.MultiMap; import consulo.util.lang.ref.SimpleReference; import jakarta.annotation.Nonnull; @@ -124,7 +128,7 @@ protected UsageInfo[] findUsages() { PsiElement element = ref.getElement(); UsageInfo info = new UsageInfo(element); - if (!(element instanceof PsiExpression) + if (!(element instanceof PsiExpression) && PsiTreeUtil.getParentOfType(element, PsiImportStaticStatement.class) == null) { info = new UsageFromJavaDoc(element); } @@ -142,19 +146,19 @@ public UsageInfo createUsageInfo(@Nonnull PsiElement usage, int startOffset, int } }; if (mySearchInCommentsAndStrings) { - String stringToSearch = + String stringToSearch = ElementDescriptionUtil.getElementDescription(myField, NonCodeSearchDescriptionLocation.STRINGS_AND_COMMENTS); TextOccurrencesUtil.addUsagesInStringsAndComments(myField, stringToSearch, usages, nonCodeUsageFactory); } if (mySearchForTextOccurrences) { - String stringToSearch = + String stringToSearch = ElementDescriptionUtil.getElementDescription(myField, NonCodeSearchDescriptionLocation.NON_JAVA); TextOccurrencesUtil.addTextOccurences( - myField, - stringToSearch, - GlobalSearchScope.projectScope(myProject), - usages, + myField, + stringToSearch, + GlobalSearchScope.projectScope(myProject), + usages, nonCodeUsageFactory ); } @@ -165,16 +169,17 @@ public UsageInfo createUsageInfo(@Nonnull PsiElement usage, int startOffset, int @Override protected void refreshElements(@Nonnull PsiElement[] elements) { LOG.assertTrue(elements.length == 1 && elements[0] instanceof PsiField); - myField = (PsiField)elements[0]; + myField = (PsiField) elements[0]; } @Override @RequiredUIAccess + @RequiredWriteAction protected void performRefactoring(@Nonnull UsageInfo[] usages) { PsiExpression initializer = myField.getInitializer(); LOG.assertTrue(initializer != null); - initializer = normalize((PsiExpression)initializer.copy()); + initializer = normalize((PsiExpression) initializer.copy()); for (UsageInfo info : usages) { if (info instanceof UsageFromJavaDoc || info instanceof NonCodeUsageInfo) { continue; @@ -188,7 +193,7 @@ protected void performRefactoring(@Nonnull UsageInfo[] usages) { inlineExpressionUsage(expression, initializer); } else { - PsiImportStaticStatement importStaticStatement = + PsiImportStaticStatement importStaticStatement = PsiTreeUtil.getParentOfType(element, PsiImportStaticStatement.class); LOG.assertTrue(importStaticStatement != null, element.getText()); importStaticStatement.delete(); @@ -248,9 +253,10 @@ else if (initializer1 instanceof PsiMethodCallExpression methodCall) { } } - InlineUtil.inlineVariable(myField, initializer1, (PsiJavaCodeReferenceElement)expr); + InlineUtil.inlineVariable(myField, initializer1, (PsiJavaCodeReferenceElement) expr); } + @RequiredWriteAction private static PsiExpression normalize(PsiExpression expression) { if (expression instanceof PsiArrayInitializerExpression) { PsiElementFactory factory = JavaPsiFacade.getInstance(expression.getProject()).getElementFactory(); @@ -259,7 +265,7 @@ private static PsiExpression normalize(PsiExpression expression) { if (type != null) { String typeString = type.getCanonicalText(); PsiNewExpression result = - (PsiNewExpression)factory.createExpressionFromText("new " + typeString + "{}", expression); + (PsiNewExpression) factory.createExpressionFromText("new " + typeString + "{}", expression); result.getArrayInitializer().replace(expression); return result; } @@ -316,11 +322,14 @@ protected boolean preprocessUsages(@Nonnull SimpleReference refUsag if (!myInlineThisOnly) { for (UsageInfo info : usagesIn) { - if (info instanceof UsageFromJavaDoc) { - PsiElement element = info.getElement(); - if (element instanceof PsiDocMethodOrFieldRef && !PsiTreeUtil.isAncestor(myField, element, false)) { - conflicts.putValue(element, "Inlined method is used in javadoc"); - } + PsiElement element = info.getElement(); + if (element instanceof PsiDocMethodOrFieldRef psiDocMethodOrFieldRef + && !PsiTreeUtil.isAncestor(myField, psiDocMethodOrFieldRef, false)) { + conflicts.putValue(psiDocMethodOrFieldRef, JavaRefactoringLocalize.inlineFieldUsedInJavadoc().get()); + } + if (element instanceof PsiLiteralExpression + && ContainerUtil.or(element.getReferences(), JavaLangClassMemberReference.class::isInstance)) { + conflicts.putValue(element, JavaRefactoringLocalize.inlineFieldUsedInReflection().get()); } } } @@ -336,8 +345,8 @@ private static boolean isAccessedForWriting(PsiExpression expr) { return PsiUtil.isAccessedForWriting(expr); } - @Override @Nonnull + @Override protected Collection getElementsToWrite(@Nonnull UsageViewDescriptor descriptor) { if (myInlineThisOnly) { return Collections.singletonList(myRefExpr); diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineFieldDialog.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineFieldDialog.java index 50a75ea1c2..d559a6eab5 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineFieldDialog.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineFieldDialog.java @@ -21,97 +21,105 @@ import com.intellij.java.language.psi.PsiReferenceExpression; import com.intellij.java.language.psi.PsiSubstitutor; import com.intellij.java.language.psi.util.PsiFormatUtil; +import consulo.annotation.access.RequiredReadAction; import consulo.application.HelpManager; -import consulo.language.editor.refactoring.RefactoringBundle; import consulo.language.editor.refactoring.inline.InlineOptionsWithSearchSettingsDialog; import consulo.language.editor.refactoring.localize.RefactoringLocalize; import consulo.localize.LocalizeValue; import consulo.project.Project; +import consulo.ui.annotation.RequiredUIAccess; import jakarta.annotation.Nonnull; public class InlineFieldDialog extends InlineOptionsWithSearchSettingsDialog { - public static final String REFACTORING_NAME = RefactoringBundle.message("inline.field.title"); - private final PsiReferenceExpression myReferenceExpression; - - private final PsiField myField; - protected final int myOccurrencesNumber; - - public InlineFieldDialog(Project project, PsiField field, PsiReferenceExpression ref) { - super(project, true, field); - myField = field; - myReferenceExpression = ref; - myInvokedOnReference = myReferenceExpression != null; - - setTitle(REFACTORING_NAME); - myOccurrencesNumber = initOccurrencesNumber(myField); - init(); - } - - @Nonnull - @Override - protected LocalizeValue getNameLabelText() { - String fieldText = PsiFormatUtil.formatVariable(myField, PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_TYPE, PsiSubstitutor.EMPTY); - return RefactoringLocalize.inlineFieldFieldNameLabel(fieldText); - } - - @Nonnull - @Override - protected LocalizeValue getBorderTitle() { - return RefactoringLocalize.inlineFieldBorderTitle(); - } - - @Nonnull - @Override - protected LocalizeValue getInlineThisText() { - return RefactoringLocalize.thisReferenceOnlyAndKeepTheField(); - } - - @Nonnull - @Override - protected LocalizeValue getInlineAllText() { - final String occurrencesString = myOccurrencesNumber > -1 ? " (" + myOccurrencesNumber + " occurrence" + (myOccurrencesNumber == 1 ? ")" : "s)") : ""; - return LocalizeValue.join(RefactoringLocalize.allReferencesAndRemoveTheField(), LocalizeValue.localizeTODO(occurrencesString)); - } - - @Override - protected boolean isInlineThis() { - return JavaRefactoringSettings.getInstance().INLINE_FIELD_THIS; - } - - @Override - protected boolean isSearchInCommentsAndStrings() { - return JavaRefactoringSettings.getInstance().RENAME_SEARCH_IN_COMMENTS_FOR_FIELD; - } - - @Override - protected void saveSearchInCommentsAndStrings(boolean searchInComments) { - JavaRefactoringSettings.getInstance().RENAME_SEARCH_IN_COMMENTS_FOR_FIELD = searchInComments; - } - - @Override - protected boolean isSearchForTextOccurrences() { - return JavaRefactoringSettings.getInstance().RENAME_SEARCH_FOR_TEXT_FOR_FIELD; - } - - @Override - protected void saveSearchInTextOccurrences(boolean searchInTextOccurrences) { - JavaRefactoringSettings.getInstance().RENAME_SEARCH_FOR_TEXT_FOR_FIELD = searchInTextOccurrences; - } - - @Override - protected void doAction() { - super.doAction(); - invokeRefactoring( - new InlineConstantFieldProcessor(myField, getProject(), myReferenceExpression, isInlineThisOnly(), isSearchInCommentsAndStrings(), - isSearchForTextOccurrences())); - JavaRefactoringSettings settings = JavaRefactoringSettings.getInstance(); - if (myRbInlineThisOnly.isEnabled() && myRbInlineAll.isEnabled()) { - settings.INLINE_FIELD_THIS = isInlineThisOnly(); + private final PsiReferenceExpression myReferenceExpression; + + private final PsiField myField; + protected final int myOccurrencesNumber; + + @RequiredReadAction + public InlineFieldDialog(Project project, PsiField field, PsiReferenceExpression ref) { + super(project, true, field); + myField = field; + myReferenceExpression = ref; + myInvokedOnReference = myReferenceExpression != null; + + setTitle(RefactoringLocalize.inlineFieldTitle()); + myOccurrencesNumber = initOccurrencesNumber(myField); + init(); + } + + @Nonnull + @Override + protected LocalizeValue getNameLabelText() { + String fieldText = PsiFormatUtil.formatVariable(myField, PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_TYPE, PsiSubstitutor.EMPTY); + return RefactoringLocalize.inlineFieldFieldNameLabel(fieldText); + } + + @Nonnull + @Override + protected LocalizeValue getBorderTitle() { + return RefactoringLocalize.inlineFieldBorderTitle(); + } + + @Nonnull + @Override + protected LocalizeValue getInlineThisText() { + return RefactoringLocalize.thisReferenceOnlyAndKeepTheField(); + } + + @Nonnull + @Override + protected LocalizeValue getInlineAllText() { + String occurrencesString = + myOccurrencesNumber > -1 ? " (" + myOccurrencesNumber + " occurrence" + (myOccurrencesNumber == 1 ? ")" : "s)") : ""; + return LocalizeValue.join(RefactoringLocalize.allReferencesAndRemoveTheField(), LocalizeValue.localizeTODO(occurrencesString)); + } + + @Override + protected boolean isInlineThis() { + return JavaRefactoringSettings.getInstance().INLINE_FIELD_THIS; + } + + @Override + protected boolean isSearchInCommentsAndStrings() { + return JavaRefactoringSettings.getInstance().RENAME_SEARCH_IN_COMMENTS_FOR_FIELD; + } + + @Override + protected void saveSearchInCommentsAndStrings(boolean searchInComments) { + JavaRefactoringSettings.getInstance().RENAME_SEARCH_IN_COMMENTS_FOR_FIELD = searchInComments; + } + + @Override + protected boolean isSearchForTextOccurrences() { + return JavaRefactoringSettings.getInstance().RENAME_SEARCH_FOR_TEXT_FOR_FIELD; + } + + @Override + protected void saveSearchInTextOccurrences(boolean searchInTextOccurrences) { + JavaRefactoringSettings.getInstance().RENAME_SEARCH_FOR_TEXT_FOR_FIELD = searchInTextOccurrences; } - } - @Override - protected void doHelpAction() { - HelpManager.getInstance().invokeHelp(HelpID.INLINE_FIELD); - } + @Override + protected void doAction() { + super.doAction(); + invokeRefactoring(new InlineConstantFieldProcessor( + myField, + getProject(), + myReferenceExpression, + isInlineThisOnly(), + isSearchInCommentsAndStrings(), + isSearchForTextOccurrences() + )); + JavaRefactoringSettings settings = JavaRefactoringSettings.getInstance(); + if (myRbInlineThisOnly.isEnabled() && myRbInlineAll.isEnabled()) { + settings.INLINE_FIELD_THIS = isInlineThisOnly(); + } + } + + @Override + @RequiredUIAccess + protected void doHelpAction() { + HelpManager.getInstance().invokeHelp(HelpID.INLINE_FIELD); + } } diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineLocalHandler.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineLocalHandler.java index ebb372652a..540cf65e87 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineLocalHandler.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineLocalHandler.java @@ -1,4 +1,3 @@ - /* * Copyright 2000-2009 JetBrains s.r.o. * @@ -23,16 +22,15 @@ import com.intellij.java.language.impl.codeInsight.ExceptionUtil; import com.intellij.java.language.psi.*; import com.intellij.java.language.psi.util.PsiUtil; -import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.annotation.component.ExtensionImpl; -import consulo.application.Application; import consulo.application.util.query.Query; import consulo.codeEditor.Editor; import consulo.codeEditor.EditorColors; +import consulo.java.localize.JavaRefactoringLocalize; import consulo.language.ast.IElementType; import consulo.language.editor.TargetElementUtil; import consulo.language.editor.highlight.HighlightManager; -import consulo.language.editor.refactoring.RefactoringBundle; import consulo.language.editor.refactoring.localize.RefactoringLocalize; import consulo.language.editor.refactoring.util.CommonRefactoringUtil; import consulo.language.editor.refactoring.util.RefactoringMessageDialog; @@ -47,7 +45,7 @@ import consulo.localize.LocalizeValue; import consulo.logging.Logger; import consulo.project.Project; -import consulo.project.ui.wm.WindowManager; +import consulo.ui.annotation.RequiredUIAccess; import consulo.undoRedo.CommandProcessor; import consulo.util.collection.ArrayUtil; import jakarta.annotation.Nonnull; @@ -59,293 +57,309 @@ @ExtensionImpl public class InlineLocalHandler extends JavaInlineActionHandler { - private static final Logger LOG = Logger.getInstance(InlineLocalHandler.class); - - private static final String REFACTORING_NAME = RefactoringBundle.message("inline.variable.title"); - - public boolean canInlineElement(PsiElement element) { - return element instanceof PsiLocalVariable; - } - - @RequiredReadAction - public void inlineElement(Project project, Editor editor, PsiElement element) { - final PsiReference psiReference = TargetElementUtil.findReference(editor); - final PsiReferenceExpression refExpr = psiReference instanceof PsiReferenceExpression referenceExpression ? referenceExpression : null; - invoke(project, editor, (PsiLocalVariable) element, refExpr); - } - - /** - * should be called in AtomicAction - */ - @RequiredReadAction - public static void invoke(@Nonnull final Project project, final Editor editor, final PsiLocalVariable local, PsiReferenceExpression refExpr) { - if (!CommonRefactoringUtil.checkReadOnlyStatus(project, local)) return; - - final HighlightManager highlightManager = HighlightManager.getInstance(project); - - final String localName = local.getName(); - - final Query query = ReferencesSearch.search(local, GlobalSearchScope.allScope(project), false); - if (query.findFirst() == null) { - LOG.assertTrue(refExpr == null); - LocalizeValue message = RefactoringLocalize.variableIsNeverUsed(localName); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME, HelpID.INLINE_VARIABLE); - return; - } + private static final Logger LOG = Logger.getInstance(InlineLocalHandler.class); - final PsiClass containingClass = PsiTreeUtil.getParentOfType(local, PsiClass.class); - final List innerClassesWithUsages = Collections.synchronizedList(new ArrayList()); - final List innerClassUsages = Collections.synchronizedList(new ArrayList()); - query.forEach(psiReference -> { - final PsiElement element = psiReference.getElement(); - PsiElement innerClass = PsiTreeUtil.getParentOfType(element, PsiClass.class, PsiLambdaExpression.class); - while (innerClass != containingClass && innerClass != null) { - final PsiClass parentPsiClass = PsiTreeUtil.getParentOfType(innerClass, PsiClass.class, true); - if (parentPsiClass == containingClass) { - if (innerClass instanceof PsiLambdaExpression) { - if (PsiTreeUtil.isAncestor(innerClass, local, false)) { - innerClassesWithUsages.add(element); - } else { - innerClassesWithUsages.add(innerClass); - } - innerClass = parentPsiClass; - continue; - } - innerClassesWithUsages.add(innerClass); - innerClassUsages.add(element); - } - innerClass = parentPsiClass; - } - return true; - }); - - final PsiCodeBlock containerBlock = PsiTreeUtil.getParentOfType(local, PsiCodeBlock.class); - if (containerBlock == null) { - LocalizeValue message = RefactoringLocalize.cannotPerformRefactoringWithReason( - LocalizeValue.localizeTODO("Variable is declared outside a code block") - ); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME, HelpID.INLINE_VARIABLE); - return; - } + private static final LocalizeValue REFACTORING_NAME = RefactoringLocalize.inlineVariableTitle(); - final PsiExpression defToInline = innerClassesWithUsages.isEmpty() - ? getDefToInline(local, refExpr, containerBlock) - : getDefToInline(local, innerClassesWithUsages.get(0), containerBlock); - if (defToInline == null) { - LocalizeValue message = RefactoringLocalize.cannotPerformRefactoringWithReason( - refExpr == null - ? RefactoringLocalize.variableHasNoInitializer(localName) - : LocalizeValue.localizeTODO(RefactoringBundle.message("variable.has.no.dominating.definition", localName)) - ); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME, HelpID.INLINE_VARIABLE); - return; + @Override + public boolean canInlineElement(PsiElement element) { + return element instanceof PsiLocalVariable; } - final List refsToInlineList = new ArrayList<>(); - Collections.addAll(refsToInlineList, DefUseUtil.getRefs(containerBlock, local, defToInline)); - for (PsiElement innerClassUsage : innerClassUsages) { - if (!refsToInlineList.contains(innerClassUsage)) { - refsToInlineList.add(innerClassUsage); - } - } - if (refsToInlineList.size() == 0) { - LocalizeValue message = RefactoringLocalize.variableIsNeverUsedBeforeModification(localName); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME, HelpID.INLINE_VARIABLE); - return; - } - final PsiElement[] refsToInline = PsiUtilBase.toPsiElementArray(refsToInlineList); - - if (refExpr != null && PsiUtil.isAccessedForReading(refExpr) && ArrayUtil.find(refsToInline, refExpr) < 0) { - final PsiElement[] defs = DefUseUtil.getDefs(containerBlock, local, refExpr); - LOG.assertTrue(defs.length > 0); - highlightManager.addOccurrenceHighlights(editor, defs, EditorColors.SEARCH_RESULT_ATTRIBUTES, true, null); - LocalizeValue message = - RefactoringLocalize.cannotPerformRefactoringWithReason(RefactoringLocalize.variableIsAccessedForWriting(localName)); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME, HelpID.INLINE_VARIABLE); - return; + @Override + @RequiredUIAccess + public void inlineElement(Project project, Editor editor, PsiElement element) { + PsiReference psiReference = TargetElementUtil.findReference(editor); + PsiReferenceExpression refExpr = psiReference instanceof PsiReferenceExpression re ? re : null; + invoke(project, editor, (PsiLocalVariable) element, refExpr); } - PsiTryStatement tryStatement = PsiTreeUtil.getParentOfType(defToInline, PsiTryStatement.class); - if (tryStatement != null) { - if (ExceptionUtil.getThrownExceptions(defToInline).isEmpty()) { - tryStatement = null; - } - } - PsiFile workingFile = local.getContainingFile(); - for (PsiElement ref : refsToInline) { - final PsiFile otherFile = ref.getContainingFile(); - if (!otherFile.equals(workingFile)) { - LocalizeValue message = RefactoringLocalize.variableIsReferencedInMultipleFiles(localName); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME, HelpID.INLINE_VARIABLE); - return; - } - if (tryStatement != null && !PsiTreeUtil.isAncestor(tryStatement, ref, false)) { - CommonRefactoringUtil.showErrorHint( - project, - editor, - "Unable to inline outside try/catch statement", - REFACTORING_NAME, - HelpID.INLINE_VARIABLE - ); - return; - } - } + /** + * should be called in AtomicAction + */ + @RequiredUIAccess + public static void invoke(@Nonnull Project project, Editor editor, PsiLocalVariable local, PsiReferenceExpression refExpr) { + if (!CommonRefactoringUtil.checkReadOnlyStatus(project, local)) { + return; + } - for (final PsiElement ref : refsToInline) { - final PsiElement[] defs = DefUseUtil.getDefs(containerBlock, local, ref); - boolean isSameDefinition = true; - for (PsiElement def : defs) { - isSameDefinition &= isSameDefinition(def, defToInline); - } - if (!isSameDefinition) { - highlightManager.addOccurrenceHighlights(editor, defs, EditorColors.WRITE_SEARCH_RESULT_ATTRIBUTES, true, null); - highlightManager.addOccurrenceHighlights(editor, new PsiElement[]{ref}, EditorColors.SEARCH_RESULT_ATTRIBUTES, true, null); - LocalizeValue message = RefactoringLocalize.cannotPerformRefactoringWithReason( - RefactoringLocalize.variableIsAccessedForWritingAndUsedWithInlined(localName)); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME, HelpID.INLINE_VARIABLE); - return; - } - } + HighlightManager highlightManager = HighlightManager.getInstance(project); - final PsiElement writeAccess = checkRefsInAugmentedAssignmentOrUnaryModified(refsToInline); - if (writeAccess != null) { - HighlightManager.getInstance(project).addOccurrenceHighlights(editor, new PsiElement[]{writeAccess}, EditorColors.WRITE_SEARCH_RESULT_ATTRIBUTES, true, null); - LocalizeValue message = - RefactoringLocalize.cannotPerformRefactoringWithReason(RefactoringLocalize.variableIsAccessedForWriting(localName)); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME, HelpID.INLINE_VARIABLE); - return; - } + String localName = local.getName(); - if (editor != null && !project.getApplication().isUnitTestMode()) { - // TODO : check if initializer uses fieldNames that possibly will be hidden by other - // locals with the same names after inlining - highlightManager.addOccurrenceHighlights( - editor, - refsToInline, - EditorColors.SEARCH_RESULT_ATTRIBUTES, true, null - ); - int occurrencesCount = refsToInline.length; - LocalizeValue message = isInliningVariableInitializer(defToInline) - ? RefactoringLocalize.inlineLocalVariablePrompt(localName) - : RefactoringLocalize.inlineLocalVariableDefinitionPrompt(localName); - LocalizeValue occurencesString = RefactoringLocalize.occurencesString(occurrencesCount); - RefactoringMessageDialog dialog = new RefactoringMessageDialog( - REFACTORING_NAME, - message + " " + occurencesString, - HelpID.INLINE_VARIABLE, - "OptionPane.questionIcon", - true, - project); - dialog.show(); - if (!dialog.isOK()) { - return; - } - } + Query query = ReferencesSearch.search(local, GlobalSearchScope.allScope(project), false); + if (query.findFirst() == null) { + LOG.assertTrue(refExpr == null); + LocalizeValue message = RefactoringLocalize.variableIsNeverUsed(localName); + CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME.get(), HelpID.INLINE_VARIABLE); + return; + } - final Runnable runnable = () -> { - try { - PsiExpression[] exprs = new PsiExpression[refsToInline.length]; - for (int idx = 0; idx < refsToInline.length; idx++) { - PsiJavaCodeReferenceElement refElement = (PsiJavaCodeReferenceElement) refsToInline[idx]; - exprs[idx] = InlineUtil.inlineVariable(local, defToInline, refElement); + PsiClass containingClass = PsiTreeUtil.getParentOfType(local, PsiClass.class); + List innerClassesWithUsages = Collections.synchronizedList(new ArrayList()); + List innerClassUsages = Collections.synchronizedList(new ArrayList()); + query.forEach(psiReference -> { + PsiElement element = psiReference.getElement(); + PsiElement innerClass = PsiTreeUtil.getParentOfType(element, PsiClass.class, PsiLambdaExpression.class); + while (innerClass != containingClass && innerClass != null) { + PsiClass parentPsiClass = PsiTreeUtil.getParentOfType(innerClass, PsiClass.class, true); + if (parentPsiClass == containingClass) { + if (innerClass instanceof PsiLambdaExpression) { + if (PsiTreeUtil.isAncestor(innerClass, local, false)) { + innerClassesWithUsages.add(element); + } + else { + innerClassesWithUsages.add(innerClass); + } + innerClass = parentPsiClass; + continue; + } + innerClassesWithUsages.add(innerClass); + innerClassUsages.add(element); + } + innerClass = parentPsiClass; + } + return true; + }); + + PsiCodeBlock containerBlock = PsiTreeUtil.getParentOfType(local, PsiCodeBlock.class); + if (containerBlock == null) { + LocalizeValue message = RefactoringLocalize.cannotPerformRefactoringWithReason( + JavaRefactoringLocalize.inlineLocalVariableDeclaredOutsideCannotRefactorMessage() + ); + CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME.get(), HelpID.INLINE_VARIABLE); + return; } - if (!isInliningVariableInitializer(defToInline)) { - defToInline.getParent().delete(); - } else { - defToInline.delete(); + PsiExpression defToInline = innerClassesWithUsages.isEmpty() + ? getDefToInline(local, refExpr, containerBlock) + : getDefToInline(local, innerClassesWithUsages.get(0), containerBlock); + if (defToInline == null) { + LocalizeValue message = RefactoringLocalize.cannotPerformRefactoringWithReason( + refExpr == null + ? RefactoringLocalize.variableHasNoInitializer(localName) + : RefactoringLocalize.variableHasNoDominatingDefinition() + ); + CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME.get(), HelpID.INLINE_VARIABLE); + return; } - if (ReferencesSearch.search(local).findFirst() == null) { - QuickFixFactory.getInstance().createRemoveUnusedVariableFix(local).invoke(project, editor, local.getContainingFile()); + List refsToInlineList = new ArrayList<>(); + Collections.addAll(refsToInlineList, DefUseUtil.getRefs(containerBlock, local, defToInline)); + for (PsiElement innerClassUsage : innerClassUsages) { + if (!refsToInlineList.contains(innerClassUsage)) { + refsToInlineList.add(innerClassUsage); + } + } + if (refsToInlineList.size() == 0) { + LocalizeValue message = RefactoringLocalize.variableIsNeverUsedBeforeModification(localName); + CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME.get(), HelpID.INLINE_VARIABLE); + return; + } + PsiElement[] refsToInline = PsiUtilBase.toPsiElementArray(refsToInlineList); + + if (refExpr != null && PsiUtil.isAccessedForReading(refExpr) && ArrayUtil.find(refsToInline, refExpr) < 0) { + PsiElement[] defs = DefUseUtil.getDefs(containerBlock, local, refExpr); + LOG.assertTrue(defs.length > 0); + highlightManager.addOccurrenceHighlights(editor, defs, EditorColors.SEARCH_RESULT_ATTRIBUTES, true, null); + LocalizeValue message = + RefactoringLocalize.cannotPerformRefactoringWithReason(RefactoringLocalize.variableIsAccessedForWriting(localName)); + CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME.get(), HelpID.INLINE_VARIABLE); + return; } - if (editor != null && !project.getApplication().isUnitTestMode()) { - highlightManager.addOccurrenceHighlights(editor, exprs, EditorColors.SEARCH_RESULT_ATTRIBUTES, true, null); + PsiTryStatement tryStatement = PsiTreeUtil.getParentOfType(defToInline, PsiTryStatement.class); + if (tryStatement != null) { + if (ExceptionUtil.getThrownExceptions(defToInline).isEmpty()) { + tryStatement = null; + } + } + PsiFile workingFile = local.getContainingFile(); + for (PsiElement ref : refsToInline) { + PsiFile otherFile = ref.getContainingFile(); + if (!otherFile.equals(workingFile)) { + LocalizeValue message = RefactoringLocalize.variableIsReferencedInMultipleFiles(localName); + CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME.get(), HelpID.INLINE_VARIABLE); + return; + } + if (tryStatement != null && !PsiTreeUtil.isAncestor(tryStatement, ref, false)) { + CommonRefactoringUtil.showErrorHint( + project, + editor, + JavaRefactoringLocalize.inlineLocalUnableTryCatchWarningMessage().get(), + REFACTORING_NAME.get(), + HelpID.INLINE_VARIABLE + ); + return; + } + } + + for (PsiElement ref : refsToInline) { + PsiElement[] defs = DefUseUtil.getDefs(containerBlock, local, ref); + boolean isSameDefinition = true; + for (PsiElement def : defs) { + isSameDefinition &= isSameDefinition(def, defToInline); + } + if (!isSameDefinition) { + highlightManager.addOccurrenceHighlights(editor, defs, EditorColors.WRITE_SEARCH_RESULT_ATTRIBUTES, true, null); + highlightManager.addOccurrenceHighlights(editor, new PsiElement[]{ref}, EditorColors.SEARCH_RESULT_ATTRIBUTES, true, null); + LocalizeValue message = RefactoringLocalize.cannotPerformRefactoringWithReason( + RefactoringLocalize.variableIsAccessedForWritingAndUsedWithInlined(localName) + ); + CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME.get(), HelpID.INLINE_VARIABLE); + return; + } } - for (final PsiExpression expr : exprs) { - InlineUtil.tryToInlineArrayCreationForVarargs(expr); + PsiElement writeAccess = checkRefsInAugmentedAssignmentOrUnaryModified(refsToInline); + if (writeAccess != null) { + HighlightManager.getInstance(project) + .addOccurrenceHighlights(editor, new PsiElement[]{writeAccess}, EditorColors.WRITE_SEARCH_RESULT_ATTRIBUTES, true, null); + LocalizeValue message = + RefactoringLocalize.cannotPerformRefactoringWithReason(RefactoringLocalize.variableIsAccessedForWriting(localName)); + CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME.get(), HelpID.INLINE_VARIABLE); + return; } - } catch (IncorrectOperationException e) { - LOG.error(e); - } - }; - - CommandProcessor.getInstance().executeCommand( - project, - () -> Application.get().runWriteAction(runnable), - RefactoringLocalize.inlineCommand(localName).get(), - null - ); - } - - @Nullable - public static PsiElement checkRefsInAugmentedAssignmentOrUnaryModified(final PsiElement[] refsToInline) { - for (PsiElement element : refsToInline) { - - PsiElement parent = element.getParent(); - if (parent instanceof PsiArrayAccessExpression arrayAccessExpression) { - if (arrayAccessExpression.getIndexExpression() == element) continue; - element = parent; - parent = parent.getParent(); - } - - if (parent instanceof PsiAssignmentExpression assignment && element == assignment.getLExpression() - || isUnaryWriteExpression(parent)) { - - return element; - } + + if (editor != null && !project.getApplication().isUnitTestMode()) { + // TODO : check if initializer uses fieldNames that possibly will be hidden by other + // locals with the same names after inlining + highlightManager.addOccurrenceHighlights( + editor, + refsToInline, + EditorColors.SEARCH_RESULT_ATTRIBUTES, true, null + ); + int occurrencesCount = refsToInline.length; + LocalizeValue message = isInliningVariableInitializer(defToInline) + ? RefactoringLocalize.inlineLocalVariablePrompt(localName) + : RefactoringLocalize.inlineLocalVariableDefinitionPrompt(localName); + LocalizeValue occurrencesString = RefactoringLocalize.occurencesString(occurrencesCount); + RefactoringMessageDialog dialog = new RefactoringMessageDialog( + REFACTORING_NAME.get(), + message + " " + occurrencesString, + HelpID.INLINE_VARIABLE, + "OptionPane.questionIcon", + true, + project + ); + dialog.show(); + if (!dialog.isOK()) { + return; + } + } + + @RequiredWriteAction + Runnable runnable = () -> { + try { + PsiExpression[] exprs = new PsiExpression[refsToInline.length]; + for (int idx = 0; idx < refsToInline.length; idx++) { + PsiJavaCodeReferenceElement refElement = (PsiJavaCodeReferenceElement) refsToInline[idx]; + exprs[idx] = InlineUtil.inlineVariable(local, defToInline, refElement); + } + + if (!isInliningVariableInitializer(defToInline)) { + defToInline.getParent().delete(); + } + else { + defToInline.delete(); + } + + if (ReferencesSearch.search(local).findFirst() == null) { + QuickFixFactory.getInstance().createRemoveUnusedVariableFix(local).invoke(project, editor, local.getContainingFile()); + } + + if (editor != null && !project.getApplication().isUnitTestMode()) { + highlightManager.addOccurrenceHighlights(editor, exprs, EditorColors.SEARCH_RESULT_ATTRIBUTES, true, null); + } + + for (PsiExpression expr : exprs) { + InlineUtil.tryToInlineArrayCreationForVarargs(expr); + } + } + catch (IncorrectOperationException e) { + LOG.error(e); + } + }; + + CommandProcessor.getInstance().newCommand() + .project(project) + .name(RefactoringLocalize.inlineCommand(localName)) + .inWriteAction() + .run(runnable); } - return null; - } - private static boolean isUnaryWriteExpression(PsiElement parent) { - IElementType tokenType = null; - if (parent instanceof PsiPrefixExpression prefixExpression) { - tokenType = prefixExpression.getOperationTokenType(); + @Nullable + public static PsiElement checkRefsInAugmentedAssignmentOrUnaryModified( PsiElement[] refsToInline) { + for (PsiElement element : refsToInline) { + + PsiElement parent = element.getParent(); + if (parent instanceof PsiArrayAccessExpression arrayAccessExpression) { + if (arrayAccessExpression.getIndexExpression() == element) { + continue; + } + element = parent; + parent = parent.getParent(); + } + + if (parent instanceof PsiAssignmentExpression assignment && element == assignment.getLExpression() + || isUnaryWriteExpression(parent)) { + + return element; + } + } + return null; } - if (parent instanceof PsiPostfixExpression postfixExpression) { - tokenType = postfixExpression.getOperationTokenType(); + + private static boolean isUnaryWriteExpression(PsiElement parent) { + IElementType tokenType = null; + if (parent instanceof PsiPrefixExpression prefixExpression) { + tokenType = prefixExpression.getOperationTokenType(); + } + if (parent instanceof PsiPostfixExpression postfixExpression) { + tokenType = postfixExpression.getOperationTokenType(); + } + return tokenType == JavaTokenType.PLUSPLUS || tokenType == JavaTokenType.MINUSMINUS; } - return tokenType == JavaTokenType.PLUSPLUS || tokenType == JavaTokenType.MINUSMINUS; - } - - private static boolean isSameDefinition(final PsiElement def, final PsiExpression defToInline) { - if (def instanceof PsiLocalVariable localVar) return defToInline.equals(localVar.getInitializer()); - final PsiElement parent = def.getParent(); - return parent instanceof PsiAssignmentExpression assignment && defToInline.equals(assignment.getRExpression()); - } - - private static boolean isInliningVariableInitializer(final PsiExpression defToInline) { - return defToInline.getParent() instanceof PsiVariable; - } - - @Nullable - private static PsiExpression getDefToInline( - final PsiLocalVariable local, - final PsiElement refExpr, - final PsiCodeBlock block - ) { - if (refExpr != null) { - PsiElement def; - if (refExpr instanceof PsiReferenceExpression referenceExpression && PsiUtil.isAccessedForWriting(referenceExpression)) { - def = refExpr; - } else { - final PsiElement[] defs = DefUseUtil.getDefs(block, local, refExpr); - if (defs.length == 1) { - def = defs[0]; - } else { - return null; + + private static boolean isSameDefinition( PsiElement def, PsiExpression defToInline) { + if (def instanceof PsiLocalVariable localVar) { + return defToInline.equals(localVar.getInitializer()); } - } + PsiElement parent = def.getParent(); + return parent instanceof PsiAssignmentExpression assignment && defToInline.equals(assignment.getRExpression()); + } - if (def instanceof PsiReferenceExpression && def.getParent() instanceof PsiAssignmentExpression assignmentExpression) { - if (assignmentExpression.getOperationTokenType() != JavaTokenType.EQ) return null; - final PsiExpression rExpr = assignmentExpression.getRExpression(); - if (rExpr != null) return rExpr; - } + private static boolean isInliningVariableInitializer( PsiExpression defToInline) { + return defToInline.getParent() instanceof PsiVariable; + } + + @Nullable + private static PsiExpression getDefToInline(PsiLocalVariable local, PsiElement refExpr, PsiCodeBlock block) { + if (refExpr != null) { + PsiElement def; + if (refExpr instanceof PsiReferenceExpression referenceExpression && PsiUtil.isAccessedForWriting(referenceExpression)) { + def = refExpr; + } + else { + PsiElement[] defs = DefUseUtil.getDefs(block, local, refExpr); + if (defs.length == 1) { + def = defs[0]; + } + else { + return null; + } + } + + if (def instanceof PsiReferenceExpression && def.getParent() instanceof PsiAssignmentExpression assignmentExpression) { + if (assignmentExpression.getOperationTokenType() != JavaTokenType.EQ) { + return null; + } + PsiExpression rExpr = assignmentExpression.getRExpression(); + if (rExpr != null) { + return rExpr; + } + } + } + return local.getInitializer(); } - return local.getInitializer(); - } } diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineMethodDialog.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineMethodDialog.java index f45db73a71..25267ca713 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineMethodDialog.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineMethodDialog.java @@ -21,114 +21,133 @@ import com.intellij.java.language.psi.PsiMethod; import com.intellij.java.language.psi.PsiSubstitutor; import com.intellij.java.language.psi.util.PsiFormatUtil; +import consulo.annotation.access.RequiredReadAction; import consulo.application.HelpManager; import consulo.codeEditor.Editor; -import consulo.language.editor.refactoring.RefactoringBundle; import consulo.language.editor.refactoring.inline.InlineOptionsWithSearchSettingsDialog; import consulo.language.editor.refactoring.localize.RefactoringLocalize; import consulo.localize.LocalizeValue; import consulo.project.Project; +import consulo.ui.annotation.RequiredUIAccess; import jakarta.annotation.Nonnull; public class InlineMethodDialog extends InlineOptionsWithSearchSettingsDialog { - public static final String REFACTORING_NAME = RefactoringBundle.message("inline.method.title"); - private final PsiJavaCodeReferenceElement myReferenceElement; - private final Editor myEditor; - private final boolean myAllowInlineThisOnly; - - private final PsiMethod myMethod; - - private int myOccurrencesNumber = -1; - - public InlineMethodDialog(Project project, PsiMethod method, PsiJavaCodeReferenceElement ref, Editor editor, - final boolean allowInlineThisOnly) { - super(project, true, method); - myMethod = method; - myReferenceElement = ref; - myEditor = editor; - myAllowInlineThisOnly = allowInlineThisOnly; - myInvokedOnReference = ref != null; - - setTitle(REFACTORING_NAME); - myOccurrencesNumber = initOccurrencesNumber(method); - init(); - } - - @Nonnull - @Override - protected LocalizeValue getNameLabelText() { - String methodText = PsiFormatUtil.formatMethod(myMethod, - PsiSubstitutor.EMPTY, PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_PARAMETERS, PsiFormatUtil.SHOW_TYPE); - return RefactoringLocalize.inlineMethodMethodLabel(methodText); - } - - @Nonnull - @Override - protected LocalizeValue getBorderTitle() { - return RefactoringLocalize.inlineMethodBorderTitle(); - } - - @Nonnull - @Override - protected LocalizeValue getInlineThisText() { - return RefactoringLocalize.thisInvocationOnlyAndKeepTheMethod(); - } - - @Nonnull - @Override - protected LocalizeValue getInlineAllText() { - final String occurrencesString = myOccurrencesNumber > -1 ? " (" + myOccurrencesNumber + " occurrence" + (myOccurrencesNumber == 1 ? ")" : "s)") : ""; - LocalizeValue prefix = myMethod.isWritable() - ? RefactoringLocalize.allInvocationsAndRemoveTheMethod() - : RefactoringLocalize.allInvocationsInProject(); - return LocalizeValue.join(prefix, LocalizeValue.localizeTODO(occurrencesString)); - } - - @Override - protected void doAction() { - super.doAction(); - invokeRefactoring( - new InlineMethodProcessor(getProject(), myMethod, myReferenceElement, myEditor, isInlineThisOnly(), isSearchInCommentsAndStrings(), - isSearchForTextOccurrences())); - JavaRefactoringSettings settings = JavaRefactoringSettings.getInstance(); - if (myRbInlineThisOnly.isEnabled() && myRbInlineAll.isEnabled()) { - settings.INLINE_METHOD_THIS = isInlineThisOnly(); + private final PsiJavaCodeReferenceElement myReferenceElement; + private final Editor myEditor; + private final boolean myAllowInlineThisOnly; + + private final PsiMethod myMethod; + + private int myOccurrencesNumber = -1; + + @RequiredReadAction + public InlineMethodDialog( + Project project, + PsiMethod method, + PsiJavaCodeReferenceElement ref, + Editor editor, + boolean allowInlineThisOnly + ) { + super(project, true, method); + myMethod = method; + myReferenceElement = ref; + myEditor = editor; + myAllowInlineThisOnly = allowInlineThisOnly; + myInvokedOnReference = ref != null; + + setTitle(RefactoringLocalize.inlineMethodTitle()); + myOccurrencesNumber = initOccurrencesNumber(method); + init(); + } + + @Nonnull + @Override + protected LocalizeValue getNameLabelText() { + String methodText = PsiFormatUtil.formatMethod( + myMethod, + PsiSubstitutor.EMPTY, + PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_PARAMETERS, + PsiFormatUtil.SHOW_TYPE + ); + return RefactoringLocalize.inlineMethodMethodLabel(methodText); + } + + @Nonnull + @Override + protected LocalizeValue getBorderTitle() { + return RefactoringLocalize.inlineMethodBorderTitle(); + } + + @Nonnull + @Override + protected LocalizeValue getInlineThisText() { + return RefactoringLocalize.thisInvocationOnlyAndKeepTheMethod(); + } + + @Nonnull + @Override + protected LocalizeValue getInlineAllText() { + String occurrencesString = + myOccurrencesNumber > -1 ? " (" + myOccurrencesNumber + " occurrence" + (myOccurrencesNumber == 1 ? ")" : "s)") : ""; + LocalizeValue prefix = myMethod.isWritable() + ? RefactoringLocalize.allInvocationsAndRemoveTheMethod() + : RefactoringLocalize.allInvocationsInProject(); + return LocalizeValue.join(prefix, LocalizeValue.localizeTODO(occurrencesString)); + } + + @Override + @RequiredReadAction + protected void doAction() { + super.doAction(); + invokeRefactoring(new InlineMethodProcessor( + getProject(), + myMethod, + myReferenceElement, + myEditor, + isInlineThisOnly(), + isSearchInCommentsAndStrings(), + isSearchForTextOccurrences() + )); + JavaRefactoringSettings settings = JavaRefactoringSettings.getInstance(); + if (myRbInlineThisOnly.isEnabled() && myRbInlineAll.isEnabled()) { + settings.INLINE_METHOD_THIS = isInlineThisOnly(); + } + } + + @Override + @RequiredUIAccess + protected void doHelpAction() { + HelpManager.getInstance().invokeHelp(myMethod.isConstructor() ? HelpID.INLINE_CONSTRUCTOR : HelpID.INLINE_METHOD); + } + + @Override + @RequiredReadAction + protected boolean canInlineThisOnly() { + return InlineMethodHandler.checkRecursive(myMethod) || myAllowInlineThisOnly; + } + + @Override + protected boolean isInlineThis() { + return JavaRefactoringSettings.getInstance().INLINE_METHOD_THIS; + } + + @Override + protected boolean isSearchInCommentsAndStrings() { + return JavaRefactoringSettings.getInstance().RENAME_SEARCH_IN_COMMENTS_FOR_METHOD; + } + + @Override + protected void saveSearchInCommentsAndStrings(boolean searchInComments) { + JavaRefactoringSettings.getInstance().RENAME_SEARCH_IN_COMMENTS_FOR_METHOD = searchInComments; + } + + @Override + protected boolean isSearchForTextOccurrences() { + return JavaRefactoringSettings.getInstance().RENAME_SEARCH_FOR_TEXT_FOR_METHOD; + } + + @Override + protected void saveSearchInTextOccurrences(boolean searchInTextOccurrences) { + JavaRefactoringSettings.getInstance().RENAME_SEARCH_FOR_TEXT_FOR_METHOD = searchInTextOccurrences; } - } - - @Override - protected void doHelpAction() { - if (myMethod.isConstructor()) HelpManager.getInstance().invokeHelp(HelpID.INLINE_CONSTRUCTOR); - else HelpManager.getInstance().invokeHelp(HelpID.INLINE_METHOD); - } - - @Override - protected boolean canInlineThisOnly() { - return InlineMethodHandler.checkRecursive(myMethod) || myAllowInlineThisOnly; - } - - @Override - protected boolean isInlineThis() { - return JavaRefactoringSettings.getInstance().INLINE_METHOD_THIS; - } - - @Override - protected boolean isSearchInCommentsAndStrings() { - return JavaRefactoringSettings.getInstance().RENAME_SEARCH_IN_COMMENTS_FOR_METHOD; - } - - @Override - protected void saveSearchInCommentsAndStrings(boolean searchInComments) { - JavaRefactoringSettings.getInstance().RENAME_SEARCH_IN_COMMENTS_FOR_METHOD = searchInComments; - } - - @Override - protected boolean isSearchForTextOccurrences() { - return JavaRefactoringSettings.getInstance().RENAME_SEARCH_FOR_TEXT_FOR_METHOD; - } - - @Override - protected void saveSearchInTextOccurrences(boolean searchInTextOccurrences) { - JavaRefactoringSettings.getInstance().RENAME_SEARCH_FOR_TEXT_FOR_METHOD = searchInTextOccurrences; - } } diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineMethodHandler.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineMethodHandler.java index b8e65b683f..ffe56a42fc 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineMethodHandler.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineMethodHandler.java @@ -1,4 +1,3 @@ - /* * Copyright 2000-2009 JetBrains s.r.o. * @@ -21,158 +20,181 @@ import com.intellij.java.impl.refactoring.util.RefactoringUtil; import com.intellij.java.language.JavaLanguage; import com.intellij.java.language.psi.*; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; import consulo.codeEditor.Editor; import consulo.language.editor.TargetElementUtil; -import consulo.language.editor.refactoring.RefactoringBundle; import consulo.language.editor.refactoring.localize.RefactoringLocalize; import consulo.language.editor.refactoring.util.CommonRefactoringUtil; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiReference; import consulo.localize.LocalizeValue; import consulo.project.Project; +import consulo.ui.annotation.RequiredUIAccess; import consulo.virtualFileSystem.ReadonlyStatusHandler; import consulo.virtualFileSystem.VirtualFile; @ExtensionImpl public class InlineMethodHandler extends JavaInlineActionHandler { - private static final String REFACTORING_NAME = RefactoringBundle.message("inline.method.title"); - - public boolean canInlineElement(PsiElement element) { - return element instanceof PsiMethod && element.getNavigationElement() instanceof PsiMethod && element.getLanguage() == JavaLanguage.INSTANCE; - } - - public void inlineElement(final Project project, Editor editor, PsiElement element) { - PsiMethod method = (PsiMethod) element.getNavigationElement(); - final PsiCodeBlock methodBody = method.getBody(); - if (methodBody == null) { - LocalizeValue message = method.hasModifierProperty(PsiModifier.ABSTRACT) - ? RefactoringLocalize.refactoringCannotBeAppliedToAbstractMethods(REFACTORING_NAME) - : RefactoringLocalize.refactoringCannotBeAppliedNoSourcesAttached(REFACTORING_NAME); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME, HelpID.INLINE_METHOD); - return; + private static final LocalizeValue REFACTORING_NAME = RefactoringLocalize.inlineMethodTitle(); + + @Override + @RequiredReadAction + public boolean canInlineElement(PsiElement element) { + return element instanceof PsiMethod method + && method.getNavigationElement() instanceof PsiMethod + && method.getLanguage() == JavaLanguage.INSTANCE; } - PsiReference reference = editor != null ? TargetElementUtil.findReference(editor, editor.getCaretModel().getOffset()) : null; - if (reference != null) { - final PsiElement refElement = reference.getElement(); - if (refElement != null && !isEnabledForLanguage(refElement.getLanguage())) { - LocalizeValue message = - RefactoringLocalize.refactoringIsNotSupportedForLanguage("Inline of Java method", refElement.getLanguage().getDisplayName()); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME, HelpID.INLINE_METHOD); - return; - } - } - boolean allowInlineThisOnly = false; - if (InlineMethodProcessor.checkBadReturns(method) && !InlineUtil.allUsagesAreTailCalls(method)) { - if (reference != null && InlineUtil.getTailCallType(reference) != InlineUtil.TailCallType.None) { - allowInlineThisOnly = true; - } else { - LocalizeValue message = RefactoringLocalize.refactoringIsNotSupportedWhenReturnStatementInterruptsTheExecutionFlow(REFACTORING_NAME); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME, HelpID.INLINE_METHOD); - return; - } - } + @Override + @RequiredUIAccess + public void inlineElement(Project project, Editor editor, PsiElement element) { + PsiMethod method = (PsiMethod) element.getNavigationElement(); + PsiCodeBlock methodBody = method.getBody(); + if (methodBody == null) { + LocalizeValue message = method.isAbstract() + ? RefactoringLocalize.refactoringCannotBeAppliedToAbstractMethods(REFACTORING_NAME) + : RefactoringLocalize.refactoringCannotBeAppliedNoSourcesAttached(REFACTORING_NAME); + CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME.get(), HelpID.INLINE_METHOD); + return; + } - if (reference == null && checkRecursive(method)) { - LocalizeValue message = RefactoringLocalize.refactoringIsNotSupportedForRecursiveMethods(REFACTORING_NAME); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME, HelpID.INLINE_METHOD); - return; - } + PsiReference reference = editor != null ? TargetElementUtil.findReference(editor, editor.getCaretModel().getOffset()) : null; + if (reference != null) { + PsiElement refElement = reference.getElement(); + if (refElement != null && !isEnabledForLanguage(refElement.getLanguage())) { + LocalizeValue message = RefactoringLocalize.refactoringIsNotSupportedForLanguage( + "Inline of Java method", + refElement.getLanguage().getDisplayName() + ); + CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME.get(), HelpID.INLINE_METHOD); + return; + } + } + boolean allowInlineThisOnly = false; + if (InlineMethodProcessor.checkBadReturns(method) && !InlineUtil.allUsagesAreTailCalls(method)) { + if (reference != null && InlineUtil.getTailCallType(reference) != InlineUtil.TailCallType.None) { + allowInlineThisOnly = true; + } + else { + LocalizeValue message = + RefactoringLocalize.refactoringIsNotSupportedWhenReturnStatementInterruptsTheExecutionFlow(REFACTORING_NAME); + CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME.get(), HelpID.INLINE_METHOD); + return; + } + } - if (reference instanceof PsiMethodReferenceExpression) { - CommonRefactoringUtil.showErrorHint(project, editor, REFACTORING_NAME + " cannot be applied to method references", REFACTORING_NAME, HelpID.INLINE_METHOD); - return; - } + if (reference == null && checkRecursive(method)) { + LocalizeValue message = RefactoringLocalize.refactoringIsNotSupportedForRecursiveMethods(REFACTORING_NAME); + CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME.get(), HelpID.INLINE_METHOD); + return; + } - if (reference != null) { - final String errorMessage = InlineMethodProcessor.checkCalledInSuperOrThisExpr(methodBody, reference.getElement()); - if (errorMessage != null) { - CommonRefactoringUtil.showErrorHint(project, editor, errorMessage, REFACTORING_NAME, HelpID.INLINE_METHOD); - return; - } - } + if (reference instanceof PsiMethodReferenceExpression) { + CommonRefactoringUtil.showErrorHint( + project, + editor, + REFACTORING_NAME + " cannot be applied to method references", + REFACTORING_NAME.get(), + HelpID.INLINE_METHOD + ); + return; + } - if (method.isConstructor()) { - if (method.isVarArgs()) { - LocalizeValue message = RefactoringLocalize.refactoringCannotBeAppliedToVarargConstructors(REFACTORING_NAME); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME, HelpID.INLINE_CONSTRUCTOR); - return; - } - final boolean chainingConstructor = isChainingConstructor(method); - if (!chainingConstructor) { - if (!isThisReference(reference)) { - LocalizeValue message = RefactoringLocalize.refactoringCannotBeAppliedToInlineNonChainingConstructors(REFACTORING_NAME); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME, HelpID.INLINE_CONSTRUCTOR); - return; + if (reference != null) { + String errorMessage = InlineMethodProcessor.checkCalledInSuperOrThisExpr(methodBody, reference.getElement()); + if (errorMessage != null) { + CommonRefactoringUtil.showErrorHint(project, editor, errorMessage, REFACTORING_NAME.get(), HelpID.INLINE_METHOD); + return; + } } - allowInlineThisOnly = true; - } - if (reference != null) { - final PsiElement refElement = reference.getElement(); - PsiCall constructorCall = refElement instanceof PsiJavaCodeReferenceElement ? RefactoringUtil.getEnclosingConstructorCall((PsiJavaCodeReferenceElement) refElement) : null; - if (constructorCall == null || !method.equals(constructorCall.resolveMethod())) reference = null; - } - } else { - if (reference != null && !method.getManager().areElementsEquivalent(method, reference.resolve())) { - reference = null; - } - } - final boolean invokedOnReference = reference != null; - if (!invokedOnReference) { - final VirtualFile vFile = method.getContainingFile().getVirtualFile(); - ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(vFile); - } - PsiJavaCodeReferenceElement refElement = reference != null ? (PsiJavaCodeReferenceElement) reference.getElement() : null; - InlineMethodDialog dialog = new InlineMethodDialog(project, method, refElement, editor, allowInlineThisOnly); - dialog.show(); - } - - public static boolean isChainingConstructor(PsiMethod constructor) { - PsiCodeBlock body = constructor.getBody(); - if (body != null) { - PsiStatement[] statements = body.getStatements(); - if (statements.length == 1 && statements[0] instanceof PsiExpressionStatement) { - PsiExpression expression = ((PsiExpressionStatement) statements[0]).getExpression(); - if (expression instanceof PsiMethodCallExpression) { - PsiReferenceExpression methodExpr = ((PsiMethodCallExpression) expression).getMethodExpression(); - if ("this".equals(methodExpr.getReferenceName())) { - PsiElement resolved = methodExpr.resolve(); - return resolved instanceof PsiMethod && ((PsiMethod) resolved).isConstructor(); //delegated via "this" call - } + if (method.isConstructor()) { + if (method.isVarArgs()) { + LocalizeValue message = RefactoringLocalize.refactoringCannotBeAppliedToVarargConstructors(REFACTORING_NAME); + CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME.get(), HelpID.INLINE_CONSTRUCTOR); + return; + } + boolean chainingConstructor = isChainingConstructor(method); + if (!chainingConstructor) { + if (!isThisReference(reference)) { + LocalizeValue message = RefactoringLocalize.refactoringCannotBeAppliedToInlineNonChainingConstructors(REFACTORING_NAME); + CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME.get(), HelpID.INLINE_CONSTRUCTOR); + return; + } + allowInlineThisOnly = true; + } + if (reference != null) { + PsiElement refElement = reference.getElement(); + PsiCall constructorCall = refElement instanceof PsiJavaCodeReferenceElement javaCodeRef + ? RefactoringUtil.getEnclosingConstructorCall(javaCodeRef) + : null; + if (constructorCall == null || !method.equals(constructorCall.resolveMethod())) { + reference = null; + } + } + } + else { + if (reference != null && !method.getManager().areElementsEquivalent(method, reference.resolve())) { + reference = null; + } } - } + + boolean invokedOnReference = reference != null; + if (!invokedOnReference) { + VirtualFile vFile = method.getContainingFile().getVirtualFile(); + ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(vFile); + } + PsiJavaCodeReferenceElement refElement = reference != null ? (PsiJavaCodeReferenceElement) reference.getElement() : null; + InlineMethodDialog dialog = new InlineMethodDialog(project, method, refElement, editor, allowInlineThisOnly); + dialog.show(); } - return false; - } - public static boolean checkRecursive(PsiMethod method) { - return checkCalls(method.getBody(), method); - } + @RequiredReadAction + public static boolean isChainingConstructor(PsiMethod constructor) { + PsiCodeBlock body = constructor.getBody(); + if (body != null) { + PsiStatement[] statements = body.getStatements(); + if (statements.length == 1 && statements[0] instanceof PsiExpressionStatement exprStmt + && exprStmt.getExpression() instanceof PsiMethodCallExpression call) { + PsiReferenceExpression methodExpr = call.getMethodExpression(); + if ("this".equals(methodExpr.getReferenceName())) { + PsiElement resolved = methodExpr.resolve(); + return resolved instanceof PsiMethod method && method.isConstructor(); //delegated via "this" call + } + } + } + return false; + } - private static boolean checkCalls(PsiElement scope, PsiMethod method) { - if (scope instanceof PsiMethodCallExpression) { - PsiMethod refMethod = (PsiMethod) ((PsiMethodCallExpression) scope).getMethodExpression().resolve(); - if (method.equals(refMethod)) return true; + @RequiredReadAction + public static boolean checkRecursive(PsiMethod method) { + return checkCalls(method.getBody(), method); } - for (PsiElement child = scope.getFirstChild(); child != null; child = child.getNextSibling()) { - if (checkCalls(child, method)) return true; + @RequiredReadAction + private static boolean checkCalls(PsiElement scope, PsiMethod method) { + if (scope instanceof PsiMethodCallExpression call) { + PsiMethod refMethod = (PsiMethod) call.getMethodExpression().resolve(); + if (method.equals(refMethod)) { + return true; + } + } + + for (PsiElement child = scope.getFirstChild(); child != null; child = child.getNextSibling()) { + if (checkCalls(child, method)) { + return true; + } + } + + return false; } - return false; - } - - public static boolean isThisReference(PsiReference reference) { - if (reference != null) { - final PsiElement referenceElement = reference.getElement(); - if (referenceElement instanceof PsiJavaCodeReferenceElement && - referenceElement.getParent() instanceof PsiMethodCallExpression && - "this".equals(((PsiJavaCodeReferenceElement) referenceElement).getReferenceName())) { - return true; - } + @RequiredReadAction + public static boolean isThisReference(PsiReference reference) { + return reference != null + && reference.getElement() instanceof PsiJavaCodeReferenceElement javaCodeRef + && javaCodeRef.getParent() instanceof PsiMethodCallExpression + && "this".equals(javaCodeRef.getReferenceName()); } - return false; - } } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineMethodProcessor.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineMethodProcessor.java index 151b05f5ad..9867716f6c 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineMethodProcessor.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineMethodProcessor.java @@ -672,16 +672,13 @@ public void inlineMethodCall(PsiReferenceExpression ref) throws IncorrectOperati resultVar = (PsiLocalVariable)statement.getDeclaredElements()[0]; } } - if (statements.length > 0) { - if (statements[statements.length - 1] instanceof PsiReturnStatement returnStmt - && tailCall != InlineUtil.TailCallType.Return) { - PsiExpression returnValue = returnStmt.getReturnValue(); - if (returnValue != null && PsiUtil.isStatement(returnValue)) { - PsiExpressionStatement exprStatement = - (PsiExpressionStatement)myFactory.createStatementFromText("a;", null); - exprStatement.getExpression().replace(returnValue); - anchorParent.addBefore(exprStatement, anchor); - } + if (statements[statements.length - 1] instanceof PsiReturnStatement returnStmt + && tailCall != InlineUtil.TailCallType.Return) { + PsiExpression returnValue = returnStmt.getReturnValue(); + if (returnValue != null && PsiUtil.isStatement(returnValue)) { + PsiExpressionStatement exprStatement = (PsiExpressionStatement)myFactory.createStatementFromText("a;", null); + exprStatement.getExpression().replace(returnValue); + anchorParent.addBefore(exprStatement, anchor); } } } @@ -707,14 +704,12 @@ public void inlineMethodCall(PsiReferenceExpression ref) throws IncorrectOperati else if (methodCall.getParent() instanceof PsiExpressionStatement || tailCall == InlineUtil.TailCallType.Return) { methodCall.getParent().delete(); } + else if (blockData.resultVar != null) { + PsiExpression expr = myFactory.createExpressionFromText(blockData.resultVar.getName(), null); + methodCall.replace(expr); + } else { - if (blockData.resultVar != null) { - PsiExpression expr = myFactory.createExpressionFromText(blockData.resultVar.getName(), null); - methodCall.replace(expr); - } - else { - //?? - } + //?? } if (thisVar != null) { @@ -783,7 +778,7 @@ private boolean syncNeeded(PsiReferenceExpression ref) { return !sourceContainingClass.equals(targetContainingClass); } - @RequiredReadAction + @RequiredWriteAction private BlockData prepareBlock( PsiReferenceExpression ref, PsiSubstitutor callSubstitutor, @@ -985,7 +980,6 @@ private void addParamAndThisVarInitializers(BlockData blockData, PsiMethodCallEx do { parentClass = PsiTreeUtil.getParentOfType(parentClass, PsiClass.class, true); if (InheritanceUtil.isInheritorOrSelf(parentClass, containingClass, true)) { - LOG.assertTrue(parentClass != null); String childClassName = parentClass.getName(); qualifier = myFactory.createExpressionFromText( childClassName != null ? childClassName + ".this" : "this", diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineParameterDialog.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineParameterDialog.java index 8d1bf9be6a..078db86006 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineParameterDialog.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineParameterDialog.java @@ -30,53 +30,64 @@ * @author yole */ public class InlineParameterDialog extends RefactoringDialog { - private JCheckBox myCreateLocalCheckbox; - private final PsiCallExpression myMethodCall; - private final PsiMethod myMethod; - private final PsiParameter myParameter; - private final PsiExpression myInitializer; + private JCheckBox myCreateLocalCheckbox; + private final PsiCallExpression myMethodCall; + private final PsiMethod myMethod; + private final PsiParameter myParameter; + private final PsiExpression myInitializer; - public InlineParameterDialog(PsiCallExpression methodCall, PsiMethod method, PsiParameter psiParameter, PsiExpression initializer, - boolean createLocal) { - super(method.getProject(), true); - myMethodCall = methodCall; - myMethod = method; - myParameter = psiParameter; - myInitializer = initializer; - init(); - myCreateLocalCheckbox.setSelected(createLocal); - setTitle(InlineParameterHandler.REFACTORING_NAME); - } + public InlineParameterDialog( + PsiCallExpression methodCall, + PsiMethod method, + PsiParameter psiParameter, + PsiExpression initializer, + boolean createLocal + ) { + super(method.getProject(), true); + myMethodCall = methodCall; + myMethod = method; + myParameter = psiParameter; + myInitializer = initializer; + init(); + myCreateLocalCheckbox.setSelected(createLocal); + setTitle(InlineParameterHandler.REFACTORING_NAME); + } - @Override - protected JComponent createNorthPanel() { - final JPanel panel = new JPanel(new BorderLayout()); - panel.add( - new JLabel( - RefactoringLocalize.inlineParameterConfirmation(myParameter.getName(), myInitializer.getText()).get(), - UIManager.getIcon("OptionPane.questionIcon"), - 2 - ), - BorderLayout.NORTH - ); - return panel; - } + @Override + protected JComponent createNorthPanel() { + final JPanel panel = new JPanel(new BorderLayout()); + panel.add( + new JLabel( + RefactoringLocalize.inlineParameterConfirmation(myParameter.getName(), myInitializer.getText()).get(), + UIManager.getIcon("OptionPane.questionIcon"), + 2 + ), + BorderLayout.NORTH + ); + return panel; + } - @Override - protected JComponent createCenterPanel() { - JPanel panel = new JPanel(new BorderLayout()); - myCreateLocalCheckbox = new JCheckBox(RefactoringLocalize.inlineParameterReplaceWithLocalCheckbox().get()); - panel.add(myCreateLocalCheckbox, BorderLayout.SOUTH); - return panel; - } + @Override + protected JComponent createCenterPanel() { + JPanel panel = new JPanel(new BorderLayout()); + myCreateLocalCheckbox = new JCheckBox(RefactoringLocalize.inlineParameterReplaceWithLocalCheckbox().get()); + panel.add(myCreateLocalCheckbox, BorderLayout.SOUTH); + return panel; + } - @Override - protected String getHelpId() { - return HelpID.INLINE_VARIABLE; - } + @Override + protected String getHelpId() { + return HelpID.INLINE_VARIABLE; + } - @Override - protected void doAction() { - invokeRefactoring(new InlineParameterExpressionProcessor(myMethodCall, myMethod, myParameter, myInitializer, myCreateLocalCheckbox.isSelected())); - } + @Override + protected void doAction() { + invokeRefactoring(new InlineParameterExpressionProcessor( + myMethodCall, + myMethod, + myParameter, + myInitializer, + myCreateLocalCheckbox.isSelected() + )); + } } diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineParameterExpressionProcessor.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineParameterExpressionProcessor.java index a621836cc8..7cdd4db504 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineParameterExpressionProcessor.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineParameterExpressionProcessor.java @@ -81,7 +81,7 @@ public InlineParameterExpressionProcessor( @Nonnull @Override protected String getCommandName() { - return InlineParameterHandler.REFACTORING_NAME; + return InlineParameterHandler.REFACTORING_NAME.get(); } @Nonnull diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineParameterHandler.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineParameterHandler.java index a3f5941740..de6b633829 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineParameterHandler.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineParameterHandler.java @@ -29,7 +29,6 @@ import consulo.codeEditor.Editor; import consulo.language.editor.PsiEquivalenceUtil; import consulo.language.editor.WriteCommandAction; -import consulo.language.editor.refactoring.RefactoringBundle; import consulo.language.editor.refactoring.localize.RefactoringLocalize; import consulo.language.editor.refactoring.util.CommonRefactoringUtil; import consulo.language.editor.refactoring.util.RefactoringMessageDialog; @@ -42,7 +41,7 @@ import consulo.logging.Logger; import consulo.project.Project; import consulo.ui.annotation.RequiredUIAccess; -import consulo.util.lang.ref.Ref; +import consulo.util.lang.ref.SimpleReference; import jakarta.annotation.Nullable; import java.util.*; @@ -52,258 +51,258 @@ */ @ExtensionImpl public class InlineParameterHandler extends JavaInlineActionHandler { - private static final Logger LOG = Logger.getInstance(InlineParameterHandler.class); - public static final String REFACTORING_NAME = RefactoringBundle.message("inline.parameter.refactoring"); + private static final Logger LOG = Logger.getInstance(InlineParameterHandler.class); + public static final LocalizeValue REFACTORING_NAME = RefactoringLocalize.inlineParameterRefactoring(); - @RequiredReadAction - public boolean canInlineElement(PsiElement element) { - if (element instanceof PsiParameter) { - final PsiElement parent = element.getParent(); - if (parent instanceof PsiParameterList && - parent.getParent() instanceof PsiMethod && - element.getLanguage() == JavaLanguage.INSTANCE) { - return true; - } + @Override + @RequiredReadAction + public boolean canInlineElement(PsiElement element) { + return element instanceof PsiParameter param + && param.getParent() instanceof PsiParameterList paramList + && paramList.getParent() instanceof PsiMethod + && param.getLanguage() == JavaLanguage.INSTANCE; } - return false; - } - @RequiredReadAction - @RequiredUIAccess - public void inlineElement(final Project project, final Editor editor, final PsiElement psiElement) { - final PsiParameter psiParameter = (PsiParameter) psiElement; - final PsiParameterList parameterList = (PsiParameterList) psiParameter.getParent(); - if (!(parameterList.getParent() instanceof PsiMethod)) { - return; - } - final int index = parameterList.getParameterIndex(psiParameter); - final PsiMethod method = (PsiMethod) parameterList.getParent(); + @Override + @RequiredUIAccess + public void inlineElement(final Project project, Editor editor, PsiElement psiElement) { + final PsiParameter psiParameter = (PsiParameter) psiElement; + PsiParameterList parameterList = (PsiParameterList) psiParameter.getParent(); + if (!(parameterList.getParent() instanceof PsiMethod)) { + return; + } + int index = parameterList.getParameterIndex(psiParameter); + final PsiMethod method = (PsiMethod) parameterList.getParent(); - String errorMessage = getCannotInlineMessage(psiParameter, method); - if (errorMessage != null) { - CommonRefactoringUtil.showErrorHint(project, editor, errorMessage, RefactoringLocalize.inlineParameterRefactoring().get(), null); - return; - } + String errorMessage = getCannotInlineMessage(psiParameter, method); + if (errorMessage != null) { + CommonRefactoringUtil.showErrorHint( + project, + editor, + errorMessage, + RefactoringLocalize.inlineParameterRefactoring().get(), + null + ); + return; + } + + SimpleReference refInitializer = new SimpleReference<>(); + SimpleReference refConstantInitializer = new SimpleReference<>(); + SimpleReference refMethodCall = new SimpleReference<>(); + List occurrences = Collections.synchronizedList(new ArrayList()); + Collection containingFiles = Collections.synchronizedSet(new HashSet()); + containingFiles.add(psiParameter.getContainingFile()); + boolean result = ReferencesSearch.search(method).forEach(psiReference -> { + PsiElement element = psiReference.getElement(); + PsiElement parent = element.getParent(); + if (parent instanceof PsiCallExpression methodCall) { + occurrences.add(psiReference); + containingFiles.add(element.getContainingFile()); + PsiExpression[] expressions = methodCall.getArgumentList().getExpressions(); + if (expressions.length <= index) { + return false; + } + PsiExpression argument = expressions[index]; + if (!refInitializer.isNull()) { + return argument != null + && PsiEquivalenceUtil.areElementsEquivalent(refInitializer.get(), argument) + && PsiEquivalenceUtil.areElementsEquivalent(refMethodCall.get(), methodCall); + } + if (InlineToAnonymousConstructorProcessor.isConstant(argument) || getReferencedFinalField(argument) != null) { + if (refConstantInitializer.isNull()) { + refConstantInitializer.set(argument); + } + else if (!isSameConstant(argument, refConstantInitializer.get())) { + return false; + } + } + else if (!isRecursiveReferencedParameter(argument, psiParameter)) { + if (!refConstantInitializer.isNull()) { + return false; + } + refInitializer.set(argument); + refMethodCall.set(methodCall); + } + } + return true; + }); + int offset = editor.getCaretModel().getOffset(); + PsiElement refExpr = psiElement.getContainingFile().findElementAt(offset); + PsiCodeBlock codeBlock = PsiTreeUtil.getParentOfType(refExpr, PsiCodeBlock.class); + if (codeBlock != null) { + PsiElement[] defs = DefUseUtil.getDefs(codeBlock, psiParameter, refExpr); + if (defs.length == 1) { + final PsiElement def = defs[0]; + if (def instanceof PsiReferenceExpression referenceExpression && PsiUtil.isOnAssignmentLeftHand(referenceExpression)) { + final PsiExpression rExpr = ((PsiAssignmentExpression) def.getParent()).getRExpression(); + if (rExpr != null) { + final PsiElement[] refs = DefUseUtil.getRefs(codeBlock, psiParameter, refExpr); - final Ref refInitializer = new Ref<>(); - final Ref refConstantInitializer = new Ref<>(); - final Ref refMethodCall = new Ref<>(); - final List occurrences = Collections.synchronizedList(new ArrayList()); - final Collection containingFiles = Collections.synchronizedSet(new HashSet()); - containingFiles.add(psiParameter.getContainingFile()); - boolean result = ReferencesSearch.search(method).forEach(psiReference -> { - PsiElement element = psiReference.getElement(); - final PsiElement parent = element.getParent(); - if (parent instanceof PsiCallExpression methodCall) { - occurrences.add(psiReference); - containingFiles.add(element.getContainingFile()); - final PsiExpression[] expressions = methodCall.getArgumentList().getExpressions(); - if (expressions.length <= index) return false; - PsiExpression argument = expressions[index]; + if (InlineLocalHandler.checkRefsInAugmentedAssignmentOrUnaryModified(refs) == null) { + new WriteCommandAction(project) { + @Override + protected void run(Result result) throws Throwable { + for (final PsiElement ref : refs) { + InlineUtil.inlineVariable(psiParameter, rExpr, (PsiJavaCodeReferenceElement) ref); + } + def.getParent().delete(); + } + }.execute(); + return; + } + } + } + } + } + if (occurrences.isEmpty()) { + CommonRefactoringUtil + .showErrorHint(project, editor, "Method has no usages", RefactoringLocalize.inlineParameterRefactoring().get(), null); + return; + } + if (!result) { + CommonRefactoringUtil.showErrorHint( + project, + editor, + "Cannot find constant initializer for parameter", + RefactoringLocalize.inlineParameterRefactoring().get(), + null + ); + return; + } if (!refInitializer.isNull()) { - return argument != null - && PsiEquivalenceUtil.areElementsEquivalent(refInitializer.get(), argument) - && PsiEquivalenceUtil.areElementsEquivalent(refMethodCall.get(), methodCall); + if (project.getApplication().isUnitTestMode()) { + InlineParameterExpressionProcessor processor = new InlineParameterExpressionProcessor( + refMethodCall.get(), + method, + psiParameter, + refInitializer.get(), + method.getProject().getUserData(InlineParameterExpressionProcessor.CREATE_LOCAL_FOR_TESTS) + ); + processor.run(); + } + else { + boolean createLocal = ReferencesSearch.search(psiParameter).findAll().size() > 1; + InlineParameterDialog dlg = + new InlineParameterDialog(refMethodCall.get(), method, psiParameter, refInitializer.get(), createLocal); + dlg.show(); + } + return; } - if (InlineToAnonymousConstructorProcessor.isConstant(argument) || getReferencedFinalField(argument) != null) { - if (refConstantInitializer.isNull()) { - refConstantInitializer.set(argument); - } - else if (!isSameConstant(argument, refConstantInitializer.get())) { - return false; - } - } else if (!isRecursiveReferencedParameter(argument, psiParameter)) { - if (!refConstantInitializer.isNull()) return false; - refInitializer.set(argument); - refMethodCall.set(methodCall); + if (refConstantInitializer.isNull()) { + CommonRefactoringUtil.showErrorHint( + project, + editor, + "Cannot find constant initializer for parameter", + RefactoringLocalize.inlineParameterRefactoring().get(), + null + ); + return; } - } - return true; - }); - final int offset = editor.getCaretModel().getOffset(); - final PsiElement refExpr = psiElement.getContainingFile().findElementAt(offset); - final PsiCodeBlock codeBlock = PsiTreeUtil.getParentOfType(refExpr, PsiCodeBlock.class); - if (codeBlock != null) { - final PsiElement[] defs = DefUseUtil.getDefs(codeBlock, psiParameter, refExpr); - if (defs.length == 1) { - final PsiElement def = defs[0]; - if (def instanceof PsiReferenceExpression referenceExpression && PsiUtil.isOnAssignmentLeftHand(referenceExpression)) { - final PsiExpression rExpr = ((PsiAssignmentExpression)def.getParent()).getRExpression(); - if (rExpr != null) { - final PsiElement[] refs = DefUseUtil.getRefs(codeBlock, psiParameter, refExpr); - if (InlineLocalHandler.checkRefsInAugmentedAssignmentOrUnaryModified(refs) == null) { - new WriteCommandAction(project) { - @Override - protected void run(Result result) throws Throwable { - for (final PsiElement ref : refs) { - InlineUtil.inlineVariable(psiParameter, rExpr, (PsiJavaCodeReferenceElement)ref); - } - def.getParent().delete(); + final SimpleReference isNotConstantAccessible = new SimpleReference<>(); + PsiExpression constantExpression = refConstantInitializer.get(); + constantExpression.accept(new JavaRecursiveElementVisitor() { + @Override + @RequiredReadAction + public void visitReferenceExpression(PsiReferenceExpression expression) { + super.visitReferenceExpression(expression); + PsiElement resolved = expression.resolve(); + if (resolved instanceof PsiMember member && !PsiUtil.isAccessible(member, method, null)) { + isNotConstantAccessible.set(Boolean.TRUE); } - }.execute(); - return; } - } + }); + if (!isNotConstantAccessible.isNull() && isNotConstantAccessible.get()) { + CommonRefactoringUtil.showErrorHint( + project, + editor, + "Constant initializer is not accessible in method body", + RefactoringLocalize.inlineParameterRefactoring().get(), + null + ); + return; } - } - } - if (occurrences.isEmpty()) { - CommonRefactoringUtil - .showErrorHint(project, editor, "Method has no usages", RefactoringLocalize.inlineParameterRefactoring().get(), null); - return; - } - if (!result) { - CommonRefactoringUtil.showErrorHint( - project, - editor, - "Cannot find constant initializer for parameter", - RefactoringLocalize.inlineParameterRefactoring().get(), - null - ); - return; - } - if (!refInitializer.isNull()) { - if (project.getApplication().isUnitTestMode()) { - final InlineParameterExpressionProcessor processor = - new InlineParameterExpressionProcessor( - refMethodCall.get(), - method, - psiParameter, - refInitializer.get(), - method.getProject().getUserData(InlineParameterExpressionProcessor.CREATE_LOCAL_FOR_TESTS) - ); - processor.run(); - } - else { - final boolean createLocal = ReferencesSearch.search(psiParameter).findAll().size() > 1; - InlineParameterDialog dlg = new InlineParameterDialog(refMethodCall.get(), method, psiParameter, refInitializer.get(), createLocal); - dlg.show(); - } - return; - } - if (refConstantInitializer.isNull()) { - CommonRefactoringUtil.showErrorHint( - project, - editor, - "Cannot find constant initializer for parameter", - RefactoringLocalize.inlineParameterRefactoring().get(), - null - ); - return; - } - final Ref isNotConstantAccessible = new Ref<>(); - final PsiExpression constantExpression = refConstantInitializer.get(); - constantExpression.accept(new JavaRecursiveElementVisitor(){ - @Override - @RequiredReadAction - public void visitReferenceExpression(PsiReferenceExpression expression) { - super.visitReferenceExpression(expression); - final PsiElement resolved = expression.resolve(); - if (resolved instanceof PsiMember member && !PsiUtil.isAccessible(member, method, null)) { - isNotConstantAccessible.set(Boolean.TRUE); + for (PsiReference psiReference : ReferencesSearch.search(psiParameter)) { + PsiElement element = psiReference.getElement(); + if (element instanceof PsiExpression expression && PsiUtil.isAccessedForWriting(expression)) { + CommonRefactoringUtil.showErrorHint( + project, + editor, + "Inline parameter which has write usages is not supported", + RefactoringLocalize.inlineParameterRefactoring().get(), + null + ); + return; + } } - } - }); - if (!isNotConstantAccessible.isNull() && isNotConstantAccessible.get()) { - CommonRefactoringUtil.showErrorHint( - project, - editor, - "Constant initializer is not accessible in method body", - RefactoringLocalize.inlineParameterRefactoring().get(), - null - ); - return; - } - for (PsiReference psiReference : ReferencesSearch.search(psiParameter)) { - final PsiElement element = psiReference.getElement(); - if (element instanceof PsiExpression expression && PsiUtil.isAccessedForWriting(expression)) { - CommonRefactoringUtil.showErrorHint( - project, - editor, - "Inline parameter which has write usages is not supported", - RefactoringLocalize.inlineParameterRefactoring().get(), - null - ); - return; - } - } + if (!project.getApplication().isUnitTestMode()) { + LocalizeValue occurrencesString = RefactoringLocalize.occurencesString(occurrences.size()); + String question = RefactoringLocalize.inlineParameterConfirmation(psiParameter.getName(), constantExpression.getText()).get() + + " " + occurrencesString; + RefactoringMessageDialog dialog = new RefactoringMessageDialog( + REFACTORING_NAME.get(), + question, + HelpID.INLINE_VARIABLE, + "OptionPane.questionIcon", + true, + project + ); + dialog.show(); + if (!dialog.isOK()) { + return; + } + } - if (!project.getApplication().isUnitTestMode()) { - LocalizeValue occurencesString = RefactoringLocalize.occurencesString(occurrences.size()); - String question = RefactoringLocalize.inlineParameterConfirmation(psiParameter.getName(), constantExpression.getText()).get() - + " " + occurencesString; - RefactoringMessageDialog dialog = new RefactoringMessageDialog( - REFACTORING_NAME, - question, - HelpID.INLINE_VARIABLE, - "OptionPane.questionIcon", - true, - project - ); - dialog.show(); - if (!dialog.isOK()){ - return; - } + SameParameterValueInspection.InlineParameterValueFix.inlineSameParameterValue(method, psiParameter, constantExpression); } - SameParameterValueInspection.InlineParameterValueFix.inlineSameParameterValue(method, psiParameter, constantExpression); - } - - @Nullable - @RequiredReadAction - private static PsiField getReferencedFinalField(final PsiExpression argument) { - if (argument instanceof PsiReferenceExpression referenceExpression) { - final PsiElement element = referenceExpression.resolve(); - if (element instanceof PsiField field) { - final PsiModifierList modifierList = field.getModifierList(); - if (modifierList != null && modifierList.hasModifierProperty(PsiModifier.FINAL)) { - return field; + @Nullable + @RequiredReadAction + private static PsiField getReferencedFinalField(PsiExpression argument) { + if (argument instanceof PsiReferenceExpression referenceExpression && referenceExpression.resolve() instanceof PsiField field) { + PsiModifierList modifierList = field.getModifierList(); + if (modifierList != null && modifierList.hasModifierProperty(PsiModifier.FINAL)) { + return field; + } } - } + return null; } - return null; - } - @RequiredReadAction - private static boolean isRecursiveReferencedParameter(final PsiExpression argument, final PsiParameter param) { - if (argument instanceof PsiReferenceExpression referenceExpression) { - final PsiElement element = referenceExpression.resolve(); - if (element instanceof PsiParameter) { - return element.equals(param); - } + @RequiredReadAction + private static boolean isRecursiveReferencedParameter(PsiExpression argument, PsiParameter param) { + return argument instanceof PsiReferenceExpression referenceExpression + && referenceExpression.resolve() instanceof PsiParameter parameter + && parameter.equals(param); } - return false; - } - @RequiredReadAction - private static boolean isSameConstant(final PsiExpression expr1, final PsiExpression expr2) { - boolean expr1Null = InlineToAnonymousConstructorProcessor.ourNullPattern.accepts(expr1); - boolean expr2Null = InlineToAnonymousConstructorProcessor.ourNullPattern.accepts(expr2); - if (expr1Null || expr2Null) { - return expr1Null && expr2Null; - } - final PsiField field1 = getReferencedFinalField(expr1); - final PsiField field2 = getReferencedFinalField(expr2); - if (field1 != null && field1 == field2) { - return true; + @RequiredReadAction + private static boolean isSameConstant(PsiExpression expr1, PsiExpression expr2) { + boolean expr1Null = InlineToAnonymousConstructorProcessor.ourNullPattern.accepts(expr1); + boolean expr2Null = InlineToAnonymousConstructorProcessor.ourNullPattern.accepts(expr2); + if (expr1Null || expr2Null) { + return expr1Null && expr2Null; + } + PsiField field1 = getReferencedFinalField(expr1); + PsiField field2 = getReferencedFinalField(expr2); + if (field1 != null && field1 == field2) { + return true; + } + Object value1 = JavaPsiFacade.getInstance(expr1.getProject()).getConstantEvaluationHelper().computeConstantExpression(expr1); + Object value2 = JavaPsiFacade.getInstance(expr2.getProject()).getConstantEvaluationHelper().computeConstantExpression(expr2); + return value1 != null && value2 != null && value1.equals(value2); } - Object value1 = JavaPsiFacade.getInstance(expr1.getProject()).getConstantEvaluationHelper().computeConstantExpression(expr1); - Object value2 = JavaPsiFacade.getInstance(expr2.getProject()).getConstantEvaluationHelper().computeConstantExpression(expr2); - return value1 != null && value2 != null && value1.equals(value2); - } - @Nullable - private static String getCannotInlineMessage(final PsiParameter psiParameter, final PsiMethod method) { - if (psiParameter.isVarArgs()) { - return RefactoringLocalize.inlineParameterErrorVarargs().get(); - } - if (method.findSuperMethods().length > 0 || - OverridingMethodsSearch.search(method, true).toArray(PsiMethod.EMPTY_ARRAY).length > 0) { - return RefactoringLocalize.inlineParameterErrorHierarchy().get(); + @Nullable + private static String getCannotInlineMessage(PsiParameter psiParameter, PsiMethod method) { + if (psiParameter.isVarArgs()) { + return RefactoringLocalize.inlineParameterErrorVarargs().get(); + } + if (method.findSuperMethods().length > 0 || + OverridingMethodsSearch.search(method, true).toArray(PsiMethod.EMPTY_ARRAY).length > 0) { + return RefactoringLocalize.inlineParameterErrorHierarchy().get(); + } + return null; } - return null; - } } diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/psi/MutationUtils.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/psi/MutationUtils.java index 3379dde65d..c4889a267f 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/psi/MutationUtils.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/psi/MutationUtils.java @@ -17,6 +17,7 @@ import com.intellij.java.language.psi.*; import com.intellij.java.language.psi.codeStyle.JavaCodeStyleManager; +import consulo.annotation.access.RequiredWriteAction; import consulo.language.codeStyle.CodeStyleManager; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiManager; @@ -25,93 +26,85 @@ import consulo.project.Project; public class MutationUtils { - private MutationUtils() { - super(); - } - - - public static void replaceType(String newExpression, - PsiTypeElement typeElement) - throws IncorrectOperationException { - final PsiManager mgr = typeElement.getManager(); - final PsiElementFactory factory = JavaPsiFacade.getInstance(mgr.getProject()).getElementFactory(); - final PsiType newType = - factory.createTypeFromText(newExpression, null); - final PsiTypeElement newTypeElement = factory.createTypeElement(newType); - final PsiElement insertedElement = typeElement.replace(newTypeElement); - final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(mgr.getProject()); - final PsiElement shortenedElement = JavaCodeStyleManager.getInstance(mgr.getProject()).shortenClassReferences(insertedElement); - codeStyleManager.reformat(shortenedElement); - } + private MutationUtils() { + super(); + } - public static void replaceExpression(String newExpression, - PsiExpression exp) - throws IncorrectOperationException { - final PsiManager mgr = exp.getManager(); - final PsiElementFactory factory = JavaPsiFacade.getInstance(mgr.getProject()).getElementFactory(); - final PsiExpression newCall = - factory.createExpressionFromText(newExpression, null); - final PsiElement insertedElement = exp.replace(newCall); - final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(mgr.getProject()); - final PsiElement shortenedElement = JavaCodeStyleManager.getInstance(mgr.getProject()).shortenClassReferences(insertedElement); - codeStyleManager.reformat(shortenedElement); - } + @RequiredWriteAction + public static void replaceType(String newExpression, PsiTypeElement typeElement) throws IncorrectOperationException { + PsiManager mgr = typeElement.getManager(); + PsiElementFactory factory = JavaPsiFacade.getInstance(mgr.getProject()).getElementFactory(); + PsiType newType = factory.createTypeFromText(newExpression, null); + PsiTypeElement newTypeElement = factory.createTypeElement(newType); + PsiElement insertedElement = typeElement.replace(newTypeElement); + CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(mgr.getProject()); + PsiElement shortenedElement = JavaCodeStyleManager.getInstance(mgr.getProject()).shortenClassReferences(insertedElement); + codeStyleManager.reformat(shortenedElement); + } - public static void replaceExpressionIfValid(String newExpression, - PsiExpression exp) throws IncorrectOperationException { - final PsiManager mgr = exp.getManager(); - final PsiElementFactory factory = JavaPsiFacade.getInstance(mgr.getProject()).getElementFactory(); - final PsiExpression newCall; - try { - newCall = factory.createExpressionFromText(newExpression, null); - } catch (IncorrectOperationException e) { - return; + @RequiredWriteAction + public static void replaceExpression(String newExpression, PsiExpression exp) throws IncorrectOperationException { + PsiManager mgr = exp.getManager(); + PsiElementFactory factory = JavaPsiFacade.getInstance(mgr.getProject()).getElementFactory(); + PsiExpression newCall = factory.createExpressionFromText(newExpression, null); + PsiElement insertedElement = exp.replace(newCall); + CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(mgr.getProject()); + PsiElement shortenedElement = JavaCodeStyleManager.getInstance(mgr.getProject()).shortenClassReferences(insertedElement); + codeStyleManager.reformat(shortenedElement); } - final PsiElement insertedElement = exp.replace(newCall); - final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(mgr.getProject()); - final PsiElement shortenedElement = JavaCodeStyleManager.getInstance(mgr.getProject()).shortenClassReferences(insertedElement); - codeStyleManager.reformat(shortenedElement); - } - public static void replaceReference(String className, - PsiJavaCodeReferenceElement reference) - throws IncorrectOperationException { - final PsiManager mgr = reference.getManager(); - final Project project = mgr.getProject(); - final JavaPsiFacade facade = JavaPsiFacade.getInstance(mgr.getProject()); - final PsiElementFactory factory = facade.getElementFactory(); - final GlobalSearchScope scope = GlobalSearchScope.allScope(project); + @RequiredWriteAction + public static void replaceExpressionIfValid(String newExpression, PsiExpression exp) throws IncorrectOperationException { + PsiManager mgr = exp.getManager(); + PsiElementFactory factory = JavaPsiFacade.getInstance(mgr.getProject()).getElementFactory(); + PsiExpression newCall; + try { + newCall = factory.createExpressionFromText(newExpression, null); + } + catch (IncorrectOperationException e) { + return; + } + PsiElement insertedElement = exp.replace(newCall); + CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(mgr.getProject()); + PsiElement shortenedElement = JavaCodeStyleManager.getInstance(mgr.getProject()).shortenClassReferences(insertedElement); + codeStyleManager.reformat(shortenedElement); + } + @RequiredWriteAction + public static void replaceReference(String className, PsiJavaCodeReferenceElement reference) throws IncorrectOperationException { + PsiManager mgr = reference.getManager(); + Project project = mgr.getProject(); + JavaPsiFacade facade = JavaPsiFacade.getInstance(mgr.getProject()); + PsiElementFactory factory = facade.getElementFactory(); + GlobalSearchScope scope = GlobalSearchScope.allScope(project); - final PsiElement insertedElement; - final PsiElement parent = reference.getParent(); - if (parent instanceof PsiReferenceExpression) { - final PsiClass aClass = facade.findClass(className, scope); - if (aClass == null) return; - ((PsiReferenceExpression) parent).setQualifierExpression(factory.createReferenceExpression(aClass)); - insertedElement = ((PsiReferenceExpression) parent).getQualifierExpression(); - } else { - final PsiJavaCodeReferenceElement newReference = - factory.createReferenceElementByFQClassName(className, scope); - insertedElement = reference.replace(newReference); + PsiElement insertedElement; + if (reference.getParent() instanceof PsiReferenceExpression refExpr) { + PsiClass aClass = facade.findClass(className, scope); + if (aClass == null) { + return; + } + refExpr.setQualifierExpression(factory.createReferenceExpression(aClass)); + insertedElement = refExpr.getQualifierExpression(); + } + else { + PsiJavaCodeReferenceElement newReference = factory.createReferenceElementByFQClassName(className, scope); + insertedElement = reference.replace(newReference); + } + CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(mgr.getProject()); + PsiElement shortenedElement = JavaCodeStyleManager.getInstance(mgr.getProject()).shortenClassReferences(insertedElement); + codeStyleManager.reformat(shortenedElement); } - final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(mgr.getProject()); - final PsiElement shortenedElement = JavaCodeStyleManager.getInstance(mgr.getProject()).shortenClassReferences(insertedElement); - codeStyleManager.reformat(shortenedElement); - } - - public static void replaceStatement(String newStatement, - PsiStatement statement) - throws IncorrectOperationException { - final Project project = statement.getProject(); - final PsiManager mgr = PsiManager.getInstance(project); - final PsiElementFactory factory = JavaPsiFacade.getInstance(mgr.getProject()).getElementFactory(); - final PsiStatement newCall = - factory.createStatementFromText(newStatement, null); - final PsiElement insertedElement = statement.replace(newCall); - final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(mgr.getProject()); - final PsiElement shortenedElement = JavaCodeStyleManager.getInstance(mgr.getProject()).shortenClassReferences(insertedElement); - codeStyleManager.reformat(shortenedElement); - } + @RequiredWriteAction + public static void replaceStatement(String newStatement, PsiStatement statement) throws IncorrectOperationException { + Project project = statement.getProject(); + PsiManager mgr = PsiManager.getInstance(project); + PsiElementFactory factory = JavaPsiFacade.getInstance(mgr.getProject()).getElementFactory(); + PsiStatement newCall = factory.createStatementFromText(newStatement, null); + PsiElement insertedElement = statement.replace(newCall); + CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(mgr.getProject()); + PsiElement shortenedElement = JavaCodeStyleManager.getInstance(mgr.getProject()).shortenClassReferences(insertedElement); + codeStyleManager.reformat(shortenedElement); + } } diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/removemiddleman/usageInfo/InlineDelegatingCall.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/removemiddleman/usageInfo/InlineDelegatingCall.java index 5d7376abe7..ab5fb5f34f 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/removemiddleman/usageInfo/InlineDelegatingCall.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/removemiddleman/usageInfo/InlineDelegatingCall.java @@ -19,52 +19,56 @@ import com.intellij.java.language.psi.PsiExpressionList; import com.intellij.java.language.psi.PsiMethodCallExpression; import com.intellij.java.language.psi.PsiReferenceExpression; +import consulo.annotation.access.RequiredWriteAction; import consulo.language.psi.*; import com.intellij.java.impl.refactoring.psi.MutationUtils; import com.intellij.java.impl.refactoring.util.FixableUsageInfo; import consulo.language.util.IncorrectOperationException; public class InlineDelegatingCall extends FixableUsageInfo { - private final PsiMethodCallExpression expression; - private final String myAccess; - private final String delegatingName; - private final int[] parameterPermutation; + private final PsiMethodCallExpression expression; + private final String myAccess; + private final String delegatingName; + private final int[] parameterPermutation; - public InlineDelegatingCall(PsiMethodCallExpression expression, - int[] parameterPermutation, - String access, - String delegatingName) { - super(expression); - this.expression = expression; - this.parameterPermutation = parameterPermutation; - myAccess = access; - this.delegatingName = delegatingName; - } - - public void fixUsage() throws IncorrectOperationException { - final StringBuffer replacementText = new StringBuffer(); - final PsiReferenceExpression methodExpression = expression.getMethodExpression(); - final PsiElement qualifier = methodExpression.getQualifier(); - if (qualifier != null) { - final String qualifierText = qualifier.getText(); - replacementText.append(qualifierText + '.'); + public InlineDelegatingCall( + PsiMethodCallExpression expression, + int[] parameterPermutation, + String access, + String delegatingName + ) { + super(expression); + this.expression = expression; + this.parameterPermutation = parameterPermutation; + myAccess = access; + this.delegatingName = delegatingName; } - replacementText.append(myAccess).append("."); - replacementText.append(delegatingName).append('('); - final PsiExpressionList argumentList = expression.getArgumentList(); - assert argumentList != null; - final PsiExpression[] args = argumentList.getExpressions(); - boolean first = true; - for (int i : parameterPermutation) { - if (!first) { - replacementText.append(", "); - } - first = false; - final String argText = args[i].getText(); - replacementText.append(argText); + + @Override + @RequiredWriteAction + public void fixUsage() throws IncorrectOperationException { + StringBuilder replacementText = new StringBuilder(); + PsiReferenceExpression methodExpression = expression.getMethodExpression(); + PsiElement qualifier = methodExpression.getQualifier(); + if (qualifier != null) { + String qualifierText = qualifier.getText(); + replacementText.append(qualifierText + '.'); + } + replacementText.append(myAccess).append("."); + replacementText.append(delegatingName).append('('); + PsiExpressionList argumentList = expression.getArgumentList(); + PsiExpression[] args = argumentList.getExpressions(); + boolean first = true; + for (int i : parameterPermutation) { + if (!first) { + replacementText.append(", "); + } + first = false; + String argText = args[i].getText(); + replacementText.append(argText); + } + replacementText.append(')'); + String replacementTextString = replacementText.toString(); + MutationUtils.replaceExpression(replacementTextString, expression); } - replacementText.append(')'); - final String replacementTextString = replacementText.toString(); - MutationUtils.replaceExpression(replacementTextString, expression); - } } diff --git a/plugin/src/main/resources/LOCALIZE-LIB/en_US/consulo.java.JavaRefactoringLocalize.yaml b/plugin/src/main/resources/LOCALIZE-LIB/en_US/consulo.java.JavaRefactoringLocalize.yaml index bf02d8e472..2576e4eaba 100644 --- a/plugin/src/main/resources/LOCALIZE-LIB/en_US/consulo.java.JavaRefactoringLocalize.yaml +++ b/plugin/src/main/resources/LOCALIZE-LIB/en_US/consulo.java.JavaRefactoringLocalize.yaml @@ -148,6 +148,18 @@ global.library.source: text: 'Global Library: {0}' initialization.expression.checkbox: text: 'Initialization expression (optional):' +inline.conflicts.progress: + text: Check if inline is possible… +inline.constant.field.not.supported.for.enum.constants: + text: '{0} is not supported for enum constants' +inline.field.used.in.javadoc: + text: Inlined field is used in javadoc +inline.field.used.in.reflection: + text: Inlined field is used reflectively +inline.local.unable.try.catch.warning.message: + text: Unable to inline outside try/catch statement +inline.local.variable.declared.outside.cannot.refactor.message: + text: Variable is declared outside a code block introduce.parameter.object: text: Introduce Parameter Object introduce.parameter.object.title: From 65644ba0444b7f366b4cfde720d9376693dc332d Mon Sep 17 00:00:00 2001 From: UNV Date: Sat, 15 Nov 2025 01:57:01 +0300 Subject: [PATCH 2/2] Localizing inline inspections/refactorings (part 2). --- .../inline/InlineLocalHandler.java | 33 +- .../inline/InlineMethodHandler.java | 18 +- .../inline/InlineMethodProcessor.java | 176 +++-- .../inline/InlineParameterDialog.java | 4 +- .../InlineParameterExpressionProcessor.java | 3 + .../inline/InlineParameterHandler.java | 93 ++- .../inline/InlineToAnonymousClassHandler.java | 748 ++++++++---------- .../InlineSuperClassRefactoringHandler.java | 119 +-- .../en_US/consulo.java.JavaLocalize.yaml | 2 + .../consulo.java.JavaRefactoringLocalize.yaml | 68 ++ .../InlineToAnonymousClassMultifileTest.java | 3 +- 11 files changed, 647 insertions(+), 620 deletions(-) diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineLocalHandler.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineLocalHandler.java index 540cf65e87..8ea7f944d4 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineLocalHandler.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineLocalHandler.java @@ -46,6 +46,7 @@ import consulo.logging.Logger; import consulo.project.Project; import consulo.ui.annotation.RequiredUIAccess; +import consulo.ui.ex.awt.UIUtil; import consulo.undoRedo.CommandProcessor; import consulo.util.collection.ArrayUtil; import jakarta.annotation.Nonnull; @@ -91,7 +92,7 @@ public static void invoke(@Nonnull Project project, Editor editor, PsiLocalVaria if (query.findFirst() == null) { LOG.assertTrue(refExpr == null); LocalizeValue message = RefactoringLocalize.variableIsNeverUsed(localName); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME.get(), HelpID.INLINE_VARIABLE); + CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.INLINE_VARIABLE); return; } @@ -127,7 +128,7 @@ public static void invoke(@Nonnull Project project, Editor editor, PsiLocalVaria LocalizeValue message = RefactoringLocalize.cannotPerformRefactoringWithReason( JavaRefactoringLocalize.inlineLocalVariableDeclaredOutsideCannotRefactorMessage() ); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME.get(), HelpID.INLINE_VARIABLE); + CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.INLINE_VARIABLE); return; } @@ -140,7 +141,7 @@ public static void invoke(@Nonnull Project project, Editor editor, PsiLocalVaria ? RefactoringLocalize.variableHasNoInitializer(localName) : RefactoringLocalize.variableHasNoDominatingDefinition() ); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME.get(), HelpID.INLINE_VARIABLE); + CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.INLINE_VARIABLE); return; } @@ -153,7 +154,7 @@ public static void invoke(@Nonnull Project project, Editor editor, PsiLocalVaria } if (refsToInlineList.size() == 0) { LocalizeValue message = RefactoringLocalize.variableIsNeverUsedBeforeModification(localName); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME.get(), HelpID.INLINE_VARIABLE); + CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.INLINE_VARIABLE); return; } PsiElement[] refsToInline = PsiUtilBase.toPsiElementArray(refsToInlineList); @@ -164,7 +165,7 @@ public static void invoke(@Nonnull Project project, Editor editor, PsiLocalVaria highlightManager.addOccurrenceHighlights(editor, defs, EditorColors.SEARCH_RESULT_ATTRIBUTES, true, null); LocalizeValue message = RefactoringLocalize.cannotPerformRefactoringWithReason(RefactoringLocalize.variableIsAccessedForWriting(localName)); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME.get(), HelpID.INLINE_VARIABLE); + CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.INLINE_VARIABLE); return; } @@ -179,15 +180,15 @@ public static void invoke(@Nonnull Project project, Editor editor, PsiLocalVaria PsiFile otherFile = ref.getContainingFile(); if (!otherFile.equals(workingFile)) { LocalizeValue message = RefactoringLocalize.variableIsReferencedInMultipleFiles(localName); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME.get(), HelpID.INLINE_VARIABLE); + CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.INLINE_VARIABLE); return; } if (tryStatement != null && !PsiTreeUtil.isAncestor(tryStatement, ref, false)) { CommonRefactoringUtil.showErrorHint( project, editor, - JavaRefactoringLocalize.inlineLocalUnableTryCatchWarningMessage().get(), - REFACTORING_NAME.get(), + JavaRefactoringLocalize.inlineLocalUnableTryCatchWarningMessage(), + REFACTORING_NAME, HelpID.INLINE_VARIABLE ); return; @@ -206,7 +207,7 @@ public static void invoke(@Nonnull Project project, Editor editor, PsiLocalVaria LocalizeValue message = RefactoringLocalize.cannotPerformRefactoringWithReason( RefactoringLocalize.variableIsAccessedForWritingAndUsedWithInlined(localName) ); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME.get(), HelpID.INLINE_VARIABLE); + CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.INLINE_VARIABLE); return; } } @@ -217,7 +218,7 @@ public static void invoke(@Nonnull Project project, Editor editor, PsiLocalVaria .addOccurrenceHighlights(editor, new PsiElement[]{writeAccess}, EditorColors.WRITE_SEARCH_RESULT_ATTRIBUTES, true, null); LocalizeValue message = RefactoringLocalize.cannotPerformRefactoringWithReason(RefactoringLocalize.variableIsAccessedForWriting(localName)); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME.get(), HelpID.INLINE_VARIABLE); + CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.INLINE_VARIABLE); return; } @@ -235,10 +236,10 @@ public static void invoke(@Nonnull Project project, Editor editor, PsiLocalVaria : RefactoringLocalize.inlineLocalVariableDefinitionPrompt(localName); LocalizeValue occurrencesString = RefactoringLocalize.occurencesString(occurrencesCount); RefactoringMessageDialog dialog = new RefactoringMessageDialog( - REFACTORING_NAME.get(), - message + " " + occurrencesString, + REFACTORING_NAME, + LocalizeValue.join(message, LocalizeValue.space(), occurrencesString), HelpID.INLINE_VARIABLE, - "OptionPane.questionIcon", + UIUtil.getQuestionIcon(), true, project ); @@ -289,7 +290,7 @@ public static void invoke(@Nonnull Project project, Editor editor, PsiLocalVaria } @Nullable - public static PsiElement checkRefsInAugmentedAssignmentOrUnaryModified( PsiElement[] refsToInline) { + public static PsiElement checkRefsInAugmentedAssignmentOrUnaryModified(PsiElement[] refsToInline) { for (PsiElement element : refsToInline) { PsiElement parent = element.getParent(); @@ -321,7 +322,7 @@ private static boolean isUnaryWriteExpression(PsiElement parent) { return tokenType == JavaTokenType.PLUSPLUS || tokenType == JavaTokenType.MINUSMINUS; } - private static boolean isSameDefinition( PsiElement def, PsiExpression defToInline) { + private static boolean isSameDefinition(PsiElement def, PsiExpression defToInline) { if (def instanceof PsiLocalVariable localVar) { return defToInline.equals(localVar.getInitializer()); } @@ -329,7 +330,7 @@ private static boolean isSameDefinition( PsiElement def, PsiExpression defToInli return parent instanceof PsiAssignmentExpression assignment && defToInline.equals(assignment.getRExpression()); } - private static boolean isInliningVariableInitializer( PsiExpression defToInline) { + private static boolean isInliningVariableInitializer(PsiExpression defToInline) { return defToInline.getParent() instanceof PsiVariable; } diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineMethodHandler.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineMethodHandler.java index ffe56a42fc..6f62de8ec2 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineMethodHandler.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineMethodHandler.java @@ -55,7 +55,7 @@ public void inlineElement(Project project, Editor editor, PsiElement element) { LocalizeValue message = method.isAbstract() ? RefactoringLocalize.refactoringCannotBeAppliedToAbstractMethods(REFACTORING_NAME) : RefactoringLocalize.refactoringCannotBeAppliedNoSourcesAttached(REFACTORING_NAME); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME.get(), HelpID.INLINE_METHOD); + CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.INLINE_METHOD); return; } @@ -67,7 +67,7 @@ public void inlineElement(Project project, Editor editor, PsiElement element) { "Inline of Java method", refElement.getLanguage().getDisplayName() ); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME.get(), HelpID.INLINE_METHOD); + CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.INLINE_METHOD); return; } } @@ -79,14 +79,14 @@ public void inlineElement(Project project, Editor editor, PsiElement element) { else { LocalizeValue message = RefactoringLocalize.refactoringIsNotSupportedWhenReturnStatementInterruptsTheExecutionFlow(REFACTORING_NAME); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME.get(), HelpID.INLINE_METHOD); + CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.INLINE_METHOD); return; } } if (reference == null && checkRecursive(method)) { LocalizeValue message = RefactoringLocalize.refactoringIsNotSupportedForRecursiveMethods(REFACTORING_NAME); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME.get(), HelpID.INLINE_METHOD); + CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.INLINE_METHOD); return; } @@ -102,9 +102,9 @@ public void inlineElement(Project project, Editor editor, PsiElement element) { } if (reference != null) { - String errorMessage = InlineMethodProcessor.checkCalledInSuperOrThisExpr(methodBody, reference.getElement()); - if (errorMessage != null) { - CommonRefactoringUtil.showErrorHint(project, editor, errorMessage, REFACTORING_NAME.get(), HelpID.INLINE_METHOD); + LocalizeValue errorMessage = InlineMethodProcessor.checkCalledInSuperOrThisExpr(methodBody, reference.getElement()); + if (errorMessage != LocalizeValue.empty()) { + CommonRefactoringUtil.showErrorHint(project, editor, errorMessage, REFACTORING_NAME, HelpID.INLINE_METHOD); return; } } @@ -112,14 +112,14 @@ public void inlineElement(Project project, Editor editor, PsiElement element) { if (method.isConstructor()) { if (method.isVarArgs()) { LocalizeValue message = RefactoringLocalize.refactoringCannotBeAppliedToVarargConstructors(REFACTORING_NAME); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME.get(), HelpID.INLINE_CONSTRUCTOR); + CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.INLINE_CONSTRUCTOR); return; } boolean chainingConstructor = isChainingConstructor(method); if (!chainingConstructor) { if (!isThisReference(reference)) { LocalizeValue message = RefactoringLocalize.refactoringCannotBeAppliedToInlineNonChainingConstructors(REFACTORING_NAME); - CommonRefactoringUtil.showErrorHint(project, editor, message.get(), REFACTORING_NAME.get(), HelpID.INLINE_CONSTRUCTOR); + CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.INLINE_CONSTRUCTOR); return; } allowInlineThisOnly = true; diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineMethodProcessor.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineMethodProcessor.java index 9867716f6c..bc97b148c4 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineMethodProcessor.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineMethodProcessor.java @@ -37,6 +37,7 @@ import consulo.annotation.access.RequiredWriteAction; import consulo.codeEditor.Editor; import consulo.codeEditor.LogicalPosition; +import consulo.java.localize.JavaRefactoringLocalize; import consulo.language.Language; import consulo.language.codeStyle.CodeStyleManager; import consulo.language.editor.refactoring.BaseRefactoringProcessor; @@ -198,7 +199,7 @@ protected boolean isPreviewUsages(UsageInfo[] usages) { protected void refreshElements(PsiElement[] elements) { boolean condition = elements.length == 1 && elements[0] instanceof PsiMethod; LOG.assertTrue(condition); - myMethod = (PsiMethod)elements[0]; + myMethod = (PsiMethod) elements[0]; } @Override @@ -224,43 +225,48 @@ protected boolean preprocessUsages(@Nonnull SimpleReference refUsag for (UsageInfo info : usagesIn) { PsiElement element = info.getElement(); if (element instanceof PsiDocMethodOrFieldRef && !PsiTreeUtil.isAncestor(myMethod, element, false)) { - conflicts.putValue(element, "Inlined method is used in javadoc"); + conflicts.putValue(element, JavaRefactoringLocalize.inlineMethodUsedInJavadoc().get()); } if (element instanceof PsiMethodReferenceExpression) { conflicts.putValue(element, "Inlined method is used in method reference"); } - String errorMessage = checkCalledInSuperOrThisExpr(myMethod.getBody(), element); - if (errorMessage != null) { - conflicts.putValue(element, errorMessage); + LocalizeValue errorMessage = checkCalledInSuperOrThisExpr(myMethod.getBody(), element); + if (errorMessage != LocalizeValue.empty()) { + conflicts.putValue(element, errorMessage.get()); } } } - ArrayList refs = convertUsagesToRefs(usagesIn); + List refs = convertUsagesToRefs(usagesIn); myInliners = GenericInlineHandler.initializeInliners(myMethod, () -> myInlineThisOnly, refs); //hack to prevent conflicts 'Cannot inline reference from Java' - myInliners.put(JavaLanguage.INSTANCE, new InlineHandler.Inliner() { - @Nullable - @Override - public MultiMap getConflicts(@Nonnull PsiReference reference, @Nonnull PsiElement referenced) { - return MultiMap.empty(); - } - - @Override - @RequiredReadAction - public void inlineUsage(@Nonnull UsageInfo usage, @Nonnull PsiElement referenced) { - if (usage instanceof NonCodeUsageInfo) { - return; + myInliners.put( + JavaLanguage.INSTANCE, + new InlineHandler.Inliner() { + @Nonnull + @Override + @RequiredReadAction + public MultiMap getConflicts(@Nonnull PsiReference reference, @Nonnull PsiElement referenced) { + return MultiMap.empty(); } - throw new UnsupportedOperationException( - "usage: " + usage.getClass().getName() + ", referenced: " + referenced.getClass() - .getName() + "text: " + referenced.getText() - ); + @Override + @RequiredReadAction + public void inlineUsage(@Nonnull UsageInfo usage, @Nonnull PsiElement referenced) { + if (usage instanceof NonCodeUsageInfo) { + return; + } + + throw new UnsupportedOperationException( + "usage: " + usage.getClass().getName() + + ", referenced: " + referenced.getClass().getName() + + ", text: " + referenced.getText() + ); + } } - }); + ); for (PsiReference ref : refs) { GenericInlineHandler.collectConflicts(ref, myMethod, myInliners, conflicts); @@ -291,8 +297,8 @@ public void inlineUsage(@Nonnull UsageInfo usage, @Nonnull PsiElement referenced } @RequiredReadAction - private static ArrayList convertUsagesToRefs(UsageInfo[] usagesIn) { - ArrayList refs = new ArrayList<>(); + private static List convertUsagesToRefs(UsageInfo[] usagesIn) { + List refs = new ArrayList<>(); for (UsageInfo info : usagesIn) { PsiReference ref = info.getReference(); if (ref != null) { //ref can be null if it is conflict usage info @@ -455,8 +461,8 @@ private void doRefactoring(UsageInfo[] usages) { } } else { - myReference = addBracesWhenNeeded(new PsiReferenceExpression[]{(PsiReferenceExpression)myReference})[0]; - inlineMethodCall((PsiReferenceExpression)myReference); + myReference = addBracesWhenNeeded(new PsiReferenceExpression[]{(PsiReferenceExpression) myReference})[0]; + inlineMethodCall((PsiReferenceExpression) myReference); } } else { @@ -549,18 +555,18 @@ public static void inlineConstructorCall(PsiCall constructorCall) { PsiStatement[] statements = oldConstructor.getBody().getStatements(); LOG.assertTrue(statements.length == 1 && statements[0] instanceof PsiExpressionStatement exprStmt); - PsiExpression expression = ((PsiExpressionStatement)statements[0]).getExpression(); + PsiExpression expression = ((PsiExpressionStatement) statements[0]).getExpression(); LOG.assertTrue(expression instanceof PsiMethodCallExpression); ChangeContextUtil.encodeContextInfo(expression, true); - PsiMethodCallExpression methodCall = (PsiMethodCallExpression)expression.copy(); + PsiMethodCallExpression methodCall = (PsiMethodCallExpression) expression.copy(); PsiExpression[] args = methodCall.getArgumentList().getExpressions(); for (PsiExpression arg : args) { replaceParameterReferences(arg, oldConstructor, instanceCreationArguments); } try { - PsiExpressionList exprList = (PsiExpressionList)constructorCall.getArgumentList().replace(methodCall.getArgumentList()); + PsiExpressionList exprList = (PsiExpressionList) constructorCall.getArgumentList().replace(methodCall.getArgumentList()); ChangeContextUtil.decodeContextInfo(exprList, PsiTreeUtil.getParentOfType(constructorCall, PsiClass.class), null); } catch (IncorrectOperationException e) { @@ -581,7 +587,7 @@ private static void replaceParameterReferences( && element.getManager().areElementsEquivalent(parameter.getDeclarationScope(), oldConstructor)) { isParameterReference = true; PsiElement declarationScope = parameter.getDeclarationScope(); - PsiParameter[] declarationParameters = ((PsiMethod)declarationScope).getParameterList().getParameters(); + PsiParameter[] declarationParameters = ((PsiMethod) declarationScope).getParameterList().getParameters(); for (int j = 0; j < declarationParameters.length; j++) { if (declarationParameters[j] == parameter) { try { @@ -607,10 +613,10 @@ private static void replaceParameterReferences( public void inlineMethodCall(PsiReferenceExpression ref) throws IncorrectOperationException { InlineUtil.TailCallType tailCall = InlineUtil.getTailCallType(ref); ChangeContextUtil.encodeContextInfo(myMethod, false); - myMethodCopy = (PsiMethod)myMethod.copy(); + myMethodCopy = (PsiMethod) myMethod.copy(); ChangeContextUtil.clearContextInfo(myMethod); - PsiMethodCallExpression methodCall = (PsiMethodCallExpression)ref.getParent(); + PsiMethodCallExpression methodCall = (PsiMethodCallExpression) ref.getParent(); PsiSubstitutor callSubstitutor = getCallSubstitutor(methodCall); BlockData blockData = prepareBlock(ref, callSubstitutor, methodCall.getArgumentList(), tailCall); @@ -659,24 +665,24 @@ public void inlineMethodCall(PsiReferenceExpression ref) throws IncorrectOperati LOG.assertTrue(current != null); if (blockData.thisVar != null) { PsiDeclarationStatement statement = PsiTreeUtil.getNextSiblingOfType(current, PsiDeclarationStatement.class); - thisVar = (PsiLocalVariable)statement.getDeclaredElements()[0]; + thisVar = (PsiLocalVariable) statement.getDeclaredElements()[0]; current = statement; } for (int i = 0; i < paramVars.length; i++) { PsiDeclarationStatement statement = PsiTreeUtil.getNextSiblingOfType(current, PsiDeclarationStatement.class); - paramVars[i] = (PsiLocalVariable)statement.getDeclaredElements()[0]; + paramVars[i] = (PsiLocalVariable) statement.getDeclaredElements()[0]; current = statement; } if (blockData.resultVar != null) { PsiDeclarationStatement statement = PsiTreeUtil.getNextSiblingOfType(current, PsiDeclarationStatement.class); - resultVar = (PsiLocalVariable)statement.getDeclaredElements()[0]; + resultVar = (PsiLocalVariable) statement.getDeclaredElements()[0]; } } if (statements[statements.length - 1] instanceof PsiReturnStatement returnStmt && tailCall != InlineUtil.TailCallType.Return) { PsiExpression returnValue = returnStmt.getReturnValue(); if (returnValue != null && PsiUtil.isStatement(returnValue)) { - PsiExpressionStatement exprStatement = (PsiExpressionStatement)myFactory.createStatementFromText("a;", null); + PsiExpressionStatement exprStatement = (PsiExpressionStatement) myFactory.createStatementFromText("a;", null); exprStatement.getExpression().replace(returnValue); anchorParent.addBefore(exprStatement, anchor); } @@ -796,8 +802,8 @@ private BlockData prepareBlock( resultName = myJavaCodeStyle.propertyNameToVariableName("result", VariableKind.LOCAL_VARIABLE); resultName = myJavaCodeStyle.suggestUniqueVariableName(resultName, block.getFirstChild(), true); PsiDeclarationStatement declaration = myFactory.createVariableDeclarationStatement(resultName, returnType, null); - declaration = (PsiDeclarationStatement)block.addAfter(declaration, null); - resultVar = (PsiLocalVariable)declaration.getDeclaredElements()[0]; + declaration = (PsiDeclarationStatement) block.addAfter(declaration, null); + resultVar = (PsiLocalVariable) declaration.getDeclaredElements()[0]; } PsiParameter[] params = myMethodCopy.getParameterList().getParameters(); @@ -817,7 +823,7 @@ private BlockData prepareBlock( if (paramType instanceof PsiEllipsisType ellipsisType) { paramType = callSubstitutor.substitute(ellipsisType.toArrayType()); if (applicabilityLevel == MethodCandidateInfo.ApplicabilityLevel.VARARGS) { - defaultValue = "new " + ((PsiArrayType)paramType).getComponentType().getCanonicalText() + "[]{}"; + defaultValue = "new " + ((PsiArrayType) paramType).getComponentType().getCanonicalText() + "[]{}"; } else { defaultValue = PsiTypesUtil.getDefaultValueOfType(paramType); @@ -830,8 +836,8 @@ private BlockData prepareBlock( PsiExpression initializer = myFactory.createExpressionFromText(defaultValue, null); PsiDeclarationStatement declaration = myFactory.createVariableDeclarationStatement(name, callSubstitutor.substitute(paramType), initializer); - declaration = (PsiDeclarationStatement)block.addAfter(declaration, null); - paramVars[i] = (PsiLocalVariable)declaration.getDeclaredElements()[0]; + declaration = (PsiDeclarationStatement) block.addAfter(declaration, null); + paramVars[i] = (PsiLocalVariable) declaration.getDeclaredElements()[0]; PsiUtil.setModifierProperty(paramVars[i], PsiModifier.FINAL, param.hasModifierProperty(PsiModifier.FINAL)); } @@ -845,8 +851,8 @@ private BlockData prepareBlock( thisVarName = myJavaCodeStyle.suggestUniqueVariableName(thisVarName, block.getFirstChild(), true); PsiExpression initializer = myFactory.createExpressionFromText("null", null); PsiDeclarationStatement declaration = myFactory.createVariableDeclarationStatement(thisVarName, thisType, initializer); - declaration = (PsiDeclarationStatement)block.addAfter(declaration, null); - thisVar = (PsiLocalVariable)declaration.getDeclaredElements()[0]; + declaration = (PsiDeclarationStatement) block.addAfter(declaration, null); + thisVar = (PsiLocalVariable) declaration.getDeclaredElements()[0]; } String lockName = null; @@ -859,9 +865,9 @@ else if (myMethod.isStatic() && containingClass != null) { if (lockName != null && syncNeeded(ref)) { PsiSynchronizedStatement synchronizedStatement = - (PsiSynchronizedStatement)myFactory.createStatementFromText("synchronized(" + lockName + "){}", block); - synchronizedStatement = (PsiSynchronizedStatement)CodeStyleManager.getInstance(myProject).reformat(synchronizedStatement); - synchronizedStatement = (PsiSynchronizedStatement)block.add(synchronizedStatement); + (PsiSynchronizedStatement) myFactory.createStatementFromText("synchronized(" + lockName + "){}", block); + synchronizedStatement = (PsiSynchronizedStatement) CodeStyleManager.getInstance(myProject).reformat(synchronizedStatement); + synchronizedStatement = (PsiSynchronizedStatement) block.add(synchronizedStatement); PsiCodeBlock synchronizedBody = synchronizedStatement.getBody(); for (PsiStatement originalStatement : originalStatements) { synchronizedBody.add(originalStatement); @@ -880,19 +886,19 @@ else if (myMethod.isStatic() && containingClass != null) { if (tailCallType == InlineUtil.TailCallType.Simple) { if (returnValue instanceof PsiExpression && returnStatement.getNextSibling() == myMethodCopy.getBody().getLastBodyElement()) { - PsiExpressionStatement exprStatement = (PsiExpressionStatement)myFactory.createStatementFromText("a;", null); + PsiExpressionStatement exprStatement = (PsiExpressionStatement) myFactory.createStatementFromText("a;", null); exprStatement.getExpression().replace(returnValue); returnStatement.getParent().addBefore(exprStatement, returnStatement); statement = myFactory.createStatementFromText("return;", null); } else { - statement = (PsiStatement)returnStatement.copy(); + statement = (PsiStatement) returnStatement.copy(); } } else { statement = myFactory.createStatementFromText(resultName + "=0;", null); - statement = (PsiStatement)myCodeStyleManager.reformat(statement); - PsiAssignmentExpression assignment = (PsiAssignmentExpression)((PsiExpressionStatement)statement).getExpression(); + statement = (PsiStatement) myCodeStyleManager.reformat(statement); + PsiAssignmentExpression assignment = (PsiAssignmentExpression) ((PsiExpressionStatement) statement).getExpression(); assignment.getRExpression().replace(returnValue); } returnStatement.replace(statement); @@ -932,7 +938,10 @@ private void solveVariableNameConflicts(PsiElement scope, PsiElement placeToInse } @RequiredWriteAction - private void addParamAndThisVarInitializers(BlockData blockData, PsiMethodCallExpression methodCall) throws IncorrectOperationException { + private void addParamAndThisVarInitializers( + BlockData blockData, + PsiMethodCallExpression methodCall + ) throws IncorrectOperationException { PsiExpression[] args = methodCall.getArgumentList().getExpressions(); if (blockData.paramVars.length > 0) { for (int i = 0; i < args.length; i++) { @@ -1048,7 +1057,7 @@ private void inlineParamOrThisVariable(PsiLocalVariable variable, boolean strict declareUsedLocalsFinal(initializer, strictlyFinal); } for (PsiReference ref : refs) { - PsiJavaCodeReferenceElement javaRef = (PsiJavaCodeReferenceElement)ref; + PsiJavaCodeReferenceElement javaRef = (PsiJavaCodeReferenceElement) ref; if (initializer instanceof PsiThisExpression thisExpr && thisExpr.getQualifier() == null) { PsiClass varThisClass = RefactoringChangeUtil.getThisClass(variable); if (RefactoringChangeUtil.getThisClass(javaRef) != varThisClass) { @@ -1065,9 +1074,9 @@ private void inlineParamOrThisVariable(PsiLocalVariable variable, boolean strict //Q: move the following code to some util? (addition to inline?) if (expr instanceof PsiThisExpression && expr.getParent() instanceof PsiReferenceExpression refExpr) { PsiElement refElement = refExpr.resolve(); - PsiExpression exprCopy = (PsiExpression)refExpr.copy(); + PsiExpression exprCopy = (PsiExpression) refExpr.copy(); refExpr = - (PsiReferenceExpression)refExpr.replace(myFactory.createExpressionFromText(refExpr.getReferenceName(), null)); + (PsiReferenceExpression) refExpr.replace(myFactory.createExpressionFromText(refExpr.getReferenceName(), null)); if (refElement != null) { PsiElement newRefElement = refExpr.resolve(); if (!refElement.equals(newRefElement)) { @@ -1098,7 +1107,7 @@ class CanAllLocalsBeDeclaredFinal extends JavaRecursiveElementWalkingVisitor { public void visitReferenceExpression(PsiReferenceExpression expression) { PsiElement psiElement = expression.resolve(); if (psiElement instanceof PsiLocalVariable || psiElement instanceof PsiParameter) { - if (!RefactoringUtil.canBeDeclaredFinal((PsiVariable)psiElement)) { + if (!RefactoringUtil.canBeDeclaredFinal((PsiVariable) psiElement)) { success = false; } } @@ -1122,7 +1131,7 @@ public void visitElement(PsiElement element) { return true; } if (initializer instanceof PsiReferenceExpression refExpr) { - PsiVariable refVar = (PsiVariable)refExpr.resolve(); + PsiVariable refVar = (PsiVariable) refExpr.resolve(); if (refVar == null) { return !isAccessedForWriting; } @@ -1172,7 +1181,7 @@ else if (initializer instanceof PsiCallExpression) { return true; } } - PsiExpressionList argumentList = ((PsiCallExpression)initializer).getArgumentList(); + PsiExpressionList argumentList = ((PsiCallExpression) initializer).getArgumentList(); if (argumentList == null) { return false; } @@ -1225,13 +1234,10 @@ else if (initializer instanceof PsiSuperExpression) { @RequiredWriteAction private static void declareUsedLocalsFinal(PsiElement expr, boolean strictlyFinal) throws IncorrectOperationException { - if (expr instanceof PsiReferenceExpression refExpr) { - PsiElement refElement = refExpr.resolve(); - if (refElement instanceof PsiLocalVariable || refElement instanceof PsiParameter) { - if (strictlyFinal || RefactoringUtil.canBeDeclaredFinal((PsiVariable)refElement)) { - PsiUtil.setModifierProperty(((PsiVariable)refElement), PsiModifier.FINAL, true); - } - } + if (expr instanceof PsiReferenceExpression refExpr && refExpr.resolve() instanceof PsiVariable variable + && (variable instanceof PsiLocalVariable || variable instanceof PsiParameter) + && (strictlyFinal || RefactoringUtil.canBeDeclaredFinal(variable))) { + PsiUtil.setModifierProperty(variable, PsiModifier.FINAL, true); } PsiElement[] children = expr.getChildren(); for (PsiElement child : children) { @@ -1271,7 +1277,7 @@ private void inlineResultVariable(PsiVariable resultVar) throws IncorrectOperati PsiAssignmentExpression assignment = null; PsiReferenceExpression resultUsage = null; for (PsiReference ref1 : ReferencesSearch.search(resultVar, GlobalSearchScope.projectScope(myProject), false)) { - PsiReferenceExpression ref = (PsiReferenceExpression)ref1; + PsiReferenceExpression ref = (PsiReferenceExpression) ref1; if (ref.getParent() instanceof PsiAssignmentExpression assignmentExpr && assignmentExpr.getLExpression().equals(ref)) { if (assignment != null) { @@ -1301,9 +1307,9 @@ private void inlineResultVariable(PsiVariable resultVar) throws IncorrectOperati String name = resultVar.getName(); PsiDeclarationStatement declaration = myFactory.createVariableDeclarationStatement(name, resultVar.getType(), assignment.getRExpression()); - declaration = (PsiDeclarationStatement)assignment.getParent().replace(declaration); + declaration = (PsiDeclarationStatement) assignment.getParent().replace(declaration); resultVar.getParent().delete(); - resultVar = (PsiVariable)declaration.getDeclaredElements()[0]; + resultVar = (PsiVariable) declaration.getDeclaredElements()[0]; PsiElement parentStatement = RefactoringUtil.getParentStatement(resultUsage, true); PsiElement next = declaration.getNextSibling(); @@ -1366,10 +1372,10 @@ private PsiReferenceExpression[] addBracesWhenNeeded(PsiReferenceExpression[] re while (!parent.equals(parentStatement)) { if (parent instanceof PsiStatement && !(parent instanceof PsiDeclarationStatement)) { String text = "{\n}"; - PsiBlockStatement blockStatement = (PsiBlockStatement)myFactory.createStatementFromText(text, null); - blockStatement = (PsiBlockStatement)myCodeStyleManager.reformat(blockStatement); + PsiBlockStatement blockStatement = (PsiBlockStatement) myFactory.createStatementFromText(text, null); + blockStatement = (PsiBlockStatement) myCodeStyleManager.reformat(blockStatement); blockStatement.getCodeBlock().add(parent); - blockStatement = (PsiBlockStatement)parent.replace(blockStatement); + blockStatement = (PsiBlockStatement) parent.replace(blockStatement); PsiElement newStatement = blockStatement.getCodeBlock().getStatements()[0]; addMarkedElements(refsVector, newStatement); @@ -1379,28 +1385,27 @@ private PsiReferenceExpression[] addBracesWhenNeeded(PsiReferenceExpression[] re parent = parent.getParent(); } if (parentStatement.getParent() instanceof PsiLambdaExpression lambda) { - PsiLambdaExpression newLambdaExpr = (PsiLambdaExpression)myFactory.createExpressionFromText( + PsiLambdaExpression newLambdaExpr = (PsiLambdaExpression) myFactory.createExpressionFromText( lambda.getParameterList().getText() + " -> " + "{\n}", lambda ); PsiStatement statementFromText; if (PsiType.VOID.equals(LambdaUtil.getFunctionalInterfaceReturnType(lambda))) { statementFromText = myFactory.createStatementFromText("a;", lambda); - ((PsiExpressionStatement)statementFromText).getExpression().replace(parentStatement); + ((PsiExpressionStatement) statementFromText).getExpression().replace(parentStatement); } else { statementFromText = myFactory.createStatementFromText("return a;", lambda); - ((PsiReturnStatement)statementFromText).getReturnValue().replace(parentStatement); + ((PsiReturnStatement) statementFromText).getReturnValue().replace(parentStatement); } newLambdaExpr.getBody().add(statementFromText); - PsiCodeBlock body = (PsiCodeBlock)((PsiLambdaExpression)lambda.replace(newLambdaExpr)).getBody(); + PsiCodeBlock body = (PsiCodeBlock) ((PsiLambdaExpression) lambda.replace(newLambdaExpr)).getBody(); PsiElement newStatement = body.getStatements()[0]; addMarkedElements(refsVector, newStatement); addedBracesVector.add(body); continue; - } } else { @@ -1415,13 +1420,13 @@ private PsiReferenceExpression[] addBracesWhenNeeded(PsiReferenceExpression[] re LOG.assertTrue(initializer != null); PsiClassInitializer classInitializer = myFactory.createClassInitializer(); PsiClass containingClass = field.getContainingClass(); - classInitializer = (PsiClassInitializer)containingClass.addAfter(classInitializer, field); + classInitializer = (PsiClassInitializer) containingClass.addAfter(classInitializer, field); containingClass.addAfter(CodeEditUtil.createLineFeed(field.getManager()), field); PsiCodeBlock body = classInitializer.getBody(); PsiExpressionStatement statement = - (PsiExpressionStatement)myFactory.createStatementFromText(field.getName() + " = 0;", body); - statement = (PsiExpressionStatement)body.add(statement); - PsiAssignmentExpression assignment = (PsiAssignmentExpression)statement.getExpression(); + (PsiExpressionStatement) myFactory.createStatementFromText(field.getName() + " = 0;", body); + statement = (PsiExpressionStatement) body.add(statement); + PsiAssignmentExpression assignment = (PsiAssignmentExpression) statement.getExpression(); assignment.getLExpression().replace(RenameJavaVariableProcessor.createMemberReference(field, assignment)); assignment.getRExpression().replace(initializer); addMarkedElements(refsVector, statement); @@ -1493,7 +1498,7 @@ private static PsiExpression getSimpleReturnedExpression(PsiMethod method) { if (!(statement instanceof PsiReturnStatement)) { return null; } - return ((PsiReturnStatement)statement).getReturnValue(); + return ((PsiReturnStatement) statement).getReturnValue(); } private static void addMarkedElements(final List array, PsiElement scope) { @@ -1501,7 +1506,7 @@ private static void addMarkedElements(final List array, @Override public void visitElement(PsiElement element) { if (element.getCopyableUserData(MARK_KEY) != null) { - array.add((PsiReferenceExpression)element); + array.add((PsiReferenceExpression) element); element.putCopyableUserData(MARK_KEY, null); } super.visitElement(element); @@ -1565,17 +1570,18 @@ private PsiExpression getSimpleFieldInitializer(PsiField field, PsiClassInitiali && myManager.areElementsEquivalent(field, lExpression.resolve()) ? assignment.getRExpression() : null; } - public static String checkCalledInSuperOrThisExpr(PsiCodeBlock methodBody, PsiElement element) { + @Nonnull + public static LocalizeValue checkCalledInSuperOrThisExpr(PsiCodeBlock methodBody, PsiElement element) { if (methodBody.getStatements().length > 1) { PsiExpression expr = PsiTreeUtil.getParentOfType(element, PsiExpression.class); while (expr != null) { if (RefactoringChangeUtil.isSuperOrThisMethodCall(expr)) { - return "Inline cannot be applied to multiline method in constructor call"; + return JavaRefactoringLocalize.inlineMethodMultilineMethodInCtorCall(); } expr = PsiTreeUtil.getParentOfType(expr, PsiExpression.class, true); } } - return null; + return LocalizeValue.empty(); } public static boolean checkBadReturns(PsiMethod method) { diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineParameterDialog.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineParameterDialog.java index 078db86006..b1c14cfc2e 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineParameterDialog.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineParameterDialog.java @@ -20,6 +20,7 @@ import com.intellij.java.language.psi.PsiExpression; import com.intellij.java.language.psi.PsiMethod; import com.intellij.java.language.psi.PsiParameter; +import consulo.annotation.access.RequiredReadAction; import consulo.language.editor.refactoring.localize.RefactoringLocalize; import consulo.language.editor.refactoring.ui.RefactoringDialog; @@ -54,8 +55,9 @@ public InlineParameterDialog( } @Override + @RequiredReadAction protected JComponent createNorthPanel() { - final JPanel panel = new JPanel(new BorderLayout()); + JPanel panel = new JPanel(new BorderLayout()); panel.add( new JLabel( RefactoringLocalize.inlineParameterConfirmation(myParameter.getName(), myInitializer.getText()).get(), diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineParameterExpressionProcessor.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineParameterExpressionProcessor.java index 7cdd4db504..896b9a1ad0 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineParameterExpressionProcessor.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineParameterExpressionProcessor.java @@ -223,6 +223,7 @@ private static boolean isAccessedForWriting(PsiExpression expr) { } @Override + @RequiredWriteAction protected void performRefactoring(UsageInfo[] usages) { List thrownExceptions = ExceptionUtil.getThrownCheckedExceptions(myInitializer); Set varsUsedInInitializer = new HashSet<>(); @@ -319,11 +320,13 @@ public LocalReplacementUsageInfo(@Nonnull PsiReference element, @Nonnull PsiElem } @Nullable + @RequiredReadAction public PsiElement getReplacement() { return myReplacement.isValid() ? myReplacement : null; } @Nullable + @RequiredReadAction public PsiVariable getVariable() { return myVariable != null && myVariable.isValid() ? myVariable : null; } diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineParameterHandler.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineParameterHandler.java index de6b633829..0a9e1234ec 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineParameterHandler.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineParameterHandler.java @@ -24,9 +24,11 @@ import com.intellij.java.language.psi.*; import com.intellij.java.language.psi.util.PsiUtil; import consulo.annotation.access.RequiredReadAction; +import consulo.annotation.access.RequiredWriteAction; import consulo.annotation.component.ExtensionImpl; import consulo.application.Result; import consulo.codeEditor.Editor; +import consulo.java.localize.JavaRefactoringLocalize; import consulo.language.editor.PsiEquivalenceUtil; import consulo.language.editor.WriteCommandAction; import consulo.language.editor.refactoring.localize.RefactoringLocalize; @@ -38,10 +40,11 @@ import consulo.language.psi.search.ReferencesSearch; import consulo.language.psi.util.PsiTreeUtil; import consulo.localize.LocalizeValue; -import consulo.logging.Logger; import consulo.project.Project; import consulo.ui.annotation.RequiredUIAccess; +import consulo.ui.ex.awt.UIUtil; import consulo.util.lang.ref.SimpleReference; +import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; import java.util.*; @@ -51,7 +54,6 @@ */ @ExtensionImpl public class InlineParameterHandler extends JavaInlineActionHandler { - private static final Logger LOG = Logger.getInstance(InlineParameterHandler.class); public static final LocalizeValue REFACTORING_NAME = RefactoringLocalize.inlineParameterRefactoring(); @Override @@ -68,19 +70,18 @@ public boolean canInlineElement(PsiElement element) { public void inlineElement(final Project project, Editor editor, PsiElement psiElement) { final PsiParameter psiParameter = (PsiParameter) psiElement; PsiParameterList parameterList = (PsiParameterList) psiParameter.getParent(); - if (!(parameterList.getParent() instanceof PsiMethod)) { + if (!(parameterList.getParent() instanceof PsiMethod method)) { return; } int index = parameterList.getParameterIndex(psiParameter); - final PsiMethod method = (PsiMethod) parameterList.getParent(); - String errorMessage = getCannotInlineMessage(psiParameter, method); - if (errorMessage != null) { + LocalizeValue errorMessage = getCannotInlineMessage(psiParameter, method); + if (errorMessage != LocalizeValue.empty()) { CommonRefactoringUtil.showErrorHint( project, editor, errorMessage, - RefactoringLocalize.inlineParameterRefactoring().get(), + RefactoringLocalize.inlineParameterRefactoring(), null ); return; @@ -131,40 +132,43 @@ else if (!isRecursiveReferencedParameter(argument, psiParameter)) { PsiCodeBlock codeBlock = PsiTreeUtil.getParentOfType(refExpr, PsiCodeBlock.class); if (codeBlock != null) { PsiElement[] defs = DefUseUtil.getDefs(codeBlock, psiParameter, refExpr); - if (defs.length == 1) { - final PsiElement def = defs[0]; - if (def instanceof PsiReferenceExpression referenceExpression && PsiUtil.isOnAssignmentLeftHand(referenceExpression)) { - final PsiExpression rExpr = ((PsiAssignmentExpression) def.getParent()).getRExpression(); - if (rExpr != null) { - final PsiElement[] refs = DefUseUtil.getRefs(codeBlock, psiParameter, refExpr); + if (defs.length == 1 && defs[0] instanceof PsiReferenceExpression defRefExpr && PsiUtil.isOnAssignmentLeftHand(defRefExpr)) { + final PsiExpression rExpr = ((PsiAssignmentExpression) defRefExpr.getParent()).getRExpression(); + if (rExpr != null) { + final PsiElement[] refs = DefUseUtil.getRefs(codeBlock, psiParameter, refExpr); - if (InlineLocalHandler.checkRefsInAugmentedAssignmentOrUnaryModified(refs) == null) { - new WriteCommandAction(project) { - @Override - protected void run(Result result) throws Throwable { - for (final PsiElement ref : refs) { - InlineUtil.inlineVariable(psiParameter, rExpr, (PsiJavaCodeReferenceElement) ref); - } - def.getParent().delete(); + if (InlineLocalHandler.checkRefsInAugmentedAssignmentOrUnaryModified(refs) == null) { + new WriteCommandAction(project) { + @Override + @RequiredWriteAction + protected void run(Result result) throws Throwable { + for (PsiElement ref : refs) { + InlineUtil.inlineVariable(psiParameter, rExpr, (PsiJavaCodeReferenceElement) ref); } - }.execute(); - return; - } + defRefExpr.getParent().delete(); + } + }.execute(); + return; } } } } if (occurrences.isEmpty()) { - CommonRefactoringUtil - .showErrorHint(project, editor, "Method has no usages", RefactoringLocalize.inlineParameterRefactoring().get(), null); + CommonRefactoringUtil.showErrorHint( + project, + editor, + JavaRefactoringLocalize.inlineParameterNoUsagesWarningMessage(), + RefactoringLocalize.inlineParameterRefactoring(), + null + ); return; } if (!result) { CommonRefactoringUtil.showErrorHint( project, editor, - "Cannot find constant initializer for parameter", - RefactoringLocalize.inlineParameterRefactoring().get(), + JavaRefactoringLocalize.inlineParameterCannotFindInitializerWarningMessage(), + RefactoringLocalize.inlineParameterRefactoring(), null ); return; @@ -192,8 +196,8 @@ protected void run(Result result) throws Throwable { CommonRefactoringUtil.showErrorHint( project, editor, - "Cannot find constant initializer for parameter", - RefactoringLocalize.inlineParameterRefactoring().get(), + JavaRefactoringLocalize.inlineParameterCannotFindInitializerWarningMessage(), + RefactoringLocalize.inlineParameterRefactoring(), null ); return; @@ -216,8 +220,8 @@ public void visitReferenceExpression(PsiReferenceExpression expression) { CommonRefactoringUtil.showErrorHint( project, editor, - "Constant initializer is not accessible in method body", - RefactoringLocalize.inlineParameterRefactoring().get(), + JavaRefactoringLocalize.inlineParameterNotAccessibleWarningMessage(), + RefactoringLocalize.inlineParameterRefactoring(), null ); return; @@ -229,8 +233,8 @@ public void visitReferenceExpression(PsiReferenceExpression expression) { CommonRefactoringUtil.showErrorHint( project, editor, - "Inline parameter which has write usages is not supported", - RefactoringLocalize.inlineParameterRefactoring().get(), + LocalizeValue.localizeTODO("Inline parameter which has write usages is not supported"), + RefactoringLocalize.inlineParameterRefactoring(), null ); return; @@ -239,13 +243,16 @@ public void visitReferenceExpression(PsiReferenceExpression expression) { if (!project.getApplication().isUnitTestMode()) { LocalizeValue occurrencesString = RefactoringLocalize.occurencesString(occurrences.size()); - String question = RefactoringLocalize.inlineParameterConfirmation(psiParameter.getName(), constantExpression.getText()).get() - + " " + occurrencesString; + LocalizeValue question = LocalizeValue.join( + RefactoringLocalize.inlineParameterConfirmation(psiParameter.getName(), constantExpression.getText()), + LocalizeValue.space(), + occurrencesString + ); RefactoringMessageDialog dialog = new RefactoringMessageDialog( - REFACTORING_NAME.get(), + REFACTORING_NAME, question, HelpID.INLINE_VARIABLE, - "OptionPane.questionIcon", + UIUtil.getQuestionIcon(), true, project ); @@ -294,15 +301,15 @@ private static boolean isSameConstant(PsiExpression expr1, PsiExpression expr2) return value1 != null && value2 != null && value1.equals(value2); } - @Nullable - private static String getCannotInlineMessage(PsiParameter psiParameter, PsiMethod method) { + @Nonnull + private static LocalizeValue getCannotInlineMessage(PsiParameter psiParameter, PsiMethod method) { if (psiParameter.isVarArgs()) { - return RefactoringLocalize.inlineParameterErrorVarargs().get(); + return RefactoringLocalize.inlineParameterErrorVarargs(); } if (method.findSuperMethods().length > 0 || OverridingMethodsSearch.search(method, true).toArray(PsiMethod.EMPTY_ARRAY).length > 0) { - return RefactoringLocalize.inlineParameterErrorHierarchy().get(); + return RefactoringLocalize.inlineParameterErrorHierarchy(); } - return null; + return LocalizeValue.empty(); } } diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineToAnonymousClassHandler.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineToAnonymousClassHandler.java index e76e0da1dc..61b589b8a8 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineToAnonymousClassHandler.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/inline/InlineToAnonymousClassHandler.java @@ -25,8 +25,9 @@ import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; import consulo.application.progress.ProgressManager; -import consulo.application.util.function.Processor; import consulo.codeEditor.Editor; +import consulo.java.localize.JavaLocalize; +import consulo.java.localize.JavaRefactoringLocalize; import consulo.language.editor.TargetElementUtil; import consulo.language.editor.refactoring.localize.RefactoringLocalize; import consulo.language.editor.refactoring.util.CommonRefactoringUtil; @@ -38,454 +39,367 @@ import consulo.language.psi.util.PsiTreeUtil; import consulo.localize.LocalizeValue; import consulo.project.Project; +import consulo.ui.annotation.RequiredUIAccess; import consulo.util.collection.ArrayUtil; -import consulo.util.lang.ref.Ref; +import consulo.util.lang.ref.SimpleReference; +import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; import java.util.ArrayList; import java.util.Collection; +import java.util.function.Predicate; /** * @author yole */ @ExtensionImpl -public class InlineToAnonymousClassHandler extends JavaInlineActionHandler -{ - static final ElementPattern ourCatchClausePattern = PlatformPatterns.psiElement(PsiTypeElement.class).withParent(PlatformPatterns.psiElement(PsiParameter.class).withParent(PlatformPatterns - .psiElement(PsiCatchSection.class))); - static final ElementPattern ourThrowsClausePattern = PlatformPatterns.psiElement().withParent(PlatformPatterns.psiElement(PsiReferenceList.class).withFirstChild(PlatformPatterns.psiElement() - .withText(PsiKeyword.THROWS))); +public class InlineToAnonymousClassHandler extends JavaInlineActionHandler { + static final ElementPattern OUR_CATCH_CLAUSE_PATTERN = PlatformPatterns.psiElement(PsiTypeElement.class).withParent( + PlatformPatterns.psiElement(PsiParameter.class).withParent(PlatformPatterns.psiElement(PsiCatchSection.class)) + ); + static final ElementPattern OUR_THROWS_CLAUSE_PATTERN = PlatformPatterns.psiElement().withParent( + PlatformPatterns.psiElement(PsiReferenceList.class).withFirstChild(PlatformPatterns.psiElement().withText(PsiKeyword.THROWS)) + ); - @Override - public boolean isEnabledOnElement(PsiElement element) - { - return element instanceof PsiMethod || element instanceof PsiClass; - } + @Override + public boolean isEnabledOnElement(PsiElement element) { + return element instanceof PsiMethod || element instanceof PsiClass; + } - @Override - @RequiredReadAction - public boolean canInlineElement(final PsiElement element) - { - if (element.getLanguage() != JavaLanguage.INSTANCE) - { - return false; - } - if (element instanceof PsiMethod method && method.isConstructor() && !InlineMethodHandler.isChainingConstructor(method)) { - final PsiClass containingClass = method.getContainingClass(); - return containingClass != null && findClassInheritors(containingClass); - } - return element instanceof PsiClass psiClass && !(element instanceof PsiAnonymousClass) && findClassInheritors(psiClass); - } + @Override + @RequiredReadAction + public boolean canInlineElement(PsiElement element) { + if (element.getLanguage() != JavaLanguage.INSTANCE) { + return false; + } + if (element instanceof PsiMethod method && method.isConstructor() && !InlineMethodHandler.isChainingConstructor(method)) { + PsiClass containingClass = method.getContainingClass(); + return containingClass != null && findClassInheritors(containingClass); + } + return element instanceof PsiClass psiClass && !(element instanceof PsiAnonymousClass) && findClassInheritors(psiClass); + } - private static boolean findClassInheritors(final PsiClass element) - { - final Collection inheritors = new ArrayList<>(); - if (!ProgressManager.getInstance().runProcessWithProgressSynchronously( - () -> element.getApplication().runReadAction(() -> { - final PsiClass inheritor = ClassInheritorsSearch.search(element).findFirst(); - if (inheritor != null) - { - inheritors.add(inheritor); - } - else - { - final PsiFunctionalExpression functionalExpression = FunctionalExpressionSearch.search(element).findFirst(); - if (functionalExpression != null) - { - inheritors.add(functionalExpression); - } - } - }), - "Searching for class \"" + element.getQualifiedName() + "\" inheritors ...", - true, - element.getProject() - )) - { - return false; - } - return inheritors.isEmpty(); - } + private static boolean findClassInheritors(PsiClass element) { + Collection inheritors = new ArrayList<>(); + if (!ProgressManager.getInstance().runProcessWithProgressSynchronously( + () -> element.getApplication().runReadAction(() -> { + PsiClass inheritor = ClassInheritorsSearch.search(element).findFirst(); + if (inheritor != null) { + inheritors.add(inheritor); + } + else { + PsiFunctionalExpression functionalExpression = FunctionalExpressionSearch.search(element).findFirst(); + if (functionalExpression != null) { + inheritors.add(functionalExpression); + } + } + }), + JavaRefactoringLocalize.inlineAnonymousConflictProgress(element.getQualifiedName()), + true, + element.getProject() + )) { + return false; + } + return inheritors.isEmpty(); + } - @Override - @RequiredReadAction - public boolean canInlineElementInEditor(PsiElement element, Editor editor) - { - if (canInlineElement(element)) - { - PsiReference reference = editor != null ? TargetElementUtil.findReference(editor, editor.getCaretModel().getOffset()) : null; - if (!InlineMethodHandler.isThisReference(reference)) - { - if (element instanceof PsiMethod && reference != null) - { - final PsiElement referenceElement = reference.getElement(); - return referenceElement != null && !PsiTreeUtil.isAncestor(((PsiMethod) element).getContainingClass(), referenceElement, false); - } - return true; - } - } - return false; - } + @Override + @RequiredReadAction + public boolean canInlineElementInEditor(PsiElement element, Editor editor) { + if (canInlineElement(element)) { + PsiReference reference = editor != null ? TargetElementUtil.findReference(editor, editor.getCaretModel().getOffset()) : null; + if (!InlineMethodHandler.isThisReference(reference)) { + if (element instanceof PsiMethod method && reference != null) { + PsiElement referenceElement = reference.getElement(); + return referenceElement != null && !PsiTreeUtil.isAncestor(method.getContainingClass(), referenceElement, false); + } + return true; + } + } + return false; + } - @Override - public void inlineElement(final Project project, final Editor editor, final PsiElement psiElement) - { - final PsiClass psiClass = psiElement instanceof PsiMethod method ? method.getContainingClass() : (PsiClass) psiElement; - PsiCall callToInline = findCallToInline(editor); + @Override + @RequiredUIAccess + public void inlineElement(Project project, Editor editor, PsiElement psiElement) { + PsiClass psiClass = psiElement instanceof PsiMethod method ? method.getContainingClass() : (PsiClass) psiElement; + PsiCall callToInline = findCallToInline(editor); - final PsiClassType superType = InlineToAnonymousClassProcessor.getSuperType(psiClass); - LocalizeValue title = RefactoringLocalize.inlineToAnonymousRefactoring(); - if (superType == null) - { - CommonRefactoringUtil.showErrorHint(project, editor, "java.lang.Object is not found", title.get(), null); - return; - } + PsiClassType superType = InlineToAnonymousClassProcessor.getSuperType(psiClass); + LocalizeValue title = RefactoringLocalize.inlineToAnonymousRefactoring(); + if (superType == null) { + CommonRefactoringUtil.showErrorHint( + project, + editor, + JavaLocalize.classNotFoundErrorMessage(CommonClassNames.JAVA_LANG_OBJECT), + title, + null + ); + return; + } - final Ref errorMessage = new Ref<>(); - if (!ProgressManager.getInstance().runProcessWithProgressSynchronously( - () -> project.getApplication().runReadAction(() -> errorMessage.set(getCannotInlineMessage(psiClass))), - "Check if inline is possible...", - true, - project - )) - { - return; - } - if (errorMessage.get() != null) - { - CommonRefactoringUtil.showErrorHint(project, editor, errorMessage.get(), title.get(), null); - return; - } + SimpleReference errorMessage = new SimpleReference<>(); + if (!ProgressManager.getInstance().runProcessWithProgressSynchronously( + () -> project.getApplication().runReadAction(() -> errorMessage.set(getCannotInlineMessage(psiClass))), + JavaRefactoringLocalize.inlineConflictsProgress(), + true, + project + )) { + return; + } + if (errorMessage.get() != LocalizeValue.empty()) { + CommonRefactoringUtil.showErrorHint(project, editor, errorMessage.get(), title, null); + return; + } - new InlineToAnonymousClassDialog(project, psiClass, callToInline, canBeInvokedOnReference(callToInline, superType)).show(); - } + new InlineToAnonymousClassDialog(project, psiClass, callToInline, canBeInvokedOnReference(callToInline, superType)).show(); + } - public static boolean canBeInvokedOnReference(PsiCall callToInline, PsiType superType) - { - if (callToInline == null) - { - return false; - } - final PsiElement parent = callToInline.getParent(); - if (parent instanceof PsiExpressionStatement || parent instanceof PsiSynchronizedStatement || parent instanceof PsiReferenceExpression) - { - return true; - } - else if (parent instanceof PsiExpressionList) - { - final PsiMethodCallExpression methodCallExpression = PsiTreeUtil.getParentOfType(parent, PsiMethodCallExpression.class); - if (methodCallExpression != null) - { - int paramIdx = ArrayUtil.find(methodCallExpression.getArgumentList().getExpressions(), callToInline); - if (paramIdx != -1) - { - final JavaResolveResult resolveResult = methodCallExpression.resolveMethodGenerics(); - final PsiElement resolvedMethod = resolveResult.getElement(); - if (resolvedMethod instanceof PsiMethod method) - { - PsiType paramType; - final PsiParameter[] parameters = method.getParameterList().getParameters(); - if (paramIdx >= parameters.length) - { - final PsiParameter varargParameter = parameters[parameters.length - 1]; - paramType = varargParameter.getType(); - } - else - { - paramType = parameters[paramIdx].getType(); - } - if (paramType instanceof PsiEllipsisType ellipsisType) - { - paramType = ellipsisType.getComponentType(); - } - paramType = resolveResult.getSubstitutor().substitute(paramType); + public static boolean canBeInvokedOnReference(PsiCall callToInline, PsiType superType) { + if (callToInline == null) { + return false; + } + PsiElement parent = callToInline.getParent(); + if (parent instanceof PsiExpressionStatement || parent instanceof PsiSynchronizedStatement || parent instanceof PsiReferenceExpression) { + return true; + } + else if (parent instanceof PsiExpressionList) { + PsiMethodCallExpression methodCallExpression = PsiTreeUtil.getParentOfType(parent, PsiMethodCallExpression.class); + if (methodCallExpression != null) { + int paramIdx = ArrayUtil.find(methodCallExpression.getArgumentList().getExpressions(), callToInline); + if (paramIdx != -1) { + JavaResolveResult resolveResult = methodCallExpression.resolveMethodGenerics(); + PsiElement resolvedMethod = resolveResult.getElement(); + if (resolvedMethod instanceof PsiMethod method) { + PsiType paramType; + PsiParameter[] parameters = method.getParameterList().getParameters(); + if (paramIdx >= parameters.length) { + PsiParameter varargParameter = parameters[parameters.length - 1]; + paramType = varargParameter.getType(); + } + else { + paramType = parameters[paramIdx].getType(); + } + if (paramType instanceof PsiEllipsisType ellipsisType) { + paramType = ellipsisType.getComponentType(); + } + paramType = resolveResult.getSubstitutor().substitute(paramType); - final PsiJavaCodeReferenceElement classReference = ((PsiNewExpression) callToInline).getClassOrAnonymousClassReference(); - if (classReference != null) - { - superType = classReference.advancedResolve(false).getSubstitutor().substitute(superType); - if (TypeConversionUtil.isAssignable(paramType, superType)) - { - return true; - } - } - } - } - } - } - return false; - } + PsiJavaCodeReferenceElement classReference = ((PsiNewExpression) callToInline).getClassOrAnonymousClassReference(); + if (classReference != null) { + superType = classReference.advancedResolve(false).getSubstitutor().substitute(superType); + if (TypeConversionUtil.isAssignable(paramType, superType)) { + return true; + } + } + } + } + } + } + return false; + } + @Nullable + @RequiredReadAction + public static PsiCall findCallToInline(Editor editor) { + PsiCall callToInline = null; + PsiReference reference = editor != null ? TargetElementUtil.findReference(editor) : null; + if (reference != null && reference.getElement() instanceof PsiJavaCodeReferenceElement javaCodeRef) { + callToInline = RefactoringUtil.getEnclosingConstructorCall(javaCodeRef); + } + return callToInline; + } - @Nullable - @RequiredReadAction - public static PsiCall findCallToInline(final Editor editor) - { - PsiCall callToInline = null; - PsiReference reference = editor != null ? TargetElementUtil.findReference(editor) : null; - if (reference != null) - { - final PsiElement element = reference.getElement(); - if (element instanceof PsiJavaCodeReferenceElement javaCodeReferenceElement) - { - callToInline = RefactoringUtil.getEnclosingConstructorCall(javaCodeReferenceElement); - } - } - return callToInline; - } + @Nonnull + @RequiredReadAction + public static LocalizeValue getCannotInlineMessage(PsiClass psiClass) { + if (psiClass instanceof PsiTypeParameter) { + return JavaRefactoringLocalize.typeParametersCannotBeInlined(); + } + if (psiClass.isAnnotationType()) { + return JavaRefactoringLocalize.annotationTypesCannotBeInlined(); + } + if (psiClass.isInterface()) { + return JavaRefactoringLocalize.interfacesCannotBeInlined(); + } + if (psiClass.isEnum()) { + return JavaRefactoringLocalize.enumsCannotBeInlined(); + } + if (psiClass.isAbstract()) { + return RefactoringLocalize.inlineToAnonymousNoAbstract(); + } + if (!psiClass.getManager().isInProject(psiClass)) { + return JavaRefactoringLocalize.libraryClassesCannotBeInlined(); + } - @Nullable - @RequiredReadAction - public static String getCannotInlineMessage(final PsiClass psiClass) - { - if (psiClass instanceof PsiTypeParameter) - { - return "Type parameters cannot be inlined"; - } - if (psiClass.isAnnotationType()) - { - return "Annotation types cannot be inlined"; - } - if (psiClass.isInterface()) - { - return "Interfaces cannot be inlined"; - } - if (psiClass.isEnum()) - { - return "Enums cannot be inlined"; - } - if (psiClass.hasModifierProperty(PsiModifier.ABSTRACT)) - { - return RefactoringLocalize.inlineToAnonymousNoAbstract().get(); - } - if (!psiClass.getManager().isInProject(psiClass)) - { - return "Library classes cannot be inlined"; - } + PsiClassType[] classTypes = psiClass.getExtendsListTypes(); + for (PsiClassType classType : classTypes) { + PsiClass superClass = classType.resolve(); + if (superClass == null) { + return JavaRefactoringLocalize.classCannotBeInlinedBecauseItsSuperclassCannotBeResolved(); + } + } - PsiClassType[] classTypes = psiClass.getExtendsListTypes(); - for (PsiClassType classType : classTypes) - { - PsiClass superClass = classType.resolve(); - if (superClass == null) - { - return "Class cannot be inlined because its superclass cannot be resolved"; - } - } + PsiClassType[] interfaces = psiClass.getImplementsListTypes(); + if (interfaces.length > 1) { + return RefactoringLocalize.inlineToAnonymousNoMultipleInterfaces(); + } + if (interfaces.length == 1) { + if (interfaces[0].resolve() == null) { + return JavaRefactoringLocalize.classCannotBeInlinedBecauseAnInterfaceImplementedByItCannotBeResolved(); + } + PsiClass superClass = psiClass.getSuperClass(); + if (superClass != null && !CommonClassNames.JAVA_LANG_OBJECT.equals(superClass.getQualifiedName())) { + PsiClassType interfaceType = interfaces[0]; + if (!isRedundantImplements(superClass, interfaceType)) { + return RefactoringLocalize.inlineToAnonymousNoSuperclassAndInterface(); + } + } + } - final PsiClassType[] interfaces = psiClass.getImplementsListTypes(); - if (interfaces.length > 1) - { - return RefactoringLocalize.inlineToAnonymousNoMultipleInterfaces().get(); - } - if (interfaces.length == 1) - { - if (interfaces[0].resolve() == null) - { - return "Class cannot be inlined because an interface implemented by it cannot be resolved"; - } - final PsiClass superClass = psiClass.getSuperClass(); - if (superClass != null && !CommonClassNames.JAVA_LANG_OBJECT.equals(superClass.getQualifiedName())) - { - PsiClassType interfaceType = interfaces[0]; - if (!isRedundantImplements(superClass, interfaceType)) - { - return RefactoringLocalize.inlineToAnonymousNoSuperclassAndInterface().get(); - } - } - } + PsiMethod[] methods = psiClass.getMethods(); + for (PsiMethod method : methods) { + if (method.isConstructor()) { + if (PsiUtil.findReturnStatements(method).length > 0) { + return JavaRefactoringLocalize.classCannotBeInlinedBecauseItsConstructorContainsReturnStatements(); + } + } + else if (method.findSuperMethods().length == 0) { + if (!ReferencesSearch.search(method).forEach(new AllowedUsagesProcessor(psiClass))) { + return JavaRefactoringLocalize.classCannotBeInlinedBecauseThereAreUsagesOfItsMethodsNotInheritedFromItsSuperclassOrInterface(); + } + } + if (method.isStatic()) { + return JavaRefactoringLocalize.classCannotBeInlinedBecauseItHasStaticMethods(); + } + } - final PsiMethod[] methods = psiClass.getMethods(); - for (PsiMethod method : methods) - { - if (method.isConstructor()) - { - if (PsiUtil.findReturnStatements(method).length > 0) - { - return "Class cannot be inlined because its constructor contains 'return' statements"; - } - } - else if (method.findSuperMethods().length == 0) - { - if (!ReferencesSearch.search(method).forEach(new AllowedUsagesProcessor(psiClass))) - { - return "Class cannot be inlined because it has usages of methods not inherited from its superclass or interface"; - } - } - if (method.hasModifierProperty(PsiModifier.STATIC)) - { - return "Class cannot be inlined because it has static methods"; - } - } + PsiClass[] innerClasses = psiClass.getInnerClasses(); + for (PsiClass innerClass : innerClasses) { + if (innerClass.isStatic()) { + return JavaRefactoringLocalize.classCannotBeInlinedBecauseItHasStaticInnerClasses(); + } + if (!ReferencesSearch.search(innerClass).forEach(new AllowedUsagesProcessor(psiClass))) { + return JavaRefactoringLocalize.classCannotBeInlinedBecauseItHasUsagesOfItsInnerClasses(); + } + } - final PsiClass[] innerClasses = psiClass.getInnerClasses(); - for (PsiClass innerClass : innerClasses) - { - PsiModifierList classModifiers = innerClass.getModifierList(); - if (classModifiers.hasModifierProperty(PsiModifier.STATIC)) - { - return "Class cannot be inlined because it has static inner classes"; - } - if (!ReferencesSearch.search(innerClass).forEach(new AllowedUsagesProcessor(psiClass))) - { - return "Class cannot be inlined because it has usages of its inner classes"; - } - } + for (PsiField field : psiClass.getFields()) { + if (field.isStatic()) { + if (!field.isFinal()) { + return JavaRefactoringLocalize.classCannotBeInlinedBecauseItHasStaticNonFinalFields(); + } + Object initValue = null; + PsiExpression initializer = field.getInitializer(); + if (initializer != null) { + initValue = JavaPsiFacade.getInstance(psiClass.getProject()) + .getConstantEvaluationHelper() + .computeConstantExpression(initializer); + } + if (initValue == null) { + return JavaRefactoringLocalize.classCannotBeInlinedBecauseItHasStaticFieldsWithNonConstantInitializers(); + } + } + if (!ReferencesSearch.search(field).forEach(new AllowedUsagesProcessor(psiClass))) { + return JavaRefactoringLocalize.classCannotBeInlinedBecauseItHasUsagesOfFieldsNotInheritedFromItsSuperclass(); + } + } - final PsiField[] fields = psiClass.getFields(); - for (PsiField field : fields) - { - final PsiModifierList fieldModifiers = field.getModifierList(); - if (fieldModifiers != null && fieldModifiers.hasModifierProperty(PsiModifier.STATIC)) - { - if (!fieldModifiers.hasModifierProperty(PsiModifier.FINAL)) - { - return "Class cannot be inlined because it has static non-final fields"; - } - Object initValue = null; - final PsiExpression initializer = field.getInitializer(); - if (initializer != null) - { - initValue = JavaPsiFacade.getInstance(psiClass.getProject()).getConstantEvaluationHelper().computeConstantExpression(initializer); - } - if (initValue == null) - { - return "Class cannot be inlined because it has static fields with non-constant initializers"; - } - } - if (!ReferencesSearch.search(field).forEach(new AllowedUsagesProcessor(psiClass))) - { - return "Class cannot be inlined because it has usages of fields not inherited from its superclass"; - } - } + PsiClassInitializer[] initializers = psiClass.getInitializers(); + for (PsiClassInitializer initializer : initializers) { + if (initializer.isStatic()) { + return JavaRefactoringLocalize.classCannotBeInlinedBecauseItHasStaticInitializers(); + } + } - final PsiClassInitializer[] initializers = psiClass.getInitializers(); - for (PsiClassInitializer initializer : initializers) - { - final PsiModifierList modifiers = initializer.getModifierList(); - if (modifiers != null && modifiers.hasModifierProperty(PsiModifier.STATIC)) - { - return "Class cannot be inlined because it has static initializers"; - } - } + return getCannotInlineDueToUsagesMessage(psiClass); + } - return getCannotInlineDueToUsagesMessage(psiClass); - } + static boolean isRedundantImplements(PsiClass superClass, PsiClassType interfaceType) { + boolean redundantImplements = false; + PsiClassType[] superClassInterfaces = superClass.getImplementsListTypes(); + for (PsiClassType superClassInterface : superClassInterfaces) { + if (superClassInterface.equals(interfaceType)) { + redundantImplements = true; + break; + } + } + return redundantImplements; + } - static boolean isRedundantImplements(final PsiClass superClass, final PsiClassType interfaceType) - { - boolean redundantImplements = false; - PsiClassType[] superClassInterfaces = superClass.getImplementsListTypes(); - for (PsiClassType superClassInterface : superClassInterfaces) - { - if (superClassInterface.equals(interfaceType)) - { - redundantImplements = true; - break; - } - } - return redundantImplements; - } + @Nonnull + @RequiredReadAction + private static LocalizeValue getCannotInlineDueToUsagesMessage(PsiClass aClass) { + boolean hasUsages = false; + for (PsiReference reference : ReferencesSearch.search(aClass)) { + PsiElement element = reference.getElement(); + if (element == null) { + continue; + } + if (!PsiTreeUtil.isAncestor(aClass, element, false)) { + hasUsages = true; + } + PsiElement parentElement = element.getParent(); + if (parentElement != null) { + if (parentElement.getParent() instanceof PsiClassObjectAccessExpression) { + return JavaRefactoringLocalize.classCannotBeInlinedBecauseItHasUsagesOfItsClassLiteral(); + } + if (OUR_CATCH_CLAUSE_PATTERN.accepts(parentElement)) { + return JavaRefactoringLocalize.classCannotBeInlinedBecauseItIsUsedInACatchClause(); + } + } + if (OUR_THROWS_CLAUSE_PATTERN.accepts(element)) { + return JavaRefactoringLocalize.classCannotBeInlinedBecauseItIsUsedInAThrowsClause(); + } + if (parentElement instanceof PsiThisExpression) { + return JavaRefactoringLocalize.classCannotBeInlinedBecauseItIsUsedAsAThisQualifier(); + } + if (parentElement instanceof PsiNewExpression newExpression) { + PsiMethod[] constructors = aClass.getConstructors(); + if (constructors.length == 0) { + PsiExpressionList newArgumentList = newExpression.getArgumentList(); + if (newArgumentList != null && newArgumentList.getExpressions().length > 0) { + return JavaRefactoringLocalize.classCannotBeInlinedBecauseACallToItsConstructorIsUnresolved(); + } + } + else if (!newExpression.resolveMethodGenerics().isValidResult()) { + return JavaRefactoringLocalize.classCannotBeInlinedBecauseACallToItsConstructorIsUnresolved(); + } + } + } + if (!hasUsages) { + return RefactoringLocalize.classIsNeverUsed(); + } + return LocalizeValue.empty(); + } - @RequiredReadAction - @Nullable - private static String getCannotInlineDueToUsagesMessage(final PsiClass aClass) - { - boolean hasUsages = false; - for (PsiReference reference : ReferencesSearch.search(aClass)) - { - final PsiElement element = reference.getElement(); - if (element == null) - { - continue; - } - if (!PsiTreeUtil.isAncestor(aClass, element, false)) - { - hasUsages = true; - } - final PsiElement parentElement = element.getParent(); - if (parentElement != null) - { - final PsiElement grandPa = parentElement.getParent(); - if (grandPa instanceof PsiClassObjectAccessExpression) - { - return "Class cannot be inlined because it has usages of its class literal"; - } - if (ourCatchClausePattern.accepts(parentElement)) - { - return "Class cannot be inlined because it is used in a 'catch' clause"; - } - } - if (ourThrowsClausePattern.accepts(element)) - { - return "Class cannot be inlined because it is used in a 'throws' clause"; - } - if (parentElement instanceof PsiThisExpression) - { - return "Class cannot be inlined because it is used as a 'this' qualifier"; - } - if (parentElement instanceof PsiNewExpression newExpression) - { - final PsiMethod[] constructors = aClass.getConstructors(); - if (constructors.length == 0) - { - PsiExpressionList newArgumentList = newExpression.getArgumentList(); - if (newArgumentList != null && newArgumentList.getExpressions().length > 0) - { - return "Class cannot be inlined because a call to its constructor is unresolved"; - } - } - else - { - final JavaResolveResult resolveResult = newExpression.resolveMethodGenerics(); - if (!resolveResult.isValidResult()) - { - return "Class cannot be inlined because a call to its constructor is unresolved"; - } - } - } - } - if (!hasUsages) - { - return RefactoringLocalize.classIsNeverUsed().get(); - } - return null; - } + private static class AllowedUsagesProcessor implements Predicate { + private final PsiElement myPsiElement; - private static class AllowedUsagesProcessor implements Processor - { - private final PsiElement myPsiElement; + public AllowedUsagesProcessor(PsiElement psiElement) { + myPsiElement = psiElement; + } - public AllowedUsagesProcessor(final PsiElement psiElement) - { - myPsiElement = psiElement; - } - - @Override - @RequiredReadAction - public boolean process(final PsiReference psiReference) - { - if (PsiTreeUtil.isAncestor(myPsiElement, psiReference.getElement(), false)) - { - return true; - } - PsiElement element = psiReference.getElement(); - if (element instanceof PsiReferenceExpression referenceExpression) - { - PsiExpression qualifier = referenceExpression.getQualifierExpression(); - while (qualifier instanceof PsiParenthesizedExpression parenthesizedExpression) - { - qualifier = parenthesizedExpression.getExpression(); - } - if (qualifier instanceof PsiNewExpression newExpr) - { - PsiJavaCodeReferenceElement classRef = newExpr.getClassReference(); - if (classRef != null && myPsiElement.equals(classRef.resolve())) - { - return true; - } - } - } - return false; - } - } + @Override + @RequiredReadAction + public boolean test(PsiReference psiReference) { + if (PsiTreeUtil.isAncestor(myPsiElement, psiReference.getElement(), false)) { + return true; + } + PsiElement element = psiReference.getElement(); + if (element instanceof PsiReferenceExpression referenceExpression) { + PsiExpression qualifier = referenceExpression.getQualifierExpression(); + while (qualifier instanceof PsiParenthesizedExpression parenthesizedExpression) { + qualifier = parenthesizedExpression.getExpression(); + } + if (qualifier instanceof PsiNewExpression newExpr) { + PsiJavaCodeReferenceElement classRef = newExpr.getClassReference(); + if (classRef != null && myPsiElement.equals(classRef.resolve())) { + return true; + } + } + } + return false; + } + } } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/java/impl/refactoring/inlineSuperClass/InlineSuperClassRefactoringHandler.java b/plugin/src/main/java/com/intellij/java/impl/refactoring/inlineSuperClass/InlineSuperClassRefactoringHandler.java index 9d5758f29e..31f102c4ef 100644 --- a/plugin/src/main/java/com/intellij/java/impl/refactoring/inlineSuperClass/InlineSuperClassRefactoringHandler.java +++ b/plugin/src/main/java/com/intellij/java/impl/refactoring/inlineSuperClass/InlineSuperClassRefactoringHandler.java @@ -26,73 +26,96 @@ import com.intellij.java.language.psi.PsiAnonymousClass; import com.intellij.java.language.psi.PsiClass; import com.intellij.java.language.psi.PsiReferenceList; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ExtensionImpl; import consulo.codeEditor.Editor; +import consulo.java.localize.JavaRefactoringLocalize; import consulo.language.editor.TargetElementUtil; import consulo.language.editor.refactoring.util.CommonRefactoringUtil; import consulo.language.psi.PsiElement; import consulo.language.psi.PsiReference; import consulo.language.psi.util.PsiTreeUtil; +import consulo.localize.LocalizeValue; import consulo.project.Project; +import consulo.ui.annotation.RequiredUIAccess; import java.util.Collection; @ExtensionImpl public class InlineSuperClassRefactoringHandler extends JavaInlineActionHandler { - public static final String REFACTORING_NAME = "Inline Super Class"; + public static final LocalizeValue REFACTORING_NAME = JavaRefactoringLocalize.inlineSuperClass(); - @Override - public boolean isEnabledOnElement(PsiElement element) { - return element instanceof PsiClass; - } - - public boolean canInlineElement(PsiElement element) { - if (!(element instanceof PsiClass)) return false; - if (element.getLanguage() != JavaLanguage.INSTANCE) return false; - Collection inheritors = DirectClassInheritorsSearch.search((PsiClass)element).findAll(); - return inheritors.size() > 0; - } - - public void inlineElement(final Project project, final Editor editor, final PsiElement element) { - PsiClass superClass = (PsiClass)element; - Collection inheritors = DirectClassInheritorsSearch.search((PsiClass)element).findAll(); - if (!superClass.getManager().isInProject(superClass)) { - CommonRefactoringUtil.showErrorHint(project, editor, "Cannot inline non-project class", REFACTORING_NAME, null); - return; + @Override + public boolean isEnabledOnElement(PsiElement element) { + return element instanceof PsiClass; } - for (PsiClass inheritor : inheritors) { - if (PsiTreeUtil.isAncestor(superClass, inheritor, false)) { - CommonRefactoringUtil.showErrorHint(project, - editor, - "Cannot inline into the inner class. Move \'" + inheritor.getName() + "\' to upper level", - REFACTORING_NAME, - null); - return; - } - if (inheritor instanceof PsiAnonymousClass) { - CommonRefactoringUtil.showErrorHint(project, editor, "Cannot inline into anonymous class.", REFACTORING_NAME, null); - return; - } + @Override + @RequiredReadAction + public boolean canInlineElement(PsiElement element) { + if (!(element instanceof PsiClass)) { + return false; + } + if (element.getLanguage() != JavaLanguage.INSTANCE) { + return false; + } + Collection inheritors = DirectClassInheritorsSearch.search((PsiClass) element).findAll(); + return inheritors.size() > 0; } - PsiClass chosen = null; - PsiReference reference = editor != null ? TargetElementUtil.findReference(editor, editor.getCaretModel().getOffset()) : null; - if (reference != null) { - final PsiElement resolve = reference.resolve(); - if (resolve == superClass) { - final PsiElement referenceElement = reference.getElement(); - if (referenceElement != null) { - final PsiElement parent = referenceElement.getParent(); - if (parent instanceof PsiReferenceList) { - final PsiElement gParent = parent.getParent(); - if (gParent instanceof PsiClass && inheritors.contains(gParent)) { - chosen = (PsiClass)gParent; + @Override + @RequiredUIAccess + public void inlineElement(Project project, Editor editor, PsiElement element) { + PsiClass superClass = (PsiClass) element; + Collection inheritors = DirectClassInheritorsSearch.search((PsiClass) element).findAll(); + if (!superClass.getManager().isInProject(superClass)) { + CommonRefactoringUtil.showErrorHint( + project, + editor, + JavaRefactoringLocalize.inlineSuperNonProjectClassWarningMessage(), + REFACTORING_NAME, + null + ); + return; + } + + for (PsiClass inheritor : inheritors) { + if (PsiTreeUtil.isAncestor(superClass, inheritor, false)) { + CommonRefactoringUtil.showErrorHint( + project, + editor, + JavaRefactoringLocalize.inlineSuperNoInnerClass(inheritor.getName()), + REFACTORING_NAME, + null + ); + return; + } + if (inheritor instanceof PsiAnonymousClass) { + CommonRefactoringUtil.showErrorHint( + project, + editor, + JavaRefactoringLocalize.inlineSuperNoAnonymousClass(), + REFACTORING_NAME, + null + ); + return; + } + } + + PsiClass chosen = null; + PsiReference reference = editor != null ? TargetElementUtil.findReference(editor, editor.getCaretModel().getOffset()) : null; + if (reference != null) { + PsiElement resolve = reference.resolve(); + if (resolve == superClass) { + PsiElement referenceElement = reference.getElement(); + if (referenceElement != null + && referenceElement.getParent() instanceof PsiReferenceList refList + && refList.getParent() instanceof PsiClass psiClass + && inheritors.contains(psiClass)) { + chosen = psiClass; + } } - } } - } + new InlineSuperClassRefactoringDialog(project, superClass, chosen, inheritors.toArray(new PsiClass[inheritors.size()])).show(); } - new InlineSuperClassRefactoringDialog(project, superClass, chosen, inheritors.toArray(new PsiClass[inheritors.size()])).show(); - } } \ No newline at end of file diff --git a/plugin/src/main/resources/LOCALIZE-LIB/en_US/consulo.java.JavaLocalize.yaml b/plugin/src/main/resources/LOCALIZE-LIB/en_US/consulo.java.JavaLocalize.yaml index 79f3ea672e..1a6f93a5f4 100644 --- a/plugin/src/main/resources/LOCALIZE-LIB/en_US/consulo.java.JavaLocalize.yaml +++ b/plugin/src/main/resources/LOCALIZE-LIB/en_US/consulo.java.JavaLocalize.yaml @@ -164,6 +164,8 @@ class.file.decompiled.text: text: Decompiled .class file class.file.open.source.action: text: Open source file +class.not.found.error.message: + text: Class ''{0}'' not found dependencies.tree.node.default.package.abbreviation: text: error.package.already.contains.package.html: diff --git a/plugin/src/main/resources/LOCALIZE-LIB/en_US/consulo.java.JavaRefactoringLocalize.yaml b/plugin/src/main/resources/LOCALIZE-LIB/en_US/consulo.java.JavaRefactoringLocalize.yaml index 2576e4eaba..1bf9fd567a 100644 --- a/plugin/src/main/resources/LOCALIZE-LIB/en_US/consulo.java.JavaRefactoringLocalize.yaml +++ b/plugin/src/main/resources/LOCALIZE-LIB/en_US/consulo.java.JavaRefactoringLocalize.yaml @@ -26,6 +26,8 @@ add.property.to.constructors.checkbox: text: Add property to constructors annotation: text: Annotation +annotation.types.cannot.be.inlined: + text: Annotation types cannot be inlined can.not.find.any.available.overriding.methods.for.the.selected.method: text: Can not find any available overriding methods for the selected method can.not.find.any.available.subclasses.for.the.selected.class: @@ -45,6 +47,38 @@ choose.destination.class.label: text: Choose destination class choose.destination.package.label: text: Choose Destination Package +class.cannot.be.inlined.because.a.call.to.its.constructor.is.unresolved: + text: Class cannot be inlined because a call to its constructor is unresolved +class.cannot.be.inlined.because.an.interface.implemented.by.it.cannot.be.resolved: + text: Class cannot be inlined because an interface implemented by it cannot be resolved +class.cannot.be.inlined.because.it.has.static.fields.with.non.constant.initializers: + text: Class cannot be inlined because it has static fields with non-constant initializers +class.cannot.be.inlined.because.it.has.static.initializers: + text: Class cannot be inlined because it has static initializers +class.cannot.be.inlined.because.it.has.static.inner.classes: + text: Class cannot be inlined because it has static inner classes +class.cannot.be.inlined.because.it.has.static.methods: + text: Class cannot be inlined because it has static methods +class.cannot.be.inlined.because.it.has.static.non.final.fields: + text: Class cannot be inlined because it has static non-final fields +class.cannot.be.inlined.because.it.has.usages.of.fields.not.inherited.from.its.superclass: + text: Class cannot be inlined because it has usages of fields not inherited from its superclass +class.cannot.be.inlined.because.it.has.usages.of.its.class.literal: + text: Class cannot be inlined because it has usages of its class literal +class.cannot.be.inlined.because.it.has.usages.of.its.inner.classes: + text: Class cannot be inlined because it has usages of its inner classes +class.cannot.be.inlined.because.it.is.used.as.a.this.qualifier: + text: Class cannot be inlined because it is used as a 'this' qualifier +class.cannot.be.inlined.because.it.is.used.in.a.catch.clause: + text: Class cannot be inlined because it is used in a 'catch' clause +class.cannot.be.inlined.because.it.is.used.in.a.throws.clause: + text: Class cannot be inlined because it is used in a 'throws' clause +class.cannot.be.inlined.because.its.constructor.contains.return.statements: + text: Class cannot be inlined because its constructor contains 'return' statements +class.cannot.be.inlined.because.its.superclass.cannot.be.resolved: + text: Class cannot be inlined because its superclass cannot be resolved +class.cannot.be.inlined.because.there.are.usages.of.its.methods.not.inherited.from.its.superclass.or.interface: + text: Class cannot be inlined because there are usages of its methods not inherited from its superclass or interface class.found.column.header: text: Class found class.references.to.be.made.inner: @@ -100,6 +134,8 @@ do.you.wish.to.invert.all.uses.of.parameter: text: Do you wish to invert all uses of parameter {0}? do.you.wish.to.invert.all.uses.of.variable: text: Do you wish to invert all uses of variable {0}? +enums.cannot.be.inlined: + text: Enums cannot be inlined existing.wrapper.class.label: text: Use Existing Parameter Class exposed.delegation.command.name: @@ -148,6 +184,8 @@ global.library.source: text: 'Global Library: {0}' initialization.expression.checkbox: text: 'Initialization expression (optional):' +inline.anonymous.conflict.progress: + text: Searching for class "{0}" inheritors… inline.conflicts.progress: text: Check if inline is possible… inline.constant.field.not.supported.for.enum.constants: @@ -160,6 +198,30 @@ inline.local.unable.try.catch.warning.message: text: Unable to inline outside try/catch statement inline.local.variable.declared.outside.cannot.refactor.message: text: Variable is declared outside a code block +inline.method.multiline.method.in.ctor.call: + text: Inline cannot be applied to multiline method in constructor call +inline.method.used.in.javadoc: + text: Inlined method is used in javadoc +inline.parameter.cannot.find.initializer.warning.message: + text: Cannot find constant initializer for parameter +inline.parameter.no.usages.warning.message: + text: Method has no usages +inline.parameter.not.accessible.warning.message: + text: Constant initializer is not accessible in method body +inline.super.class: + text: Inline Super Class +inline.super.class.action.name: + text: Inline Super Class\u2026 +inline.super.class.label: + text: Class {0} +inline.super.no.anonymous.class: + text: Cannot inline into anonymous class. +inline.super.no.inner.class: + text: Cannot inline into the inner class. Move ''{0}'' to upper level +inline.super.non.project.class.warning.message: + text: Cannot inline non-project class +interfaces.cannot.be.inlined: + text: Interfaces cannot be inlined introduce.parameter.object: text: Introduce Parameter Object introduce.parameter.object.title: @@ -190,6 +252,8 @@ invert.variable.command.name: text: Inverted javadoced.class: text: Javadoced class +library.classes.cannot.be.inlined: + text: Library classes cannot be inlined make.class.an.inner.class.border: text: Make class {0} an inner class make.class.inner: @@ -300,6 +364,8 @@ push.javadoc.down.title: text: Push Javadoc Down push.up.javadoc.command.name: text: Push up Javadoc +records.cannot.be.inlined: + text: Record classes cannot be inlined refactor: text: Refactor reference: @@ -443,6 +509,8 @@ type.parameter.to.be.remove: text: Type parameter to be remove type.parameters.can.not.be.introduced.as.type.parameters: text: Type parameters can not be introduced as type parameters. +type.parameters.cannot.be.inlined: + text: Type parameters cannot be inlined type.selected.is.not.in.class.context: text: Type selected is not in class context. unable.to.find.the.requested.class: diff --git a/plugin/src/test/java_/com/intellij/refactoring/inline/InlineToAnonymousClassMultifileTest.java b/plugin/src/test/java_/com/intellij/refactoring/inline/InlineToAnonymousClassMultifileTest.java index c5d75c333c..78300a8ace 100644 --- a/plugin/src/test/java_/com/intellij/refactoring/inline/InlineToAnonymousClassMultifileTest.java +++ b/plugin/src/test/java_/com/intellij/refactoring/inline/InlineToAnonymousClassMultifileTest.java @@ -18,6 +18,7 @@ import com.intellij.JavaTestUtil; import com.intellij.java.impl.refactoring.inline.InlineToAnonymousClassHandler; import com.intellij.java.impl.refactoring.inline.InlineToAnonymousClassProcessor; +import consulo.localize.LocalizeValue; import consulo.virtualFileSystem.LocalFileSystem; import consulo.virtualFileSystem.VirtualFile; import com.intellij.java.language.psi.PsiClass; @@ -58,7 +59,7 @@ private void doTest(String className) throws Exception { PsiTestUtil.removeAllRoots(myModule, IdeaTestUtil.getMockJdk17()); final VirtualFile rootDir = PsiTestUtil.createTestProjectStructure(myProject, myModule, rootBefore, myFilesToDelete); PsiClass classToInline = myJavaFacade.findClass(className, ProjectScope.getAllScope(myProject)); - assertEquals(null, InlineToAnonymousClassHandler.getCannotInlineMessage(classToInline)); + assertEquals(LocalizeValue.empty(), InlineToAnonymousClassHandler.getCannotInlineMessage(classToInline)); InlineToAnonymousClassProcessor processor = new InlineToAnonymousClassProcessor(myProject, classToInline, null, false, false, false);