void (@NotNull TextEditor textEditor, int @NotNull [] passesToIgnore, boolean canChangeDocument, @Nullable Runnable callbackWhileWaiting) { ((CoreProgressManager)ProgressManager.getInstance()).suppressAllDeprioritizationsDuringLongTestsExecutionIn(() -> { VirtualFile virtualFile = textEditor.getFile(); PsiFile psiFile = PsiManagerEx.getInstanceEx(myProject).findFile(virtualFile); // findCachedFile doesn't work with the temp file system in tests psiFile = psiFile instanceof PsiCompiledFile compiled ? compiled.getDecompiledPsiFile() : psiFile; LOG.assertTrue(psiFile != null, "PsiFile not found for " + virtualFile); HighlightingSession session = queuePassesCreation(textEditor, virtualFile, psiFile, passesToIgnore); if (session == null) { LOG.error("Can't create session for " + textEditor + " (" + textEditor.getClass() + ")," + " fileEditor.getBackgroundHighlighter()=" + textEditor.getBackgroundHighlighter() + "; virtualFile=" + virtualFile + "; psiFile=" + psiFile); throw new ProcessCanceledException(); } ProgressIndicator progress = session.getProgressIndicator(); // there can be PCE in FJP during queuePassesCreation // no PCE guarantees session is not null progress.checkCanceled(); try { long start = System.currentTimeMillis(); waitInOtherThread(600_000, canChangeDocument, () -> { progress.checkCanceled(); if (callbackWhileWaiting != null) { callbackWhileWaiting.run(); } // give other threads a chance to do smth useful if (System.currentTimeMillis() > start + 50) { TimeoutUtil.sleep(10); } EDT.dispatchAllInvocationEvents(); Throwable savedException = PassExecutorService.getSavedException((DaemonProgressIndicator)progress); if (savedException != null) throw savedException; return progress.isRunning(); }); if (progress.isRunning() && !progress.isCanceled()) { throw new RuntimeException("Highlighting still running after " + (System.currentTimeMillis() - start) / 1000 + " seconds. Still submitted passes: " + myPassExecutorService.getAllSubmittedPasses() + " ForkJoinPool.commonPool(): " + ForkJoinPool.commonPool() + "\n" + ", ForkJoinPool.commonPool() active thread count: " + ForkJoinPool.commonPool().getActiveThreadCount() + ", ForkJoinPool.commonPool() has queued submissions: " + ForkJoinPool.commonPool().hasQueuedSubmissions() + "\n" + ThreadDumper.dumpThreadsToString()); } ((HighlightingSessionImpl)session).applyFileLevelHighlightsRequests(); EDT.dispatchAllInvocationEvents(); EDT.dispatchAllInvocationEvents(); assert progress.isCanceled(); } catch (Throwable e) { Throwable unwrapped = ExceptionUtilRt.unwrapException(e, ExecutionException.class); if (progress.isCanceled() && progress.isRunning()) { unwrapped.addSuppressed(new RuntimeException("Daemon progress was canceled unexpectedly: " + progress)); } ExceptionUtil.rethrow(unwrapped); } finally { progress.cancel(); waitForTermination(); } return null; }); }