blob: bb376dc83eb7e037e0abe1cce4b04b59ee871e4f [file] [log] [blame]
/*
* Copyright 2000-2009 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.codeInspection;
import com.intellij.codeHighlighting.HighlightDisplayLevel;
import com.intellij.codeHighlighting.TextEditorHighlightingPass;
import com.intellij.codeInsight.daemon.impl.*;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiFile;
import com.intellij.util.NotNullProducer;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.FilteringIterator;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
public abstract class DefaultHighlightVisitorBasedInspection extends GlobalSimpleInspectionTool {
private final boolean highlightErrorElements;
private final boolean runAnnotators;
public DefaultHighlightVisitorBasedInspection(boolean highlightErrorElements, boolean runAnnotators) {
this.highlightErrorElements = highlightErrorElements;
this.runAnnotators = runAnnotators;
}
public static class AnnotatorBasedInspection extends DefaultHighlightVisitorBasedInspection {
public static final String ANNOTATOR_SHORT_NAME = "Annotator";
public AnnotatorBasedInspection() {
super(false, true);
}
@Nls
@NotNull
@Override
public String getDisplayName() {
return getShortName();
}
@NotNull
@Override
public String getShortName() {
return ANNOTATOR_SHORT_NAME;
}
}
public static class SyntaxErrorInspection extends DefaultHighlightVisitorBasedInspection {
public SyntaxErrorInspection() {
super(true, false);
}
@Nls
@NotNull
@Override
public String getDisplayName() {
return "Syntax error";
}
@NotNull
@Override
public String getShortName() {
return "SyntaxError";
}
}
@NotNull
@Override
public HighlightDisplayLevel getDefaultLevel() {
return HighlightDisplayLevel.ERROR;
}
@Override
public void checkFile(@NotNull PsiFile originalFile,
@NotNull final InspectionManager manager,
@NotNull ProblemsHolder problemsHolder,
@NotNull final GlobalInspectionContext globalContext,
@NotNull final ProblemDescriptionsProcessor problemDescriptionsProcessor) {
for (Pair<PsiFile, HighlightInfo> pair : runGeneralHighlighting(originalFile, highlightErrorElements, runAnnotators,
problemsHolder.isOnTheFly())) {
PsiFile file = pair.first;
HighlightInfo info = pair.second;
TextRange range = new TextRange(info.startOffset, info.endOffset);
PsiElement element = file.findElementAt(info.startOffset);
while (element != null && !element.getTextRange().contains(range)) {
element = element.getParent();
}
if (element == null) {
element = file;
}
GlobalInspectionUtil.createProblem(
element,
info,
range.shiftRight(-element.getNode().getStartOffset()),
info.getProblemGroup(),
manager,
problemDescriptionsProcessor,
globalContext
);
}
}
public static List<Pair<PsiFile,HighlightInfo>> runGeneralHighlighting(PsiFile file,
final boolean highlightErrorElements,
final boolean runAnnotators, boolean isOnTheFly) {
MyPsiElementVisitor visitor = new MyPsiElementVisitor(highlightErrorElements, runAnnotators, isOnTheFly);
file.accept(visitor);
return new ArrayList<Pair<PsiFile, HighlightInfo>>(visitor.result);
}
@Nls
@NotNull
@Override
public String getGroupDisplayName() {
return GENERAL_GROUP_NAME;
}
private static class MyPsiElementVisitor extends PsiElementVisitor {
private final boolean highlightErrorElements;
private final boolean runAnnotators;
private final boolean myOnTheFly;
private List<Pair<PsiFile, HighlightInfo>> result = new ArrayList<Pair<PsiFile, HighlightInfo>>();
public MyPsiElementVisitor(boolean highlightErrorElements, boolean runAnnotators, boolean isOnTheFly) {
this.highlightErrorElements = highlightErrorElements;
this.runAnnotators = runAnnotators;
myOnTheFly = isOnTheFly;
}
@Override
public void visitFile(final PsiFile file) {
final VirtualFile virtualFile = file.getVirtualFile();
if (virtualFile == null) {
return;
}
final Project project = file.getProject();
Document document = PsiDocumentManager.getInstance(project).getDocument(file);
if (document == null) return;
//final HighlightInfoFilter[] filters = ApplicationManager.getApplication().getExtensions(HighlightInfoFilter.EXTENSION_POINT_NAME);
DaemonProgressIndicator progress = new DaemonProgressIndicator();
progress.start();
TextEditorHighlightingPassRegistrarEx passRegistrarEx = TextEditorHighlightingPassRegistrarEx.getInstanceEx(project);
List<TextEditorHighlightingPass> passes = passRegistrarEx.instantiateMainPasses(file, document, HighlightInfoProcessor.getEmpty());
List<GeneralHighlightingPass> gpasses = ContainerUtil.collect(passes.iterator(), FilteringIterator.instanceOf(GeneralHighlightingPass.class));
for (final GeneralHighlightingPass gpass : gpasses) {
gpass.setHighlightVisitorProducer(new NotNullProducer<HighlightVisitor[]>() {
@NotNull
@Override
public HighlightVisitor[] produce() {
gpass.incVisitorUsageCount(1);
return new HighlightVisitor[]{new DefaultHighlightVisitor(project, highlightErrorElements, runAnnotators, true)};
}
});
}
for (TextEditorHighlightingPass pass : gpasses) {
pass.doCollectInformation(progress);
List<HighlightInfo> infos = pass.getInfos();
for (HighlightInfo info : infos) {
if (info == null) continue;
//if (info.type == HighlightInfoType.INJECTED_LANGUAGE_FRAGMENT) continue;
if (info.getSeverity().compareTo(HighlightSeverity.INFORMATION) <= 0) continue;
result.add(Pair.create(file, info));
}
}
//GeneralHighlightingPass pass =
// new GeneralHighlightingPass(project, file, document, 0, file.getTextLength(), true, new ProperTextRange(0, document.getTextLength()), null, HighlightInfoProcessor.getEmpty()) {
// @NotNull
// @Override
// protected HighlightVisitor[] createHighlightVisitors() {
// return new HighlightVisitor[]{new DefaultHighlightVisitor(project, highlightErrorElements, runAnnotators, true)};
// }
//
// @Override
// protected HighlightInfoHolder createInfoHolder(final PsiFile file) {
// return new CustomHighlightInfoHolder(file, getColorsScheme(), filters) {
// @Override
// public boolean add(@Nullable HighlightInfo info) {
// if (info == null) return true;
// if (info.type == HighlightInfoType.INJECTED_LANGUAGE_FRAGMENT) return true;
// if (info.getSeverity() == HighlightSeverity.INFORMATION) return true;
//
// result.add(Pair.create(file, info));
//
// return true;
// }
// };
// }
//
// @Override
// protected boolean isFailFastOnAcquireReadAction() {
// return myOnTheFly;
// }
// };
//progress.start();
//pass.collectInformation(progress);
}
}
}