blob: 9b2ef11a395ffcb598e1393cfacb0d856ac99eae [file] [log] [blame]
/*
* 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;
/**
* Created by IntelliJ IDEA.
* User: sweinreuter
* Date: 10.08.2007
*/
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);
}
}
}
}
}