void (final SAXParseException e, final ValidateXmlActionHandler.ProblemType warning) { try { ApplicationManager.getApplication().runReadAction(() -> { if (e.getPublicId() != null) { return; } final VirtualFile errorFile = myHandler.getProblemFile(e); if (!Comparing.equal(errorFile, file.getVirtualFile()) && errorFile != null) { return; // error in attached schema } if (document.getLineCount() < e.getLineNumber() || e.getLineNumber() <= 0) { return; } Validator.ValidationHost.ErrorType problemType = getProblemType(warning); int offset = Math.max(0, document.getLineStartOffset(e.getLineNumber() - 1) + e.getColumnNumber() - 2); if (offset >= document.getTextLength()) return; PsiElement currentElement = PsiDocumentManager.getInstance(project).getPsiFile(document).findElementAt(offset); PsiElement originalElement = currentElement; final String elementText = currentElement.getText(); if (elementText.equals("</")) { currentElement = currentElement.getNextSibling(); } else if (elementText.equals(">") || elementText.equals("/>") || elementText.equals("=")) { currentElement = currentElement.getPrevSibling(); } // Cannot find the declaration of element String localizedMessage = e.getLocalizedMessage(); // Ideally would be to switch one messageIds int endIndex = localizedMessage.indexOf(':'); if (endIndex < localizedMessage.length() - 1 && localizedMessage.charAt(endIndex + 1) == '/') { endIndex = -1; // ignore : in http:// } String messageId = endIndex != -1 ? localizedMessage.substring(0, endIndex ):""; localizedMessage = localizedMessage.substring(endIndex + 1).trim(); if ("cvc-elt.1.a".equals(messageId)) { XmlTag tag = PsiTreeUtil.getParentOfType(currentElement, XmlTag.class); if (tag != null && tag.getNamespace().isEmpty()) { // "Cannot find the declaration of element" is not helpful without schema return; } } else if ("SchemeUnsupported".equals(messageId)) { unsupportedSchemeAt = offset; return; } else if (unsupportedSchemeAt == offset && ("An 'include' failed, and no 'fallback' element was found.".equals(localizedMessage) || (e.getLocalizedMessage().startsWith("Include operation failed, reverting to fallback.")))) { return; } if (localizedMessage.startsWith(CANNOT_FIND_DECLARATION_ERROR_PREFIX) || localizedMessage.startsWith(ELEMENT_ERROR_PREFIX) || localizedMessage.startsWith(ROOT_ELEMENT_ERROR_PREFIX) || localizedMessage.startsWith(CONTENT_OF_ELEMENT_TYPE_ERROR_PREFIX) ) { addProblemToTagName(currentElement, originalElement, localizedMessage, warning); //return; } else if (localizedMessage.startsWith(VALUE_ERROR_PREFIX)) { addProblemToTagName(currentElement, originalElement, localizedMessage, warning); } else { if (messageId.startsWith(ATTRIBUTE_MESSAGE_PREFIX)) { @NonNls String prefix = "of attribute "; final int i = localizedMessage.indexOf(prefix); if (i != -1) { int messagePrefixLength = prefix.length() + i; final int nextQuoteIndex = localizedMessage.indexOf(localizedMessage.charAt(messagePrefixLength), messagePrefixLength + 1); String attrName = nextQuoteIndex == -1 ? null : localizedMessage.substring(messagePrefixLength + 1, nextQuoteIndex); XmlTag parent = PsiTreeUtil.getParentOfType(originalElement,XmlTag.class); currentElement = parent.getAttribute(attrName,null); if (currentElement != null) { currentElement = ((XmlAttribute)currentElement).getValueElement(); } } if (currentElement!=null) { assertValidElement(currentElement, originalElement,localizedMessage); myHost.addMessage(currentElement,localizedMessage, problemType); } else { addProblemToTagName(originalElement, originalElement, localizedMessage, warning); } } else if (localizedMessage.startsWith(ATTRIBUTE_ERROR_PREFIX)) { final int messagePrefixLength = ATTRIBUTE_ERROR_PREFIX.length(); if ( localizedMessage.charAt(messagePrefixLength) == '"' || localizedMessage.charAt(messagePrefixLength) == '\'' ) { // extract the attribute name from message and get it from tag! final int nextQuoteIndex = localizedMessage.indexOf(localizedMessage.charAt(messagePrefixLength), messagePrefixLength + 1); String attrName = nextQuoteIndex == -1 ? null : localizedMessage.substring(messagePrefixLength + 1, nextQuoteIndex); XmlTag parent = PsiTreeUtil.getParentOfType(originalElement,XmlTag.class); currentElement = parent.getAttribute(attrName,null); if (currentElement!=null) { currentElement = SourceTreeToPsiMap.treeElementToPsi( XmlChildRole.ATTRIBUTE_NAME_FINDER.findChild( SourceTreeToPsiMap.psiElementToTree(currentElement) ) ); } } else { currentElement = PsiTreeUtil.getParentOfType(currentElement, XmlTag.class, false); } if (currentElement!=null) { assertValidElement(currentElement, originalElement,localizedMessage); myHost.addMessage(currentElement,localizedMessage, problemType); } else { addProblemToTagName(originalElement, originalElement, localizedMessage, warning); } } else if (localizedMessage.startsWith(STRING_ERROR_PREFIX)) { if (currentElement != null) { myHost.addMessage(currentElement,localizedMessage, Validator.ValidationHost.ErrorType.WARNING); } } else { currentElement = getNodeForMessage(currentElement != null ? currentElement:originalElement); assertValidElement(currentElement, originalElement,localizedMessage); if (currentElement!=null) { myHost.addMessage(currentElement,localizedMessage, problemType); } } } }); } catch (Exception ex) { if (ex instanceof ProcessCanceledException) throw (ProcessCanceledException)ex; if (ex instanceof XmlResourceResolver.IgnoredResourceException) throw (XmlResourceResolver.IgnoredResourceException)ex; LOG.error(ex); } }