com.intellij.psi.impl.source.tree.java.PsiJavaTokenImpl#com.intellij.codeInsight.navigation.NavigationGutterIconBuilder源码实例Demo

下面列出了com.intellij.psi.impl.source.tree.java.PsiJavaTokenImpl#com.intellij.codeInsight.navigation.NavigationGutterIconBuilder 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。


private void extractRelatedExpressions(@Nullable PsiElement element, @NotNull Collection<? super RelatedItemLineMarkerInfo<?>> result,
                                       @NotNull FileBase containingFile) {
    if (element == null) {
        return;
    }

    FileBase psiRelatedFile = PsiFinder.getInstance(containingFile.getProject()).findRelatedFile(containingFile);
    if (psiRelatedFile != null) {
        Collection<PsiNameIdentifierOwner> expressions = psiRelatedFile.getExpressions(element.getText());
        if (expressions.size() == 1) {
            PsiNameIdentifierOwner relatedElement = expressions.iterator().next();
            PsiElement nameIdentifier = relatedElement.getNameIdentifier();
            if (nameIdentifier != null) {
                String tooltip = GutterIconTooltipHelper
                        .composeText(new PsiElement[]{psiRelatedFile}, "", "Implements method <b>" + nameIdentifier.getText() + "</b> in <b>{0}</b>");
                result.add(NavigationGutterIconBuilder.
                        create(containingFile.isInterface() ? ORIcons.IMPLEMENTED : ORIcons.IMPLEMENTING).
                        setTooltipText(tooltip).
                        setAlignment(GutterIconRenderer.Alignment.RIGHT).
                        setTargets(Collections.singleton(nameIdentifier instanceof PsiLowerSymbol ? nameIdentifier.getFirstChild() : nameIdentifier)).
                        createLineMarkerInfo(element));
            }
        }
    }
}
 

@Override
protected void collectNavigationMarkers(@NotNull PsiElement element, @NotNull Collection<? super RelatedItemLineMarkerInfo> result) {
    if (!PlatformPatterns.psiElement(PhpTokenTypes.IDENTIFIER).withParent(PlatformPatterns.psiElement(Method.class).withName(PlatformPatterns.string().endsWith("Action"))).accepts(element)) {
        return;
    }

    Collection<FluidFile> possibleMatchedTemplates = FluidUtil.findTemplatesForControllerAction((Method) element.getParent());
    if (possibleMatchedTemplates.size() > 0) {
        result.add(
            NavigationGutterIconBuilder
                .create(FluidIcons.TEMPLATE_LINE_MARKER)
                .setTargets(possibleMatchedTemplates)
                .setTooltipText("Navigate to template")
                .createLineMarkerInfo(element)
        );
    }
}
 

@Override
protected void collectNavigationMarkers(@NotNull PsiElement element, @NotNull Collection<? super RelatedItemLineMarkerInfo> result) {
    if (!PlatformPatterns.psiElement(FluidFile.class).accepts(element)) {
        return;
    }

    Collection<Method> possibleMethodTargetsForControllerAction = FluidUtil.findPossibleMethodTargetsForControllerAction(
        element.getProject(),
        FluidUtil.inferControllerNameFromTemplateFile((FluidFile) element),
        FluidUtil.inferActionNameFromTemplateFile((FluidFile) element)
    );

    if (possibleMethodTargetsForControllerAction.size() > 0) {
        result.add(
            NavigationGutterIconBuilder
                .create(PhpIcons.METHOD)
                .setTargets(possibleMethodTargetsForControllerAction)
                .setTooltipText("Navigate to controller action")
                .createLineMarkerInfo(element)
        );
    }
}
 

