void (@NotNull HighlightInfo info, @Nullable EditorColorsScheme colorsScheme, // if null, the global scheme will be used @NotNull Document document, int group, @NotNull PsiFile psiFile, @NotNull MarkupModelEx markup, @Nullable HighlightersRecycler infosToRemove, @NotNull Long2ObjectMap<RangeMarker> range2markerCache, @NotNull SeverityRegistrar severityRegistrar) { assert !info.isFileLevelAnnotation(); int infoStartOffset = info.startOffset; int infoEndOffset = info.endOffset; int docLength = document.getTextLength(); if (infoEndOffset > docLength) { infoEndOffset = docLength; infoStartOffset = Math.min(infoStartOffset, infoEndOffset); } if (infoEndOffset == infoStartOffset && !info.isAfterEndOfLine()) { if (infoEndOffset == docLength) return; // empty highlighter beyond file boundaries infoEndOffset++; //show something in case of empty HighlightInfo } info.setGroup(group); int layer = UpdateHighlightersUtil.getLayer(info, severityRegistrar); long finalInfoRange = TextRangeScalarUtil.toScalarRange(infoStartOffset, infoEndOffset); TextAttributes infoAttributes = info.getTextAttributes(psiFile, colorsScheme); Consumer<RangeHighlighterEx> changeAttributes = finalHighlighter -> { TextAttributesKey textAttributesKey = info.forcedTextAttributesKey == null ? info.type.getAttributesKey() : info.forcedTextAttributesKey; finalHighlighter.setTextAttributesKey(textAttributesKey); if (infoAttributes == TextAttributes.ERASE_MARKER || infoAttributes != null && !infoAttributes.equals(finalHighlighter.getTextAttributes(colorsScheme))) { finalHighlighter.setTextAttributes(infoAttributes); } info.setHighlighter(finalHighlighter); finalHighlighter.setAfterEndOfLine(info.isAfterEndOfLine()); Color infoErrorStripeColor = info.getErrorStripeMarkColor(psiFile, colorsScheme); TextAttributes attributes = finalHighlighter.getTextAttributes(colorsScheme); Color attributesErrorStripeColor = attributes != null ? attributes.getErrorStripeColor() : null; if (infoErrorStripeColor != null && !infoErrorStripeColor.equals(attributesErrorStripeColor)) { finalHighlighter.setErrorStripeMarkColor(infoErrorStripeColor); } if (info != finalHighlighter.getErrorStripeTooltip()) { finalHighlighter.setErrorStripeTooltip(info); } GutterMark renderer = info.getGutterIconRenderer(); finalHighlighter.setGutterIconRenderer((GutterIconRenderer)renderer); range2markerCache.put(finalInfoRange, finalHighlighter); info.updateQuickFixFields(document, range2markerCache, finalInfoRange); }; RangeHighlighterEx salvagedFromBin = infosToRemove == null ? null : infosToRemove.pickupHighlighterFromGarbageBin(infoStartOffset, infoEndOffset, layer); RangeHighlighterEx highlighter; if (salvagedFromBin == null) { highlighter = markup.addRangeHighlighterAndChangeAttributes(null, infoStartOffset, infoEndOffset, layer, HighlighterTargetArea.EXACT_RANGE, false, changeAttributes); if (HighlightInfoType.VISIBLE_IF_FOLDED.contains(info.type)) { highlighter.setVisibleIfFolded(true); } } else { highlighter = salvagedFromBin; markup.changeAttributesInBatch(highlighter, changeAttributes); } if (LOG.isDebugEnabled()) { LOG.debug("createOrReuseHighlighterFor "+info +(salvagedFromBin == null ? "" : " (recycled)")); } if (infoAttributes != null) { TextAttributes actualAttributes = highlighter.getTextAttributes(colorsScheme); boolean attributesSet = Comparing.equal(infoAttributes, actualAttributes); if (!attributesSet) { highlighter.setTextAttributes(infoAttributes); TextAttributes afterSet = highlighter.getTextAttributes(colorsScheme); LOG.error("Expected to set " + infoAttributes + " but actual attributes are: " + actualAttributes + "; colorsScheme: '" + (colorsScheme == null ? "[global]" : colorsScheme.getName()) + "'" + "; highlighter:" + highlighter + " (" + highlighter.getClass() + ")" + "; was reused from the bin: " + (salvagedFromBin != null) + "; is being recycled: " + HighlightersRecycler.isBeingRecycled(highlighter)+ "; markup: " + markup + " (" + markup.getClass() + ")" + "; attributes after the second .setAttributes(): " + afterSet + " (set " + (infoAttributes.equals(afterSet) ? "successfully" : "not successfully") + ")"); } } }