package fr.adrienbrault.idea.symfony2plugin.dic;
import com.intellij.codeInsight.daemon.LineMarkerInfo;
import com.intellij.codeInsight.daemon.LineMarkerProvider;
import com.intellij.codeInsight.navigation.NavigationGutterIconBuilder;
import com.intellij.navigation.GotoRelatedItem;
import com.intellij.openapi.editor.markup.GutterIconRenderer;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.psi.PsiElement;
import com.intellij.util.ConstantFunction;
import com.jetbrains.php.lang.psi.elements.Method;
import fr.adrienbrault.idea.symfony2plugin.Symfony2Icons;
import fr.adrienbrault.idea.symfony2plugin.Symfony2ProjectComponent;
import fr.adrienbrault.idea.symfony2plugin.extension.ControllerActionGotoRelatedCollector;
import fr.adrienbrault.idea.symfony2plugin.extension.ControllerActionGotoRelatedCollectorParameter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* @author Daniel Espendiller <daniel@espendiller.net>
*/
public class ControllerMethodLineMarkerProvider implements LineMarkerProvider {
private static final ExtensionPointName<ControllerActionGotoRelatedCollector> EP_NAME = new ExtensionPointName<>("fr.adrienbrault.idea.symfony2plugin.extension.ControllerActionGotoRelatedCollector");
@Nullable
@Override
public LineMarkerInfo getLineMarkerInfo(@NotNull PsiElement psiElement) {
return null;
}
@Nullable
public LineMarkerInfo collect(PsiElement psiElement) {
if(!Symfony2ProjectComponent.isEnabled(psiElement)) {
return null;
}
if(!(psiElement instanceof Method) || !((Method) psiElement).getAccess().isPublic()) {
return null;
}
String methodName = ((Method) psiElement).getName();
if(!methodName.endsWith("Action")) {
return null;
}
List<GotoRelatedItem> gotoRelatedItems = getGotoRelatedItems((Method) psiElement);
if(gotoRelatedItems.size() == 0) {
return null;
}
// only one item dont need popover
if(gotoRelatedItems.size() == 1) {
GotoRelatedItem gotoRelatedItem = gotoRelatedItems.get(0);
// hell: find any possible small icon
Icon icon = null;
if(gotoRelatedItem instanceof RelatedPopupGotoLineMarker.PopupGotoRelatedItem) {
icon = ((RelatedPopupGotoLineMarker.PopupGotoRelatedItem) gotoRelatedItem).getSmallIcon();
}
if(icon == null) {
icon = Symfony2Icons.SYMFONY_LINE_MARKER;
}
NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder.create(icon).
setTargets(gotoRelatedItems.get(0).getElement());
String customName = gotoRelatedItems.get(0).getCustomName();
if(customName != null) {
builder.setTooltipText(customName);
}
return builder.createLineMarkerInfo(psiElement);
}
return new LineMarkerInfo<>(
psiElement,
psiElement.getTextRange(),
Symfony2Icons.SYMFONY_LINE_MARKER,
6,
new ConstantFunction<>("Related Files"),
new RelatedPopupGotoLineMarker.NavigationHandler(gotoRelatedItems),
GutterIconRenderer.Alignment.RIGHT
);
}
public static List<GotoRelatedItem> getGotoRelatedItems(Method method) {
List<GotoRelatedItem> gotoRelatedItems = new ArrayList<>();
ControllerActionGotoRelatedCollectorParameter parameter = new ControllerActionGotoRelatedCollectorParameter(method, gotoRelatedItems);
for(ControllerActionGotoRelatedCollector extension : EP_NAME.getExtensions()) {
extension.collectGotoRelatedItems(parameter);
}
return gotoRelatedItems;
}
@Override
public void collectSlowLineMarkers(@NotNull List<PsiElement> psiElements, @NotNull Collection<LineMarkerInfo> results) {
for(PsiElement psiElement: psiElements) {
LineMarkerInfo lineMarkerInfo = collect(psiElement);
if(lineMarkerInfo != null) {
results.add(lineMarkerInfo);
}
}
}
}