package com.neueda.jetbrains.plugin.graphdb.jetbrains.component.linemarker; import com.intellij.codeInsight.daemon.LineMarkerInfo; import com.intellij.codeInsight.daemon.LineMarkerProvider; import com.intellij.icons.AllIcons; import com.intellij.ide.DataManager; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.ex.ActionUtil; import com.intellij.openapi.editor.markup.GutterIconRenderer; import com.intellij.psi.PsiElement; import com.neueda.jetbrains.plugin.graphdb.jetbrains.actions.execute.ExecuteQueryAction; import com.neueda.jetbrains.plugin.graphdb.language.cypher.util.PsiTraversalUtilities; import org.jetbrains.annotations.NotNull; import java.util.Collection; import java.util.List; import java.util.Optional; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import static java.util.Objects.*; public class CypherLineMarkerProvider implements LineMarkerProvider { /*** * Line marker cannot be set to CypherStatementItem as it triggers following warning: * "Performance warning: LineMarker is supposed to be registered for leaf elements only" */ private static PsiElement getFirstLeaf(@NotNull PsiElement element) { PsiElement e = element; while (e.getChildren().length > 0) { e = e.getFirstChild(); } return e; } @Override public LineMarkerInfo getLineMarkerInfo(@NotNull final PsiElement element) { PsiElement queryElement = PsiTraversalUtilities.Cypher.getCypherStatement(element); PsiElement lastQueryChild = isNull(queryElement) ? null : getFirstLeaf(queryElement); if (element == lastQueryChild) { return new LineMarkerInfo<PsiElement>(element, element.getTextRange(), AllIcons.Actions.Execute, element1 -> "Execute Query", (mouseEvent, psiElement) -> getDataContext().ifPresent(c -> ActionUtil.invokeAction(new ExecuteQueryAction(queryElement), c, "", mouseEvent, null)), GutterIconRenderer.Alignment.CENTER) { @Override public GutterIconRenderer createGutterRenderer() { return new LineMarkerGutterIconRenderer<PsiElement>(this) { @Override public AnAction getClickAction() { return new ExecuteQueryAction(queryElement); } @Override public boolean isNavigateAction() { return true; } }; } }; } return null; } private Optional<DataContext> getDataContext() { try { return Optional.ofNullable( DataManager.getInstance() .getDataContextFromFocusAsync() .blockingGet(100, TimeUnit.MILLISECONDS)); } catch (TimeoutException | ExecutionException e) { return Optional.empty(); } } @Override public void collectSlowLineMarkers(@NotNull List<PsiElement> elements, @NotNull Collection<LineMarkerInfo> result) { // Method intentionally left empty. } }