package fr.adrienbrault.idea.symfony2plugin.dic.linemarker; import com.intellij.codeInsight.daemon.LineMarkerInfo; import com.intellij.codeInsight.daemon.LineMarkerProvider; import com.intellij.codeInsight.navigation.NavigationGutterIconBuilder; import com.intellij.patterns.XmlPatterns; import com.intellij.patterns.XmlTagPattern; import com.intellij.psi.PsiElement; import com.intellij.psi.xml.XmlTag; import fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent; import fr.adrienbrault.idea.symfony2plugin.config.xml.XmlHelper; import fr.adrienbrault.idea.symfony2plugin.dic.ContainerService; import fr.adrienbrault.idea.symfony2plugin.stubs.ServiceIndexUtil; import fr.adrienbrault.idea.symfony2plugin.util.dict.ServiceUtil; import org.apache.commons.lang.StringUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collection; import java.util.List; import java.util.Map; /** * @author Daniel Espendiller <daniel@espendiller.net> */ public class XmlLineMarkerProvider implements LineMarkerProvider { @Nullable private Map<String, Collection<ContainerService>> decoratedServiceCache; @Nullable @Override public LineMarkerInfo getLineMarkerInfo(@NotNull PsiElement psiElement) { return null; } @Override public void collectSlowLineMarkers(@NotNull List<PsiElement> psiElements, @NotNull Collection<LineMarkerInfo> result) { if(psiElements.size() == 0 || !Symfony2ProjectComponent.isEnabled(psiElements.get(0))) { return; } for (PsiElement psiElement : psiElements) { // <services><service id="foo"/></services> if(psiElement instanceof XmlTag && getServiceIdPattern().accepts(psiElement)) { visitServiceId((XmlTag) psiElement, result); } } decoratedServiceCache = null; } /** * <service id="foo"/> */ private void visitServiceId(@NotNull XmlTag xmlTag, @NotNull Collection<LineMarkerInfo> result) { String id = xmlTag.getAttributeValue("id"); if(StringUtils.isBlank(id)) { return; } // <service id="foo" decorates=foobar" /> String decorates = xmlTag.getAttributeValue("decorates"); if(StringUtils.isNotBlank(decorates)) { result.add(ServiceUtil.getLineMarkerForDecoratesServiceId(xmlTag, decorates, result)); } if(this.decoratedServiceCache == null) { this.decoratedServiceCache = ServiceIndexUtil.getDecoratedServices(xmlTag.getProject()); } NavigationGutterIconBuilder<PsiElement> lineMarker = ServiceUtil.getLineMarkerForDecoratedServiceId( xmlTag.getProject(), this.decoratedServiceCache, id ); if(lineMarker == null) { return; } result.add(lineMarker.createLineMarkerInfo(xmlTag)); } /** * <service id="%foo.class%"/> */ private static XmlTagPattern.Capture getServiceIdPattern() { return XmlPatterns.xmlTag().withName("service") .withChild(XmlPatterns.xmlAttribute().withName("id")).inside( XmlHelper.getInsideTagPattern("services") ).inFile(XmlHelper.getXmlFilePattern()); } }