@Override
public void collectSlowLineMarkers(@NotNull List<PsiElement> elements, @NotNull Collection<LineMarkerInfo> result) {
    for (PsiElement el : elements) {
        if (!(el instanceof FusionType)
                || !(el.getParent() instanceof FusionPrototypeSignature)
                || (((FusionPrototypeSignature) el.getParent()).isInheritedInDefinition())
                || (el.getParent().getParent().getParent() instanceof FusionPropertyDeletion)) {
            continue;
        }

        FusionType type = (FusionType) el;
        Collection<PsiElement> targets = ResolveEngine.getNodeTypeDefinitions(el.getProject(), type);
        if (!targets.isEmpty()) {
            RelatedItemLineMarkerInfo info = NavigationGutterIconBuilder
                    .create(NeosIcons.NODE_TYPE)
                    .setTargets(targets)
                    .setTooltipText("Go to node type definition")
                    .createLineMarkerInfo(el);
            result.add(info);
        }
    }
}
 

@Override
public void collectSlowLineMarkers(@NotNull List<PsiElement> elements, @NotNull Collection<LineMarkerInfo> result) {
    for (PsiElement el : elements) {
        if (el instanceof Method && ((Method) el).getAccess().isPublic()) {
            VirtualFile template = ResolveEngine.findTemplate((Method) el);
            if (template != null) {
                PsiFile target = PsiManager.getInstance(el.getProject()).findFile(template);
                RelatedItemLineMarkerInfo info = NavigationGutterIconBuilder
                        .create(NeosIcons.NODE_TYPE)
                        .setTarget(target)
                        .setTooltipText("Go to template")
                        .createLineMarkerInfo(el);
                result.add(info);
            }
        }
    }
}
 

private void classNameMarker(PhpClass currentClass, Collection<? super RelatedItemLineMarkerInfo> result, Project project) {
    Collection<PhpClass> target;
    String tooltip;

    if (Utils.isClassAtoumTest(currentClass)) {
        target = Utils.locateTestedClasses(project, currentClass);
        tooltip = "Navigate to tested class";
    } else {
        target = Utils.locateTestClasses(project, currentClass);
        tooltip = "Navigate to test";
    }

    if (target.size() == 0) {
        return;
    }

    NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder.create(Icons.ATOUM).
            setTargets(target).
            setTooltipText(tooltip);
    result.add(builder.createLineMarkerInfo(currentClass));
}
 

private void attachControllerAction(PsiElement sourceElement, Collection<LineMarkerInfo> lineMarkerInfos) {

        if(!ShopwareProjectComponent.isValidForProject(sourceElement)) {
            return;
        }

        String text = PsiElementUtils.trimQuote(sourceElement.getText());
        if(text.startsWith("{") && text.endsWith("}")) {

            List<PsiElement> controllerTargets = ExtJsUtil.getControllerTargets(sourceElement, text);
            if(controllerTargets.size() > 0) {
                NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder.create(ShopwarePluginIcons.SHOPWARE_LINEMARKER).
                    setTargets(controllerTargets).
                    setTooltipText("Navigate to action");

                lineMarkerInfos.add(builder.createLineMarkerInfo(sourceElement));
            }
        }

    }
 

public void attachTemplateBlocks(PsiElement psiElement, Collection<LineMarkerInfo> lineMarkerInfos) {

        SmartyBlockGoToHandler goToHandler = new SmartyBlockGoToHandler();
        PsiElement[] gotoDeclarationTargets = goToHandler.getGotoDeclarationTargets(psiElement, 0, null);

        if(gotoDeclarationTargets == null || gotoDeclarationTargets.length == 0) {
            return;
        }

        List<PsiElement> psiElements = Arrays.asList(gotoDeclarationTargets);
        if(psiElements.size() == 0) {
            return;
        }

        NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder.create(PhpIcons.OVERRIDES).
            setTargets(psiElements).
            setTooltipText("Navigate to block");

        lineMarkerInfos.add(builder.createLineMarkerInfo(psiElement));

    }
 

public static RelatedItemLineMarkerInfo<PsiElement> getSingleLineMarker(SmartyFile smartyFile, Collection<LineMarkerInfo> lineMarkerInfos, GotoRelatedItem gotoRelatedItem) {

        // hell: find any possible small icon
        Icon icon = null;
        if(gotoRelatedItem instanceof RelatedPopupGotoLineMarker.PopupGotoRelatedItem) {
            icon = ((RelatedPopupGotoLineMarker.PopupGotoRelatedItem) gotoRelatedItem).getSmallIcon();
        }

        if(icon == null) {
            icon = ShopwarePluginIcons.SHOPWARE_LINEMARKER;
        }

        NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder.create(icon).
            setTargets(gotoRelatedItem.getElement());

        String customName = gotoRelatedItem.getCustomName();
        if(customName != null) {
            builder.setTooltipText(customName);
        }

        return builder.createLineMarkerInfo(smartyFile);
    }
 

