mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
move package as directory: move non-java files as well; fix imports on classes in moved file(s)
This commit is contained in:
+42
-33
@@ -25,7 +25,6 @@ import com.intellij.codeInsight.ChangeContextUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
@@ -52,7 +51,7 @@ public class MoveDirectoryWithClassesProcessor extends BaseRefactoringProcessor
|
||||
private PsiDirectory myTargetDirectory;
|
||||
private boolean mySearchInComments;
|
||||
private boolean mySearchInNonJavaFiles;
|
||||
private Map<PsiClass, TargetDirectoryWrapper> myClassesToMove;
|
||||
private Map<PsiFile, TargetDirectoryWrapper> myFilesToMove;
|
||||
private NonCodeUsageInfo[] myNonCodeUsages;
|
||||
private MoveCallback myMoveCallback;
|
||||
|
||||
@@ -69,16 +68,16 @@ public class MoveDirectoryWithClassesProcessor extends BaseRefactoringProcessor
|
||||
mySearchInComments = searchInComments;
|
||||
mySearchInNonJavaFiles = searchInNonJavaFiles;
|
||||
myMoveCallback = moveCallback;
|
||||
myClassesToMove = new HashMap<PsiClass, TargetDirectoryWrapper>();
|
||||
myFilesToMove = new HashMap<PsiFile, TargetDirectoryWrapper>();
|
||||
for (PsiDirectory dir : directories) {
|
||||
collectClasses(myClassesToMove, dir, includeSelf ? dir.getParentDirectory() : dir, getTargetDirectory(dir));
|
||||
collectFiles2Move(myFilesToMove, dir, includeSelf ? dir.getParentDirectory() : dir, getTargetDirectory(dir));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UsageViewDescriptor createUsageViewDescriptor(UsageInfo[] usages) {
|
||||
PsiElement[] elements = new PsiElement[myClassesToMove.size()];
|
||||
final PsiClass[] classes = myClassesToMove.keySet().toArray(new PsiClass[myClassesToMove.keySet().size()]);
|
||||
PsiElement[] elements = new PsiElement[myFilesToMove.size()];
|
||||
final PsiFile[] classes = myFilesToMove.keySet().toArray(new PsiFile[myFilesToMove.keySet().size()]);
|
||||
System.arraycopy(classes, 0, elements, 0, classes.length);
|
||||
return new MoveClassesOrPackagesViewDescriptor(elements, false, false, getTargetName());
|
||||
}
|
||||
@@ -92,11 +91,14 @@ public class MoveDirectoryWithClassesProcessor extends BaseRefactoringProcessor
|
||||
public UsageInfo[] findUsages() {
|
||||
final List<UsageInfo> usages = new ArrayList<UsageInfo>();
|
||||
final Set<String> packageNames = new HashSet<String>();
|
||||
for (PsiClass psiClass : myClassesToMove.keySet()) {
|
||||
Collections.addAll(usages, MoveClassesOrPackagesUtil.findUsages(psiClass, mySearchInComments, mySearchInNonJavaFiles, psiClass.getName()));
|
||||
final String fqName = psiClass.getQualifiedName();
|
||||
assert fqName != null;
|
||||
packageNames.add(StringUtil.getPackageName(fqName));
|
||||
for (PsiFile psiFile : myFilesToMove.keySet()) {
|
||||
if (psiFile instanceof PsiClassOwner) {
|
||||
final PsiClass[] classes = ((PsiClassOwner)psiFile).getClasses();
|
||||
for (PsiClass aClass : classes) {
|
||||
Collections.addAll(usages, MoveClassesOrPackagesUtil.findUsages(aClass, mySearchInComments, mySearchInNonJavaFiles, aClass.getName()));
|
||||
}
|
||||
packageNames.add(((PsiClassOwner)psiFile).getPackageName());
|
||||
}
|
||||
}
|
||||
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(myProject);
|
||||
for (String packageName : packageNames) {
|
||||
@@ -136,12 +138,12 @@ public class MoveDirectoryWithClassesProcessor extends BaseRefactoringProcessor
|
||||
@Override
|
||||
protected boolean preprocessUsages(Ref<UsageInfo[]> refUsages) {
|
||||
final MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>();
|
||||
for (PsiClass psiClass : myClassesToMove.keySet()) {
|
||||
for (PsiFile psiFile : myFilesToMove.keySet()) {
|
||||
try {
|
||||
myClassesToMove.get(psiClass).checkMove(psiClass);
|
||||
myFilesToMove.get(psiFile).checkMove(psiFile);
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
conflicts.putValue(psiClass, e.getMessage());
|
||||
conflicts.putValue(psiFile, e.getMessage());
|
||||
}
|
||||
}
|
||||
return showConflicts(conflicts);
|
||||
@@ -153,9 +155,9 @@ public class MoveDirectoryWithClassesProcessor extends BaseRefactoringProcessor
|
||||
@Override
|
||||
public void performRefactoring(UsageInfo[] usages) {
|
||||
//try to create all directories beforehand
|
||||
for (PsiClass psiClass : myClassesToMove.keySet()) {
|
||||
for (PsiFile psiFile : myFilesToMove.keySet()) {
|
||||
try {
|
||||
myClassesToMove.get(psiClass).findOrCreateTargetDirectory();
|
||||
myFilesToMove.get(psiFile).findOrCreateTargetDirectory();
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
Messages.showErrorDialog(myProject, e.getMessage(), CommonBundle.getErrorTitle());
|
||||
@@ -163,16 +165,25 @@ public class MoveDirectoryWithClassesProcessor extends BaseRefactoringProcessor
|
||||
}
|
||||
}
|
||||
final Map<PsiElement, PsiElement> oldToNewElementsMapping = new HashMap<PsiElement, PsiElement>();
|
||||
for (PsiClass psiClass : myClassesToMove.keySet()) {
|
||||
ChangeContextUtil.encodeContextInfo(psiClass, true);
|
||||
final RefactoringElementListener listener = getTransaction().getElementListener(psiClass);
|
||||
final PsiDirectory moveDestination = myClassesToMove.get(psiClass).getTargetDirectory();
|
||||
final PsiClass newClass = MoveClassesOrPackagesUtil.doMoveClass(psiClass, moveDestination);
|
||||
oldToNewElementsMapping.put(psiClass, newClass);
|
||||
listener.elementMoved(newClass);
|
||||
for (PsiFile psiFile : myFilesToMove.keySet()) {
|
||||
ChangeContextUtil.encodeContextInfo(psiFile, true);
|
||||
final RefactoringElementListener listener = getTransaction().getElementListener(psiFile);
|
||||
final PsiDirectory moveDestination = myFilesToMove.get(psiFile).getTargetDirectory();
|
||||
if (psiFile instanceof PsiClassOwner) {
|
||||
for (PsiClass psiClass : ((PsiClassOwner)psiFile).getClasses()) {
|
||||
final PsiClass newClass = MoveClassesOrPackagesUtil.doMoveClass(psiClass, moveDestination);
|
||||
oldToNewElementsMapping.put(psiClass, newClass);
|
||||
listener.elementMoved(newClass);
|
||||
}
|
||||
} else {
|
||||
if (!moveDestination.equals(psiFile.getContainingDirectory())) {
|
||||
psiFile.getManager().moveFile(psiFile, moveDestination);
|
||||
listener.elementMoved(psiFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (PsiClass psiClass : myClassesToMove.keySet()) {
|
||||
ChangeContextUtil.decodeContextInfo(psiClass, null, null);
|
||||
for (PsiElement newElement : oldToNewElementsMapping.values()) {
|
||||
ChangeContextUtil.decodeContextInfo(newElement, null, null);
|
||||
}
|
||||
myNonCodeUsages = MoveClassesOrPackagesProcessor.retargetUsages(usages, oldToNewElementsMapping);
|
||||
for (UsageInfo usage : usages) {
|
||||
@@ -196,7 +207,7 @@ public class MoveDirectoryWithClassesProcessor extends BaseRefactoringProcessor
|
||||
}
|
||||
}
|
||||
|
||||
private static void collectClasses(Map<PsiClass, TargetDirectoryWrapper> classesToMove,
|
||||
private static void collectFiles2Move(Map<PsiFile, TargetDirectoryWrapper> files2Move,
|
||||
PsiDirectory directory,
|
||||
PsiDirectory rootDirectory,
|
||||
@NotNull TargetDirectoryWrapper targetDirectory) {
|
||||
@@ -207,13 +218,11 @@ public class MoveDirectoryWithClassesProcessor extends BaseRefactoringProcessor
|
||||
? targetDirectory
|
||||
: targetDirectory.findOrCreateChild(relativePath);
|
||||
for (PsiElement child : children) {
|
||||
if (child instanceof PsiJavaFile) {
|
||||
for (PsiClass aClass : ((PsiJavaFile)child).getClasses()) {
|
||||
classesToMove.put(aClass, newTargetDirectory);
|
||||
}
|
||||
if (child instanceof PsiFile) {
|
||||
files2Move.put((PsiFile)child, newTargetDirectory);
|
||||
}
|
||||
else if (child instanceof PsiDirectory){
|
||||
collectClasses(classesToMove, (PsiDirectory)child, directory, newTargetDirectory);
|
||||
collectFiles2Move(files2Move, (PsiDirectory)child, directory, newTargetDirectory);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -281,9 +290,9 @@ public class MoveDirectoryWithClassesProcessor extends BaseRefactoringProcessor
|
||||
return new TargetDirectoryWrapper(this, relativePath);
|
||||
}
|
||||
|
||||
public void checkMove(PsiClass psiClass) throws IncorrectOperationException {
|
||||
public void checkMove(PsiFile psiFile) throws IncorrectOperationException {
|
||||
if (myTargetDirectory != null) {
|
||||
psiClass.getManager().checkMove(psiClass, myTargetDirectory);
|
||||
psiFile.getManager().checkMove(psiFile, myTargetDirectory);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+18
-3
@@ -19,16 +19,20 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.javadoc.PsiDocComment;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Maxim.Medvedev
|
||||
*/
|
||||
public class MoveJavaClassHandler implements MoveClassHandler {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.move.moveClassesOrPackages.MoveJavaClassHandler");
|
||||
|
||||
public PsiClass doMoveClass(@NotNull PsiClass aClass, @NotNull PsiDirectory moveDestination) throws IncorrectOperationException {
|
||||
public PsiClass doMoveClass(@NotNull final PsiClass aClass, @NotNull PsiDirectory moveDestination) throws IncorrectOperationException {
|
||||
PsiFile file = aClass.getContainingFile();
|
||||
final PsiPackage newPackage = JavaDirectoryService.getInstance().getPackage(moveDestination);
|
||||
|
||||
@@ -51,18 +55,26 @@ public class MoveJavaClassHandler implements MoveClassHandler {
|
||||
moveDestination.findFile(file.getName()) != null) {
|
||||
// moving second of two classes which were in the same file to a different directory (IDEADEV-3089)
|
||||
correctSelfReferences(aClass, newPackage);
|
||||
PsiFile newFile = moveDestination.findFile(file.getName());
|
||||
final PsiFile newFile = moveDestination.findFile(file.getName());
|
||||
LOG.assertTrue(newFile != null);
|
||||
newClass = (PsiClass)newFile.add(aClass);
|
||||
correctOldClassReferences(newClass, aClass);
|
||||
aClass.delete();
|
||||
}
|
||||
return newClass;
|
||||
}
|
||||
|
||||
private static void correctOldClassReferences(final PsiClass newClass, final PsiClass oldClass) {
|
||||
newClass.accept(new JavaRecursiveElementVisitor() {
|
||||
final Set<PsiImportStatementBase> importsToDelete = new HashSet<PsiImportStatementBase>();
|
||||
newClass.getContainingFile().accept(new JavaRecursiveElementVisitor() {
|
||||
@Override
|
||||
public void visitReferenceElement(PsiJavaCodeReferenceElement reference) {
|
||||
if (reference.isReferenceTo(oldClass)) {
|
||||
final PsiImportStatementBase importStatement = PsiTreeUtil.getParentOfType(reference, PsiImportStatementBase.class);
|
||||
if (importStatement != null) {
|
||||
importsToDelete.add(importStatement);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
reference.bindToElement(newClass);
|
||||
}
|
||||
@@ -73,6 +85,9 @@ public class MoveJavaClassHandler implements MoveClassHandler {
|
||||
super.visitReferenceElement(reference);
|
||||
}
|
||||
});
|
||||
for (PsiImportStatementBase importStatement : importsToDelete) {
|
||||
importStatement.delete();
|
||||
}
|
||||
}
|
||||
|
||||
private static void correctSelfReferences(final PsiClass aClass, final PsiPackage newContainingPackage) {
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package pack2;
|
||||
|
||||
import pack1.*;
|
||||
import target.pack1.S1;
|
||||
|
||||
public class UsagesFromBoth {
|
||||
S1 s1;
|
||||
S2 s2;
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
package target.pack1;
|
||||
|
||||
public class S1{}
|
||||
+1
@@ -0,0 +1 @@
|
||||
readme
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
package pack1;
|
||||
|
||||
public class S2{}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package pack2;
|
||||
|
||||
import pack1.*;
|
||||
import target.pack1.S1;
|
||||
|
||||
public class UsagesFromBoth2 {
|
||||
S1 s1;
|
||||
S2 s2;
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
package pack1;
|
||||
|
||||
public class S1{}
|
||||
+1
@@ -0,0 +1 @@
|
||||
readme
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package pack2;
|
||||
|
||||
import pack1.*;
|
||||
|
||||
public class UsagesFromBoth {
|
||||
S1 s1;
|
||||
S2 s2;
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
package pack1;
|
||||
|
||||
public class S2{}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package pack2;
|
||||
|
||||
import pack1.*;
|
||||
|
||||
public class UsagesFromBoth2 {
|
||||
S1 s1;
|
||||
S2 s2;
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package pack2;
|
||||
|
||||
import pack1.*;
|
||||
import target.pack1.S1;
|
||||
|
||||
public class UsagesFromBoth {
|
||||
S1 s1;
|
||||
S2 s2;
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package target.pack1;
|
||||
|
||||
public class S1{
|
||||
S11 s11;
|
||||
}
|
||||
|
||||
class S11{}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package target.pack1;
|
||||
|
||||
class US {
|
||||
S11 myS11WithoutImport;
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
package pack1;
|
||||
|
||||
public class S2{}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package pack2;
|
||||
|
||||
import pack1.*;
|
||||
import target.pack1.S1;
|
||||
|
||||
public class UsagesFromBoth2 {
|
||||
S1 s1;
|
||||
S2 s2;
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package pack1;
|
||||
|
||||
public class S1{
|
||||
S11 s11;
|
||||
}
|
||||
|
||||
class S11{}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
package pack1;
|
||||
|
||||
class US {
|
||||
S11 myS11WithoutImport;
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package pack2;
|
||||
|
||||
import pack1.*;
|
||||
|
||||
public class UsagesFromBoth {
|
||||
S1 s1;
|
||||
S2 s2;
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
package pack1;
|
||||
|
||||
public class S2{}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package pack2;
|
||||
|
||||
import pack1.*;
|
||||
|
||||
public class UsagesFromBoth2 {
|
||||
S1 s1;
|
||||
S2 s2;
|
||||
}
|
||||
@@ -31,6 +31,15 @@ public class MovePackageAsDirectoryTest extends MultiFileTestCase {
|
||||
doTest(createAction("pack1", "target"));
|
||||
}
|
||||
|
||||
public void testMovePackageWithTxtFilesInside() throws Exception {
|
||||
doTest(createAction("pack1", "target"));
|
||||
}
|
||||
|
||||
public void testMultipleClassesInOneFile() throws Exception {
|
||||
doTest(createAction("pack1", "target"));
|
||||
}
|
||||
|
||||
|
||||
public void testRemoveUnresolvedImports() throws Exception {
|
||||
doTest(createAction("pack1", "target"));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user