mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-18 09:34:34 +07:00
replace highlighters after visible pass
This commit is contained in:
+11
-12
@@ -245,14 +245,6 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
|
||||
@Override public void visitClass(PsiClass aClass) {
|
||||
super.visitClass(aClass);
|
||||
if (aClass instanceof JspClass) return;
|
||||
if (aClass.isAnnotationType()) {
|
||||
if (!PsiUtil.isLanguageLevel5OrHigher(aClass)) {
|
||||
HighlightInfo info = HighlightInfo
|
||||
.createHighlightInfo(HighlightInfoType.ERROR, aClass.getNameIdentifier(), JavaErrorMessages.message("annotations.prior.15"));
|
||||
QuickFixAction.registerQuickFixAction(info, new IncreaseLanguageLevelFix(LanguageLevel.JDK_1_5));
|
||||
myHolder.add(info);
|
||||
}
|
||||
}
|
||||
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkInterfaceMultipleInheritance(aClass));
|
||||
if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkDuplicateTopLevelClass(aClass));
|
||||
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkEnumMustNotBeLocal(aClass));
|
||||
@@ -391,10 +383,17 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
|
||||
myHolder.add(HighlightUtil.checkVariableAlreadyDefined((PsiVariable)parent));
|
||||
}
|
||||
else if (parent instanceof PsiClass) {
|
||||
myHolder.add(HighlightClassUtil.checkClassAlreadyImported((PsiClass)parent, identifier));
|
||||
myHolder.add(HighlightClassUtil.checkExternalizableHasPublicNoArgsConstructor((PsiClass)parent, identifier));
|
||||
if (!(parent instanceof PsiAnonymousClass)) {
|
||||
myHolder.add(HighlightNamesUtil.highlightClassName((PsiClass)parent, ((PsiClass)parent).getNameIdentifier()));
|
||||
PsiClass aClass = (PsiClass)parent;
|
||||
if (aClass.isAnnotationType() && !PsiUtil.isLanguageLevel5OrHigher(aClass)) {
|
||||
HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, identifier, JavaErrorMessages.message("annotations.prior.15"));
|
||||
QuickFixAction.registerQuickFixAction(info, new IncreaseLanguageLevelFix(LanguageLevel.JDK_1_5));
|
||||
myHolder.add(info);
|
||||
}
|
||||
|
||||
myHolder.add(HighlightClassUtil.checkClassAlreadyImported(aClass, identifier));
|
||||
myHolder.add(HighlightClassUtil.checkExternalizableHasPublicNoArgsConstructor(aClass, identifier));
|
||||
if (!(parent instanceof PsiAnonymousClass) && aClass.getNameIdentifier() == identifier) {
|
||||
myHolder.add(HighlightNamesUtil.highlightClassName(aClass, identifier));
|
||||
}
|
||||
}
|
||||
else if (parent instanceof PsiMethod) {
|
||||
|
||||
+3
-3
@@ -103,7 +103,7 @@ public abstract class ImportClassFixBase<T extends PsiElement & PsiReference> im
|
||||
|
||||
public enum Result {
|
||||
POPUP_SHOWN,
|
||||
CLASS_IMPORTED,
|
||||
CLASS_AUTO_IMPORTED,
|
||||
POPUP_NOT_SHOWN
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ public abstract class ImportClassFixBase<T extends PsiElement & PsiReference> im
|
||||
action.execute();
|
||||
}
|
||||
});
|
||||
return Result.CLASS_IMPORTED;
|
||||
return Result.CLASS_AUTO_IMPORTED;
|
||||
}
|
||||
|
||||
if (doShow && canImportHere) {
|
||||
@@ -174,7 +174,7 @@ public abstract class ImportClassFixBase<T extends PsiElement & PsiReference> im
|
||||
return false;
|
||||
}
|
||||
Result result = doFix(editor, true, false);
|
||||
return result == Result.POPUP_SHOWN || result == Result.CLASS_IMPORTED;
|
||||
return result == Result.POPUP_SHOWN || result == Result.CLASS_AUTO_IMPORTED;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -205,7 +205,7 @@ public class ImportHelperTest extends DaemonAnalyzerTestCase {
|
||||
|
||||
myEditor.getCaretModel().moveToOffset(offset - 1);
|
||||
result = new ImportClassFix((PsiJavaCodeReferenceElement)ref).doFix(getEditor(), true, false);
|
||||
assertEquals(ImportClassFixBase.Result.CLASS_IMPORTED, result);
|
||||
assertEquals(ImportClassFixBase.Result.CLASS_AUTO_IMPORTED, result);
|
||||
UIUtil.dispatchAllInvocationEvents();
|
||||
|
||||
assertEmpty(filter(doHighlighting(), HighlightSeverity.ERROR));
|
||||
@@ -234,7 +234,7 @@ public class ImportHelperTest extends DaemonAnalyzerTestCase {
|
||||
assertTrue(ref instanceof PsiJavaCodeReferenceElement);
|
||||
|
||||
ImportClassFixBase.Result result = new ImportClassFix((PsiJavaCodeReferenceElement)ref).doFix(getEditor(), true, false);
|
||||
assertEquals(ImportClassFixBase.Result.CLASS_IMPORTED, result);
|
||||
assertEquals(ImportClassFixBase.Result.CLASS_AUTO_IMPORTED, result);
|
||||
UIUtil.dispatchAllInvocationEvents();
|
||||
|
||||
assertEmpty(filter(doHighlighting(), HighlightSeverity.ERROR));
|
||||
@@ -265,7 +265,7 @@ public class ImportHelperTest extends DaemonAnalyzerTestCase {
|
||||
(PsiJavaCodeReferenceElement)getFile().findReferenceAt(getEditor().getCaretModel().getOffset() - 2);
|
||||
ImportClassFix fix = new ImportClassFix(element);
|
||||
ImportClassFixBase.Result result = fix.doFix(getEditor(), false, false);
|
||||
assertEquals(ImportClassFixBase.Result.CLASS_IMPORTED, result);
|
||||
assertEquals(ImportClassFixBase.Result.CLASS_AUTO_IMPORTED, result);
|
||||
|
||||
assertNotSame(0, ((PsiJavaFile)getFile()).getImportList().getAllImportStatements().length);
|
||||
}
|
||||
|
||||
@@ -52,19 +52,21 @@ public class Divider {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void getInsideAndOutside(@NotNull PsiFile root,
|
||||
int startOffset,
|
||||
int endOffset,
|
||||
@NotNull TextRange range,
|
||||
@NotNull List<PsiElement> inside,
|
||||
@NotNull List<PsiElement> outside) {
|
||||
@NotNull List<PsiElement> outside
|
||||
) {
|
||||
final int currentOffset = root.getTextRange().getStartOffset();
|
||||
final Condition<PsiElement>[] filters = Extensions.getExtensions(CollectHighlightsUtil.EP_NAME);
|
||||
|
||||
int offset = currentOffset;
|
||||
|
||||
final TIntStack starts = new TIntStack(STARTING_TREE_HEIGHT);
|
||||
starts.push(startOffset);
|
||||
final Stack<PsiElement> elements = new Stack<PsiElement>(STARTING_TREE_HEIGHT);
|
||||
final Stack<PsiElement> children = new Stack<PsiElement>(STARTING_TREE_HEIGHT);
|
||||
PsiElement element = root;
|
||||
@@ -96,7 +98,6 @@ public class Divider {
|
||||
offset += element.getTextLength();
|
||||
}
|
||||
|
||||
if (elements.isEmpty()) break;
|
||||
int start = starts.pop();
|
||||
if (startOffset <= start && offset <= endOffset) {
|
||||
if (range.containsRange(start, offset)) {
|
||||
@@ -107,6 +108,7 @@ public class Divider {
|
||||
}
|
||||
}
|
||||
|
||||
if (elements.isEmpty()) break;
|
||||
element = elements.pop();
|
||||
child = children.pop();
|
||||
}
|
||||
@@ -120,7 +122,5 @@ public class Divider {
|
||||
child = PsiUtilBase.NULL_PSI_ELEMENT;
|
||||
}
|
||||
}
|
||||
|
||||
outside.add(root);
|
||||
}
|
||||
}
|
||||
|
||||
+200
-94
@@ -31,12 +31,15 @@ import com.intellij.lang.injection.InjectedLanguageManager;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.HighlighterColors;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.editor.colors.EditorColors;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsManager;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsScheme;
|
||||
import com.intellij.openapi.editor.colors.TextAttributesKey;
|
||||
import com.intellij.openapi.editor.ex.MarkupModelEx;
|
||||
import com.intellij.openapi.editor.markup.MarkupModel;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.fileTypes.SyntaxHighlighter;
|
||||
@@ -52,6 +55,7 @@ import com.intellij.problems.Problem;
|
||||
import com.intellij.problems.WolfTheProblemSolver;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
|
||||
import com.intellij.psi.impl.source.tree.injected.Place;
|
||||
import com.intellij.psi.search.PsiSearchHelper;
|
||||
import com.intellij.psi.search.TodoItem;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
@@ -60,6 +64,7 @@ import com.intellij.util.SmartList;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.*;
|
||||
@@ -74,10 +79,10 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP
|
||||
private final int myStartOffset;
|
||||
private final int myEndOffset;
|
||||
private final boolean myUpdateAll;
|
||||
private final TextRange myPriorityRange;
|
||||
private final ProperTextRange myPriorityRange;
|
||||
private final Editor myEditor;
|
||||
|
||||
private volatile Collection<HighlightInfo> myHighlights = Collections.emptyList();
|
||||
private final Map<TextRange,Collection<HighlightInfo>> myInjectedPsiHighlights = new HashMap<TextRange, Collection<HighlightInfo>>();
|
||||
private final Collection<HighlightInfo> myHighlights = new ArrayList<HighlightInfo>();
|
||||
|
||||
protected volatile boolean myHasErrorElement;
|
||||
private volatile boolean myErrorFound;
|
||||
@@ -86,15 +91,15 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP
|
||||
return o1.order() - o2.order();
|
||||
}
|
||||
};
|
||||
private Runnable myApplyCommand;
|
||||
|
||||
public GeneralHighlightingPass(@NotNull Project project,
|
||||
@NotNull PsiFile file,
|
||||
@NotNull Document document,
|
||||
int startOffset,
|
||||
int endOffset,
|
||||
boolean updateAll
|
||||
) {
|
||||
this(project, file, document, startOffset, endOffset, updateAll, new TextRange(0,0));
|
||||
boolean updateAll) {
|
||||
this(project, file, document, startOffset, endOffset, updateAll, new ProperTextRange(0,document.getTextLength()), null);
|
||||
}
|
||||
public GeneralHighlightingPass(@NotNull Project project,
|
||||
@NotNull PsiFile file,
|
||||
@@ -102,18 +107,29 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP
|
||||
int startOffset,
|
||||
int endOffset,
|
||||
boolean updateAll,
|
||||
@NotNull TextRange priorityRange) {
|
||||
@NotNull ProperTextRange priorityRange,
|
||||
@Nullable Editor editor) {
|
||||
super(project, document, PRESENTABLE_NAME, file, true);
|
||||
myStartOffset = startOffset;
|
||||
myEndOffset = endOffset;
|
||||
myUpdateAll = updateAll;
|
||||
myPriorityRange = priorityRange;
|
||||
myEditor = editor;
|
||||
|
||||
LOG.assertTrue(file.isValid());
|
||||
setId(Pass.UPDATE_ALL);
|
||||
myHasErrorElement = !isWholeFileHighlighting() && Boolean.TRUE.equals(myFile.getUserData(HAS_ERROR_ELEMENT));
|
||||
FileStatusMap fileStatusMap = ((DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(myProject)).getFileStatusMap();
|
||||
myErrorFound = !isWholeFileHighlighting() && fileStatusMap.wasErrorFound(myDocument);
|
||||
|
||||
myApplyCommand = new Runnable() {
|
||||
public void run() {
|
||||
ProperTextRange range = new ProperTextRange(myStartOffset, myEndOffset);
|
||||
MarkupModel model = myDocument.getMarkupModel(myProject);
|
||||
UpdateHighlightersUtil.cleanFileLevelHighlights(myProject, Pass.UPDATE_ALL,myFile);
|
||||
UpdateHighlightersUtil.setHighlightersInRange(range, myHighlights, (MarkupModelEx)model, Pass.UPDATE_ALL, myDocument, myProject);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static final Key<AtomicInteger> HIGHLIGHT_VISITOR_INSTANCE_COUNT = new Key<AtomicInteger>("HIGHLIGHT_VISITOR_INSTANCE_COUNT");
|
||||
@@ -144,26 +160,94 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP
|
||||
}
|
||||
|
||||
protected void collectInformationWithProgress(final ProgressIndicator progress) {
|
||||
final Collection<HighlightInfo> result = new THashSet<HighlightInfo>(100);
|
||||
final Set<HighlightInfo> result = new THashSet<HighlightInfo>(100);
|
||||
final Set<HighlightInfo> outsideResult = new THashSet<HighlightInfo>(100);
|
||||
|
||||
DaemonCodeAnalyzer daemonCodeAnalyzer = DaemonCodeAnalyzer.getInstance(myProject);
|
||||
FileStatusMap fileStatusMap = ((DaemonCodeAnalyzerImpl)daemonCodeAnalyzer).getFileStatusMap();
|
||||
final FileStatusMap fileStatusMap = ((DaemonCodeAnalyzerImpl)daemonCodeAnalyzer).getFileStatusMap();
|
||||
HighlightVisitor[] highlightVisitors = createHighlightVisitors();
|
||||
HighlightVisitor[] filteredVisitors = filterVisitors(highlightVisitors, myFile);
|
||||
List<PsiElement> inside = new ArrayList<PsiElement>();
|
||||
List<PsiElement> outside = new ArrayList<PsiElement>();
|
||||
final HighlightVisitor[] filteredVisitors = filterVisitors(highlightVisitors, myFile);
|
||||
final List<PsiElement> inside = new ArrayList<PsiElement>();
|
||||
final List<PsiElement> outside = new ArrayList<PsiElement>();
|
||||
try {
|
||||
Divider.getInsideAndOutside(myFile, myStartOffset, myEndOffset, myPriorityRange, inside, outside, HighlightLevelUtil.AnalysisLevel.HIGHLIGHT);
|
||||
final List<PsiFile> injectedInside = new ArrayList<PsiFile>();
|
||||
final List<PsiFile> injectedOutside = new ArrayList<PsiFile>();
|
||||
divideInjectedPsiHighlights(inside, outside, progress, injectedInside, injectedOutside);
|
||||
|
||||
List<PsiElement> elements = inside;
|
||||
elements.addAll(outside);
|
||||
setProgressLimit((long)(inside.size()+outside.size()) /** filteredVisitors.length*/);
|
||||
|
||||
result.addAll(collectHighlights(elements, progress, filteredVisitors));
|
||||
if (!addInjectedPsiHighlights(elements, progress)) throw new ProcessCanceledException();
|
||||
final boolean forceHighlightParents = forceHighlightParents();
|
||||
|
||||
if (!isDumbMode()) {
|
||||
result.addAll(highlightTodos(myFile, myDocument.getCharsSequence(), 0, myFile.getTextLength(), progress));
|
||||
highlightTodos(myFile, myDocument.getCharsSequence(), myStartOffset, myEndOffset, progress, myPriorityRange, result, outsideResult);
|
||||
}
|
||||
|
||||
collectHighlights(inside, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!addInjectedPsiHighlights(injectedInside, progress, Collections.synchronizedSet(result))) throw new ProcessCanceledException();
|
||||
|
||||
if (!outside.isEmpty() || !injectedOutside.isEmpty()) {
|
||||
if (!inside.isEmpty()) { // do not apply when there were no elements to highlight
|
||||
// clear infos found in visible area to avoid applying them twice
|
||||
final List<HighlightInfo> toApply = new ArrayList<HighlightInfo>(result.size());
|
||||
for (HighlightInfo info : result) {
|
||||
if (myPriorityRange.containsRange(info.getStartOffset(), info.getEndOffset())) {
|
||||
toApply.add(info);
|
||||
}
|
||||
else {
|
||||
outsideResult.add(info);
|
||||
}
|
||||
}
|
||||
myHighlights.addAll(toApply);
|
||||
result.clear();
|
||||
result.addAll(outsideResult);
|
||||
|
||||
UIUtil.invokeLaterIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (progress.isCanceled()) return;
|
||||
MarkupModel markupModel = myDocument.getMarkupModel(myProject);
|
||||
UpdateHighlightersUtil.cleanFileLevelHighlights(myProject, Pass.UPDATE_ALL, myFile);
|
||||
|
||||
UpdateHighlightersUtil.setHighlightersInRange(myPriorityRange, toApply, (MarkupModelEx)markupModel, Pass.UPDATE_ALL, myDocument, myProject);
|
||||
}
|
||||
});
|
||||
UIUtil.invokeLaterIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (progress.isCanceled() || myEditor == null) return;
|
||||
new ShowAutoImportPass(myProject, myFile, myEditor).applyInformationToEditor();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
final List<HighlightInfo> injectedOutsideInfos = Collections.synchronizedList(new ArrayList<HighlightInfo>());
|
||||
if (!addInjectedPsiHighlights(injectedOutside, progress, injectedOutsideInfos)) throw new ProcessCanceledException();
|
||||
|
||||
myApplyCommand = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
UpdateHighlightersUtil.setHighlightersToEditorOutsideRange(myProject, myDocument, result, myStartOffset, myEndOffset, myPriorityRange, Pass.UPDATE_ALL);
|
||||
Map<TextRange,Collection<HighlightInfo>> myInjectedPsiHighlights = new HashMap<TextRange, Collection<HighlightInfo>>();
|
||||
for (HighlightInfo info : injectedOutsideInfos) {
|
||||
TextRange textRange = new TextRange(info.getStartOffset(), info.getEndOffset());
|
||||
Collection<HighlightInfo> storedInfos = myInjectedPsiHighlights.get(textRange);
|
||||
if (storedInfos == null) {
|
||||
storedInfos = new SmartList<HighlightInfo>();
|
||||
myInjectedPsiHighlights.put(textRange, storedInfos);
|
||||
}
|
||||
storedInfos.add(info);
|
||||
}
|
||||
|
||||
UpdateHighlightersUtil.setHighlightersToEditor(myProject, myDocument, myInjectedPsiHighlights, Pass.UPDATE_ALL);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}, outside, progress, filteredVisitors, result, forceHighlightParents);
|
||||
|
||||
if (myUpdateAll) {
|
||||
fileStatusMap.setErrorFoundFlag(myDocument, myErrorFound);
|
||||
}
|
||||
@@ -171,17 +255,21 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP
|
||||
finally {
|
||||
incVisitorUsageCount(-1);
|
||||
}
|
||||
myHighlights = result;
|
||||
myHighlights.addAll(result);
|
||||
}
|
||||
|
||||
// returns false if canceled
|
||||
private boolean addInjectedPsiHighlights(@NotNull final List<PsiElement> elements, final ProgressIndicator progress) {
|
||||
private void divideInjectedPsiHighlights(@NotNull final List<PsiElement> elements1,
|
||||
@NotNull final List<PsiElement> elements2,
|
||||
@NotNull final ProgressIndicator progress,
|
||||
@NotNull List<PsiFile> inside,
|
||||
@NotNull List<PsiFile> outside) {
|
||||
List<DocumentWindow> injected = InjectedLanguageUtil.getCachedInjectedDocuments(myFile);
|
||||
Collection<PsiElement> hosts = new THashSet<PsiElement>(elements.size() + injected.size());
|
||||
Collection<PsiElement> hosts = new THashSet<PsiElement>(elements1.size() + elements2.size() + injected.size());
|
||||
|
||||
// rehighlight all injected PSI regardless the range,
|
||||
// since change in one place can lead to invalidation of injected PSI in (completely) other place.
|
||||
for (DocumentWindow documentRange : injected) {
|
||||
progress.checkCanceled();
|
||||
if (!documentRange.isValid()) continue;
|
||||
PsiFile file = PsiDocumentManager.getInstance(myProject).getPsiFile(documentRange);
|
||||
if (file == null) continue;
|
||||
@@ -193,40 +281,50 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP
|
||||
hosts.add(context);
|
||||
}
|
||||
}
|
||||
hosts.addAll(elements);
|
||||
|
||||
final Collection<PsiFile> injectedFiles = new THashSet<PsiFile>();
|
||||
EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme();
|
||||
final TextAttributes injectedAttributes = scheme.getAttributes(EditorColors.INJECTED_LANGUAGE_FRAGMENT);
|
||||
hosts.addAll(elements1);
|
||||
hosts.addAll(elements2);
|
||||
|
||||
for (PsiElement element : hosts) {
|
||||
progress.checkCanceled();
|
||||
final List<PsiFile> destination = myPriorityRange.contains(element.getTextRange()) ? inside : outside;
|
||||
InjectedLanguageUtil.enumerate(element, myFile, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
|
||||
public void visit(@NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) {
|
||||
if (injectedFiles.add(injectedPsi)) { // for concatenations there can be many injection hosts with only one injected PSI
|
||||
for (PsiLanguageInjectionHost.Shred place : places) {
|
||||
TextRange textRange = place.getRangeInsideHost().shiftRight(place.host.getTextRange().getStartOffset());
|
||||
if (textRange.isEmpty()) continue;
|
||||
String desc = injectedPsi.getLanguage().getDisplayName() + ": " + injectedPsi.getText();
|
||||
HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.INJECTED_LANGUAGE_FRAGMENT, textRange, null, desc, injectedAttributes);
|
||||
addHighlightInfo(textRange, info);
|
||||
}
|
||||
}
|
||||
destination.add(injectedPsi); // for concatenations there can be many injection hosts with only one injected PSI
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
|
||||
// returns false if canceled
|
||||
private boolean addInjectedPsiHighlights(@NotNull final List<PsiFile> injectedFiles,
|
||||
final ProgressIndicator progress,
|
||||
final Collection<HighlightInfo> infos) {
|
||||
EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme();
|
||||
final TextAttributes injectedAttributes = scheme.getAttributes(EditorColors.INJECTED_LANGUAGE_FRAGMENT);
|
||||
|
||||
if (injectedFiles.isEmpty()) return true;
|
||||
final InjectedLanguageManager injectedLanguageManager = InjectedLanguageManager.getInstance(myProject);
|
||||
|
||||
return JobUtil.invokeConcurrentlyUnderMyProgress(new ArrayList<PsiFile>(injectedFiles), new Processor<PsiFile>() {
|
||||
public boolean process(final PsiFile injectedPsi) {
|
||||
DocumentWindow documentWindow = (DocumentWindow)PsiDocumentManager.getInstance(myProject).getCachedDocument(injectedPsi);
|
||||
|
||||
Place places = InjectedLanguageUtil.getShreds(injectedPsi);
|
||||
for (PsiLanguageInjectionHost.Shred place : places) {
|
||||
TextRange textRange = place.getRangeInsideHost().shiftRight(place.host.getTextRange().getStartOffset());
|
||||
if (textRange.isEmpty()) continue;
|
||||
String desc = injectedPsi.getLanguage().getDisplayName() + ": " + injectedPsi.getText();
|
||||
HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.INJECTED_LANGUAGE_FRAGMENT, textRange, null, desc, injectedAttributes);
|
||||
infos.add(info);
|
||||
}
|
||||
|
||||
HighlightInfoHolder holder = createInfoHolder(injectedPsi);
|
||||
runHighlightVisitosForInjected(injectedPsi, holder, progress);
|
||||
for (int i=0; i<holder.size();i++) {
|
||||
HighlightInfo info = holder.get(i);
|
||||
final int startOffset = documentWindow.injectedToHost(info.startOffset);
|
||||
final TextRange fixedTextRange = getFixedTextRange(documentWindow, startOffset);
|
||||
addPatchedInfos(info, injectedPsi, documentWindow, injectedLanguageManager, fixedTextRange);
|
||||
addPatchedInfos(info, injectedPsi, documentWindow, injectedLanguageManager, fixedTextRange, infos);
|
||||
}
|
||||
holder.clear();
|
||||
highlightInjectedSyntax(injectedPsi, holder);
|
||||
@@ -235,20 +333,21 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP
|
||||
final int startOffset = info.startOffset;
|
||||
final TextRange fixedTextRange = getFixedTextRange(documentWindow, startOffset);
|
||||
if (fixedTextRange == null) {
|
||||
addHighlightInfo(new TextRange(info.startOffset, info.endOffset), info);
|
||||
infos.add(info);
|
||||
}
|
||||
else {
|
||||
HighlightInfo patched =
|
||||
new HighlightInfo(info.forcedTextAttributes, info.type, fixedTextRange.getStartOffset(), fixedTextRange.getEndOffset(),
|
||||
info.description, info.toolTip, info.type.getSeverity(null), info.isAfterEndOfLine, null, false);
|
||||
addHighlightInfo(fixedTextRange, patched);
|
||||
infos.add(patched);
|
||||
}
|
||||
}
|
||||
|
||||
if (!isDumbMode()) {
|
||||
Collection<HighlightInfo> todos = highlightTodos(injectedPsi, injectedPsi.getText(), 0, injectedPsi.getTextLength(), progress);
|
||||
List<HighlightInfo> todos = new ArrayList<HighlightInfo>();
|
||||
highlightTodos(injectedPsi, injectedPsi.getText(), 0, injectedPsi.getTextLength(), progress, myPriorityRange, todos, todos);
|
||||
for (HighlightInfo info : todos) {
|
||||
addPatchedInfos(info, injectedPsi, documentWindow, injectedLanguageManager, null);
|
||||
addPatchedInfos(info, injectedPsi, documentWindow, injectedLanguageManager, null, infos);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -272,8 +371,12 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP
|
||||
return fixedTextRange;
|
||||
}
|
||||
|
||||
private void addPatchedInfos(HighlightInfo info, PsiFile injectedPsi, DocumentWindow documentWindow, InjectedLanguageManager injectedLanguageManager,
|
||||
TextRange fixedTextRange) {
|
||||
private static void addPatchedInfos(HighlightInfo info,
|
||||
PsiFile injectedPsi,
|
||||
DocumentWindow documentWindow,
|
||||
InjectedLanguageManager injectedLanguageManager,
|
||||
TextRange fixedTextRange,
|
||||
Collection<HighlightInfo> out) {
|
||||
ProperTextRange textRange = new ProperTextRange(info.startOffset, info.endOffset);
|
||||
List<TextRange> editables = injectedLanguageManager.intersectWithAllEditableFragments(injectedPsi, textRange);
|
||||
for (TextRange editable : editables) {
|
||||
@@ -297,18 +400,7 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP
|
||||
}
|
||||
}
|
||||
}
|
||||
addHighlightInfo(hostRange, patched);
|
||||
}
|
||||
}
|
||||
|
||||
private void addHighlightInfo(@NotNull TextRange textRange, @NotNull HighlightInfo highlightInfo) {
|
||||
synchronized (myInjectedPsiHighlights) {
|
||||
Collection<HighlightInfo> infos = myInjectedPsiHighlights.get(textRange);
|
||||
if (infos == null) {
|
||||
infos = new SmartList<HighlightInfo>();
|
||||
myInjectedPsiHighlights.put(textRange, infos);
|
||||
}
|
||||
infos.add(highlightInfo);
|
||||
out.add(patched);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -393,14 +485,7 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP
|
||||
protected void applyInformationWithProgress() {
|
||||
myFile.putUserData(HAS_ERROR_ELEMENT, myHasErrorElement);
|
||||
|
||||
ProperTextRange range = new ProperTextRange(myStartOffset, myEndOffset);
|
||||
Collection<HighlightInfo> infos = myInjectedPsiHighlights.get(range);
|
||||
if (infos == null) {
|
||||
infos = new ArrayList<HighlightInfo>(myHighlights.size());
|
||||
myInjectedPsiHighlights.put(range, infos);
|
||||
}
|
||||
infos.addAll(myHighlights);
|
||||
UpdateHighlightersUtil.setHighlightersToEditor(myProject, myDocument, myInjectedPsiHighlights, Pass.UPDATE_ALL);
|
||||
myApplyCommand.run();
|
||||
|
||||
if (myUpdateAll) {
|
||||
reportErrorsToWolf();
|
||||
@@ -409,27 +494,24 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP
|
||||
|
||||
@NotNull
|
||||
Collection<HighlightInfo> getHighlights() {
|
||||
ArrayList<HighlightInfo> list = new ArrayList<HighlightInfo>(myHighlights);
|
||||
for (Collection<HighlightInfo> infos : myInjectedPsiHighlights.values()) {
|
||||
list.addAll(infos);
|
||||
}
|
||||
return list;
|
||||
return new ArrayList<HighlightInfo>(myHighlights);
|
||||
}
|
||||
|
||||
private Collection<HighlightInfo> collectHighlights(@NotNull final List<PsiElement> elements, @NotNull final ProgressIndicator progress,
|
||||
final HighlightVisitor[] visitors) {
|
||||
private void collectHighlights(@NotNull final List<PsiElement> elements1,
|
||||
@NotNull final Runnable after1,
|
||||
@NotNull final List<PsiElement> elements2,
|
||||
@NotNull final ProgressIndicator progress,
|
||||
@NotNull final HighlightVisitor[] visitors,
|
||||
@NotNull final Set<HighlightInfo> gotHighlights,
|
||||
final boolean forceHighlightParents) {
|
||||
final Set<PsiElement> skipParentsSet = new THashSet<PsiElement>();
|
||||
final Set<HighlightInfo> gotHighlights = new THashSet<HighlightInfo>();
|
||||
|
||||
final boolean forceHighlightParents = forceHighlightParents();
|
||||
|
||||
final HighlightInfoHolder holder = createInfoHolder(myFile);
|
||||
setProgressLimit((long)elements.size() * visitors.length);
|
||||
|
||||
final int chunkSize = Math.max(1, elements.size() / 100); // one percent precision is enough
|
||||
for (final HighlightVisitor visitor : visitors) {
|
||||
Runnable action = new Runnable() {
|
||||
public void run() {
|
||||
final int chunkSize = Math.max(1, (elements1.size()+elements2.size()) / 100); // one percent precision is enough
|
||||
|
||||
final Runnable action = new Runnable() {
|
||||
public void run() {
|
||||
for (List<PsiElement> elements : new List[]{elements1, elements2}) {
|
||||
int nextLimit = chunkSize;
|
||||
for (int i = 0; i < elements.size(); i++) {
|
||||
PsiElement element = elements.get(i);
|
||||
@@ -445,7 +527,10 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP
|
||||
}
|
||||
holder.clear();
|
||||
|
||||
visitor.visit(element, holder);
|
||||
for (final HighlightVisitor visitor : visitors) {
|
||||
visitor.visit(element, holder);
|
||||
}
|
||||
|
||||
if (i == nextLimit) {
|
||||
advanceProgress(chunkSize);
|
||||
nextLimit = i + chunkSize;
|
||||
@@ -466,21 +551,35 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP
|
||||
}
|
||||
UIUtil.invokeLaterIfNeeded(new Runnable() {
|
||||
public void run() {
|
||||
if (myProject.isDisposed()) return;
|
||||
if (progress.isCanceled()) return;
|
||||
UpdateHighlightersUtil.addHighlighterToEditorIncrementally(myProject, myDocument, myFile, 0, myDocument.getTextLength(), info, Pass.UPDATE_ALL);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
advanceProgress(elements.size() - (nextLimit-chunkSize));
|
||||
if (elements == elements1) after1.run();
|
||||
}
|
||||
};
|
||||
if (!visitor.analyze(action, myUpdateAll, myFile)) {
|
||||
}
|
||||
};
|
||||
|
||||
analyzeByVisitors(progress, visitors, action, 0);
|
||||
}
|
||||
|
||||
private void analyzeByVisitors(final ProgressIndicator progress, final HighlightVisitor[] visitors, final Runnable action, final int i) {
|
||||
if (i == visitors.length) {
|
||||
action.run();
|
||||
}
|
||||
else {
|
||||
if (!visitors[i].analyze(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
analyzeByVisitors(progress, visitors, action, i+1);
|
||||
}
|
||||
}, myUpdateAll, myFile)) {
|
||||
cancelAndRestartDaemonLater(progress, myProject, this);
|
||||
}
|
||||
}
|
||||
|
||||
return gotHighlights;
|
||||
}
|
||||
|
||||
private static HighlightVisitor[] filterVisitors(HighlightVisitor[] highlightVisitors, final PsiFile file) {
|
||||
@@ -529,17 +628,19 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP
|
||||
return new HighlightInfoHolder(file, filters);
|
||||
}
|
||||
|
||||
private static Collection<HighlightInfo> highlightTodos(@NotNull PsiFile file,
|
||||
@NotNull CharSequence text,
|
||||
int startOffset,
|
||||
int endOffset,
|
||||
@NotNull ProgressIndicator progress) {
|
||||
private static void highlightTodos(@NotNull PsiFile file,
|
||||
@NotNull CharSequence text,
|
||||
int startOffset,
|
||||
int endOffset,
|
||||
@NotNull ProgressIndicator progress,
|
||||
@NotNull ProperTextRange priorityRange,
|
||||
@NotNull Collection<HighlightInfo> result,
|
||||
@NotNull Collection<HighlightInfo> outsideResult) {
|
||||
PsiManager psiManager = file.getManager();
|
||||
PsiSearchHelper helper = psiManager.getSearchHelper();
|
||||
TodoItem[] todoItems = helper.findTodoItems(file, startOffset, endOffset);
|
||||
if (todoItems.length == 0) return Collections.emptyList();
|
||||
if (todoItems.length == 0) return;
|
||||
|
||||
List<HighlightInfo> list = new ArrayList<HighlightInfo>(todoItems.length);
|
||||
for (TodoItem todoItem : todoItems) {
|
||||
progress.checkCanceled();
|
||||
TextRange range = todoItem.getTextRange();
|
||||
@@ -547,9 +648,13 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP
|
||||
TextAttributes attributes = todoItem.getPattern().getAttributes().getTextAttributes();
|
||||
HighlightInfo info = HighlightInfo.createHighlightInfo(HighlightInfoType.TODO, range, description, description, attributes);
|
||||
assert info != null;
|
||||
list.add(info);
|
||||
if (priorityRange.containsRange(info.getStartOffset(), info.getEndOffset())) {
|
||||
result.add(info);
|
||||
}
|
||||
else {
|
||||
outsideResult.add(info);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private void reportErrorsToWolf() {
|
||||
@@ -576,7 +681,8 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP
|
||||
return myUpdateAll ? super.getProgress() : -1;
|
||||
}
|
||||
|
||||
private static List<Problem> convertToProblems(final Collection<HighlightInfo> infos, final VirtualFile file,
|
||||
private static List<Problem> convertToProblems(final Collection<HighlightInfo> infos,
|
||||
final VirtualFile file,
|
||||
final boolean hasErrorElement) {
|
||||
List<Problem> problems = new SmartList<Problem>();
|
||||
for (HighlightInfo info : infos) {
|
||||
|
||||
+3
-2
@@ -23,6 +23,7 @@ import com.intellij.codeHighlighting.TextEditorHighlightingPassRegistrar;
|
||||
import com.intellij.openapi.components.AbstractProjectComponent;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.ProperTextRange;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -51,7 +52,7 @@ public class GeneralHighlightingPassFactory extends AbstractProjectComponent imp
|
||||
TextRange textRange = FileStatusMap.getDirtyTextRange(editor, Pass.UPDATE_ALL);
|
||||
if (textRange == null) return new ProgressableTextEditorHighlightingPass.EmptyPass(myProject, editor.getDocument()
|
||||
);
|
||||
TextRange visibleRange = VisibleHighlightingPassFactory.calculateVisibleRange(editor);
|
||||
return new GeneralHighlightingPass(myProject, file, editor.getDocument(), textRange.getStartOffset(), textRange.getEndOffset(), true, visibleRange);
|
||||
ProperTextRange visibleRange = VisibleHighlightingPassFactory.calculateVisibleRange(editor);
|
||||
return new GeneralHighlightingPass(myProject, file, editor.getDocument(), textRange.getStartOffset(), textRange.getEndOffset(), true, visibleRange, editor);
|
||||
}
|
||||
}
|
||||
|
||||
+113
-32
@@ -38,10 +38,7 @@ import com.intellij.openapi.fileEditor.FileEditor;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.fileEditor.TextEditor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
@@ -94,14 +91,8 @@ public class UpdateHighlightersUtil {
|
||||
return o1.getStartOffset() - o2.getStartOffset();
|
||||
}
|
||||
};
|
||||
private static final Comparator<TextRange> BY_START_OFFSET_OR_CONTAINS = new Comparator<TextRange>() {
|
||||
public int compare(final TextRange o1, final TextRange o2) {
|
||||
if (o1.contains(o2) || o2.contains(o1)) return 0;
|
||||
return o1.getStartOffset() - o2.getStartOffset();
|
||||
}
|
||||
};
|
||||
|
||||
private static void cleanFileLevelHighlights(@NotNull Project project, final int group, PsiFile psiFile) {
|
||||
public static void cleanFileLevelHighlights(@NotNull Project project, final int group, PsiFile psiFile) {
|
||||
if (psiFile == null || !psiFile.getViewProvider().isPhysical()) return;
|
||||
VirtualFile vFile = psiFile.getViewProvider().getVirtualFile();
|
||||
final FileEditorManager manager = FileEditorManager.getInstance(project);
|
||||
@@ -191,11 +182,10 @@ public class UpdateHighlightersUtil {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean success = createOrReuseHighlighterFor(info, document, group, file, (MarkupModelEx)markup, null, null, startOffset, endOffset,
|
||||
SeverityRegistrar.getInstance(project));
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
if (info.getStartOffset() < startOffset || info.getEndOffset() > endOffset) return;
|
||||
|
||||
createOrReuseHighlighterFor(info, document, group, file, (MarkupModelEx)markup, null, null,
|
||||
SeverityRegistrar.getInstance(project));
|
||||
|
||||
DaemonCodeAnalyzerImpl.addHighlight(markup, project, info);
|
||||
clearWhiteSpaceOptimizationFlag(document);
|
||||
@@ -241,7 +231,24 @@ public class UpdateHighlightersUtil {
|
||||
}
|
||||
}
|
||||
|
||||
private static void setHighlightersInRange(final TextRange range,
|
||||
// set highlights inside startOffset,endOffset but outside range
|
||||
public static void setHighlightersToEditorOutsideRange(@NotNull Project project,
|
||||
@NotNull Document document,
|
||||
@NotNull Collection<HighlightInfo> infos,
|
||||
int startOffset, int endOffset, @NotNull ProperTextRange range,
|
||||
final int group) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
|
||||
PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document);
|
||||
cleanFileLevelHighlights(project, group, psiFile);
|
||||
|
||||
MarkupModel markup = document.getMarkupModel(project);
|
||||
assertMarkupConsistent(markup, project);
|
||||
|
||||
setHighlightersOutsideRange(startOffset, endOffset, range, infos, (MarkupModelEx)markup, group, document, project);
|
||||
}
|
||||
|
||||
public static void setHighlightersInRange(final TextRange range,
|
||||
Collection<HighlightInfo> highlightsCo,
|
||||
final MarkupModelEx markup,
|
||||
final int group,
|
||||
@@ -293,10 +300,88 @@ public class UpdateHighlightersUtil {
|
||||
if (isWarningCoveredByError(info, overlappingIntervals, severityRegistrar)) {
|
||||
return true;
|
||||
}
|
||||
boolean success = createOrReuseHighlighterFor(info, document, group, psiFile, markup, infosToRemove,
|
||||
ranges2markersCache, range.getStartOffset(), range.getEndOffset(),
|
||||
if (info.getStartOffset() >= range.getStartOffset() && info.getEndOffset() <= range.getEndOffset()) {
|
||||
createOrReuseHighlighterFor(info, document, group, psiFile, markup, infosToRemove,
|
||||
ranges2markersCache,
|
||||
severityRegistrar);
|
||||
changed[0] = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
for (RangeHighlighter highlighter : infosToRemove.forAllInGarbageBin()) {
|
||||
markup.removeHighlighter(highlighter);
|
||||
changed[0] = true;
|
||||
}
|
||||
|
||||
if (changed[0]) {
|
||||
clearWhiteSpaceOptimizationFlag(document);
|
||||
}
|
||||
assertMarkupConsistent(markup, project);
|
||||
}
|
||||
|
||||
private static void setHighlightersOutsideRange(final int startOffset, final int endOffset, final TextRange range,
|
||||
Collection<HighlightInfo> highlightsCo,
|
||||
final MarkupModelEx markup,
|
||||
final int group,
|
||||
final Document document,
|
||||
final Project project) {
|
||||
final List<HighlightInfo> highlights = new ArrayList<HighlightInfo>(highlightsCo);
|
||||
|
||||
final SeverityRegistrar severityRegistrar = SeverityRegistrar.getInstance(project);
|
||||
final HighlightersRecycler infosToRemove = new HighlightersRecycler();
|
||||
DaemonCodeAnalyzerImpl.processHighlights(document, project, null, startOffset, endOffset, new Processor<HighlightInfo>() {
|
||||
@Override
|
||||
public boolean process(HighlightInfo info) {
|
||||
if (info.group == group) {
|
||||
RangeHighlighter highlighter = info.highlighter;
|
||||
int endOffset = highlighter.getEndOffset();
|
||||
int startOffset = highlighter.getStartOffset();
|
||||
boolean willBeRemoved = endOffset == document.getTextLength() && range.getEndOffset() != document.getTextLength()
|
||||
|| !range.contains(startOffset)
|
||||
&& !range.containsRange(startOffset, endOffset);
|
||||
if (willBeRemoved) {
|
||||
infosToRemove.recycleHighlighter(highlighter);
|
||||
info.highlighter = null;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
Collections.sort(highlights, BY_START_OFFSET_NODUPS);
|
||||
final Map<TextRange, RangeMarker> ranges2markersCache = new THashMap<TextRange, RangeMarker>(10);
|
||||
final PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document);
|
||||
final boolean[] changed = {false};
|
||||
RangeMarkerTree.sweep(new RangeMarkerTree.Generator<HighlightInfo>(){
|
||||
@Override
|
||||
public boolean generate(final Processor<HighlightInfo> processor) {
|
||||
return ContainerUtil.process(highlights, new Processor<HighlightInfo>() {
|
||||
@Override
|
||||
public boolean process(HighlightInfo info) {
|
||||
return info.getStartOffset() < startOffset || info.getEndOffset() > endOffset || processor.process(info);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, new MarkupModelEx.SweepProcessor<HighlightInfo>() {
|
||||
@Override
|
||||
public boolean process(int offset, HighlightInfo info, boolean atStart, Collection<HighlightInfo> overlappingIntervals) {
|
||||
if (!atStart) {
|
||||
return true;
|
||||
}
|
||||
if (info.isFileLevelAnnotation && psiFile != null && psiFile.getViewProvider().isPhysical()) {
|
||||
addFileLevelHighlight(project, group, info, psiFile);
|
||||
changed[0] = true;
|
||||
return true;
|
||||
}
|
||||
if (isWarningCoveredByError(info, overlappingIntervals, severityRegistrar)) {
|
||||
return true;
|
||||
}
|
||||
if (new TextRange(startOffset,endOffset).containsRange(info.getStartOffset(), info.getEndOffset()) &&
|
||||
(info.getStartOffset() < range.getStartOffset() || info.getEndOffset() > range.getEndOffset())) {
|
||||
createOrReuseHighlighterFor(info, document, group, psiFile, markup, infosToRemove,
|
||||
ranges2markersCache,
|
||||
severityRegistrar);
|
||||
if (success) {
|
||||
changed[0] = true;
|
||||
}
|
||||
return true;
|
||||
@@ -332,19 +417,16 @@ public class UpdateHighlightersUtil {
|
||||
}
|
||||
|
||||
// return true if changed
|
||||
private static boolean createOrReuseHighlighterFor(@NotNull final HighlightInfo info,
|
||||
@NotNull final Document document,
|
||||
final int group,
|
||||
@NotNull final PsiFile psiFile,
|
||||
@NotNull MarkupModelEx markup,
|
||||
@Nullable HighlightersRecycler infosToRemove,
|
||||
@Nullable final Map<TextRange, RangeMarker> ranges2markersCache,
|
||||
int rangeStartOffset,
|
||||
int rangeEndOffset,
|
||||
SeverityRegistrar severityRegistrar) {
|
||||
private static void createOrReuseHighlighterFor(@NotNull final HighlightInfo info,
|
||||
@NotNull final Document document,
|
||||
final int group,
|
||||
@NotNull final PsiFile psiFile,
|
||||
@NotNull MarkupModelEx markup,
|
||||
@Nullable HighlightersRecycler infosToRemove,
|
||||
@Nullable final Map<TextRange, RangeMarker> ranges2markersCache,
|
||||
SeverityRegistrar severityRegistrar) {
|
||||
final int infoStartOffset = info.startOffset;
|
||||
int infoEndOffset = info.endOffset;
|
||||
if (infoStartOffset < rangeStartOffset || infoEndOffset > rangeEndOffset) return false;
|
||||
|
||||
if (infoEndOffset == infoStartOffset && !info.isAfterEndOfLine) {
|
||||
infoEndOffset++; //show something in case of empty highlightinfo
|
||||
@@ -398,7 +480,6 @@ public class UpdateHighlightersUtil {
|
||||
info.getTextAttributes(psiFile) +
|
||||
"; highlighter:" +
|
||||
highlighter.getTextAttributes();
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+3
-2
@@ -24,6 +24,7 @@ import com.intellij.openapi.components.AbstractProjectComponent;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.LogicalPosition;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.ProperTextRange;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -36,7 +37,7 @@ public abstract class VisibleHighlightingPassFactory extends AbstractProjectComp
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static TextRange calculateVisibleRange(@NotNull Editor editor) {
|
||||
public static ProperTextRange calculateVisibleRange(@NotNull Editor editor) {
|
||||
Rectangle rect = editor.getScrollingModel().getVisibleArea();
|
||||
LogicalPosition startPosition = editor.xyToLogicalPosition(new Point(rect.x, rect.y));
|
||||
|
||||
@@ -45,7 +46,7 @@ public abstract class VisibleHighlightingPassFactory extends AbstractProjectComp
|
||||
|
||||
int visibleEnd = editor.logicalPositionToOffset(new LogicalPosition(endPosition.line + 1, 0));
|
||||
|
||||
return new TextRange(visibleStart, visibleEnd);
|
||||
return new ProperTextRange(visibleStart, visibleEnd);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
Reference in New Issue
Block a user