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); } } }
public String[] knownNamespaces() { final PsiElement parentElement = getParent(); BidirectionalMap<String, String> map = initNamespaceMaps(parentElement); Set<String> known = Collections.emptySet(); if (map != null) { known = new HashSet<String>(map.values()); } if (parentElement instanceof XmlTag) { if (known.isEmpty()) return ((XmlTag) parentElement).knownNamespaces(); ContainerUtil.addAll(known, ((XmlTag) parentElement).knownNamespaces()); } else { XmlExtension xmlExtension = XmlExtension.getExtensionByElement(this); if (xmlExtension != null) { final XmlFile xmlFile = xmlExtension.getContainingFile(this); if (xmlFile != null) { final XmlTag rootTag = xmlFile.getRootTag(); if (rootTag != null && rootTag != this) { if (known.isEmpty()) return rootTag.knownNamespaces(); ContainerUtil.addAll(known, rootTag.knownNamespaces()); } } } } return ArrayUtil.toStringArray(known); }
@Nullable private BidirectionalMap<String, String> computeNamespaceMap(PsiElement parent) { BidirectionalMap<String, String> map = null; if (hasNamespaceDeclarations()) { map = new BidirectionalMap<String, String>(); final XmlAttribute[] attributes = getAttributes(); for (final XmlAttribute attribute : attributes) { if (attribute.isNamespaceDeclaration()) { final String name = attribute.getName(); int splitIndex = name.indexOf(':'); final String value = getRealNs(attribute.getValue()); if (value != null) { if (splitIndex < 0) { map.put("", value); } else { map.put(XmlUtil.findLocalNameByQualifiedName(name), value); } } } } } if (parent instanceof XmlDocument) { final XmlExtension extension = XmlExtension.getExtensionByElement(parent); if (extension != null) { final String[][] defaultNamespace = extension.getNamespacesFromDocument((XmlDocument) parent, map != null); if (defaultNamespace != null) { if (map == null) { map = new BidirectionalMap<String, String>(); } for (final String[] prefix2ns : defaultNamespace) { map.put(prefix2ns[0], getRealNs(prefix2ns[1])); } } } } return map; }
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 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 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); } } }
private XmlNSDescriptor getDefaultNSDescriptorInner( final String namespace, final boolean strict) { final XmlFile containingFile = XmlUtil.getContainingFile(this); if (containingFile == null) return null; final XmlProlog prolog = getProlog(); final XmlDoctype doctype = prolog != null ? prolog.getDoctype() : null; boolean dtdUriFromDocTypeIsNamespace = false; if (XmlUtil.HTML_URI.equals(namespace)) { XmlNSDescriptor nsDescriptor = doctype != null ? getNsDescriptorFormDocType(doctype, containingFile, true) : null; if (doctype != null) { LOG.debug( "Descriptor from doctype " + doctype + " is " + (nsDescriptor != null ? nsDescriptor.getClass().getCanonicalName() : "NULL")); } if (nsDescriptor == null) { String htmlns = ExternalResourceManagerEx.getInstanceEx().getDefaultHtmlDoctype(getProject()); if (htmlns.isEmpty()) { htmlns = Html5SchemaProvider.getHtml5SchemaLocation(); } nsDescriptor = getDefaultNSDescriptor(htmlns, false); } return new HtmlNSDescriptorImpl(nsDescriptor); } else if (XmlUtil.XHTML_URI.equals(namespace)) { String xhtmlNamespace = XmlUtil.getDefaultXhtmlNamespace(getProject()); if (xhtmlNamespace == null || xhtmlNamespace.isEmpty()) { xhtmlNamespace = Html5SchemaProvider.getXhtml5SchemaLocation(); } return getDefaultNSDescriptor(xhtmlNamespace, false); } else if (namespace != null && namespace != XmlUtil.EMPTY_URI) { if (doctype == null || !namespace.equals(XmlUtil.getDtdUri(doctype))) { boolean documentIsSchemaThatDefinesNs = namespace.equals(XmlUtil.getTargetSchemaNsFromTag(getRootTag())); final XmlFile xmlFile = documentIsSchemaThatDefinesNs ? containingFile : XmlUtil.findNamespace(containingFile, namespace); if (xmlFile != null) { final XmlDocument document = xmlFile.getDocument(); if (document != null) { return (XmlNSDescriptor) document.getMetaData(); } } } else { dtdUriFromDocTypeIsNamespace = true; } } if (strict && !dtdUriFromDocTypeIsNamespace) return null; if (doctype != null) { XmlNSDescriptor descr = getNsDescriptorFormDocType(doctype, containingFile, false); if (descr != null) { return XmlExtension.getExtension(containingFile) .getDescriptorFromDoctype(containingFile, descr); } } if (strict) return null; if (namespace == XmlUtil.EMPTY_URI) { final XmlFile xmlFile = XmlUtil.findNamespace(containingFile, namespace); if (xmlFile != null) { return (XmlNSDescriptor) xmlFile.getDocument().getMetaData(); } } try { final PsiFile fileFromText = PsiFileFactory.getInstance(getProject()) .createFileFromText( containingFile.getName() + ".dtd", DTDLanguage.INSTANCE, XmlUtil.generateDocumentDTD(this, false), false, false); if (fileFromText instanceof XmlFile) { fileFromText.putUserData(AUTO_GENERATED, Boolean.TRUE); return (XmlNSDescriptor) ((XmlFile) fileFromText).getDocument().getMetaData(); } } catch (ProcessCanceledException ex) { throw ex; } catch (RuntimeException ignored) { } // e.g. dtd isn't mapped to xml type return null; }
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); } }