@NotNull
  public static HighlightInfo fromAnnotation(
      @NotNull Annotation annotation, @Nullable TextRange fixedRange, boolean batchMode) {
    final TextAttributes forcedAttributes = annotation.getEnforcedTextAttributes();
    final TextAttributesKey forcedAttributesKey =
        forcedAttributes == null ? annotation.getTextAttributes() : null;

    HighlightInfo info =
        new HighlightInfo(
            forcedAttributes,
            forcedAttributesKey,
            convertType(annotation),
            fixedRange != null ? fixedRange.getStartOffset() : annotation.getStartOffset(),
            fixedRange != null ? fixedRange.getEndOffset() : annotation.getEndOffset(),
            annotation.getMessage(),
            annotation.getTooltip(),
            annotation.getSeverity(),
            annotation.isAfterEndOfLine(),
            annotation.needsUpdateOnTyping(),
            annotation.isFileLevelAnnotation(),
            0);
    info.setGutterIconRenderer(annotation.getGutterIconRenderer());
    info.setProblemGroup(annotation.getProblemGroup());
    appendFixes(
        fixedRange, info, batchMode ? annotation.getBatchFixes() : annotation.getQuickFixes());
    return info;
  }
  public boolean equalsByActualOffset(@NotNull HighlightInfo info) {
    if (info == this) return true;

    return info.getSeverity() == getSeverity()
        && info.getActualStartOffset() == getActualStartOffset()
        && info.getActualEndOffset() == getActualEndOffset()
        && Comparing.equal(info.type, type)
        && Comparing.equal(info.gutterIconRenderer, gutterIconRenderer)
        && Comparing.equal(info.forcedTextAttributes, forcedTextAttributes)
        && Comparing.equal(info.forcedTextAttributesKey, forcedTextAttributesKey)
        && Comparing.strEqual(info.getDescription(), getDescription());
  }
  public boolean equals(Object obj) {
    if (obj == this) return true;
    if (!(obj instanceof HighlightInfo)) return false;
    HighlightInfo info = (HighlightInfo) obj;

    return info.getSeverity() == getSeverity()
        && info.startOffset == startOffset
        && info.endOffset == endOffset
        && Comparing.equal(info.type, type)
        && Comparing.equal(info.gutterIconRenderer, gutterIconRenderer)
        && Comparing.equal(info.forcedTextAttributes, forcedTextAttributes)
        && Comparing.equal(info.forcedTextAttributesKey, forcedTextAttributesKey)
        && Comparing.strEqual(info.getDescription(), getDescription());
  }
 private static boolean isAcceptedByFilters(
     @NotNull HighlightInfo info, @Nullable PsiElement psiElement) {
   PsiFile file = psiElement == null ? null : psiElement.getContainingFile();
   for (HighlightInfoFilter filter : FILTERS) {
     if (!filter.accept(info, file)) {
       return false;
     }
   }
   info.psiElement = psiElement;
   return true;
 }
 private static void appendFixes(
     @Nullable TextRange fixedRange,
     @NotNull HighlightInfo info,
     @Nullable List<Annotation.QuickFixInfo> fixes) {
   if (fixes != null) {
     for (final Annotation.QuickFixInfo quickFixInfo : fixes) {
       TextRange range = fixedRange != null ? fixedRange : quickFixInfo.textRange;
       HighlightDisplayKey key =
           quickFixInfo.key != null
               ? quickFixInfo.key
               : HighlightDisplayKey.find(ANNOTATOR_INSPECTION_SHORT_NAME);
       info.registerFix(
           quickFixInfo.quickFix, null, HighlightDisplayKey.getDisplayNameByKey(key), range, key);
     }
   }
 }