@Override
  public PsiElement getDocumentationElementForLookupItem(final PsiManager psiManager, Object object, PsiElement element) {

    if (object instanceof XmlExtension.TagInfo) {
      return ((XmlExtension.TagInfo)object).getDeclaration();
    }

    final PsiElement originalElement = element;
    boolean isAttrCompletion = element instanceof XmlAttribute;

    if (!isAttrCompletion && element instanceof XmlToken) {
      final IElementType tokenType = ((XmlToken)element).getTokenType();

      if (tokenType == XmlTokenType.XML_EMPTY_ELEMENT_END || tokenType == XmlTokenType.XML_TAG_END) {
        isAttrCompletion = true;
      } else if (element.getParent() instanceof XmlAttribute) {
        isAttrCompletion = true;
      }
    } else if (!isAttrCompletion && element instanceof PsiWhiteSpace) {
      PsiElement prevSibling = element.getPrevSibling();
      if (prevSibling instanceof XmlTag && prevSibling.getLastChild() instanceof PsiErrorElement) {
        isAttrCompletion = true;
        element = prevSibling;
      }
    }

    element = PsiTreeUtil.getParentOfType(element, XmlTag.class, false);

    if (element != null) {
      XmlTag xmlTag = (XmlTag)element;
      XmlElementDescriptor elementDescriptor;

      if (isAttrCompletion && object instanceof String) {
        elementDescriptor = xmlTag.getDescriptor();

        if (elementDescriptor != null) {
          final XmlAttributeDescriptor attributeDescriptor = elementDescriptor.getAttributeDescriptor((String)object, xmlTag);
          if (attributeDescriptor != null) {
            final PsiElement declaration = attributeDescriptor.getDeclaration();
            if (declaration != null) return declaration;
          }
        }
      }

      if (object == null) return null;
      try {
        @NonNls StringBuilder tagText = new StringBuilder(object.toString());
        String namespacePrefix = XmlUtil.findPrefixByQualifiedName(object.toString());
        String namespace = xmlTag.getNamespaceByPrefix(namespacePrefix);

        if (namespace.length() > 0) {
          tagText.append(" xmlns");
          if (namespacePrefix.length() > 0) tagText.append(":").append(namespacePrefix);
          tagText.append("=\"").append(namespace).append("\"");
        }

        XmlTag tagFromText = XmlElementFactory.getInstance(xmlTag.getProject()).createTagFromText("<" + tagText +"/>");
        XmlElementDescriptor parentDescriptor = xmlTag.getDescriptor();
        elementDescriptor = (parentDescriptor!=null)?parentDescriptor.getElementDescriptor(tagFromText, xmlTag):null;

        if (elementDescriptor==null) {
          PsiElement parent = xmlTag.getParent();
          if (parent instanceof XmlTag) {
            parentDescriptor = ((XmlTag)parent).getDescriptor();
            elementDescriptor = (parentDescriptor!=null)?parentDescriptor.getElementDescriptor(tagFromText, (XmlTag)parent):null;
          }
        }

        if (elementDescriptor instanceof AnyXmlElementDescriptor) {
          final XmlNSDescriptor nsDescriptor = xmlTag.getNSDescriptor(xmlTag.getNamespaceByPrefix(namespacePrefix), true);
          elementDescriptor = (nsDescriptor != null)?nsDescriptor.getElementDescriptor(tagFromText):null;
        }

        // The very special case of xml file
        final PsiFile containingFile = xmlTag.getContainingFile();
        @Nullable XmlFile xmlFile = XmlUtil.getContainingFile(xmlTag);
        if (xmlFile != null && xmlFile != containingFile) {
          final XmlTag rootTag = xmlFile.getRootTag();
          if (rootTag != null) {
            final XmlNSDescriptor nsDescriptor = rootTag.getNSDescriptor(rootTag.getNamespaceByPrefix(namespacePrefix), true);
            elementDescriptor = (nsDescriptor != null) ? nsDescriptor.getElementDescriptor(tagFromText) : null;
          }
        }

        if (elementDescriptor != null) {
          PsiElement declaration = elementDescriptor.getDeclaration();
          if (declaration!=null) declaration.putUserData(DESCRIPTOR_KEY,elementDescriptor);
          return declaration;
        }
      }
      catch (IncorrectOperationException e) {
        LOG.error(e);
      }
    }

    if (object instanceof String && originalElement != null) {
      PsiElement result = findDeclWithName((String)object, originalElement);

      if (result == null && element != null) {
        XmlAttribute attribute = PsiTreeUtil.getParentOfType(originalElement, XmlAttribute.class, false);
        if (attribute != null) {
          XmlAttributeDescriptor descriptor = attribute.getDescriptor();
          if (descriptor != null && descriptor.getDeclaration() instanceof XmlTag) {
            result = findEnumerationValue((String)object, (XmlTag)descriptor.getDeclaration());
          }
        }
      }
      return result;
    }
    if (object instanceof XmlElementDescriptor) {
      return ((XmlElementDescriptor)object).getDeclaration();
    }
    return null;
  }
@Override
  public PsiElement getDocumentationElementForLookupItem(final PsiManager psiManager, Object object, PsiElement element)