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; } }