private void highlightInjectedSyntax(
      @NotNull PsiFile injectedPsi, @NotNull HighlightInfoHolder holder) {
    List<Trinity<IElementType, SmartPsiElementPointer<PsiLanguageInjectionHost>, TextRange>>
        tokens = InjectedLanguageUtil.getHighlightTokens(injectedPsi);
    if (tokens == null) return;

    final Language injectedLanguage = injectedPsi.getLanguage();
    Project project = injectedPsi.getProject();
    SyntaxHighlighter syntaxHighlighter =
        SyntaxHighlighterFactory.getSyntaxHighlighter(
            injectedLanguage, project, injectedPsi.getVirtualFile());
    final TextAttributes defaultAttrs = myGlobalScheme.getAttributes(HighlighterColors.TEXT);

    for (Trinity<IElementType, SmartPsiElementPointer<PsiLanguageInjectionHost>, TextRange> token :
        tokens) {
      ProgressManager.checkCanceled();
      IElementType tokenType = token.getFirst();
      PsiLanguageInjectionHost injectionHost = token.getSecond().getElement();
      if (injectionHost == null) continue;
      TextRange textRange = token.getThird();
      TextAttributesKey[] keys = syntaxHighlighter.getTokenHighlights(tokenType);
      if (textRange.getLength() == 0) continue;

      TextRange annRange = textRange.shiftRight(injectionHost.getTextRange().getStartOffset());
      // force attribute colors to override host' ones
      TextAttributes attributes = null;
      for (TextAttributesKey key : keys) {
        TextAttributes attrs2 = myGlobalScheme.getAttributes(key);
        if (attrs2 != null) {
          attributes = attributes == null ? attrs2 : TextAttributes.merge(attributes, attrs2);
        }
      }
      TextAttributes forcedAttributes;
      if (attributes == null || attributes.isEmpty() || attributes.equals(defaultAttrs)) {
        forcedAttributes = TextAttributes.ERASE_MARKER;
      } else {
        HighlightInfo info =
            HighlightInfo.newHighlightInfo(HighlightInfoType.INJECTED_LANGUAGE_FRAGMENT)
                .range(annRange)
                .textAttributes(TextAttributes.ERASE_MARKER)
                .createUnconditionally();
        holder.add(info);

        forcedAttributes =
            new TextAttributes(
                attributes.getForegroundColor(),
                attributes.getBackgroundColor(),
                attributes.getEffectColor(),
                attributes.getEffectType(),
                attributes.getFontType());
      }

      HighlightInfo info =
          HighlightInfo.newHighlightInfo(HighlightInfoType.INJECTED_LANGUAGE_FRAGMENT)
              .range(annRange)
              .textAttributes(forcedAttributes)
              .createUnconditionally();
      holder.add(info);
    }
  }
 private HighlightInfo createHighlightInfo(
     TextRange range,
     HighlightInfoType type,
     Set<Pair<Object, TextRange>> existingMarkupTooltips) {
   int start = range.getStartOffset();
   String tooltip =
       start <= myDocument.getTextLength()
           ? HighlightHandlerBase.getLineTextErrorStripeTooltip(myDocument, start, false)
           : null;
   String unescapedTooltip =
       existingMarkupTooltips.contains(new Pair<Object, TextRange>(tooltip, range))
           ? null
           : tooltip;
   HighlightInfo.Builder builder = HighlightInfo.newHighlightInfo(type).range(range);
   if (unescapedTooltip != null) {
     builder.unescapedToolTip(unescapedTooltip);
   }
   return builder.createUnconditionally();
 }
  private boolean addInjectedPsiHighlights(
      @NotNull PsiFile injectedPsi,
      TextAttributes injectedAttributes,
      @NotNull Collection<HighlightInfo> outInfos,
      @NotNull ProgressIndicator progress,
      @NotNull InjectedLanguageManager injectedLanguageManager) {
    DocumentWindow documentWindow =
        (DocumentWindow) PsiDocumentManager.getInstance(myProject).getCachedDocument(injectedPsi);
    if (documentWindow == null) return true;
    Place places = InjectedLanguageUtil.getShreds(injectedPsi);
    for (PsiLanguageInjectionHost.Shred place : places) {
      PsiLanguageInjectionHost host = place.getHost();
      if (host == null) continue;
      TextRange textRange =
          place.getRangeInsideHost().shiftRight(host.getTextRange().getStartOffset());
      if (textRange.isEmpty()) continue;
      String desc = injectedPsi.getLanguage().getDisplayName() + ": " + injectedPsi.getText();
      HighlightInfo.Builder builder =
          HighlightInfo.newHighlightInfo(HighlightInfoType.INJECTED_LANGUAGE_BACKGROUND)
              .range(textRange);
      if (injectedAttributes != null && InjectedLanguageUtil.isHighlightInjectionBackground(host)) {
        builder.textAttributes(injectedAttributes);
      }
      builder.unescapedToolTip(desc);
      HighlightInfo info = builder.createUnconditionally();
      info.setFromInjection(true);
      outInfos.add(info);
    }

    HighlightInfoHolder holder = createInfoHolder(injectedPsi);
    runHighlightVisitorsForInjected(injectedPsi, holder, progress);
    for (int i = 0; i < holder.size(); i++) {
      HighlightInfo info = holder.get(i);
      final int startOffset = documentWindow.injectedToHost(info.startOffset);
      final TextRange fixedTextRange = getFixedTextRange(documentWindow, startOffset);
      addPatchedInfos(
          info, injectedPsi, documentWindow, injectedLanguageManager, fixedTextRange, outInfos);
    }
    int injectedStart = holder.size();
    highlightInjectedSyntax(injectedPsi, holder);
    for (int i = injectedStart; i < holder.size(); i++) {
      HighlightInfo info = holder.get(i);
      final int startOffset = info.startOffset;
      final TextRange fixedTextRange = getFixedTextRange(documentWindow, startOffset);
      if (fixedTextRange == null) {
        info.setFromInjection(true);
        outInfos.add(info);
      } else {
        HighlightInfo patched =
            new HighlightInfo(
                info.forcedTextAttributes,
                info.forcedTextAttributesKey,
                info.type,
                fixedTextRange.getStartOffset(),
                fixedTextRange.getEndOffset(),
                info.getDescription(),
                info.getToolTip(),
                info.type.getSeverity(null),
                info.isAfterEndOfLine(),
                null,
                false,
                0,
                info.getProblemGroup(),
                info.getGutterIconRenderer());
        patched.setFromInjection(true);
        outInfos.add(patched);
      }
    }

    if (!isDumbMode()) {
      List<HighlightInfo> todos = new ArrayList<HighlightInfo>();
      highlightTodos(
          injectedPsi,
          injectedPsi.getText(),
          0,
          injectedPsi.getTextLength(),
          progress,
          myPriorityRange,
          todos,
          todos);
      for (HighlightInfo info : todos) {
        addPatchedInfos(info, injectedPsi, documentWindow, injectedLanguageManager, null, outInfos);
      }
    }
    advanceProgress(1);
    return true;
  }