@Override
  public void visitXmlProcessingInstruction(XmlProcessingInstruction processingInstruction) {
    super.visitXmlProcessingInstruction(processingInstruction);
    PsiElement parent = processingInstruction.getParent();

    if (parent instanceof XmlProlog && processingInstruction.getText().startsWith("<?xml")) {
      for (PsiElement e = PsiTreeUtil.prevLeaf(processingInstruction);
          e != null;
          e = PsiTreeUtil.prevLeaf(e)) {
        if (e instanceof PsiWhiteSpace && PsiTreeUtil.prevLeaf(e) != null
            || e instanceof OuterLanguageElement) {
          continue;
        }
        PsiElement eParent = e.getParent();
        if (eParent instanceof PsiComment) e = eParent;
        if (eParent instanceof XmlProcessingInstruction) break;

        addToResults(
            HighlightInfo.createHighlightInfo(
                HighlightInfoType.ERROR,
                e,
                XmlErrorMessages.message("xml.declaration.should.precede.all.document.content")));
      }
    }
  }
  @Override
  public void visitXmlToken(XmlToken token) {
    IElementType tokenType = token.getTokenType();
    if (tokenType == XmlTokenType.XML_NAME || tokenType == XmlTokenType.XML_TAG_NAME) {
      PsiElement element = token.getPrevSibling();
      while (element instanceof PsiWhiteSpace) element = element.getPrevSibling();

      if (element instanceof XmlToken) {
        if (((XmlToken) element).getTokenType() == XmlTokenType.XML_START_TAG_START) {
          PsiElement parent = element.getParent();

          if (parent instanceof XmlTag
              && !(token.getNextSibling() instanceof OuterLanguageElement)) {
            checkTag((XmlTag) parent);
          }
        }
      } else {
        PsiElement parent = token.getParent();

        if (parent instanceof XmlAttribute
            && !(token.getNextSibling() instanceof OuterLanguageElement)) {
          checkAttribute((XmlAttribute) parent);
        }
      }
    } else if (tokenType == XmlTokenType.XML_DATA_CHARACTERS
        && token.getParent() instanceof XmlText) {
      if (token.textContains(']') && token.textContains('>')) {
        String s = token.getText();
        String marker = "]]>";
        int i = s.indexOf(marker);

        if (i != -1) { // TODO: fix
          TextRange textRange = token.getTextRange();
          int start = textRange.getStartOffset() + i;
          HighlightInfoType type =
              PsiTreeUtil.getParentOfType(token, XmlTag.class) instanceof HtmlTag
                  ? HighlightInfoType.WARNING
                  : HighlightInfoType.ERROR;
          HighlightInfo info =
              HighlightInfo.createHighlightInfo(
                  type,
                  start,
                  start + marker.length(),
                  XmlErrorMessages.message(
                      "cdata.end.should.not.appear.in.content.unless.to.mark.end.of.cdata.section"));
          addToResults(info);
        }
      }
    }
  }
  private void doCheckRefs(final PsiElement value, final PsiReference[] references, int start) {
    for (int i = start; i < references.length; ++i) {
      PsiReference reference = references[i];
      ProgressManager.checkCanceled();
      if (reference == null) {
        continue;
      }
      if (!hasBadResolve(reference, false)) {
        continue;
      }
      String description = getErrorDescription(reference);

      final int startOffset = reference.getElement().getTextRange().getStartOffset();
      final TextRange referenceRange = reference.getRangeInElement();

      // logging for IDEADEV-29655
      if (referenceRange.getStartOffset() > referenceRange.getEndOffset()) {
        LOG.error(
            "Reference range start offset > end offset:  "
                + reference
                + ", start offset: "
                + referenceRange.getStartOffset()
                + ", end offset: "
                + referenceRange.getEndOffset());
      }

      HighlightInfoType type =
          getTagProblemInfoType(PsiTreeUtil.getParentOfType(value, XmlTag.class));
      if (value instanceof XmlAttributeValue) {
        PsiElement parent = value.getParent();
        if (parent instanceof XmlAttribute) {
          String name = ((XmlAttribute) parent).getName().toLowerCase();
          if (type.getSeverity(null).compareTo(HighlightInfoType.WARNING.getSeverity(null)) > 0
              && name.endsWith("stylename")) {
            type = HighlightInfoType.WARNING;
          } else if (name.equals("href")
              && type.getSeverity(null) == HighlightInfoType.WARNING.getSeverity(null)) {
            continue;
          }
        }
      }
      HighlightInfo info =
          HighlightInfo.createHighlightInfo(
              type,
              startOffset + referenceRange.getStartOffset(),
              startOffset + referenceRange.getEndOffset(),
              description);
      addToResults(info);
      if (reference instanceof QuickFixProvider)
        ((QuickFixProvider) reference).registerQuickfix(info, reference);
      UnresolvedReferenceQuickFixProvider.registerReferenceFixes(
          reference, new QuickFixActionRegistrarImpl(info));
    }
  }
  public void addMessage(
      final PsiElement context,
      final String message,
      final ErrorType type,
      final IntentionAction... fixes) {
    if (message != null && message.length() > 0) {
      final PsiFile containingFile = context.getContainingFile();
      final HighlightInfoType defaultInfoType =
          type == ErrorType.ERROR
              ? HighlightInfoType.ERROR
              : type == ErrorType.WARNING
                  ? HighlightInfoType.WARNING
                  : HighlightInfoType.WEAK_WARNING;

      if (context instanceof XmlTag
          && XmlExtension.getExtension(containingFile).shouldBeHighlightedAsTag((XmlTag) context)) {
        addElementsForTagWithManyQuickFixes((XmlTag) context, message, defaultInfoType, fixes);
      } else {
        final PsiElement contextOfFile = containingFile.getContext();
        final HighlightInfo highlightInfo;

        if (contextOfFile != null) {
          TextRange range =
              InjectedLanguageManager.getInstance(context.getProject())
                  .injectedToHost(context, context.getTextRange());
          highlightInfo = HighlightInfo.createHighlightInfo(defaultInfoType, range, message);
        } else {
          highlightInfo =
              HighlightInfo.createHighlightInfo(HighlightInfoType.WRONG_REF, context, message);
        }

        if (fixes != null) {
          for (final IntentionAction quickFixAction : fixes) {
            if (quickFixAction == null) continue;
            QuickFixAction.registerQuickFixAction(highlightInfo, quickFixAction);
          }
        }
        addToResults(highlightInfo);
      }
    }
  }
        @Override
        protected Boolean compute(PsiElement parent, Object p) {
          OuterLanguageElement element =
              PsiTreeUtil.getChildOfType(parent, OuterLanguageElement.class);

          if (element == null) {
            // JspOuterLanguageElement is located under XmlText
            for (PsiElement child = parent.getFirstChild();
                child != null;
                child = child.getNextSibling()) {
              if (child instanceof XmlText) {
                element = PsiTreeUtil.getChildOfType(child, OuterLanguageElement.class);
                if (element != null) {
                  break;
                }
              }
            }
          }
          if (element == null) return false;
          PsiFile containingFile = parent.getContainingFile();
          return containingFile.getViewProvider().getBaseLanguage() != containingFile.getLanguage();
        }
 public void addMessage(PsiElement context, String message, int type) {
   if (message != null && message.length() > 0) {
     if (context instanceof XmlTag
         && XmlExtension.getExtension(context.getContainingFile())
             .shouldBeHighlightedAsTag((XmlTag) context)) {
       HighlightInfoType infoType =
           type == ERROR
               ? HighlightInfoType.ERROR
               : type == WARNING ? HighlightInfoType.WARNING : HighlightInfoType.WEAK_WARNING;
       addElementsForTag((XmlTag) context, message, infoType, null);
     } else {
       addToResults(
           HighlightInfo.createHighlightInfo(HighlightInfoType.WRONG_REF, context, message));
     }
   }
 }
  private void bindMessageToAstNode(
      final PsiElement childByRole,
      final HighlightInfoType warning,
      final int offset,
      int length,
      final String localizedMessage,
      IntentionAction... quickFixActions) {
    if (childByRole != null) {
      final TextRange textRange = childByRole.getTextRange();
      if (length == -1) length = textRange.getLength();
      final int startOffset = textRange.getStartOffset() + offset;

      HighlightInfo highlightInfo =
          HighlightInfo.createHighlightInfo(
              warning,
              childByRole,
              startOffset,
              startOffset + length,
              localizedMessage,
              HighlightInfo.htmlEscapeToolTip(localizedMessage));

      if (highlightInfo == null) {
        highlightInfo =
            HighlightInfo.createHighlightInfo(
                warning,
                new TextRange(startOffset, startOffset + length),
                localizedMessage,
                localizedMessage,
                NONEMPTY_TEXT_ATTRIBUTES);
      }

      for (final IntentionAction quickFixAction : quickFixActions) {
        if (quickFixAction == null) continue;
        QuickFixAction.registerQuickFixAction(highlightInfo, textRange, quickFixAction, null);
      }
      addToResults(highlightInfo);
    }
  }
 public void visit(@NotNull final PsiElement element) {
   element.accept(this);
 }
  private void checkReferences(PsiElement value) {
    if (value == null) return;

    doCheckRefs(value, value.getReferences(), 0);
  }