@Override
protected void collectNavigationMarkers( @NotNull PsiElement element,
                                         @NotNull Collection< ? super RelatedItemLineMarkerInfo > result ) {
  // This must be an element with a literal expression as a parent
  if ( !(element instanceof PsiJavaTokenImpl) || !(element.getParent() instanceof PsiLiteralExpression) ) return;
  
  // The literal expression must start with the Simple language literal expression
  PsiLiteralExpression literalExpression = (PsiLiteralExpression) element.getParent();
  String value = literalExpression.getValue() instanceof String ? (String) literalExpression.getValue() : null;
  if ( ( value == null ) || !value.startsWith( SimpleAnnotator.SIMPLE_PREFIX_STR + SimpleAnnotator.SIMPLE_SEPARATOR_STR ) ) return;

  // Get the Simple language property usage
  Project project = element.getProject();
  String possibleProperties = value.substring( SimpleAnnotator.SIMPLE_PREFIX_STR.length()+ SimpleAnnotator.SIMPLE_SEPARATOR_STR.length() );
  final List<SimpleProperty> properties = SimpleUtil.findProperties( project, possibleProperties );
  if ( properties.size() > 0 ) {
    // Add the property to a collection of line marker info
    NavigationGutterIconBuilder< PsiElement > builder =
          NavigationGutterIconBuilder.create( SimpleIcons.FILE )
                                     .setTargets( properties )
                                     .setTooltipText( "Navigate to Simple language property" );
    result.add( builder.createLineMarkerInfo( element ) );
  }
}
 

@Override
protected void collectNavigationMarkers(@NotNull PsiElement element,
                        Collection<? super RelatedItemLineMarkerInfo> result) {
    if (false && element instanceof PsiNamedElement) {
        PsiNamedElement namedElement = (PsiNamedElement) element;
        String value = namedElement.getName();
        if (value != null) {
            Project project = element.getProject();
            final List<HaskellUtil.FoundDefinition> found =
                    HaskellUtil.findDefinitionNode(project, value, namedElement);
            final List<PsiNamedElement> namedNodes = ContainerUtil.newArrayList();
            for (HaskellUtil.FoundDefinition fd : found) {
                namedNodes.add(fd.element);
            }

            if (namedNodes.size() > 0) {
                NavigationGutterIconBuilder<PsiElement> builder =
                        NavigationGutterIconBuilder.create(HaskellIcons.FILE).
                                setTargets(namedNodes).
                                setTooltipText("Navigate to element definition");
                result.add(builder.createLineMarkerInfo(element));
            }
        }
    }
}
 

private void attachLineIcon(@NotNull AndroidView view, @NotNull PsiElement psiElement, @NotNull Collection<LineMarkerInfo> result) {

        JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(psiElement.getProject());
        PsiClass psiClass = psiFacade.findClass(view.getName(), GlobalSearchScope.allScope(psiElement.getProject()));
        if(psiClass == null) {
            return;
        }

        Icon icon = AndroidViewUtil.getCoreIconWithExtends(view, psiClass);
        if(icon == null) {
            icon = AndroidIcons.Views.View;
        }

        NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder.create(icon).
            setTooltipText(view.getName()).
            setTargets(view.getXmlTarget());

        result.add(builder.createLineMarkerInfo(psiElement));
    }
 

private void attachXmlRelationMarker(@NotNull PsiElement target, @NotNull XmlAttributeValue psiElement, @NotNull Collection<LineMarkerInfo> results) {
    String value = psiElement.getValue();
    if(StringUtils.isBlank(value)) {
        return;
    }

    Collection<PhpClass> classesInterface = DoctrineMetadataUtil.getClassInsideScope(psiElement, value);
    if(classesInterface.size() == 0) {
        return;
    }

    NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder.create(Symfony2Icons.DOCTRINE_LINE_MARKER).
        setTargets(classesInterface).
        setTooltipText("Navigate to class");

    results.add(builder.createLineMarkerInfo(target));
}
 

