private void checkDuplicateAttribute(XmlTag tag, final XmlAttribute attribute) {
    if (skipValidation(tag)) {
      return;
    }

    final XmlAttribute[] attributes = tag.getAttributes();
    final PsiFile containingFile = tag.getContainingFile();
    final XmlExtension extension =
        containingFile instanceof XmlFile
            ? XmlExtension.getExtension(containingFile)
            : XmlExtension.DEFAULT_EXTENSION;
    for (XmlAttribute tagAttribute : attributes) {
      ProgressManager.checkCanceled();
      if (attribute != tagAttribute
          && Comparing.strEqual(attribute.getName(), tagAttribute.getName())) {
        final String localName = attribute.getLocalName();

        if (extension.canBeDuplicated(tagAttribute))
          continue; // multiple import attributes are allowed in jsp directive

        HighlightInfo highlightInfo =
            HighlightInfo.createHighlightInfo(
                getTagProblemInfoType(tag),
                XmlChildRole.ATTRIBUTE_NAME_FINDER.findChild(
                    SourceTreeToPsiMap.psiElementToTree(attribute)),
                XmlErrorMessages.message("duplicate.attribute", localName));
        addToResults(highlightInfo);

        IntentionAction intentionAction = new RemoveAttributeIntentionFix(localName, attribute);

        QuickFixAction.registerQuickFixAction(highlightInfo, intentionAction);
      }
    }
  }
  @Nullable
  private HighlightInfo reportAttributeProblem(
      final XmlTag tag,
      final String localName,
      final XmlAttribute attribute,
      final String localizedMessage) {

    final RemoveAttributeIntentionFix removeAttributeIntention =
        new RemoveAttributeIntentionFix(localName, attribute);

    if (!(tag instanceof HtmlTag)) {
      final HighlightInfoType tagProblemInfoType = HighlightInfoType.WRONG_REF;

      final ASTNode node = SourceTreeToPsiMap.psiElementToTree(attribute);
      assert node != null;
      final ASTNode child = XmlChildRole.ATTRIBUTE_NAME_FINDER.findChild(node);
      assert child != null;
      final HighlightInfo highlightInfo =
          HighlightInfo.createHighlightInfo(tagProblemInfoType, child, localizedMessage);
      addToResults(highlightInfo);

      QuickFixAction.registerQuickFixAction(highlightInfo, removeAttributeIntention);

      return highlightInfo;
    }

    return null;
  }
  @Nullable
  public XmlAttribute getAttribute(String qname) {
    if (qname == null) return null;
    final XmlAttribute[] attributes = getAttributes();

    final boolean caseSensitive = isCaseSensitive();

    for (final XmlAttribute attribute : attributes) {
      final LeafElement attrNameElement =
          (LeafElement) XmlChildRole.ATTRIBUTE_NAME_FINDER.findChild(attribute.getNode());
      if (attrNameElement != null
          && (caseSensitive && Comparing.equal(attrNameElement.getChars(), qname)
              || !caseSensitive && Comparing.equal(attrNameElement.getChars(), qname, false))) {
        return attribute;
      }
    }
    return null;
  }
    @Override
    public void onMessage(PsiElement host, String message) {
      final ASTNode node = host.getNode();
      assert node != null;

      if (host instanceof XmlAttribute) {
        final ASTNode nameNode = XmlChildRole.ATTRIBUTE_NAME_FINDER.findChild(node);
        createAnnotation(nameNode, message);
      } else if (host instanceof XmlTag) {
        final ASTNode start = XmlChildRole.START_TAG_NAME_FINDER.findChild(node);
        if (start != null) {
          createAnnotation(start, message);
        }

        final ASTNode end = XmlChildRole.CLOSING_TAG_NAME_FINDER.findChild(node);
        if (end != null) {
          createAnnotation(end, message);
        }
      } else {
        createAnnotation(node, message);
      }
    }