mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-19 04:51:24 +07:00
Java: disallow making builder class from the constructor class itself (IDEA-254858)
GitOrigin-RevId: 071a0fd3c45f2b28b73b811e0d844a0f1b911372
This commit is contained in:
committed by
intellij-monorepo-bot
parent
cfc65a9890
commit
2870f49e0a
@@ -16,6 +16,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.InputValidatorEx;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.ui.Splitter;
|
||||
import com.intellij.openapi.util.NlsContexts;
|
||||
import com.intellij.openapi.util.NlsSafe;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.wm.IdeFocusManager;
|
||||
@@ -25,6 +26,7 @@ import com.intellij.psi.codeStyle.VariableKind;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.PropertyUtilBase;
|
||||
import com.intellij.refactoring.HelpID;
|
||||
import com.intellij.refactoring.MoveDestination;
|
||||
import com.intellij.refactoring.PackageWrapper;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.refactoring.move.moveClassesOrPackages.DestinationFolderComboBox;
|
||||
@@ -71,7 +73,6 @@ public class ReplaceConstructorWithBuilderDialog extends RefactoringDialog {
|
||||
private static final String RECENT_KEYS = "ReplaceConstructorWithBuilder.RECENT_KEYS";
|
||||
private static final String SETTER_PREFIX_KEY = "ConstructorWithBuilder.SetterPrefix";
|
||||
|
||||
|
||||
protected ReplaceConstructorWithBuilderDialog(@NotNull Project project, PsiMethod[] constructors) {
|
||||
super(project, false);
|
||||
myConstructors = constructors;
|
||||
@@ -95,21 +96,46 @@ public class ReplaceConstructorWithBuilderDialog extends RefactoringDialog {
|
||||
|
||||
final String className;
|
||||
final String packageName;
|
||||
if (myCreateBuilderClassRadioButton.isSelected()) {
|
||||
boolean createNewBuilder = myCreateBuilderClassRadioButton.isSelected();
|
||||
if (createNewBuilder) {
|
||||
className = myNewClassName.getText().trim();
|
||||
packageName = myPackageTextField.getText().trim();
|
||||
} else {
|
||||
final String fqName = myExistentClassTF.getText().trim();
|
||||
className = StringUtil.getShortName(fqName);
|
||||
packageName = StringUtil.getPackageName(fqName);
|
||||
final PsiClass builderClass = JavaPsiFacade.getInstance(myProject).findClass(StringUtil.getQualifiedName(packageName, className), GlobalSearchScope.projectScope(myProject));
|
||||
if (builderClass != null && !CommonRefactoringUtil.checkReadOnlyStatus(myProject, builderClass)) return;
|
||||
}
|
||||
final PsiClass builderClass = JavaPsiFacade.getInstance(myProject)
|
||||
.findClass(StringUtil.getQualifiedName(packageName, className), GlobalSearchScope.projectScope(myProject));
|
||||
if (!createNewBuilder) {
|
||||
if (builderClass == null) {
|
||||
String message = JavaRefactoringBundle.message("replace.constructor.builder.error.selected.class.was.not.found",
|
||||
CommonRefactoringUtil.htmlEmphasize(className));
|
||||
showErrorDialog(message);
|
||||
return;
|
||||
}
|
||||
if (builderClass == myConstructors[0].getContainingClass()) {
|
||||
showErrorDialog(JavaRefactoringBundle.message("replace.constructor.builder.error.builder.class.cannot.be.the.same",
|
||||
CommonRefactoringUtil.htmlEmphasize(className)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (builderClass != null) {
|
||||
showErrorDialog(JavaRefactoringBundle.message("replace.constructor.builder.error.class.with.chosen.name.already.exist",
|
||||
CommonRefactoringUtil.htmlEmphasize(className),
|
||||
CommonRefactoringUtil.htmlEmphasize(packageName)));
|
||||
return;
|
||||
}
|
||||
if (!createNewBuilder && !CommonRefactoringUtil.checkReadOnlyStatus(myProject, builderClass)) return;
|
||||
MoveDestination destination =
|
||||
((DestinationFolderComboBox)myDestinationCb).selectDirectory(new PackageWrapper(myConstructors[0].getManager(), packageName), false);
|
||||
invokeRefactoring(new ReplaceConstructorWithBuilderProcessor(getProject(), myConstructors, myParametersMap, className, packageName,
|
||||
((DestinationFolderComboBox)myDestinationCb).selectDirectory(new PackageWrapper(myConstructors[0].getManager(), packageName), false),
|
||||
myCreateBuilderClassRadioButton.isSelected()));
|
||||
destination, createNewBuilder));
|
||||
}
|
||||
|
||||
private void showErrorDialog(@NlsContexts.DialogMessage String message) {
|
||||
Messages.showErrorDialog(getRootPane(), message, JavaRefactoringBundle.message("replace.constructor.with.builder"));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
@@ -133,10 +159,9 @@ public class ReplaceConstructorWithBuilderDialog extends RefactoringDialog {
|
||||
}
|
||||
|
||||
private void applyNewSetterPrefix() {
|
||||
final String setterPrefix = Messages.showInputDialog(myTable, JavaRefactoringBundle
|
||||
.message("constructor.with.builder.new.setter.prefix.dialog.message"), JavaRefactoringBundle
|
||||
.message("constructor.with.builder.rename.setters.prefix.action.name"), null,
|
||||
mySetterPrefix, new MySetterPrefixInputValidator());
|
||||
String message = JavaRefactoringBundle.message("constructor.with.builder.new.setter.prefix.dialog.message");
|
||||
String title = JavaRefactoringBundle.message("constructor.with.builder.rename.setters.prefix.action.name");
|
||||
final String setterPrefix = Messages.showInputDialog(myTable, message, title, null, mySetterPrefix, new MySetterPrefixInputValidator());
|
||||
if (setterPrefix != null) {
|
||||
mySetterPrefix = setterPrefix;
|
||||
PropertiesComponent.getInstance(myProject).setValue(SETTER_PREFIX_KEY, setterPrefix);
|
||||
@@ -207,14 +232,16 @@ public class ReplaceConstructorWithBuilderDialog extends RefactoringDialog {
|
||||
}
|
||||
if (myCreateBuilderClassRadioButton.isSelected()) {
|
||||
final String className = myNewClassName.getText().trim();
|
||||
if (className.length() == 0 || !nameHelper.isQualifiedName(className)) throw new ConfigurationException(
|
||||
if (className.isEmpty()) throw new ConfigurationException(null);
|
||||
if (!nameHelper.isQualifiedName(className)) throw new ConfigurationException(
|
||||
JavaRefactoringBundle.message("replace.constructor.builder.error.invalid.builder.class.name", className));
|
||||
final String packageName = myPackageTextField.getText().trim();
|
||||
if (packageName.length() > 0 && !nameHelper.isQualifiedName(packageName)) throw new ConfigurationException(
|
||||
if (!packageName.isEmpty() && !nameHelper.isQualifiedName(packageName)) throw new ConfigurationException(
|
||||
JavaRefactoringBundle.message("replace.constructor.builder.error.invalid.builder.package.name", packageName));
|
||||
} else {
|
||||
final String qualifiedName = myExistentClassTF.getText().trim();
|
||||
if (qualifiedName.length() == 0 || !nameHelper.isQualifiedName(qualifiedName)) throw new ConfigurationException(
|
||||
if (qualifiedName.isEmpty()) throw new ConfigurationException(null);
|
||||
if (!nameHelper.isQualifiedName(qualifiedName)) throw new ConfigurationException(
|
||||
JavaRefactoringBundle.message("replace.constructor.builder.error.invalid.builder.qualified.class.name", qualifiedName));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// 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.replaceConstructorWithBuilder;
|
||||
|
||||
import com.intellij.ide.highlighter.JavaFileType;
|
||||
@@ -8,6 +8,7 @@ import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleUtilCore;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.NlsContexts;
|
||||
import com.intellij.openapi.util.NlsSafe;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -25,6 +26,7 @@ import com.intellij.refactoring.MoveDestination;
|
||||
import com.intellij.refactoring.replaceConstructorWithBuilder.usageInfo.ReplaceConstructorWithSettersChainInfo;
|
||||
import com.intellij.refactoring.util.FixableUsageInfo;
|
||||
import com.intellij.refactoring.util.FixableUsagesRefactoringProcessor;
|
||||
import com.intellij.refactoring.util.RefactoringUIUtil;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.usageView.UsageViewDescriptor;
|
||||
import com.intellij.util.CommonJavaRefactoringUtil;
|
||||
@@ -45,8 +47,8 @@ public class ReplaceConstructorWithBuilderProcessor extends FixableUsagesRefacto
|
||||
private final PsiMethod[] myConstructors;
|
||||
private final Map<String, ParameterData> myParametersMap;
|
||||
@NotNull
|
||||
private final String myClassName;
|
||||
private final String myPackageName;
|
||||
private final @NlsSafe String myClassName;
|
||||
private final @NlsSafe String myPackageName;
|
||||
private final boolean myCreateNewBuilderClass;
|
||||
private final PsiElementFactory myElementFactory;
|
||||
private final MoveDestination myMoveDestination;
|
||||
@@ -113,7 +115,6 @@ public class ReplaceConstructorWithBuilderProcessor extends FixableUsagesRefacto
|
||||
}
|
||||
|
||||
if (directory != null) {
|
||||
|
||||
final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(PsiManager.getInstance(myProject).getProject());
|
||||
final PsiJavaFile reformattedFile = (PsiJavaFile)codeStyleManager.reformat(JavaCodeStyleManager.getInstance(newFile.getProject()).shortenClassReferences(newFile));
|
||||
|
||||
@@ -125,7 +126,6 @@ public class ReplaceConstructorWithBuilderProcessor extends FixableUsagesRefacto
|
||||
|
||||
@Override
|
||||
protected void performRefactoring(UsageInfo @NotNull [] usageInfos) {
|
||||
|
||||
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(myProject);
|
||||
final PsiClass builderClass = myCreateNewBuilderClass
|
||||
? createBuilderClass()
|
||||
@@ -222,19 +222,12 @@ public class ReplaceConstructorWithBuilderProcessor extends FixableUsagesRefacto
|
||||
final PsiMethod constructor = getWorkingConstructor();
|
||||
for (PsiParameter parameter : constructor.getParameterList().getParameters()) {
|
||||
final String pureParamName = styleManager.variableNameToPropertyName(parameter.getName(), VariableKind.PARAMETER);
|
||||
if (buf.length() > 0) buf.append(", ");
|
||||
if (!buf.isEmpty()) buf.append(", ");
|
||||
buf.append(myParametersMap.get(pureParamName).getFieldName());
|
||||
}
|
||||
return myElementFactory.createMethodFromText("public " +
|
||||
constructor.getName() +
|
||||
" " +
|
||||
createMethodName +
|
||||
"(){\n return new " +
|
||||
constructor.getName() +
|
||||
"(" +
|
||||
buf +
|
||||
")" +
|
||||
";\n}", constructor);
|
||||
return myElementFactory.createMethodFromText("public " + constructor.getName() + " " + createMethodName + "(){" +
|
||||
"\n return new " + constructor.getName() + "(" + buf + ");" +
|
||||
"\n}", constructor);
|
||||
}
|
||||
|
||||
private PsiMethod getWorkingConstructor() {
|
||||
@@ -284,30 +277,19 @@ public class ReplaceConstructorWithBuilderProcessor extends FixableUsagesRefacto
|
||||
return "create" + StringUtil.capitalize(myConstructors[0].getName());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean preprocessUsages(@NotNull Ref<UsageInfo[]> refUsages) {
|
||||
final MultiMap<PsiElement, String> conflicts = new MultiMap<>();
|
||||
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(myProject);
|
||||
PsiClass anchor = myConstructors[0].getContainingClass();
|
||||
final PsiClass builderClass =
|
||||
psiFacade.findClass(StringUtil.getQualifiedName(myPackageName, myClassName), GlobalSearchScope.projectScope(myProject));
|
||||
if (builderClass == null) {
|
||||
if (!myCreateNewBuilderClass) {
|
||||
conflicts.putValue(anchor, JavaRefactoringBundle.message("replace.constructor.builder.error.selected.class.was.not.found", myClassName));
|
||||
}
|
||||
} else if (myCreateNewBuilderClass){
|
||||
conflicts.putValue(builderClass,
|
||||
JavaRefactoringBundle.message("replace.constructor.builder.error.class.with.chosen.name.already.exist"));
|
||||
}
|
||||
|
||||
final MultiMap<PsiElement, @NlsContexts.DialogMessage String> conflicts = new MultiMap<>();
|
||||
if (myMoveDestination != null && myCreateNewBuilderClass) {
|
||||
myMoveDestination.analyzeModuleConflicts(Collections.emptyList(), conflicts, refUsages.get());
|
||||
}
|
||||
|
||||
final PsiMethod commonConstructor = getMostCommonConstructor();
|
||||
if (commonConstructor == null) {
|
||||
conflicts.putValue(anchor, JavaRefactoringBundle.message("replace.constructor.builder.error.no.constructor.chain"));
|
||||
PsiClass containingClass = myConstructors[0].getContainingClass();
|
||||
assert containingClass != null;
|
||||
conflicts.putValue(containingClass, JavaRefactoringBundle.message("replace.constructor.builder.error.no.constructor.chain",
|
||||
RefactoringUIUtil.getDescription(containingClass, false)));
|
||||
}
|
||||
|
||||
return showConflicts(conflicts, refUsages.get());
|
||||
|
||||
Reference in New Issue
Block a user