private void attachRouteActions(@NotNull PsiElement psiElement, @NotNull Collection<LineMarkerInfo> lineMarkerInfos) {
    PsiElement xmlTag = psiElement.getParent();
    if(!(xmlTag instanceof XmlTag) || !Pattern.getRouteTag().accepts(xmlTag)) {
        return;
    }

    String controller = RouteHelper.getXmlController((XmlTag) xmlTag);
    if(controller != null) {
        PsiElement[] methods = RouteHelper.getMethodsOnControllerShortcut(xmlTag.getProject(), controller);
        if(methods.length > 0) {
            NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder.create(Symfony2Icons.TWIG_CONTROLLER_LINE_MARKER).
                setTargets(methods).
                setTooltipText("Navigate to action");

            lineMarkerInfos.add(builder.createLineMarkerInfo(psiElement));
        }
    }
}
 

/**
 * Find controller definition in yaml structor
 *
 * foo:
 *   defaults: { _controller: "Bundle:Foo:Bar" }
 *   controller: "Bundle:Foo:Bar"
 */
private void attachRouteActions(@NotNull Collection<LineMarkerInfo> lineMarkerInfos, @NotNull PsiElement psiElement) {
    if(psiElement.getNode().getElementType() != YAMLTokenTypes.SCALAR_KEY) {
        return;
    }

    PsiElement yamlKeyValue = psiElement.getParent();
    if(!(yamlKeyValue instanceof YAMLKeyValue)) {
        return;
    }

    String yamlController = RouteHelper.getYamlController((YAMLKeyValue) yamlKeyValue);
    if(yamlController != null) {
        PsiElement[] methods = RouteHelper.getMethodsOnControllerShortcut(psiElement.getProject(), yamlController);
        if(methods.length > 0) {
            NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder.create(Symfony2Icons.TWIG_CONTROLLER_LINE_MARKER).
                setTargets(methods).
                setTooltipText("Navigate to action");

            lineMarkerInfos.add(builder.createLineMarkerInfo(psiElement));
        }
    }
}
 

/**
 * Constraints in same namespace and validateBy service name
 */
private void validatorClassMarker(PsiElement psiElement, Collection<LineMarkerInfo> results) {
    PsiElement phpClassContext = psiElement.getContext();
    if(!(phpClassContext instanceof PhpClass) || !PhpElementsUtil.isInstanceOf((PhpClass) phpClassContext, "\\Symfony\\Component\\Validator\\Constraint")) {
        return;
    }

    // class in same namespace
    String className = ((PhpClass) phpClassContext).getFQN() + "Validator";
    Collection<PhpClass> phpClasses = new ArrayList<>(PhpElementsUtil.getClassesInterface(psiElement.getProject(), className));

    // @TODO: validateBy alias

    if(phpClasses.size() == 0) {
        return;
    }

    NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder.create(Symfony2Icons.SYMFONY_LINE_MARKER).
        setTargets(phpClasses).
        setTooltipText("Navigate to validator");

    results.add(builder.createLineMarkerInfo(psiElement));
}
 

/**
 * "FooValidator" back to "Foo" constraint
 */
private void constraintValidatorClassMarker(PsiElement psiElement, Collection<LineMarkerInfo> results) {
    PsiElement phpClass = psiElement.getContext();
    if(!(phpClass instanceof PhpClass) || !PhpElementsUtil.isInstanceOf((PhpClass) phpClass, "Symfony\\Component\\Validator\\ConstraintValidatorInterface")) {
        return;
    }

    String fqn = ((PhpClass) phpClass).getFQN();
    if(!fqn.endsWith("Validator")) {
        return;
    }

    Collection<PhpClass> phpClasses = new ArrayList<>(
        PhpElementsUtil.getClassesInterface(psiElement.getProject(), fqn.substring(0, fqn.length() - "Validator".length()))
    );

    if(phpClasses.size() == 0) {
        return;
    }

    NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder.create(Symfony2Icons.SYMFONY_LINE_MARKER).
        setTargets(phpClasses).
        setTooltipText("Navigate to constraint");

    results.add(builder.createLineMarkerInfo(psiElement));
}
 

