package fr.adrienbrault.idea.symfony2plugin.routing;
import com.intellij.codeInsight.daemon.LineMarkerInfo;
import com.intellij.codeInsight.daemon.LineMarkerProvider;
import com.intellij.codeInsight.daemon.RelatedItemLineMarkerInfo;
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.PsiFile;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import fr.adrienbrault.idea.symfony2plugin.Symfony2Icons;
import fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent;
import fr.adrienbrault.idea.symfony2plugin.config.xml.XmlHelper;
import fr.adrienbrault.idea.symfony2plugin.util.resource.FileResourceUtil;
import org.apache.commons.lang.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.List;
/**
* @author Daniel Espendiller <daniel@espendiller.net>
*/
public class XmlLineMarkerProvider implements LineMarkerProvider {
@Override
public void collectSlowLineMarkers(@NotNull List<PsiElement> psiElements, @NotNull Collection<LineMarkerInfo> lineMarkerInfos) {
if(psiElements.size() == 0 || !Symfony2ProjectComponent.isEnabled(psiElements.get(0))) {
return;
}
for(PsiElement psiElement: psiElements) {
if(psiElement instanceof XmlTag) {
attachRouteActions((XmlTag) psiElement, lineMarkerInfos);
} else if(psiElement instanceof XmlFile) {
RelatedItemLineMarkerInfo<PsiElement> lineMarker = FileResourceUtil.getFileImplementsLineMarker((PsiFile) psiElement);
if(lineMarker != null) {
lineMarkerInfos.add(lineMarker);
}
}
}
}
private void attachRouteActions(XmlTag xmlTag, @NotNull Collection<LineMarkerInfo> lineMarkerInfos) {
if(!Pattern.getRouteTag().accepts(xmlTag)) {
return;
}
for(XmlTag subTag : xmlTag.getSubTags()) {
if("default".equalsIgnoreCase(subTag.getName())) {
XmlAttribute xmlAttr = subTag.getAttribute("key");
if(xmlAttr != null && "_controller".equals(xmlAttr.getValue())) {
String actionName = subTag.getValue().getTrimmedText();
if(StringUtils.isNotBlank(actionName)) {
PsiElement[] methods = RouteHelper.getMethodsOnControllerShortcut(xmlTag.getProject(), actionName);
if(methods.length > 0) {
NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder.create(Symfony2Icons.TWIG_CONTROLLER_LINE_MARKER).
setTargets(methods).
setTooltipText("Navigate to action");
lineMarkerInfos.add(builder.createLineMarkerInfo(xmlTag));
}
}
}
}
}
}
@Nullable
@Override
public LineMarkerInfo getLineMarkerInfo(@NotNull PsiElement psiElement) {
return null;
}
private static class Pattern {
public static XmlTagPattern.Capture getRouteTag() {
return XmlPatterns.xmlTag().withName("route").withParent(
XmlPatterns.xmlTag().withName("routes")
).inFile(XmlHelper.getXmlFilePattern());
}
}
}