@Nullable("null means the file is clean") public static TextRange getDirtyTextRange(@NotNull Editor editor, int passId) { Document document = editor.getDocument(); FileStatusMap me = DaemonCodeAnalyzerEx.getInstanceEx(editor.getProject()).getFileStatusMap(); TextRange dirtyScope = me.getFileDirtyScope(document, passId); if (dirtyScope == null) return null; TextRange documentRange = TextRange.from(0, document.getTextLength()); return documentRange.intersection(dirtyScope); }
private void applyInformationToEditorsLater( @NotNull final FileEditor fileEditor, @NotNull final TextEditorHighlightingPass pass, @NotNull final DaemonProgressIndicator updateProgress, @NotNull final AtomicInteger threadsToStartCountdown) { ApplicationManager.getApplication() .invokeLater( (DumbAwareRunnable) () -> { if (isDisposed() || myProject.isDisposed()) { updateProgress.cancel(); } if (updateProgress.isCanceled()) { log(updateProgress, pass, " is canceled during apply, sorry"); return; } Document document = pass.getDocument(); try { if (fileEditor.getComponent().isDisplayable() || ApplicationManager.getApplication().isUnitTestMode()) { pass.applyInformationToEditor(); FileStatusMap fileStatusMap = DaemonCodeAnalyzerEx.getInstanceEx(myProject).getFileStatusMap(); if (document != null) { fileStatusMap.markFileUpToDate(document, pass.getId()); } log(updateProgress, pass, " Applied"); } } catch (ProcessCanceledException e) { log(updateProgress, pass, "Error " + e); throw e; } catch (RuntimeException e) { VirtualFile file = document == null ? null : FileDocumentManager.getInstance().getFile(document); FileType fileType = file == null ? null : file.getFileType(); String message = "Exception while applying information to " + fileEditor + "(" + fileType + ")"; log(updateProgress, pass, message + e); throw new RuntimeException(message, e); } if (threadsToStartCountdown.decrementAndGet() == 0) { log(updateProgress, pass, "Stopping "); updateProgress.stopIfRunning(); } else { log( updateProgress, pass, "Finished but there are passes in the queue: " + threadsToStartCountdown.get()); } }, Registry.is("ide.perProjectModality") ? ModalityState.defaultModalityState() : ModalityState.stateForComponent(fileEditor.getComponent())); }
@Override @NotNull public List<TextEditorHighlightingPass> instantiatePasses( @NotNull final PsiFile psiFile, @NotNull final Editor editor, @NotNull final int[] passesToIgnore) { synchronized (this) { if (!checkedForCycles) { checkedForCycles = true; checkForCycles(); } } PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject); final Document document = editor.getDocument(); PsiFile fileFromDoc = documentManager.getPsiFile(document); if (!(fileFromDoc instanceof PsiCompiledElement)) { assert fileFromDoc == psiFile : "Files are different: " + psiFile + ";" + fileFromDoc; Document documentFromFile = documentManager.getDocument(psiFile); assert documentFromFile == document : "Documents are different. Doc: " + document + "; Doc from file: " + documentFromFile + "; File: " + psiFile + "; Virtual file: " + PsiUtilCore.getVirtualFile(psiFile); } final TIntObjectHashMap<TextEditorHighlightingPass> id2Pass = new TIntObjectHashMap<TextEditorHighlightingPass>(); final TIntArrayList passesRefusedToCreate = new TIntArrayList(); myRegisteredPassFactories.forEachKey( new TIntProcedure() { @Override public boolean execute(int passId) { if (ArrayUtil.find(passesToIgnore, passId) != -1) { return true; } PassConfig passConfig = myRegisteredPassFactories.get(passId); TextEditorHighlightingPassFactory factory = passConfig.passFactory; final TextEditorHighlightingPass pass = factory.createHighlightingPass(psiFile, editor); if (pass == null) { passesRefusedToCreate.add(passId); } else { // init with editor's colors scheme pass.setColorsScheme(editor.getColorsScheme()); TIntArrayList ids = new TIntArrayList(passConfig.completionPredecessorIds.length); for (int id : passConfig.completionPredecessorIds) { if (myRegisteredPassFactories.containsKey(id)) ids.add(id); } pass.setCompletionPredecessorIds( ids.isEmpty() ? ArrayUtil.EMPTY_INT_ARRAY : ids.toNativeArray()); ids = new TIntArrayList(passConfig.startingPredecessorIds.length); for (int id : passConfig.startingPredecessorIds) { if (myRegisteredPassFactories.containsKey(id)) ids.add(id); } pass.setStartingPredecessorIds( ids.isEmpty() ? ArrayUtil.EMPTY_INT_ARRAY : ids.toNativeArray()); pass.setId(passId); id2Pass.put(passId, pass); } return true; } }); DaemonCodeAnalyzerEx daemonCodeAnalyzer = DaemonCodeAnalyzerEx.getInstanceEx(myProject); final FileStatusMap statusMap = daemonCodeAnalyzer.getFileStatusMap(); passesRefusedToCreate.forEach( new TIntProcedure() { @Override public boolean execute(int passId) { statusMap.markFileUpToDate(document, passId); return true; } }); return (List) Arrays.asList(id2Pass.getValues()); }