package fr.adrienbrault.idea.symfony2plugin.templating;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.Annotator;
import com.intellij.psi.PsiElement;
import fr.adrienbrault.idea.symfony2plugin.Settings;
import fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent;
import fr.adrienbrault.idea.symfony2plugin.TwigHelper;
import fr.adrienbrault.idea.symfony2plugin.asset.dic.AssetDirectoryReader;
import fr.adrienbrault.idea.symfony2plugin.asset.dic.AssetFile;
import fr.adrienbrault.idea.symfony2plugin.routing.PhpRoutingAnnotator;
import fr.adrienbrault.idea.symfony2plugin.templating.assets.TwigNamedAssetsServiceParser;
import fr.adrienbrault.idea.symfony2plugin.templating.util.TwigUtil;
import fr.adrienbrault.idea.symfony2plugin.util.service.ServiceXmlParserFactory;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import java.util.Set;
/**
* @author Daniel Espendiller <daniel@espendiller.net>
*/
public class TwigAnnotator implements Annotator {
@Override
public void annotate(@NotNull final PsiElement element, @NotNull AnnotationHolder holder) {
if(!Symfony2ProjectComponent.isEnabled(element.getProject())) {
return;
}
if(Settings.getInstance(element.getProject()).twigAnnotateRoute) {
this.annotateRoute(element, holder);
}
if(Settings.getInstance(element.getProject()).twigAnnotateAsset) {
this.annotateAsset(element, holder);
}
if(Settings.getInstance(element.getProject()).twigAnnotateAssetTags) {
this.annotateAssetsTag(element, holder);
}
if(Settings.getInstance(element.getProject()).twigAnnotateTemplate) {
this.annotateTemplate(element, holder);
}
}
private void annotateRoute(@NotNull final PsiElement element, @NotNull AnnotationHolder holder) {
if(!TwigHelper.getAutocompletableRoutePattern().accepts(element)) {
return;
}
String text = element.getText();
if(StringUtils.isBlank(text) || fr.adrienbrault.idea.symfony2plugin.util.StringUtils.isInterpolatedString(text)) {
return;
}
PhpRoutingAnnotator.annotateRouteName(element, holder, text);
}
private void annotateTemplate(@NotNull final PsiElement element, @NotNull AnnotationHolder holder) {
if(!(TwigHelper.getTemplateFileReferenceTagPattern().accepts(element) || TwigHelper.getPrintBlockFunctionPattern("include", "source").accepts(element)) || !TwigUtil.isValidTemplateString(element)) {
return;
}
String templateName = element.getText();
PsiElement[] psiElements = TwigHelper.getTemplatePsiElements(element.getProject(), templateName);
if(psiElements.length > 0) {
return;
}
holder.createWarningAnnotation(element, "Missing Template");
holder.createWarningAnnotation(element, "Create Template")
.registerFix(new PhpTemplateAnnotator.CreateTemplateFix(templateName));
}
private void annotateAsset(@NotNull final PsiElement element, @NotNull AnnotationHolder holder) {
if(!TwigHelper.getAutocompletableAssetPattern().accepts(element)) {
return;
}
for (final AssetFile assetFile : new AssetDirectoryReader().setProject(element.getProject()).getAssetFiles()) {
if(assetFile.toString().equals(element.getText())) {
return;
}
}
holder.createWarningAnnotation(element, "Missing asset");
}
private void annotateAssetsTag(@NotNull final PsiElement element, @NotNull AnnotationHolder holder) {
if(TwigHelper.getAutocompletableAssetTag("stylesheets").accepts(element)) {
String templateName = element.getText();
if (isKnownAssetFileOrFolder(element, templateName, TwigHelper.CSS_FILES_EXTENSIONS)) {
return;
}
holder.createWarningAnnotation(element, "Missing asset");
}
if(TwigHelper.getAutocompletableAssetTag("javascripts").accepts(element)) {
String templateName = element.getText();
if (isKnownAssetFileOrFolder(element, templateName, TwigHelper.JS_FILES_EXTENSIONS)) {
return;
}
holder.createWarningAnnotation(element, "Missing asset");
}
}
private boolean isKnownAssetFileOrFolder(PsiElement element, String templateName, String... fileTypes) {
// custom assets
if(templateName.startsWith("@") && templateName.length() > 1) {
TwigNamedAssetsServiceParser twigPathServiceParser = ServiceXmlParserFactory.getInstance(element.getProject(), TwigNamedAssetsServiceParser.class);
Set<String> strings = twigPathServiceParser.getNamedAssets().keySet();
if(strings.contains(templateName.substring(1))) {
return true;
}
}
return TwigHelper.resolveAssetsFiles(element.getProject(), templateName, fileTypes).size() > 0;
}
}