package com.intellij.javascript.flex.refactoring.moveClass;
import com.intellij.lang.javascript.JavaScriptSupportLoader;
import com.intellij.lang.javascript.flex.XmlBackedJSClassImpl;
import com.intellij.lang.javascript.psi.JSFile;
import com.intellij.lang.javascript.psi.JSVarStatement;
import com.intellij.lang.javascript.psi.ecmal4.JSPackageStatement;
import com.intellij.lang.javascript.psi.ecmal4.JSQualifiedNamedElement;
import com.intellij.lang.javascript.psi.ecmal4.XmlBackedJSClass;
import com.intellij.lang.javascript.psi.ecmal4.XmlBackedJSClassFactory;
import com.intellij.lang.javascript.psi.impl.JSPsiImplUtils;
import com.intellij.lang.javascript.psi.resolve.JSResolveUtil;
import com.intellij.lang.javascript.refactoring.util.JSRefactoringUtil;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiDirectoryContainer;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiReference;
import com.intellij.psi.xml.XmlFile;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.move.MoveCallback;
import com.intellij.refactoring.move.MoveHandlerDelegate;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection;
/**
* @author Maxim.Mossienko
*/
public class FlexMoveFileRefactoringHandler extends MoveHandlerDelegate {
@Override
public boolean tryToMove(PsiElement element, Project project, DataContext dataContext, @Nullable PsiReference reference, Editor editor) {
PsiElement adjusted = adjustForMove(element);
if (adjusted == null) return false;
if (!JSRefactoringUtil.checkReadOnlyStatus(adjusted, editor, RefactoringBundle.message("move.title"))) return true;
doMove(project, new PsiElement[]{element}, null, null);
return true;
}
@Override
public void doMove(Project project, PsiElement[] elements, @Nullable PsiElement targetContainer, @Nullable MoveCallback callback) {
if (elements.length == 0) {
return;
}
Collection<JSQualifiedNamedElement> adjusted = new ArrayList<>(elements.length);
for (PsiElement element : elements) {
final JSQualifiedNamedElement e = adjustForMove(element);
if (!JSRefactoringUtil.checkReadOnlyStatus(e, null, RefactoringBundle.message("move.title"))) return;
adjusted.add(e);
}
new FlexMoveClassDialog(project, adjusted, targetContainer, callback).show();
}
@Override
public boolean isValidTarget(PsiElement psiElement, PsiElement[] sources) {
return psiElement instanceof PsiDirectoryContainer; // follow Java that handles DND to 'folder' node as plain file moving
}
@Override
public boolean canMove(PsiElement[] elements, @Nullable PsiElement targetContainer) {
if (elements.length == 0) {
return false;
}
final JSQualifiedNamedElement first = adjustForMove(elements[0]);
if (first == null) {
return false;
}
if (JSResolveUtil.isFileLocalSymbol(first)) {
if (elements.length > 1) {
return false;
}
else {
return super.canMove(elements, targetContainer);
}
}
for (PsiElement element : elements) {
if (adjustForMove(element) == null) return false;
}
return super.canMove(elements, targetContainer);
}
@Nullable
public static JSQualifiedNamedElement adjustForMove(PsiElement element) {
PsiFile file = element.getContainingFile();
if (file == null || !file.getLanguage().is(JavaScriptSupportLoader.ECMA_SCRIPT_L4) && !JavaScriptSupportLoader.isFlexMxmFile(file)) {
return null;
}
if (element instanceof JSPackageStatement) {
return null;
}
if (element instanceof XmlBackedJSClassImpl) {
return (JSQualifiedNamedElement)element;
}
if (element instanceof JSQualifiedNamedElement) {
final PsiElement parent = JSResolveUtil.findParent(element);
if (parent instanceof JSPackageStatement || (parent instanceof JSFile && JSResolveUtil.getXmlBackedClass((JSFile)parent) == null)) {
return (JSQualifiedNamedElement)element;
}
}
if (element instanceof JSVarStatement && ((JSVarStatement)element).getVariables().length == 1) {
final PsiElement parent = JSResolveUtil.findParent(element);
if (parent instanceof JSPackageStatement || (parent instanceof JSFile && JSResolveUtil.getXmlBackedClass((JSFile)parent) == null)) {
return ((JSVarStatement)element).getVariables()[0];
}
}
if (element instanceof JSFile) {
final XmlBackedJSClass xmlBackedClass = JSResolveUtil.getXmlBackedClass((JSFile)element);
if (xmlBackedClass != null) {
return xmlBackedClass;
}
return JSPsiImplUtils.findQualifiedElement((JSFile)element);
}
if (element instanceof XmlFile && JavaScriptSupportLoader.isFlexMxmFile((PsiFile)element)) {
return XmlBackedJSClassFactory.getXmlBackedClass((XmlFile)element);
}
return null;
}
}