private void visitRootElements(@NotNull Collection<LineMarkerInfo> result, @NotNull PsiElement psiElement, @NotNull LazyConfigTreeSignatures function) {
    PsiElement parent = psiElement.getParent();
    if(!(parent instanceof YAMLKeyValue)) {
        return;
    }

    String keyText = ((YAMLKeyValue) parent).getKeyText();
    Map<String, Collection<String>> treeSignatures = function.value();
    if(!treeSignatures.containsKey(keyText)) {
        return;
    }

    NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder.create(Symfony2Icons.SYMFONY_LINE_MARKER)
        .setTargets(new MyClassIdLazyValue(psiElement.getProject(), treeSignatures.get(keyText), keyText))
        .setTooltipText("Navigate to configuration");

    result.add(builder.createLineMarkerInfo(psiElement));
}
 

@Nullable
public static RelatedItemLineMarkerInfo<PsiElement> getFileImplementsLineMarker(@NotNull PsiFile psiFile) {
    final Project project = psiFile.getProject();

    VirtualFile virtualFile = psiFile.getVirtualFile();
    if(virtualFile == null) {
        return null;
    }

    String bundleLocateName = FileResourceUtil.getBundleLocateName(project, virtualFile);
    if(bundleLocateName == null) {
        return null;
    }

    if(FileResourceUtil.getFileResourceRefers(project, bundleLocateName).size() == 0) {
        return null;
    }

    NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder.create(PhpIcons.IMPLEMENTS).
        setTargets(new FileResourceUtil.FileResourceNotNullLazyValue(project, bundleLocateName)).
        setTooltipText("Navigate to resource");

    return builder.createLineMarkerInfo(psiFile);
}
 

@Override
protected void collectNavigationMarkers(@NotNull PsiElement element, @NotNull Collection<? super RelatedItemLineMarkerInfo> result) {
    PsiElement parent = element.getParent();
    FileBase containingFile = (FileBase) element.getContainingFile();

    if (element instanceof PsiTypeConstrName) {
        FileBase psiRelatedFile = PsiFinder.getInstance(containingFile.getProject()).findRelatedFile(containingFile);
        if (psiRelatedFile != null) {
            Collection<PsiType> expressions = psiRelatedFile.getExpressions(element.getText(), PsiType.class);
            if (expressions.size() == 1) {
                PsiType relatedType = expressions.iterator().next();
                PsiElement symbol = PsiTreeUtil.findChildOfType(element, PsiLowerSymbol.class);
                PsiElement relatedSymbol = PsiTreeUtil.findChildOfType(relatedType, PsiLowerSymbol.class);
                if (symbol != null && relatedSymbol != null) {
                    result.add(NavigationGutterIconBuilder.
                            create(containingFile.isInterface() ? ORIcons.IMPLEMENTED : ORIcons.IMPLEMENTING).
                            setAlignment(GutterIconRenderer.Alignment.RIGHT).
                            setTargets(Collections.singleton(relatedSymbol.getFirstChild())).
                            createLineMarkerInfo(symbol.getFirstChild()));
                }
            }
        }
    } else if (element instanceof PsiLowerSymbol && parent instanceof PsiLet && ((PsiNameIdentifierOwner) parent).getNameIdentifier() == element) {
        extractRelatedExpressions(element.getFirstChild(), result, containingFile);
    } else if (element instanceof PsiLowerSymbol && parent instanceof PsiVal && ((PsiNameIdentifierOwner) parent).getNameIdentifier() == element) {
        extractRelatedExpressions(element.getFirstChild(), result, containingFile);
    } else if (element instanceof PsiLowerSymbol && parent instanceof PsiExternal && ((PsiNameIdentifierOwner) parent).getNameIdentifier() == element) {
        extractRelatedExpressions(element.getFirstChild(), result, containingFile);
    } else if (element instanceof PsiUpperSymbol && parent instanceof PsiInnerModule && ((PsiNameIdentifierOwner) parent).getNameIdentifier() == element) {
        extractRelatedExpressions(element.getFirstChild(), result, containingFile);
    } else if (element instanceof PsiUpperSymbol && parent instanceof PsiException && ((PsiNameIdentifierOwner) parent).getNameIdentifier() == element) {
        extractRelatedExpressions(element.getFirstChild(), result, containingFile);
    }
}
 

