private void checkTagByDescriptor(final XmlTag tag) { String name = tag.getName(); XmlElementDescriptor elementDescriptor; final PsiElement parent = tag.getParent(); if (parent instanceof XmlTag) { XmlTag parentTag = (XmlTag) parent; elementDescriptor = XmlUtil.getDescriptorFromContext(tag); final XmlElementDescriptor parentDescriptor = parentTag.getDescriptor(); if (parentDescriptor != null && elementDescriptor == null && shouldBeValidated(tag)) { if (tag instanceof HtmlTag) { // XmlEntitiesInspection inspection = getInspectionProfile(tag, // HtmlStyleLocalInspection.SHORT_NAME); // if (inspection != null /*&& // isAdditionallyDeclared(inspection.getAdditionalEntries(XmlEntitiesInspection.UNKNOWN_TAG), name)*/) { return; // } } addElementsForTag( tag, XmlErrorMessages.message("element.is.not.allowed.here", name), getTagProblemInfoType(tag), null); return; } if (elementDescriptor instanceof AnyXmlElementDescriptor || elementDescriptor == null) { elementDescriptor = tag.getDescriptor(); } if (elementDescriptor == null) return; } else { // root tag elementDescriptor = tag.getDescriptor(); if (elementDescriptor == null) { addElementsForTag( tag, XmlErrorMessages.message("element.must.be.declared", name), HighlightInfoType.WRONG_REF, null); return; } } checkRequiredAttributes(tag, name, elementDescriptor); if (elementDescriptor instanceof Validator) { //noinspection unchecked ((Validator<XmlTag>) elementDescriptor).validate(tag, this); } }
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); } } }
@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 checkRequiredAttributes( XmlTag tag, String name, XmlElementDescriptor elementDescriptor) { XmlAttributeDescriptor[] attributeDescriptors = elementDescriptor.getAttributesDescriptors(tag); Set<String> requiredAttributes = null; for (XmlAttributeDescriptor attribute : attributeDescriptors) { if (attribute != null && attribute.isRequired()) { if (requiredAttributes == null) { requiredAttributes = new HashSet<String>(); } requiredAttributes.add(attribute.getName(tag)); } } if (requiredAttributes != null) { for (final String attrName : requiredAttributes) { if (tag.getAttribute(attrName, "") == null && !XmlExtension.getExtension(tag.getContainingFile()) .isRequiredAttributeImplicitlyPresent(tag, attrName)) { final InsertRequiredAttributeFix insertRequiredAttributeIntention = new InsertRequiredAttributeFix(tag, attrName, null); final String localizedMessage = XmlErrorMessages.message("element.doesnt.have.required.attribute", name, attrName); final InspectionProfile profile = InspectionProjectProfileManager.getInstance(tag.getProject()).getInspectionProfile(); final LocalInspectionToolWrapper toolWrapper = (LocalInspectionToolWrapper) profile.getInspectionTool(RequiredAttributesInspection.SHORT_NAME, tag); if (toolWrapper != null) { RequiredAttributesInspection inspection = (RequiredAttributesInspection) toolWrapper.getTool(); reportOneTagProblem( tag, attrName, localizedMessage, insertRequiredAttributeIntention, HighlightDisplayKey.find(RequiredAttributesInspection.SHORT_NAME), inspection, XmlEntitiesInspection.NOT_REQUIRED_ATTRIBUTE); } } } } }
public static String getErrorDescription(final PsiReference reference) { String message; if (reference instanceof EmptyResolveMessageProvider) { message = ((EmptyResolveMessageProvider) reference).getUnresolvedMessagePattern(); } else { //noinspection UnresolvedPropertyKey message = PsiBundle.message("cannot.resolve.symbol"); } String description; try { description = MessageFormat.format(message, reference.getCanonicalText()); } catch (IllegalArgumentException ex) { // unresolvedMessage provided by third-party reference contains wrong format string (e.g. {}), // tolerate it description = message; LOG.warn( XmlErrorMessages.message( "plugin.reference.message.problem", reference.getClass().getName(), message)); } return description; }
private void checkAttribute(XmlAttribute attribute) { XmlTag tag = attribute.getParent(); final String name = attribute.getName(); PsiElement prevLeaf = PsiTreeUtil.prevLeaf(attribute); if (!(prevLeaf instanceof PsiWhiteSpace)) { TextRange textRange = attribute.getTextRange(); addToResults( HighlightInfo.createHighlightInfo( tag instanceof HtmlTag ? HighlightInfoType.WARNING : HighlightInfoType.ERROR, textRange.getStartOffset(), textRange.getStartOffset(), XmlErrorMessages.message("attribute.should.be.preceded.with.space"))); } if (attribute.isNamespaceDeclaration()) { checkReferences(attribute.getValueElement()); return; } final String namespace = attribute.getNamespace(); if (XmlUtil.XML_SCHEMA_INSTANCE_URI.equals(namespace)) { checkReferences(attribute.getValueElement()); return; } XmlElementDescriptor elementDescriptor = tag.getDescriptor(); if (elementDescriptor == null || elementDescriptor instanceof AnyXmlElementDescriptor || ourDoJaxpTesting) { return; } XmlAttributeDescriptor attributeDescriptor = elementDescriptor.getAttributeDescriptor(attribute); if (attributeDescriptor == null) { if (!XmlUtil.attributeFromTemplateFramework(name, tag)) { final String localizedMessage = XmlErrorMessages.message("attribute.is.not.allowed.here", name); final HighlightInfo highlightInfo = reportAttributeProblem(tag, name, attribute, localizedMessage); if (highlightInfo != null) { final XmlFile xmlFile = (XmlFile) tag.getContainingFile(); if (xmlFile != null) { XmlExtension.getExtension(xmlFile).createAddAttributeFix(attribute, highlightInfo); } } } } else { checkDuplicateAttribute(tag, attribute); if (tag instanceof HtmlTag && attribute.getValueElement() == null && !HtmlUtil.isSingleHtmlAttribute(name)) { final String localizedMessage = XmlErrorMessages.message("empty.attribute.is.not.allowed", name); reportAttributeProblem(tag, name, attribute, localizedMessage); } // we skip resolve of attribute references since there is separate check when taking attribute // descriptors PsiReference[] attrRefs = attribute.getReferences(); doCheckRefs(attribute, attrRefs, attribute.getNamespacePrefix().length() > 0 ? 2 : 1); } }