/* * Copyright 2007 Sascha Weinreuter * * 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 org.intellij.plugins.relaxNG.compact; import com.intellij.codeInsight.daemon.EmptyResolveMessageProvider; import com.intellij.codeInspection.*; import com.intellij.lang.annotation.Annotation; import com.intellij.lang.annotation.AnnotationHolder; import com.intellij.lang.annotation.Annotator; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiPolyVariantReference; import com.intellij.psi.PsiReference; import org.intellij.plugins.relaxNG.compact.psi.*; import org.jetbrains.annotations.NotNull; import java.text.MessageFormat; public class ReferenceAnnotator extends RncElementVisitor implements Annotator { private AnnotationHolder myHolder; @Override public synchronized void annotate(@NotNull PsiElement psiElement, @NotNull AnnotationHolder holder) { myHolder = holder; try { psiElement.accept(this); } finally { myHolder = null; } } @Override public void visitInclude(RncInclude include) { checkReferences(include.getReferences()); } @Override public void visitExternalRef(RncExternalRef ref) { checkReferences(ref.getReferences()); } @Override public void visitRef(RncRef pattern) { checkReferences(pattern.getReferences()); } @Override public void visitParentRef(RncParentRef pattern) { checkReferences(pattern.getReferences()); } @Override public void visitName(RncName name) { checkReferences(name.getReferences()); } private void checkReferences(PsiReference[] references) { for (PsiReference reference : references) { if (!reference.isSoft()) { if (reference.resolve() == null) { if (reference instanceof PsiPolyVariantReference) { final PsiPolyVariantReference pvr = (PsiPolyVariantReference)reference; if (pvr.multiResolve(false).length == 0) { addError(reference); } } else { addError(reference); } } } } } private void addError(PsiReference reference) { final TextRange rangeInElement = reference.getRangeInElement(); final TextRange range = TextRange.from(reference.getElement().getTextRange().getStartOffset() + rangeInElement.getStartOffset(), rangeInElement.getLength()); final Annotation annotation; if (reference instanceof EmptyResolveMessageProvider) { final String s = ((EmptyResolveMessageProvider)reference).getUnresolvedMessagePattern(); annotation = myHolder.createErrorAnnotation(range, MessageFormat.format(s, reference.getCanonicalText())); } else { annotation = myHolder.createErrorAnnotation(range, "Cannot resolve symbol"); } annotation.setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL); if (reference instanceof LocalQuickFixProvider) { LocalQuickFix[] fixes = ((LocalQuickFixProvider)reference).getQuickFixes(); if (fixes != null) { InspectionManager inspectionManager = InspectionManager.getInstance(reference.getElement().getProject()); for (LocalQuickFix fix : fixes) { ProblemDescriptor descriptor = inspectionManager.createProblemDescriptor(reference.getElement(), annotation.getMessage(), fix, ProblemHighlightType.LIKE_UNKNOWN_SYMBOL, true); annotation.registerFix(fix, null, null, descriptor); } } } } }