run highlight visitors for injected fragments
[fedora-idea.git] / platform / lang-impl / src / com / intellij / codeInsight / daemon / impl / analysis / DefaultHighlightVisitor.java
blob79b10a407bf81d7fb6a7aac137ab50c3a9f63764
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.intellij.codeInsight.daemon.impl.analysis;
19 import com.intellij.codeInsight.daemon.impl.*;
20 import com.intellij.codeInsight.highlighting.HighlightErrorFilter;
21 import com.intellij.lang.Language;
22 import com.intellij.lang.LanguageAnnotators;
23 import com.intellij.lang.annotation.Annotation;
24 import com.intellij.lang.annotation.Annotator;
25 import com.intellij.openapi.extensions.ExtensionPointName;
26 import com.intellij.openapi.extensions.Extensions;
27 import com.intellij.openapi.project.DumbAware;
28 import com.intellij.openapi.project.DumbService;
29 import com.intellij.openapi.project.Project;
30 import com.intellij.openapi.util.TextRange;
31 import com.intellij.openapi.util.text.StringUtil;
32 import com.intellij.psi.*;
33 import org.jetbrains.annotations.NotNull;
35 import java.util.Collection;
36 import java.util.List;
38 /**
39 * @author yole
41 public class DefaultHighlightVisitor extends PsiElementVisitor implements HighlightVisitor, DumbAware {
42 private final AnnotationHolderImpl myAnnotationHolder = new AnnotationHolderImpl();
43 private HighlightInfoHolder myHolder;
45 public static final ExtensionPointName<HighlightErrorFilter> FILTER_EP_NAME = ExtensionPointName.create("com.intellij.highlightErrorFilter");
46 private final HighlightErrorFilter[] myErrorFilters;
47 private final Project myProject;
49 public DefaultHighlightVisitor(Project project) {
50 myProject = project;
51 myErrorFilters = Extensions.getExtensions(FILTER_EP_NAME, project);
54 public boolean suitableForFile(final PsiFile file) {
55 return true;
58 public void visit(final PsiElement element, final HighlightInfoHolder holder) {
59 myHolder = holder;
60 assert !myAnnotationHolder.hasAnnotations() : myAnnotationHolder;
61 element.accept(this);
64 public boolean analyze(final Runnable action, final boolean updateWholeFile, final PsiFile file) {
65 try {
66 action.run();
68 finally {
69 myAnnotationHolder.clear();
70 myHolder = null;
72 return true;
75 public HighlightVisitor clone() {
76 return new DefaultHighlightVisitor(myProject);
79 public int order() {
80 return 2;
83 public void visitElement(final PsiElement element) {
84 runAnnotators(element);
87 private static final PerThreadMap<Annotator,Language> cachedAnnotators = new PerThreadMap<Annotator, Language>() {
88 @NotNull
89 @Override
90 public Collection<Annotator> initialValue(@NotNull Language key) {
91 return LanguageAnnotators.INSTANCE.allForLanguage(key);
95 private void runAnnotators(final PsiElement element) {
96 List<Annotator> annotators = cachedAnnotators.get(element.getLanguage());
97 if (!annotators.isEmpty()) {
98 final boolean dumb = DumbService.getInstance(myProject).isDumb();
99 //noinspection ForLoopReplaceableByForEach
100 for (int i = 0; i < annotators.size(); i++) {
101 Annotator annotator = annotators.get(i);
102 if (dumb && !(annotator instanceof DumbAware)) {
103 continue;
106 annotator.annotate(element, myAnnotationHolder);
108 if (myAnnotationHolder.hasAnnotations()) {
109 for (Annotation annotation : myAnnotationHolder) {
110 myHolder.add(HighlightInfo.fromAnnotation(annotation));
112 myAnnotationHolder.clear();
117 public void visitErrorElement(final PsiErrorElement element) {
118 for(HighlightErrorFilter errorFilter: myErrorFilters) {
119 if (!errorFilter.shouldHighlightErrorElement(element)) return;
122 HighlightInfo info = createErrorElementInfo(element);
123 myHolder.add(info);
126 public static HighlightInfo createErrorElementInfo(final PsiErrorElement element) {
127 TextRange range = element.getTextRange();
128 if (!range.isEmpty()) {
129 final HighlightInfo highlightInfo = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, range, element.getErrorDescription());
130 for(ErrorQuickFixProvider provider: Extensions.getExtensions(ErrorQuickFixProvider.EP_NAME)) {
131 provider.registerErrorQuickFix(element, highlightInfo);
133 return highlightInfo;
135 int offset = range.getStartOffset();
136 PsiFile containingFile = element.getContainingFile();
137 int fileLength = containingFile.getTextLength();
138 FileViewProvider viewProvider = containingFile.getViewProvider();
139 PsiElement elementAtOffset = viewProvider.findElementAt(offset, viewProvider.getBaseLanguage());
140 String text = elementAtOffset == null ? null : elementAtOffset.getText();
141 HighlightInfo info;
142 if (offset < fileLength && text != null && !StringUtil.startsWithChar(text, '\n') && !StringUtil.startsWithChar(text, '\r')) {
143 info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, offset, offset + 1, element.getErrorDescription());
145 else {
146 int start;
147 int end;
148 if (offset > 0) {
149 start = offset/* - 1*/;
150 end = offset;
152 else {
153 start = offset;
154 end = offset < fileLength ? offset + 1 : offset;
156 info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, element, start, end, element.getErrorDescription(),element.getErrorDescription(), true, null);
158 return info;