blob: 103dc784644b205b2564bf5a377e12dbe5fce0c0 [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.moveClassesOrPackages;
import com.intellij.codeInsight.ChangeContextUtil;
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.usageView.UsageInfo;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
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");
@Override
public void finishMoveClass(@NotNull PsiClass aClass) {
if (aClass.getContainingFile() instanceof PsiJavaFile) {
ChangeContextUtil.decodeContextInfo(aClass, null, null);
}
}
@Override
public void prepareMove(@NotNull PsiClass aClass) {
if (aClass.getContainingFile() instanceof PsiJavaFile) {
ChangeContextUtil.encodeContextInfo(aClass, true);
}
}
public PsiClass doMoveClass(@NotNull final PsiClass aClass, @NotNull PsiDirectory moveDestination) throws IncorrectOperationException {
PsiFile file = aClass.getContainingFile();
final PsiPackage newPackage = JavaDirectoryService.getInstance().getPackage(moveDestination);
PsiClass newClass = null;
if (file instanceof PsiJavaFile) {
if (!moveDestination.equals(file.getContainingDirectory()) &&
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);
final PsiFile newFile = moveDestination.findFile(file.getName());
LOG.assertTrue(newFile != null);
newClass = (PsiClass)newFile.add(aClass);
correctOldClassReferences(newClass, aClass);
aClass.delete();
}
else if (((PsiJavaFile)file).getClasses().length > 1) {
correctSelfReferences(aClass, newPackage);
final PsiClass created = JavaDirectoryService.getInstance().createClass(moveDestination, aClass.getName());
if (aClass.getDocComment() == null) {
final PsiDocComment createdDocComment = created.getDocComment();
if (createdDocComment != null) {
aClass.addAfter(createdDocComment, null);
}
}
newClass = (PsiClass)created.replace(aClass);
correctOldClassReferences(newClass, aClass);
aClass.delete();
}
}
return newClass;
}
private static void correctOldClassReferences(final PsiClass newClass, final PsiClass oldClass) {
final Set<PsiImportStatementBase> importsToDelete = new HashSet<PsiImportStatementBase>();
newClass.getContainingFile().accept(new JavaRecursiveElementVisitor() {
@Override
public void visitReferenceElement(PsiJavaCodeReferenceElement reference) {
if (reference.isValid() && reference.isReferenceTo(oldClass)) {
final PsiImportStatementBase importStatement = PsiTreeUtil.getParentOfType(reference, PsiImportStatementBase.class);
if (importStatement != null) {
importsToDelete.add(importStatement);
return;
}
try {
reference.bindToElement(newClass);
}
catch (IncorrectOperationException e) {
LOG.error(e);
}
}
super.visitReferenceElement(reference);
}
});
for (PsiImportStatementBase importStatement : importsToDelete) {
importStatement.delete();
}
}
private static void correctSelfReferences(final PsiClass aClass, final PsiPackage newContainingPackage) {
final PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage(aClass.getContainingFile().getContainingDirectory());
if (aPackage != null) {
aClass.accept(new JavaRecursiveElementWalkingVisitor() {
@Override
public void visitReferenceElement(PsiJavaCodeReferenceElement reference) {
if (reference.isQualified() && reference.isReferenceTo(aClass)) {
final PsiElement qualifier = reference.getQualifier();
if (qualifier instanceof PsiJavaCodeReferenceElement && ((PsiJavaCodeReferenceElement)qualifier).isReferenceTo(aPackage)) {
try {
((PsiJavaCodeReferenceElement)qualifier).bindToElement(newContainingPackage);
}
catch (IncorrectOperationException e) {
LOG.error(e);
}
}
}
super.visitReferenceElement(reference);
}
});
}
}
public String getName(PsiClass clazz) {
final PsiFile file = clazz.getContainingFile();
if (!(file instanceof PsiJavaFile)) return null;
return ((PsiJavaFile)file).getClasses().length > 1 ? clazz.getName() + "." + StdFileTypes.JAVA.getDefaultExtension() : file.getName();
}
@Override
public void preprocessUsages(Collection<UsageInfo> results) {
}
}