private static void process(
      PsiField psiField, Collection<? super RelatedItemLineMarkerInfo> result) {
    if (!isExtensionPointNameDeclarationField(psiField)) return;

    final PsiClass epClass = resolveExtensionPointClass(psiField);
    if (epClass == null) return;

    final String epName = resolveEpName(psiField);
    if (epName == null) return;

    ExtensionPointLocator locator = new ExtensionPointLocator(epClass);
    List<ExtensionPointCandidate> targets =
        ContainerUtil.filter(
            locator.findDirectCandidates(),
            new Condition<ExtensionPointCandidate>() {
              @Override
              public boolean value(ExtensionPointCandidate candidate) {
                return epName.equals(candidate.epName);
              }
            });

    final RelatedItemLineMarkerInfo<PsiElement> info =
        NavigationGutterIconBuilder.create(AllIcons.Nodes.Plugin, CONVERTER, RELATED_ITEM_PROVIDER)
            .setTargets(targets)
            .setPopupTitle("Choose Extension Point")
            .setTooltipText("Extension Point Declaration")
            .setAlignment(GutterIconRenderer.Alignment.RIGHT)
            .createLineMarkerInfo(psiField.getNameIdentifier());
    result.add(info);
  }
  /**
   * spring bean reference annotator
   *
   * @param psiElement psi element
   * @param holder annotation holder
   */
  public void annotate(PsiElement psiElement, AnnotationHolder holder) {
    if (!(psiElement instanceof PsiJavaFile)) {
      return;
    }

    // Get java classes
    for (PsiClass javaClass : ((PsiJavaFile) psiElement).getClasses()) {

      PsiClass superClass = javaClass.getSuperClass();
      PsiField[] superClassFields =
          superClass != null ? superClass.getAllFields() : new PsiField[] {};
      for (PsiField field : javaClass.getAllFields()) {
        // We don't need scan super class fields
        if (isContain(superClassFields, field)) {
          continue;
        }

        PsiModifierList modifierList = field.getModifierList();
        if (modifierList == null) {
          continue;
        }
        for (PsiAnnotation psiAnnotation : modifierList.getAnnotations()) {
          String qcName = psiAnnotation.getQualifiedName();
          if (qcName == null || !qcName.startsWith("org.unitils.spring.annotation.")) {
            continue;
          }

          SpringManager springManager = SpringManager.getInstance(psiElement.getProject());
          SpringModel springModel =
              springManager.getCombinedModel(ModuleUtil.findModuleForPsiElement(psiElement));
          if (springModel == null) {
            continue;
          }

          // by type
          if (qcName.endsWith("SpringBeanByType")) {
            final PsiType type = field.getType();
            if (!(type instanceof PsiClassType)) {
              continue;
            }
            final PsiClass typeClass = ((PsiClassType) type).resolve();
            if (typeClass == null) {
              continue;
            }
            List<SpringBaseBeanPointer> springBaseBeanPointerList =
                springModel.findBeansByPsiClass(typeClass);
            if (springBaseBeanPointerList.size() > 0) {
              List<PsiElement> elements = new ArrayList<PsiElement>();
              for (SpringBaseBeanPointer springBaseBeanPointer : springBaseBeanPointerList) {
                elements.add(springBaseBeanPointer.getPsiElement());
              }
              NavigationGutterIconBuilder.create(SpringIcons.SPRING_BEAN_ICON)
                  .setTooltipText("Navigate to the spring bean declaration(s)")
                  .setTargets(elements)
                  .install(holder, field.getNameIdentifier());
            }
          }
          // by name
          else {
            String beanName = field.getName();
            if (qcName.endsWith("SpringBean")) {
              PsiAnnotationMemberValue attributeValue = psiAnnotation.findAttributeValue("value");
              if (attributeValue != null && attributeValue.getText() != null) {
                beanName = attributeValue.getText().replace("\"", "");
              }
            }
            if (beanName != null && StringUtil.isNotEmpty(beanName)) {
              SpringBeanPointer springBeanPointer = springModel.findBeanByName(beanName);
              if (springBeanPointer != null) {
                NavigationGutterIconBuilder.create(SpringIcons.SPRING_BEAN_ICON)
                    .setTooltipText("Navigate to the spring bean declaration(s)")
                    .setTarget(springBeanPointer.getPsiElement())
                    .install(holder, field.getNameIdentifier());
              }
            }
          }
        }
      }
    }
  }
  @Override
  protected void collectNavigationMarkers(
      @NotNull PsiElement element, Collection<? super RelatedItemLineMarkerInfo> result) {
    if (element instanceof PerlNamespaceDefinition) {
      PsiElement nameIdentifier = ((PerlNamespaceDefinition) element).getNameIdentifier();
      if (nameIdentifier == null) nameIdentifier = element;

      List<PerlNamespaceDefinition> parentNamespaces =
          ((PerlNamespaceDefinition) element).getParentNamespaceDefinitions();
      if (parentNamespaces.size() > 0) {
        NavigationGutterIconBuilder<PsiElement> builder =
            NavigationGutterIconBuilder.create(AllIcons.Gutter.ImplementingMethod)
                .setTargets(parentNamespaces)
                .setTooltipText("Parent classes");

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

      Collection<PerlNamespaceDefinition> childNamespaces =
          ((PerlNamespaceDefinition) element).getChildNamespaceDefinitions();
      if (childNamespaces.size() > 0) {
        NavigationGutterIconBuilder<PsiElement> builder =
            NavigationGutterIconBuilder.create(AllIcons.Gutter.ImplementedMethod)
                .setTargets(childNamespaces)
                .setTooltipText("Subclasses");

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

    } else if (element instanceof PerlSubDefinitionBase
        && ((PerlSubDefinitionBase) element).isMethod()) {
      PerlNamespaceDefinition containingNamespace =
          PsiTreeUtil.getParentOfType(element, PerlNamespaceDefinition.class);
      if (containingNamespace != null) {
        final String packageName = ((PerlSubDefinitionBase) element).getPackageName();
        final String subName = ((PerlSubDefinitionBase) element).getSubName();
        PsiElement nameIdentifier = ((PerlSubDefinitionBase) element).getNameIdentifier();
        if (nameIdentifier == null) nameIdentifier = element;

        if (StringUtil.isNotEmpty(packageName) && StringUtil.isNotEmpty(subName)) {
          Collection<PsiElement> superMethods =
              PerlMro.resolveSub(element.getProject(), packageName, subName, true);
          if (superMethods.size() > 0) {
            NavigationGutterIconBuilder<PsiElement> builder =
                NavigationGutterIconBuilder.create(AllIcons.Gutter.OverridingMethod)
                    .setTargets(superMethods)
                    .setTooltipText("Overriding method");

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

          final List<PerlSubBase> overridingSubs = new ArrayList<PerlSubBase>();

          PerlPackageUtil.processChildNamespacesSubs(
              containingNamespace,
              null,
              new Processor<PerlSubBase>() {
                @Override
                public boolean process(PerlSubBase perlSubBase) {
                  String subBaseName = perlSubBase.getSubName();
                  if (StringUtil.isNotEmpty(subBaseName)
                      && subName.equals(subBaseName)
                      && perlSubBase.isMethod()) {
                    overridingSubs.add(perlSubBase);
                    return false;
                  }
                  return true;
                }
              });

          if (overridingSubs.size() > 0) {
            NavigationGutterIconBuilder<PsiElement> builder =
                NavigationGutterIconBuilder.create(AllIcons.Gutter.OverridenMethod)
                    .setTargets(overridingSubs)
                    .setTooltipText("Overriden methods");

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