mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-02-05 08:06:56 +07:00
[java-refactoring] ConvertToInstanceMethodHandler: separate targetQualifiers computation logic from UI
GitOrigin-RevId: 4f0e3c3af486085920b3f3883935910cb9dd280e
This commit is contained in:
committed by
intellij-monorepo-bot
parent
2dec24aa8f
commit
e1751e5f4d
@@ -10,22 +10,18 @@ import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.ScrollType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.NlsContexts;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiIdentifier;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.refactoring.HelpID;
|
||||
import com.intellij.refactoring.RefactoringActionHandler;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.refactoring.actions.BaseRefactoringAction;
|
||||
import com.intellij.refactoring.util.CommonRefactoringUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.siyeh.ig.psiutils.MethodUtils;
|
||||
import com.siyeh.ig.psiutils.VariableAccessUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class ConvertToInstanceMethodHandler implements RefactoringActionHandler, ContextAwareActionHandler {
|
||||
private static final Logger LOG = Logger.getInstance(ConvertToInstanceMethodHandler.class);
|
||||
|
||||
@@ -54,62 +50,16 @@ public class ConvertToInstanceMethodHandler implements RefactoringActionHandler,
|
||||
@Override
|
||||
public void invoke(@NotNull Project project, PsiElement @NotNull [] elements, DataContext dataContext) {
|
||||
if (elements.length != 1 || !(elements[0] instanceof PsiMethod method)) return;
|
||||
if (!method.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
String message = JavaRefactoringBundle.message("convertToInstanceMethod.method.is.not.static", method.getName());
|
||||
@NotNull PossibleInstanceQualifiers result = PossibleInstanceQualifiers.build(method);
|
||||
if (result instanceof PossibleInstanceQualifiers.Invalid error) {
|
||||
Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
|
||||
CommonRefactoringUtil.showErrorHint(project, editor, message, getRefactoringName(), HelpID.CONVERT_TO_INSTANCE_METHOD);
|
||||
return;
|
||||
CommonRefactoringUtil.showErrorHint(project, editor, RefactoringBundle.getCannotRefactorMessage(error.message()),
|
||||
getRefactoringName(),
|
||||
HelpID.CONVERT_TO_INSTANCE_METHOD);
|
||||
}
|
||||
final PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
List<Object> targetQualifiers = new ArrayList<>();
|
||||
boolean classTypesFound = false;
|
||||
boolean resolvableClassesFound = false;
|
||||
for (final PsiParameter parameter : parameters) {
|
||||
if (VariableAccessUtils.variableIsAssigned(parameter, parameter.getDeclarationScope())) continue;
|
||||
final PsiType type = parameter.getType();
|
||||
if (type instanceof PsiClassType) {
|
||||
classTypesFound = true;
|
||||
final PsiClass psiClass = ((PsiClassType)type).resolve();
|
||||
if (psiClass != null && !(psiClass instanceof PsiTypeParameter)) {
|
||||
resolvableClassesFound = true;
|
||||
if (method.getManager().isInProject(psiClass)) {
|
||||
targetQualifiers.add(parameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (result instanceof PossibleInstanceQualifiers.Valid targetQualifiers) {
|
||||
new ConvertToInstanceMethodDialog(method, targetQualifiers.toArray()).show();
|
||||
}
|
||||
PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass == null || containingClass.getQualifiedName() == null) return;
|
||||
String className = containingClass.getName();
|
||||
if (!containingClass.isEnum() && !(containingClass instanceof PsiImplicitClass)) {
|
||||
PsiMethod[] constructors = containingClass.getConstructors();
|
||||
boolean noArgConstructor =
|
||||
constructors.length == 0 || ContainerUtil.exists(constructors, constructor -> constructor.getParameterList().isEmpty());
|
||||
if (noArgConstructor) {
|
||||
targetQualifiers.add("this / new " + className + "()");
|
||||
}
|
||||
}
|
||||
|
||||
if (targetQualifiers.isEmpty()) {
|
||||
String message;
|
||||
if (!classTypesFound) {
|
||||
message = JavaRefactoringBundle.message("convertToInstanceMethod.no.parameters.with.reference.type");
|
||||
}
|
||||
else if (!resolvableClassesFound) {
|
||||
message = JavaRefactoringBundle.message("convertToInstanceMethod.all.reference.type.parameters.have.unknown.types");
|
||||
}
|
||||
else {
|
||||
message = JavaRefactoringBundle.message("convertToInstanceMethod.all.reference.type.parameters.are.not.in.project");
|
||||
}
|
||||
if (!(containingClass instanceof PsiImplicitClass)) {
|
||||
message += " " + JavaRefactoringBundle.message("convertToInstanceMethod.no.default.ctor");
|
||||
}
|
||||
Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
|
||||
CommonRefactoringUtil.showErrorHint(project, editor, RefactoringBundle.getCannotRefactorMessage(message), getRefactoringName(), HelpID.CONVERT_TO_INSTANCE_METHOD);
|
||||
return;
|
||||
}
|
||||
|
||||
new ConvertToInstanceMethodDialog(method, ArrayUtil.toObjectArray(targetQualifiers)).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.refactoring.convertToInstanceMethod;
|
||||
|
||||
import com.intellij.java.refactoring.JavaRefactoringBundle;
|
||||
import com.intellij.openapi.util.NlsContexts;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.siyeh.ig.psiutils.VariableAccessUtils;
|
||||
import one.util.streamex.StreamEx;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A container for possible qualifiers for 'Convert to instance method' refactoring
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public sealed interface PossibleInstanceQualifiers {
|
||||
/**
|
||||
* Represents valid list of qualifiers
|
||||
*
|
||||
* @param qualifiers list of qualifier parameters
|
||||
* @param thisOrNewQualifierName name of 'this/new Object' qualifier, or null if such a name is impossible to use in this context
|
||||
*/
|
||||
record Valid(@NotNull List<@NotNull PsiParameter> qualifiers, @Nullable String thisOrNewQualifierName) implements PossibleInstanceQualifiers {
|
||||
Object[] toArray() {
|
||||
if (thisOrNewQualifierName == null) {
|
||||
return ArrayUtil.toObjectArray(qualifiers);
|
||||
}
|
||||
return StreamEx.<Object>of(qualifiers).append(thisOrNewQualifierName).toArray();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents invalid context in case if conversion to an instance method is not supported
|
||||
*
|
||||
* @param message message explaining why conversion is not possible
|
||||
*/
|
||||
record Invalid(@NlsContexts.DialogMessage String message) implements PossibleInstanceQualifiers {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param method method to convert
|
||||
* @return PossibleInstanceQualifiers instance
|
||||
*/
|
||||
static @NotNull PossibleInstanceQualifiers build(@NotNull PsiMethod method) {
|
||||
if (!method.hasModifierProperty(PsiModifier.STATIC)) {
|
||||
return new Invalid(JavaRefactoringBundle.message("convertToInstanceMethod.method.is.not.static", method.getName()));
|
||||
}
|
||||
List<PsiParameter> targetQualifiers = new ArrayList<>();
|
||||
String thisOrNewQualifierName = null;
|
||||
final PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
boolean classTypesFound = false;
|
||||
boolean resolvableClassesFound = false;
|
||||
for (final PsiParameter parameter : parameters) {
|
||||
if (VariableAccessUtils.variableIsAssigned(parameter, parameter.getDeclarationScope())) continue;
|
||||
final PsiType type = parameter.getType();
|
||||
if (type instanceof PsiClassType) {
|
||||
classTypesFound = true;
|
||||
final PsiClass psiClass = ((PsiClassType)type).resolve();
|
||||
if (psiClass != null && !(psiClass instanceof PsiTypeParameter)) {
|
||||
resolvableClassesFound = true;
|
||||
if (method.getManager().isInProject(psiClass)) {
|
||||
targetQualifiers.add(parameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
PsiClass containingClass = method.getContainingClass();
|
||||
if (containingClass == null || containingClass.getQualifiedName() == null) {
|
||||
return new Invalid(JavaRefactoringBundle.message("convertToInstanceMethod.unsupported.containing.class"));
|
||||
}
|
||||
String className = containingClass.getName();
|
||||
if (!containingClass.isEnum() && !(containingClass instanceof PsiImplicitClass)) {
|
||||
PsiMethod[] constructors = containingClass.getConstructors();
|
||||
boolean noArgConstructor =
|
||||
constructors.length == 0 || ContainerUtil.exists(constructors, constructor -> constructor.getParameterList().isEmpty());
|
||||
if (noArgConstructor) {
|
||||
thisOrNewQualifierName = "this / new " + className + "()";
|
||||
}
|
||||
}
|
||||
|
||||
if (!targetQualifiers.isEmpty() || thisOrNewQualifierName != null) {
|
||||
return new Valid(targetQualifiers, thisOrNewQualifierName);
|
||||
}
|
||||
String message;
|
||||
if (!classTypesFound) {
|
||||
message = JavaRefactoringBundle.message("convertToInstanceMethod.no.parameters.with.reference.type");
|
||||
}
|
||||
else if (!resolvableClassesFound) {
|
||||
message = JavaRefactoringBundle.message("convertToInstanceMethod.all.reference.type.parameters.have.unknown.types");
|
||||
}
|
||||
else {
|
||||
message = JavaRefactoringBundle.message("convertToInstanceMethod.all.reference.type.parameters.are.not.in.project");
|
||||
}
|
||||
if (!(containingClass instanceof PsiImplicitClass)) {
|
||||
message += " " + JavaRefactoringBundle.message("convertToInstanceMethod.no.default.ctor");
|
||||
}
|
||||
return new Invalid(message);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user