@Override
protected void collectNavigationMarkers(@NotNull PsiElement element, @NotNull Collection<? super RelatedItemLineMarkerInfo> result) {
    if (!TYPO3CMSProjectSettings.isEnabled(element)) {
        return;
    }

    if (!getPositionPattern().accepts(element)) {
        return;
    }

    StringLiteralExpression literalExpression = (StringLiteralExpression) element.getParent();
    String value = literalExpression.getContents();

    if (value.isEmpty()) {
        return;
    }

    PsiElement methodReference = PsiTreeUtil.getParentOfType(element, MethodReference.class);
    if (PhpElementsUtil.isMethodWithFirstStringOrFieldReference(methodReference, "getAjaxUrl") || PhpElementsUtil.isMethodWithFirstStringOrFieldReference(methodReference, "buildUriFromRoute")) {

        if (RouteIndex.hasRoute(element.getProject(), value)) {
            Collection<RouteStub> routes = RouteIndex.getRoute(element.getProject(), value);
            routes.forEach(def -> {
                PsiElement[] routeDefinitionElements = RouteHelper.getRouteDefinitionElements(element.getProject(), value);
                NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder
                    .create(TYPO3CMSIcons.ROUTE_ICON)
                    .setTargets(routeDefinitionElements);

                if (def.getPath() != null) {
                    builder.setTooltipTitle("Path: " + def.getPath());
                }

                result.add(builder.createLineMarkerInfo(element));
            });

        }
    }
}
 

@Override
public void collectSlowLineMarkers(@NotNull List<PsiElement> elements, @NotNull Collection<LineMarkerInfo> result) {
    for (PsiElement el : elements) {
        if (!NeosProjectService.isEnabled(el)) {
            return;
        }

        if (!el.getContainingFile().getVirtualFile().getName().startsWith("NodeTypes.")) {
            continue;
        }

        if (!(el instanceof YAMLKeyValue)) {
            continue;
        }

        YAMLMapping parentMapping = ((YAMLKeyValue) el).getParentMapping();
        if (parentMapping != null && parentMapping.getParent() instanceof YAMLDocument) {
            String nodeType = ((YAMLKeyValue) el).getKeyText();
            String[] nodeTypeSplit = nodeType.split(":");

            if (nodeTypeSplit.length < 2) {
                continue;
            }

            List<PsiElement> targets = ResolveEngine.getPrototypeDefinitions(el.getProject(), nodeTypeSplit[1], nodeTypeSplit[0]);
            if (!targets.isEmpty()) {
                RelatedItemLineMarkerInfo info = NavigationGutterIconBuilder
                        .create(FusionIcons.PROTOTYPE)
                        .setTargets(targets)
                        .setTooltipText("Go to Fusion prototype")
                        .createLineMarkerInfo(el);
                result.add(info);
            }
        }
    }
}
 

private void attachDefineTargets(PsiElement psiElement, Collection<LineMarkerInfo> lineMarkerInfos, boolean attachController) {
    if(!ShopwareProjectComponent.isValidForProject(psiElement)) {
        return;
    }

    String text = PsiElementUtils.trimQuote(psiElement.getText());
    if(!text.startsWith("Shopware.apps.")) {
        return;
    }

    String[] namespaces = StringUtils.split(text, ".");
    if(namespaces.length < 3) {
        return;
    }

    List<PsiElement> psiElementList = new ArrayList<>();

    if(attachController) {
        attachController(psiElement.getProject(), namespaces, psiElementList);
    }

    attachModels(psiElement.getProject(), namespaces, psiElementList);

    if(psiElementList.size() == 0) {
        return;
    }

    NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder.create(ShopwarePluginIcons.SHOPWARE_LINEMARKER).
        setTargets(psiElementList).
        setTooltipText("Navigate");

    lineMarkerInfos.add(builder.createLineMarkerInfo(psiElement));
}
 

