| /* |
| * Copyright 2000-2010 JetBrains s.r.o. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.intellij.lang.ant.validation; |
| |
| import com.intellij.lang.ant.AntBundle; |
| import com.intellij.lang.ant.dom.*; |
| import com.intellij.openapi.util.TextRange; |
| import com.intellij.psi.xml.XmlTag; |
| import com.intellij.util.StringBuilderSpinAllocator; |
| import com.intellij.util.xml.DomElement; |
| import com.intellij.util.xml.highlighting.DomElementAnnotationHolder; |
| import com.intellij.util.xml.highlighting.DomElementsAnnotator; |
| |
| import java.util.List; |
| |
| public class AntAnnotator implements DomElementsAnnotator { |
| |
| public void annotate(DomElement element, final DomElementAnnotationHolder holder) { |
| element.accept(new AntDomRecursiveVisitor() { |
| |
| public void visitTypeDef(AntDomTypeDef typedef) { |
| final List<String> errors = typedef.getErrorDescriptions(); |
| if (!errors.isEmpty()) { |
| final StringBuilder builder = StringBuilderSpinAllocator.alloc(); |
| try { |
| builder.append(AntBundle.message("failed.to.load.types")).append(":"); |
| for (String error : errors) { |
| builder.append("\n").append(error); |
| } |
| createAnnotationOnTag(typedef, builder.toString(), holder); |
| } |
| finally { |
| StringBuilderSpinAllocator.dispose(builder); |
| } |
| } |
| super.visitTypeDef(typedef); |
| } |
| |
| public void visitAntDomCustomElement(AntDomCustomElement custom) { |
| if (custom.getDefinitionClass() == null) { |
| final AntDomNamedElement declaringElement = custom.getDeclaringElement(); |
| if (declaringElement instanceof AntDomTypeDef) { |
| String failedMessage = AntBundle.message("using.definition.which.type.failed.to.load"); |
| final String error = custom.getLoadError(); |
| if (error != null) { |
| failedMessage = failedMessage + ": " + error; |
| } |
| createAnnotationOnTag(custom, failedMessage, holder); |
| } |
| } |
| super.visitAntDomCustomElement(custom); |
| } |
| |
| public void visitAntDomElement(AntDomElement element) { |
| //for (GenericDomValue child : DomUtil.getDefinedChildrenOfType(element, GenericDomValue.class, false, true)) { |
| // final XmlElement valueElement = DomUtil.getValueElement(child); |
| // if (valueElement != null) { |
| // checkReferences(valueElement, holder, child); |
| // } |
| //} |
| super.visitAntDomElement(element); |
| } |
| }); |
| } |
| |
| private static void createAnnotationOnTag(AntDomElement custom, String failedMessage, DomElementAnnotationHolder holder) { |
| final XmlTag tag = custom.getXmlTag(); |
| if (tag == null) { |
| return; |
| } |
| final String name = custom.getXmlElementName(); |
| final TextRange absoluteRange = new TextRange(0, name.length()).shiftRight(tag.getTextRange().getStartOffset() + 1); |
| holder.createProblem(custom, failedMessage); |
| //holder.createErrorAnnotation(absoluteRange, failedMessage); |
| } |
| |
| //private static void addDefinitionQuickFixes(final Annotation annotation, final AntStructuredElement se) { |
| // if (se.getSourceElement().getName().length() == 0) return; |
| // |
| // final AntProject project = se.getAntProject(); |
| // annotation.registerFix(new AntCreateMacroDefFix(se)); |
| // annotation.registerFix(new AntCreatePresetDefFix(se)); |
| // for (final AntFile antFile : project.getImportedFiles()) { |
| // annotation.registerFix(new AntCreateMacroDefFix(se, antFile)); |
| // annotation.registerFix(new AntCreatePresetDefFix(se, antFile)); |
| // } |
| //} |
| |
| //private static void checkValidAttributes(final AntStructuredElement se, final AntTypeDefinition def, final @NonNls AnnotationHolder holder) { |
| // final XmlTag sourceElement = se.getSourceElement(); |
| // for (final XmlAttribute attr : sourceElement.getAttributes()) { |
| // @NonNls final String name = attr.getName(); |
| // if (name.startsWith("xmlns")) continue; |
| // final AntAttributeType type = def.getAttributeType(name); |
| // final PsiElement attrName = attr.getFirstChild(); |
| // if (attrName != null) { |
| // if (type == null) { |
| // if (!isSuccessorOfUndefinedElement(se)) { |
| // holder.createErrorAnnotation(attrName, AntBundle.message("attribute.is.not.allowed.here", name)); |
| // } |
| // } |
| // else { |
| // final String attrValue = attr.getValue(); |
| // if (type == AntAttributeType.INTEGER) { |
| // try { |
| // Integer.parseInt(se.computeAttributeValue(attrValue)); |
| // } |
| // catch (NumberFormatException e) { |
| // holder.createErrorAnnotation(attrName, AntBundle.message("integer.attribute.has.invalid.value", name)); |
| // } |
| // } |
| // else if (type == AntAttributeType.STRING) { |
| // if (attrValue != null && AntProperty.TSTAMP_PATTERN_ATTRIBUTE_NAME.equalsIgnoreCase(name)) { |
| // final PsiElement parent = se.getParent(); |
| // if (parent instanceof AntProperty && ((AntProperty)parent).isTstamp()) { |
| // try { |
| // new SimpleDateFormat(attrValue); |
| // } |
| // catch (IllegalArgumentException e) { |
| // holder.createErrorAnnotation(attr.getValueElement(), e.getMessage()); |
| // } |
| // } |
| // } |
| // } |
| // } |
| // } |
| // } |
| //} |
| |
| //private static void checkReferences(final XmlElement xmlElement, final @NonNls DomElementAnnotationHolder holder, DomElement domElement) { |
| // if (xmlElement == null) { |
| // return; |
| // } |
| // Set<PsiReference> processed = null; |
| // for (final PsiReference ref : xmlElement.getReferences()) { |
| // if (!(ref instanceof AntDomReference)) { |
| // continue; |
| // } |
| // final AntDomReference antDomRef = (AntDomReference)ref; |
| // if (antDomRef.shouldBeSkippedByAnnotator()) { |
| // continue; |
| // } |
| // if (processed != null && processed.contains(ref)) { |
| // continue; |
| // } |
| // if (ref.resolve() == null) { |
| // final TextRange absoluteRange = ref.getRangeInElement().shiftRight(ref.getElement().getTextRange().getStartOffset()); |
| // final Annotation annotation = holder.createProblem(absoluteRange, antDomRef.getUnresolvedMessagePattern()); |
| // annotation.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL); |
| // if (ref instanceof AntDomFileReference) { |
| // if (processed == null) { |
| // processed = new HashSet<PsiReference>(); |
| // } |
| // ContainerUtil.addAll(processed, ((AntDomFileReference)ref).getFileReferenceSet().getAllReferences()); |
| // } |
| // |
| // //final IntentionAction[] intentionActions = antRef.getFixes(); |
| // //for (final IntentionAction action : intentionActions) { |
| // // annotation.registerFix(action); |
| // //} |
| // } |
| // } |
| //} |
| } |