blob: c7d131647d6d5407d95493b0c6fa4ff514983a90 [file] [log] [blame]
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.refactoring.move.moveFilesOrDirectories;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.impl.file.JavaDirectoryServiceImpl;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.refactoring.move.MoveCallback;
import com.intellij.util.ArrayUtilRt;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
public class JavaMoveFilesOrDirectoriesHandler extends MoveFilesOrDirectoriesHandler {
@Override
public PsiElement adjustTargetForMove(DataContext dataContext, PsiElement targetContainer) {
if (targetContainer instanceof PsiPackage) {
final Module module = LangDataKeys.TARGET_MODULE.getData(dataContext);
if (module != null) {
final PsiDirectory[] directories = ((PsiPackage)targetContainer).getDirectories(GlobalSearchScope.moduleScope(module));
if (directories.length == 1) {
return directories[0];
}
}
}
return super.adjustTargetForMove(dataContext, targetContainer);
}
@Override
public PsiElement[] adjustForMove(Project project, PsiElement[] sourceElements, PsiElement targetElement) {
sourceElements = super.adjustForMove(project, sourceElements, targetElement);
if (sourceElements == null) {
return null;
}
Set<PsiElement> result = new LinkedHashSet<PsiElement>();
for (PsiElement sourceElement : sourceElements) {
result.add(sourceElement instanceof PsiClass ? sourceElement.getContainingFile() : sourceElement);
}
return PsiUtilCore.toPsiElementArray(result);
}
@Override
public void doMove(final Project project, PsiElement[] elements, PsiElement targetContainer, MoveCallback callback) {
elements = super.adjustForMove(project, elements, targetContainer);
if (elements == null) {
return;
}
MoveFilesOrDirectoriesUtil
.doMove(project, elements, new PsiElement[]{targetContainer}, callback, new Function<PsiElement[], PsiElement[]>() {
@Override
public PsiElement[] fun(final PsiElement[] elements) {
return new WriteCommandAction<PsiElement[]>(project, "Regrouping ...") {
@Override
protected void run(Result<PsiElement[]> result) throws Throwable {
final List<PsiElement> adjustedElements = new ArrayList<PsiElement>();
for (int i = 0, length = elements.length; i < length; i++) {
PsiElement element = elements[i];
if (element instanceof PsiClass) {
final PsiClass topLevelClass = PsiUtil.getTopLevelClass(element);
if (topLevelClass != null) {
elements[i] = topLevelClass;
final PsiFile containingFile = obtainContainingFile(topLevelClass, elements);
if (containingFile != null && !adjustedElements.contains(containingFile)) {
adjustedElements.add(containingFile);
continue;
}
}
}
adjustedElements.add(element);
}
result.setResult(PsiUtilCore.toPsiElementArray(adjustedElements));
}
}.execute().getResultObject();
}
});
}
@Nullable
private static PsiFile obtainContainingFile(@NotNull PsiElement element, PsiElement[] elements) {
final PsiFile containingFile = element.getContainingFile();
final PsiClass[] classes = ((PsiClassOwner)containingFile).getClasses();
final Set<PsiClass> nonMovedClasses = new HashSet<PsiClass>();
for (PsiClass aClass : classes) {
if (ArrayUtilRt.find(elements, aClass) < 0) {
nonMovedClasses.add(aClass);
}
}
if (nonMovedClasses.isEmpty()) {
return containingFile;
}
else {
final PsiDirectory containingDirectory = containingFile.getContainingDirectory();
if (containingDirectory != null) {
try {
JavaDirectoryServiceImpl.checkCreateClassOrInterface(containingDirectory, ((PsiClass)element).getName());
final PsiElement createdClass = containingDirectory.add(element);
element.delete();
return createdClass.getContainingFile();
}
catch (IncorrectOperationException e) {
final Iterator<PsiClass> iterator = nonMovedClasses.iterator();
final PsiClass nonMovedClass = iterator.next();
final PsiElement createdFile = containingDirectory.add(nonMovedClass).getContainingFile();
nonMovedClass.delete();
while (iterator.hasNext()) {
final PsiClass currentClass = iterator.next();
createdFile.add(currentClass);
currentClass.delete();
}
return containingFile;
}
}
}
return null;
}
}