private static boolean infoEquals(HighlightInfo expectedInfo, HighlightInfo info) {
   if (expectedInfo == info) return true;
   return info.getSeverity() == expectedInfo.getSeverity()
       && info.startOffset == expectedInfo.startOffset
       && info.endOffset == expectedInfo.endOffset
       && info.isAfterEndOfLine() == expectedInfo.isAfterEndOfLine()
       && (expectedInfo.type == WHATEVER || expectedInfo.type.equals(info.type))
       && (Comparing.strEqual(ANY_TEXT, expectedInfo.getDescription())
           || Comparing.strEqual(info.getDescription(), expectedInfo.getDescription()))
       && (expectedInfo.forcedTextAttributes == null
           || Comparing.equal(
               expectedInfo.getTextAttributes(null, null), info.getTextAttributes(null, null)))
       && (expectedInfo.forcedTextAttributesKey == null
           || expectedInfo.forcedTextAttributesKey.equals(info.forcedTextAttributesKey));
 }
 private static void duplicateHighlighters(
     MarkupModel to, MarkupModel from, int offset, TextRange textRange) {
   for (RangeHighlighter rangeHighlighter : from.getAllHighlighters()) {
     if (!rangeHighlighter.isValid()) continue;
     Object tooltip = rangeHighlighter.getErrorStripeTooltip();
     HighlightInfo highlightInfo =
         tooltip instanceof HighlightInfo ? (HighlightInfo) tooltip : null;
     if (highlightInfo != null) {
       if (highlightInfo.getSeverity() != HighlightSeverity.INFORMATION) continue;
       if (highlightInfo.type.getAttributesKey() == EditorColors.IDENTIFIER_UNDER_CARET_ATTRIBUTES)
         continue;
     }
     final int localOffset = textRange.getStartOffset();
     final int start = Math.max(rangeHighlighter.getStartOffset(), localOffset) - localOffset;
     final int end =
         Math.min(rangeHighlighter.getEndOffset(), textRange.getEndOffset()) - localOffset;
     if (start > end) continue;
     final RangeHighlighter h =
         to.addRangeHighlighter(
             start + offset,
             end + offset,
             rangeHighlighter.getLayer(),
             rangeHighlighter.getTextAttributes(),
             rangeHighlighter.getTargetArea());
     ((RangeHighlighterEx) h)
         .setAfterEndOfLine(((RangeHighlighterEx) rangeHighlighter).isAfterEndOfLine());
   }
 }
  @Override
  public boolean accept(@NotNull HighlightInfo highlightInfo, @Nullable PsiFile file) {
    if (null != file && HighlightSeverity.ERROR.equals(highlightInfo.getSeverity())) {
      final String description = StringUtil.notNullize(highlightInfo.getDescription());

      if (HighlightInfoType.UNHANDLED_EXCEPTION.equals(highlightInfo.type)
          && (StringUtil.startsWith(description, UNHANDLED_EXCEPTION_PREFIX_TEXT)
              || StringUtil.startsWith(description, UNHANDLED_EXCEPTIONS_PREFIX_TEXT)
              || StringUtil.startsWith(
                  description, UNHANDLED_AUTOCLOSABLE_EXCEPTIONS_PREFIX_TEXT))) {
        final String unhandledExceptions =
            description.substring(description.indexOf(':') + 1).trim();
        final String[] exceptionFQNs = unhandledExceptions.split(",");
        if (exceptionFQNs.length > 0) {
          final PsiMethod psiMethod =
              PsiTreeUtil.getParentOfType(
                  file.findElementAt(highlightInfo.getStartOffset()), PsiMethod.class);
          if (null != psiMethod) {
            return !SneakyTrowsExceptionHandler.isExceptionHandled(psiMethod, exceptionFQNs);
          }
        }
      }
    }
    return true;
  }
 @NotNull
 public static List<HighlightInfo> filter(
     @NotNull List<HighlightInfo> infos, @NotNull HighlightSeverity minSeverity) {
   ArrayList<HighlightInfo> result = new ArrayList<HighlightInfo>();
   for (final HighlightInfo info : infos) {
     if (info.getSeverity().compareTo(minSeverity) >= 0) result.add(info);
   }
   return result;
 }
  private Map<ProblemDescriptor, HighlightDisplayLevel> runXmlFileSchemaValidation(
      @NotNull XmlFile xmlFile) {
    final AnnotationHolderImpl holder = new AnnotationHolderImpl(new AnnotationSession(xmlFile));

    final List<ExternalAnnotator> annotators =
        ExternalLanguageAnnotators.allForFile(StdLanguages.XML, xmlFile);
    for (ExternalAnnotator<?, ?> annotator : annotators) {
      processAnnotator(xmlFile, holder, annotator);
    }

    if (!holder.hasAnnotations()) return Collections.emptyMap();

    Map<ProblemDescriptor, HighlightDisplayLevel> problemsMap =
        new LinkedHashMap<ProblemDescriptor, HighlightDisplayLevel>();
    for (final Annotation annotation : holder) {
      final HighlightInfo info = HighlightInfo.fromAnnotation(annotation);
      if (info.getSeverity() == HighlightSeverity.INFORMATION) continue;

      final PsiElement startElement = xmlFile.findElementAt(info.startOffset);
      final PsiElement endElement =
          info.startOffset == info.endOffset
              ? startElement
              : xmlFile.findElementAt(info.endOffset - 1);
      if (startElement == null || endElement == null) continue;

      final ProblemDescriptor descriptor =
          myInspectionManager.createProblemDescriptor(
              startElement,
              endElement,
              info.getDescription(),
              ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
              false);
      final HighlightDisplayLevel level =
          info.getSeverity() == HighlightSeverity.ERROR
              ? HighlightDisplayLevel.ERROR
              : HighlightDisplayLevel.WARNING;
      problemsMap.put(descriptor, level);
    }
    return problemsMap;
  }
 private boolean expectedInfosContainsInfo(HighlightInfo info) {
   if (info.getTextAttributes(null, null) == TextAttributes.ERASE_MARKER) return true;
   final Collection<ExpectedHighlightingSet> expectedHighlights = myHighlightingTypes.values();
   for (ExpectedHighlightingSet highlightingSet : expectedHighlights) {
     if (highlightingSet.severity != info.getSeverity()) continue;
     if (!highlightingSet.enabled) return true;
     final Set<HighlightInfo> infos = highlightingSet.infos;
     for (HighlightInfo expectedInfo : infos) {
       if (infoEquals(expectedInfo, info)) {
         return true;
       }
     }
   }
   return false;
 }
  public static String composeText(
      final Map<String, ExpectedHighlightingSet> types,
      Collection<HighlightInfo> infos,
      String text) {
    // filter highlighting data and map each highlighting to a tag name
    List<Pair<String, HighlightInfo>> list =
        ContainerUtil.mapNotNull(
            infos,
            (NullableFunction<HighlightInfo, Pair<String, HighlightInfo>>)
                info -> {
                  for (Map.Entry<String, ExpectedHighlightingSet> entry : types.entrySet()) {
                    final ExpectedHighlightingSet set = entry.getValue();
                    if (set.enabled
                        && set.severity == info.getSeverity()
                        && set.endOfLine == info.isAfterEndOfLine()) {
                      return Pair.create(entry.getKey(), info);
                    }
                  }
                  return null;
                });

    boolean showAttributesKeys = false;
    for (ExpectedHighlightingSet eachSet : types.values()) {
      for (HighlightInfo eachInfo : eachSet.infos) {
        if (eachInfo.forcedTextAttributesKey != null) {
          showAttributesKeys = true;
          break;
        }
      }
    }

    // sort filtered highlighting data by end offset in descending order
    Collections.sort(
        list,
        (o1, o2) -> {
          HighlightInfo i1 = o1.second;
          HighlightInfo i2 = o2.second;

          int byEnds = i2.endOffset - i1.endOffset;
          if (byEnds != 0) return byEnds;

          if (!i1.isAfterEndOfLine() && !i2.isAfterEndOfLine()) {
            int byStarts = i1.startOffset - i2.startOffset;
            if (byStarts != 0) return byStarts;
          } else {
            int byEOL = Comparing.compare(i2.isAfterEndOfLine(), i1.isAfterEndOfLine());
            if (byEOL != 0) return byEOL;
          }

          int bySeverity = i2.getSeverity().compareTo(i1.getSeverity());
          if (bySeverity != 0) return bySeverity;

          return Comparing.compare(i1.getDescription(), i2.getDescription());
        });

    // combine highlighting data with original text
    StringBuilder sb = new StringBuilder();
    Couple<Integer> result = composeText(sb, list, 0, text, text.length(), 0, showAttributesKeys);
    sb.insert(0, text.substring(0, result.second));
    return sb.toString();
  }