package fr.adrienbrault.idea.symfony2plugin.templating;
import com.intellij.codeInsight.hint.HintManager;
import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.Annotator;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.util.IncorrectOperationException;
import com.jetbrains.php.lang.psi.elements.MethodReference;
import com.jetbrains.twig.TwigFileType;
import fr.adrienbrault.idea.symfony2plugin.Settings;
import fr.adrienbrault.idea.symfony2plugin.Symfony2InterfacesUtil;
import fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent;
import fr.adrienbrault.idea.symfony2plugin.TwigHelper;
import fr.adrienbrault.idea.symfony2plugin.templating.ui.TemplateCreationSelectionDialog;
import fr.adrienbrault.idea.symfony2plugin.templating.util.TwigUtil;
import fr.adrienbrault.idea.symfony2plugin.util.IdeHelper;
import fr.adrienbrault.idea.symfony2plugin.util.ParameterBag;
import fr.adrienbrault.idea.symfony2plugin.util.PsiElementUtils;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
/**
* @author Daniel Espendiller <daniel@espendiller.net>
*/
public class PhpTemplateAnnotator implements Annotator {
@Override
public void annotate(@NotNull final PsiElement element, @NotNull AnnotationHolder holder) {
if(!Symfony2ProjectComponent.isEnabled(element.getProject()) || !Settings.getInstance(element.getProject()).phpAnnotateTemplate) {
return;
}
MethodReference methodReference = PsiElementUtils.getMethodReferenceWithFirstStringParameter(element);
if (methodReference == null || !new Symfony2InterfacesUtil().isTemplatingRenderCall(methodReference)) {
return;
}
ParameterBag parameterBag = PsiElementUtils.getCurrentParameterIndex(element.getParent());
if(parameterBag == null || parameterBag.getIndex() != 0) {
return;
}
String templateName = Symfony2InterfacesUtil.getFirstArgumentStringValue(methodReference);
if(templateName == null || StringUtils.isBlank(templateName)) {
return;
}
if(TwigHelper.getTemplatePsiElements(element.getProject(), templateName).length > 0) {
return;
}
holder.createWarningAnnotation(element, "Missing Template");
holder.createWarningAnnotation(element, "Create Template")
.registerFix(new CreateTemplateFix(templateName));
}
public static class CreateTemplateFix extends BaseIntentionAction {
private String templateName;
public CreateTemplateFix(String templateName) {
this.templateName = templateName;
}
@NotNull
@Override
public String getText() {
return "Create template";
}
@NotNull
@Override
public String getFamilyName() {
return "Symfony";
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
return true;
}
@Override
public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
Collection<String> templatePaths = TwigUtil.getCreateAbleTemplatePaths(project, templateName);
if(templatePaths.size() == 0) {
HintManager.getInstance().showErrorHint(editor, "Can not find a target dir");
return;
}
if(templatePaths.size() == 1) {
createFile(templatePaths.iterator().next());
return;
}
TemplateCreationSelectionDialog.create(editor, templatePaths, this::createFile);
}
private void createFile(@NotNull String relativePath) {
VirtualFile relativeBlockScopeFile = null;
int i = relativePath.lastIndexOf("/");
if(i > 0) {
relativeBlockScopeFile = VfsUtil.findRelativeFile(project.getBaseDir(), relativePath.substring(0, i).split("/"));
}
String content = TwigUtil.buildStringFromTwigCreateContainer(project, relativeBlockScopeFile);
IdeHelper.RunnableCreateAndOpenFile runnableCreateAndOpenFile = IdeHelper.getRunnableCreateAndOpenFile(project, TwigFileType.INSTANCE, project.getBaseDir(), relativePath);
if(content != null) {
runnableCreateAndOpenFile.setContent(content);
}
ApplicationManager.getApplication().runWriteAction(runnableCreateAndOpenFile);
}
});
}
}
}