mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-18 09:34:34 +07:00
extract class: allow to make nested (IDEA-144033)
This commit is contained in:
@@ -63,6 +63,7 @@ class ExtractClassDialog extends RefactoringDialog implements MemberInfoChangeLi
|
||||
private JCheckBox myGenerateAccessorsCb;
|
||||
private final JavaVisibilityPanel myVisibilityPanel;
|
||||
private final JCheckBox extractAsEnum;
|
||||
private final JCheckBox createInner;
|
||||
private final List<MemberInfo> enumConstants = new ArrayList<MemberInfo>();
|
||||
|
||||
ExtractClassDialog(PsiClass sourceClass, PsiMember selectedMember) {
|
||||
@@ -129,6 +130,7 @@ class ExtractClassDialog extends RefactoringDialog implements MemberInfoChangeLi
|
||||
if (!hasConstants) {
|
||||
extractAsEnum.setVisible(false);
|
||||
}
|
||||
createInner = new JCheckBox("Create nested class");
|
||||
super.init();
|
||||
validateButtons();
|
||||
}
|
||||
@@ -152,9 +154,8 @@ class ExtractClassDialog extends RefactoringDialog implements MemberInfoChangeLi
|
||||
false),
|
||||
newClassName, myVisibilityPanel.getVisibility(),
|
||||
isGenerateAccessors(),
|
||||
isExtractAsEnum()
|
||||
? enumConstants
|
||||
: Collections.<MemberInfo>emptyList());
|
||||
isExtractAsEnum() ? enumConstants : Collections.<MemberInfo>emptyList());
|
||||
processor.setExtractInnerClass(createInner.isSelected());
|
||||
if (processor.getCreatedClass() == null) {
|
||||
Messages.showErrorDialog(myVisibilityPanel, "Unable to create class with the given name");
|
||||
classNameField.requestFocusInWindow();
|
||||
@@ -243,12 +244,15 @@ class ExtractClassDialog extends RefactoringDialog implements MemberInfoChangeLi
|
||||
}
|
||||
|
||||
protected JComponent createNorthPanel() {
|
||||
final JPanel checkboxPanel = new JPanel(new BorderLayout());
|
||||
checkboxPanel.add(createInner, BorderLayout.WEST);
|
||||
checkboxPanel.add(extractAsEnum, BorderLayout.EAST);
|
||||
FormBuilder builder = FormBuilder.createFormBuilder()
|
||||
.addComponent(
|
||||
JBLabelDecorator.createJBLabelDecorator(RefactorJBundle.message("extract.class.from.label", sourceClass.getQualifiedName()))
|
||||
.setBold(true))
|
||||
.addLabeledComponent(RefactorJBundle.message("name.for.new.class.label"), classNameField, UIUtil.LARGE_VGAP)
|
||||
.addLabeledComponent(new JLabel(), extractAsEnum)
|
||||
.addLabeledComponent(new JLabel(), checkboxPanel)
|
||||
.addLabeledComponent(RefactorJBundle.message("package.for.new.class.label"), packageTextField);
|
||||
|
||||
if (JavaProjectRootsUtil.getSuitableDestinationSourceRoots(myProject).size() > 1) {
|
||||
@@ -349,6 +353,14 @@ class ExtractClassDialog extends RefactoringDialog implements MemberInfoChangeLi
|
||||
table.repaint();
|
||||
}
|
||||
});
|
||||
createInner.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
final boolean isCreateInner = createInner.isSelected();
|
||||
packageTextField.setEnabled(!isCreateInner);
|
||||
myDestinationFolderComboBox.setEnabled(!isCreateInner);
|
||||
}
|
||||
});
|
||||
myGenerateAccessorsCb = new JCheckBox("Generate accessors");
|
||||
myGenerateAccessorsCb.setMnemonic('G');
|
||||
panel.add(myGenerateAccessorsCb, BorderLayout.SOUTH);
|
||||
|
||||
+27
-5
@@ -84,6 +84,7 @@ public class ExtractClassProcessor extends FixableUsagesRefactoringProcessor {
|
||||
private boolean delegationRequired = false;
|
||||
private final ExtractEnumProcessor myExtractEnumProcessor;
|
||||
private final PsiClass myClass;
|
||||
private boolean extractInnerClass;
|
||||
|
||||
public ExtractClassProcessor(PsiClass sourceClass,
|
||||
List<PsiField> fields,
|
||||
@@ -150,6 +151,10 @@ public class ExtractClassProcessor extends FixableUsagesRefactoringProcessor {
|
||||
return myClass;
|
||||
}
|
||||
|
||||
public void setExtractInnerClass(boolean extractInnerClass) {
|
||||
this.extractInnerClass = extractInnerClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean preprocessUsages(@NotNull final Ref<UsageInfo[]> refUsages) {
|
||||
final MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>();
|
||||
@@ -166,7 +171,7 @@ public class ExtractClassProcessor extends FixableUsagesRefactoringProcessor {
|
||||
final Project project = sourceClass.getProject();
|
||||
final GlobalSearchScope scope = GlobalSearchScope.allScope(project);
|
||||
final PsiClass existingClass =
|
||||
JavaPsiFacade.getInstance(project).findClass(StringUtil.getQualifiedName(newPackageName, newClassName), scope);
|
||||
JavaPsiFacade.getInstance(project).findClass(getQualifiedName(), scope);
|
||||
if (existingClass != null) {
|
||||
conflicts.putValue(existingClass, RefactorJBundle.message("cannot.perform.the.refactoring") +
|
||||
RefactorJBundle.message("there.already.exists.a.class.with.the.chosen.name"));
|
||||
@@ -193,6 +198,10 @@ public class ExtractClassProcessor extends FixableUsagesRefactoringProcessor {
|
||||
return showConflicts(conflicts, refUsages.get());
|
||||
}
|
||||
|
||||
private String getQualifiedName() {
|
||||
return extractInnerClass ? newClassName : StringUtil.getQualifiedName(newPackageName, newClassName);
|
||||
}
|
||||
|
||||
|
||||
private void calculateInitializersConflicts(MultiMap<PsiElement, String> conflicts) {
|
||||
final PsiClassInitializer[] initializers = sourceClass.getInitializers();
|
||||
@@ -412,7 +421,7 @@ public class ExtractClassProcessor extends FixableUsagesRefactoringProcessor {
|
||||
final String delegateVisibility = calculateDelegateVisibility();
|
||||
if (delegateVisibility.length() > 0) fieldBuffer.append(delegateVisibility).append(' ');
|
||||
fieldBuffer.append("final ");
|
||||
final String fullyQualifiedName = StringUtil.getQualifiedName(newPackageName, newClassName);
|
||||
final String fullyQualifiedName = getQualifiedName();
|
||||
fieldBuffer.append(fullyQualifiedName);
|
||||
if (!typeParams.isEmpty()) {
|
||||
fieldBuffer.append('<');
|
||||
@@ -497,7 +506,7 @@ public class ExtractClassProcessor extends FixableUsagesRefactoringProcessor {
|
||||
assert innerName != null;
|
||||
final String sourceClassQualifiedName = sourceClass.getQualifiedName();
|
||||
assert sourceClassQualifiedName != null;
|
||||
final String newInnerClassName = StringUtil.getQualifiedName(newPackageName, newClassName) + innerName.substring(sourceClassQualifiedName.length());
|
||||
final String newInnerClassName = getQualifiedName() + innerName.substring(sourceClassQualifiedName.length());
|
||||
boolean hasExternalReference = false;
|
||||
for (PsiReference reference : calls) {
|
||||
final PsiElement referenceElement = reference.getElement();
|
||||
@@ -552,7 +561,7 @@ public class ExtractClassProcessor extends FixableUsagesRefactoringProcessor {
|
||||
final Project project = psiManager.getProject();
|
||||
final GlobalSearchScope scope = GlobalSearchScope.allScope(project);
|
||||
final Iterable<PsiReference> calls = ReferencesSearch.search(method, scope);
|
||||
final String fullyQualifiedName = StringUtil.getQualifiedName(newPackageName, newClassName);
|
||||
final String fullyQualifiedName = getQualifiedName();
|
||||
for (PsiReference reference : calls) {
|
||||
final PsiElement referenceElement = reference.getElement();
|
||||
|
||||
@@ -594,7 +603,7 @@ public class ExtractClassProcessor extends FixableUsagesRefactoringProcessor {
|
||||
final Project project = psiManager.getProject();
|
||||
final GlobalSearchScope scope = GlobalSearchScope.allScope(project);
|
||||
|
||||
final String qualifiedName = StringUtil.getQualifiedName(newPackageName, newClassName);
|
||||
final String qualifiedName = getQualifiedName();
|
||||
@NonNls String getter = null;
|
||||
if (myGenerateAccessors) {
|
||||
getter = GenerateMembersUtil.suggestGetterName(field);
|
||||
@@ -683,6 +692,19 @@ public class ExtractClassProcessor extends FixableUsagesRefactoringProcessor {
|
||||
}
|
||||
|
||||
final String classString = extractedClassBuilder.buildBeanClass();
|
||||
if (extractInnerClass) {
|
||||
final PsiFileFactory factory = PsiFileFactory.getInstance(project);
|
||||
final PsiJavaFile newFile = (PsiJavaFile)factory.createFileFromText(newClassName + ".java", JavaFileType.INSTANCE, classString);
|
||||
final PsiClass psiClass = newFile.getClasses()[0];
|
||||
if (!psiClass.isEnum()) {
|
||||
final PsiModifierList modifierList = psiClass.getModifierList();
|
||||
assert modifierList != null;
|
||||
modifierList.setModifierProperty(PsiModifier.STATIC, true);
|
||||
}
|
||||
final PsiElement addedClass = sourceClass.add(psiClass);
|
||||
return (PsiClass)CodeStyleManager.getInstance(manager)
|
||||
.reformat(JavaCodeStyleManager.getInstance(project).shortenClassReferences(addedClass));
|
||||
}
|
||||
|
||||
try {
|
||||
final PsiFile containingFile = sourceClass.getContainingFile();
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
class Test {
|
||||
final Extracted extracted = new Extracted(this);
|
||||
|
||||
void bar(){
|
||||
System.out.println(extracted.getMyT());
|
||||
}
|
||||
|
||||
String foo() {
|
||||
return "";
|
||||
}
|
||||
|
||||
void bazz() {
|
||||
bar();
|
||||
}
|
||||
|
||||
public static class Extracted {
|
||||
private final Test test;
|
||||
String myT;
|
||||
|
||||
public String getMyT() {
|
||||
return myT;
|
||||
}
|
||||
|
||||
public Extracted(Test test) {
|
||||
this.test = test;
|
||||
this.myT = test.foo();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
class Test {
|
||||
String myT = foo();
|
||||
|
||||
void bar(){
|
||||
System.out.println(myT);
|
||||
}
|
||||
|
||||
String foo() {
|
||||
return "";
|
||||
}
|
||||
|
||||
void bazz() {
|
||||
bar();
|
||||
}
|
||||
}
|
||||
@@ -192,11 +192,37 @@ public class ExtractClassTest extends MultiFileTestCase{
|
||||
});
|
||||
}
|
||||
|
||||
private static void doTest(final PsiClass aClass, final ArrayList<PsiMethod> methods, final ArrayList<PsiField> fields, final String conflicts,
|
||||
public void testInnerClass() throws Exception {
|
||||
doTest((rootDir, rootAfter) -> {
|
||||
PsiClass aClass = myJavaFacade.findClass("Test", GlobalSearchScope.projectScope(myProject));
|
||||
|
||||
assertNotNull("Class Test not found", aClass);
|
||||
|
||||
final ArrayList<PsiField> fields = new ArrayList<>();
|
||||
fields.add(aClass.findFieldByName("myT", false));
|
||||
|
||||
doTest(aClass, new ArrayList<>(), fields, null, true, true);
|
||||
});
|
||||
}
|
||||
|
||||
private static void doTest(final PsiClass aClass,
|
||||
final ArrayList<PsiMethod> methods,
|
||||
final ArrayList<PsiField> fields,
|
||||
final String conflicts,
|
||||
boolean generateGettersSetters) {
|
||||
doTest(aClass, methods, fields, conflicts, generateGettersSetters, false);
|
||||
}
|
||||
|
||||
private static void doTest(final PsiClass aClass,
|
||||
final ArrayList<PsiMethod> methods,
|
||||
final ArrayList<PsiField> fields,
|
||||
final String conflicts,
|
||||
boolean generateGettersSetters,
|
||||
boolean inner) {
|
||||
try {
|
||||
ExtractClassProcessor processor = new ExtractClassProcessor(aClass, fields, methods, new ArrayList<>(), StringUtil.getPackageName(aClass.getQualifiedName()), null,
|
||||
"Extracted", null, generateGettersSetters, Collections.<MemberInfo>emptyList());
|
||||
processor.setExtractInnerClass(inner);
|
||||
processor.run();
|
||||
LocalFileSystem.getInstance().refresh(false);
|
||||
FileDocumentManager.getInstance().saveAllDocuments();
|
||||
|
||||
Reference in New Issue
Block a user