private void collectSubscriberTargets(@NotNull List<PsiElement> psiElements, final @NotNull Collection<LineMarkerInfo> lineMarkerInfos) {
    Collection<PhpClass> phpClasses = new ArrayList<>();

    for (PsiElement psiElement : psiElements) {
        if(psiElement instanceof PhpClass && PhpElementsUtil.isInstanceOf((PhpClass) psiElement, "Enlight\\Event\\SubscriberInterface")) {
            phpClasses.add((PhpClass) psiElement);
        }
    }

    for (PhpClass phpClass : phpClasses) {
        Method getSubscribedEvents = phpClass.findOwnMethodByName("getSubscribedEvents");
        if(getSubscribedEvents == null) {
            continue;
        }

        Map<String, Pair<String, PsiElement>> methodEvent = new HashMap<>();

        HookSubscriberUtil.visitSubscriberEvents(getSubscribedEvents, (event, methodName, key) ->
            methodEvent.put(methodName, Pair.create(event, key))
        );

        for (Method method : phpClass.getOwnMethods()) {
            if(!methodEvent.containsKey(method.getName()) || !method.getAccess().isPublic()) {
                continue;
            }

            Pair<String, PsiElement> result = methodEvent.get(method.getName());
            NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder.create(ShopwarePluginIcons.SHOPWARE_LINEMARKER).
                setTargets(new MyCollectionNotNullLazyValue(result.getSecond(), result.getFirst())).
                setTooltipText("Related Targets");

            // attach linemarker to leaf item which is our function name for performance reasons
            ASTNode node = method.getNode().findChildByType(PhpTokenTypes.IDENTIFIER);
            if(node != null) {
                lineMarkerInfos.add(builder.createLineMarkerInfo(node.getPsi()));
            }
        }
    }
}
 

@Override
public void collectSlowLineMarkers(@NotNull List<PsiElement> elements, @NotNull Collection<LineMarkerInfo> result) {
    for(PsiElement psiElement : elements) {

        if(psiElement instanceof PsiMethodCallExpression) {
            PsiMethod psiMethod = ((PsiCallExpression) psiElement).resolveMethod();
            if(psiMethod != null && ("inflate".equals(psiMethod.getName()) || "setContentView".equals(psiMethod.getName()))) {
                PsiExpressionList psiExpressionList = ((PsiCallExpression) psiElement).getArgumentList();
                if(psiExpressionList != null) {
                    PsiExpression[] psiExpressions = psiExpressionList.getExpressions();
                    if(psiExpressions.length > 0 && psiExpressions[0].getText().startsWith("R.layout")) {
                        String layoutText = psiExpressions[0].getText();

                        PsiFile xmlFile = AndroidUtils.findXmlResource(psiElement.getProject(), layoutText);
                        if(xmlFile != null) {

                            NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder.create(AndroidIcons.Views.Fragment).
                                setTooltipText(xmlFile.getName()).
                                setTargets(xmlFile);

                            result.add(builder.createLineMarkerInfo(psiElement));
                        }

                    }
                }
            }
        }

    }
}
 

private void attachEntityClass(@NotNull Collection<LineMarkerInfo> lineMarkerInfos, @NotNull PsiElement psiElement) {
    if(psiElement.getNode().getElementType() != YAMLTokenTypes.SCALAR_KEY) {
        return;
    }

    PsiElement yamlKeyValue = psiElement.getParent();
    if(!(yamlKeyValue instanceof YAMLKeyValue)) {
        return;
    }

    if(yamlKeyValue.getParent() instanceof YAMLMapping && yamlKeyValue.getParent().getParent() instanceof YAMLDocument) {
        PsiFile containingFile;
        try {
            containingFile = yamlKeyValue.getContainingFile();
        } catch (PsiInvalidElementAccessException e) {
            return;
        }

        String fileName = containingFile.getName();
        if(isMetadataFile(fileName)) {
            String keyText = ((YAMLKeyValue) yamlKeyValue).getKeyText();
            if(StringUtils.isNotBlank(keyText)) {
                Collection<PhpClass> phpClasses = PhpElementsUtil.getClassesInterface(psiElement.getProject(), keyText);
                if(phpClasses.size() > 0) {
                    NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder.create(Symfony2Icons.DOCTRINE_LINE_MARKER).
                        setTargets(phpClasses).
                        setTooltipText("Navigate to class");

                    lineMarkerInfos.add(builder.createLineMarkerInfo(psiElement));
                }
            }
        }
    }
}
 

