package com.nvlad.yii2support.views.refactor;
import com.intellij.openapi.util.Key;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiReference;
import com.intellij.refactoring.listeners.RefactoringElementListener;
import com.intellij.refactoring.rename.RenamePsiElementProcessor;
import com.jetbrains.php.lang.psi.PhpFile;
import com.jetbrains.php.lang.psi.PhpPsiElementFactory;
import com.jetbrains.php.lang.psi.elements.ParameterList;
import com.jetbrains.php.lang.psi.elements.StringLiteralExpression;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
/**
* Created by NVlad on 02.02.2017.
*/
public class RenameViewProcessor extends RenamePsiElementProcessor {
private final static Key<Boolean> WITH_EXT = Key.create("RenameViewProcessor.withExt");
private final static Key<String> OLD_EXT = Key.create("RenameViewProcessor.oldExt");
private final static Key<String> RELATIVE_PATH = Key.create("RenameViewProcessor.relativePath");
private final HashSet<PsiElement> renders = new HashSet<>();
@Override
public boolean canProcessElement(@NotNull PsiElement psiElement) {
return psiElement instanceof PhpFile;
}
@Override
public void prepareRenaming(PsiElement psiElement, String s, Map<PsiElement, String> map) {
renders.clear();
for (PsiReference reference : findReferences(psiElement)) {
final PsiElement element = reference.getElement();
if (element instanceof StringLiteralExpression) {
String fileName = ((StringLiteralExpression) element).getContents();
if (fileName.contains("/")) {
element.getParent().putUserData(RELATIVE_PATH, fileName.substring(0, fileName.lastIndexOf('/') + 1));
fileName = fileName.substring(fileName.lastIndexOf('/') + 1);
}
element.getParent().putUserData(WITH_EXT, fileName.contains("."));
String realFile = ((PsiFile) psiElement).getName();
if (realFile.contains(".")) {
element.getParent().putUserData(OLD_EXT, realFile.substring(realFile.lastIndexOf('.')));
}
renders.add(element.getParent());
}
}
}
@Nullable
@Override
public Runnable getPostRenameCallback(PsiElement psiElement, String s, RefactoringElementListener refactoringElementListener) {
return () -> {
for (PsiElement render : renders) {
StringLiteralExpression element = (StringLiteralExpression) ((ParameterList) render).getParameters()[0];
final PsiElement parent = element.getParent();
String fileName = element.getContents();
if (Objects.equals(parent.getUserData(WITH_EXT), false)) {
if (Objects.equals(fileName.substring(fileName.lastIndexOf('.')), parent.getUserData(OLD_EXT))) {
fileName = fileName.substring(0, fileName.lastIndexOf('.'));
}
}
parent.putUserData(WITH_EXT, null);
parent.putUserData(OLD_EXT, null);
if (parent.getUserData(RELATIVE_PATH) != null) {
fileName = parent.getUserData(RELATIVE_PATH) + fileName;
parent.putUserData(RELATIVE_PATH, null);
}
fileName = element.isSingleQuote() ? "'" + fileName + "'" : "\"" + fileName + "\"";
PsiElement newValue = PhpPsiElementFactory.createFromText(psiElement.getProject(), StringLiteralExpression.class, fileName);
if (newValue != null) {
element.replace(newValue);
}
}
};
}
}