@Nullable
private LineMarkerInfo attachIncludes(@NotNull TwigFile twigFile) {
    Collection<String> templateNames = TwigUtil.getTemplateNamesForFile(twigFile);

    boolean found = false;
    for(String templateName: templateNames) {
        Project project = twigFile.getProject();

        Collection<VirtualFile> containingFiles = FileBasedIndex.getInstance().getContainingFiles(
            TwigIncludeStubIndex.KEY, templateName, GlobalSearchScope.getScopeRestrictedByFileTypes(GlobalSearchScope.allScope(project), TwigFileType.INSTANCE)
        );

        // stop on first target, we load them lazily afterwards
        if(containingFiles.size() > 0) {
            found = true;
            break;
        }
    }

    if(!found) {
        return null;
    }

    NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder.create(PhpIcons.IMPLEMENTED)
        .setTargets(new MyTemplateIncludeLazyValue(twigFile, templateNames))
        .setTooltipText("Navigate to includes")
        .setCellRenderer(new MyFileReferencePsiElementListCellRenderer());

    return builder.createLineMarkerInfo(twigFile);
}
 

@Nullable
private LineMarkerInfo attachExtends(@NotNull TwigFile twigFile) {
    Collection<String> templateNames = TwigUtil.getTemplateNamesForFile(twigFile);

    boolean found = false;
    for(String templateName: templateNames) {
        Project project = twigFile.getProject();

        Collection<VirtualFile> containingFiles = FileBasedIndex.getInstance().getContainingFiles(
            TwigExtendsStubIndex.KEY, templateName, GlobalSearchScope.getScopeRestrictedByFileTypes(GlobalSearchScope.allScope(project), TwigFileType.INSTANCE)
        );

        // stop on first target, we load them lazily afterwards
        if(containingFiles.size() > 0) {
            found = true;
            break;
        }
    }

    if(!found) {
        return null;
    }

    NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder.create(PhpIcons.IMPLEMENTED)
        .setTargets(new TemplateExtendsLazyTargets(twigFile.getProject(), twigFile.getVirtualFile()))
        .setTooltipText("Navigate to extends")
        .setCellRenderer(new MyFileReferencePsiElementListCellRenderer());

    return builder.createLineMarkerInfo(twigFile);
}
 

@Nullable
private LineMarkerInfo attachBlockImplements(@NotNull PsiElement psiElement, @NotNull FileImplementsLazyLoader implementsLazyLoader) {
    if(!TwigBlockUtil.hasBlockImplementations(psiElement, implementsLazyLoader)) {
        return null;
    }

    NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder.create(PhpIcons.IMPLEMENTED)
        .setTargets(new BlockImplementationLazyValue(psiElement))
        .setTooltipText("Implementations")
        .setCellRenderer(new MyBlockListCellRenderer());

    return builder.createLineMarkerInfo(psiElement);
}
 

@Nullable
private LineMarkerInfo attachBlockOverwrites(@NotNull PsiElement psiElement, @NotNull FileOverwritesLazyLoader loader) {
    if(!TwigBlockUtil.hasBlockOverwrites(psiElement, loader)) {
        return null;
    }

    NavigationGutterIconBuilder<PsiElement> builder = NavigationGutterIconBuilder.create(PhpIcons.OVERRIDES)
        .setTargets(new BlockOverwriteLazyValue(psiElement))
        .setTooltipText("Overwrites")
        .setCellRenderer(new MyBlockListCellRenderer());

    return builder.createLineMarkerInfo(psiElement);
}