mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[threading] IJPL-218810: Always run old VFS listeners on EDT for programmatic reparse
GitOrigin-RevId: 5e2ed3f31096b1ce2abab22ecb7ceabc6880ee34
This commit is contained in:
committed by
intellij-monorepo-bot
parent
81a8fedbfa
commit
28097b60e1
@@ -1,6 +1,7 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.util;
|
||||
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
@@ -8,6 +9,8 @@ import com.intellij.openapi.vfs.newvfs.BulkFileListener;
|
||||
import com.intellij.openapi.vfs.newvfs.BulkFileListenerBackgroundable;
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFilePropertyChangeEvent;
|
||||
import com.intellij.util.concurrency.TransferredWriteActionService;
|
||||
import com.intellij.util.ui.EDT;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
@@ -33,7 +36,8 @@ public final class FileContentUtilCore {
|
||||
* @param files the files to reparse.
|
||||
*/
|
||||
public static void reparseFiles(@NotNull Collection<? extends VirtualFile> files) {
|
||||
ApplicationManager.getApplication().runWriteAction(() -> {
|
||||
Application application = ApplicationManager.getApplication();
|
||||
application.runWriteAction(() -> {
|
||||
// files must be processed under one write action to prevent firing event for invalid files.
|
||||
Set<VFilePropertyChangeEvent> events = new HashSet<>();
|
||||
for (VirtualFile file : files) {
|
||||
@@ -45,9 +49,21 @@ public final class FileContentUtilCore {
|
||||
BulkFileListener publisher = ApplicationManager.getApplication().getMessageBus().syncPublisher(VirtualFileManager.VFS_CHANGES);
|
||||
BulkFileListenerBackgroundable publisherBackgroundable = ApplicationManager.getApplication().getMessageBus().syncPublisher(VirtualFileManager.VFS_CHANGES_BG);
|
||||
List<VFileEvent> eventList = Collections.unmodifiableList(new ArrayList<>(events));
|
||||
publisher.before(eventList);
|
||||
if (EDT.isCurrentThreadEdt()) {
|
||||
publisher.before(eventList);
|
||||
} else {
|
||||
application.getService(TransferredWriteActionService.class).runOnEdtWithTransferredWriteActionAndWait(() -> {
|
||||
publisher.before(eventList);
|
||||
});
|
||||
}
|
||||
publisherBackgroundable.before(eventList);
|
||||
publisher.after(eventList);
|
||||
if (EDT.isCurrentThreadEdt()) {
|
||||
publisher.after(eventList);
|
||||
} else {
|
||||
application.getService(TransferredWriteActionService.class).runOnEdtWithTransferredWriteActionAndWait(() -> {
|
||||
publisher.after(eventList);
|
||||
});
|
||||
}
|
||||
publisherBackgroundable.after(eventList);
|
||||
|
||||
ForcefulReparseModificationTracker.increment();
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.openapi.application.impl
|
||||
package com.intellij.util.concurrency
|
||||
|
||||
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread
|
||||
import com.intellij.util.concurrency.annotations.RequiresWriteLock
|
||||
@@ -6,7 +6,6 @@ import com.intellij.lang.PsiBuilderFactory;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.impl.TransferredWriteActionService;
|
||||
import com.intellij.openapi.diagnostic.ControlFlowException;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
@@ -28,6 +27,7 @@ import com.intellij.psi.impl.file.impl.FileManagerEx;
|
||||
import com.intellij.psi.impl.file.impl.FileManagerImpl;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.serviceContainer.NonInjectable;
|
||||
import com.intellij.util.concurrency.TransferredWriteActionService;
|
||||
import com.intellij.util.concurrency.annotations.RequiresReadLock;
|
||||
import com.intellij.util.concurrency.annotations.RequiresWriteLock;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
|
||||
+1
@@ -1,6 +1,7 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.openapi.application.impl
|
||||
|
||||
import com.intellij.util.concurrency.TransferredWriteActionService
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
@ApiStatus.Internal
|
||||
|
||||
+1
-1
@@ -13,7 +13,6 @@ import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.application.TransactionGuard;
|
||||
import com.intellij.openapi.application.TransactionGuardImpl;
|
||||
import com.intellij.openapi.application.impl.InternalThreading;
|
||||
import com.intellij.openapi.application.impl.TransferredWriteActionService;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.command.UndoConfirmationPolicy;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -63,6 +62,7 @@ import com.intellij.ui.UIBundle;
|
||||
import com.intellij.ui.components.JBScrollPane;
|
||||
import com.intellij.util.*;
|
||||
import com.intellij.util.concurrency.ThreadingAssertions;
|
||||
import com.intellij.util.concurrency.TransferredWriteActionService;
|
||||
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread;
|
||||
import com.intellij.util.concurrency.annotations.RequiresEdt;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
|
||||
+1
-1
@@ -2,8 +2,8 @@
|
||||
package com.intellij.openapi.vfs.newvfs.impl;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.impl.TransferredWriteActionService;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.util.concurrency.TransferredWriteActionService;
|
||||
import com.intellij.util.ui.EDT;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
/>
|
||||
|
||||
<applicationService
|
||||
serviceInterface="com.intellij.openapi.application.impl.TransferredWriteActionService"
|
||||
serviceInterface="com.intellij.util.concurrency.TransferredWriteActionService"
|
||||
serviceImplementation="com.intellij.openapi.application.impl.TransferredWriteActionServiceImpl"
|
||||
/>
|
||||
|
||||
|
||||
+29
@@ -21,6 +21,7 @@ import com.intellij.testFramework.common.timeoutRunBlocking
|
||||
import com.intellij.testFramework.junit5.RegistryKey
|
||||
import com.intellij.testFramework.junit5.TestApplication
|
||||
import com.intellij.testFramework.junit5.TestDisposable
|
||||
import com.intellij.util.FileContentUtilCore
|
||||
import com.intellij.util.application
|
||||
import com.intellij.util.io.delete
|
||||
import com.intellij.util.io.write
|
||||
@@ -244,4 +245,32 @@ class VfsRefreshTest {
|
||||
}
|
||||
// if this test terminates, there was no hanging
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `listeners in programmatic reparse run on EDT`(@TestDisposable disposable: Disposable): Unit = timeoutRunBlocking {
|
||||
val file = createTempFile()
|
||||
val virtualFile = VirtualFileManager.getInstance().findFileByNioPath(file)!!
|
||||
val counter = AtomicInteger(0)
|
||||
|
||||
writeAction {
|
||||
virtualFile.writeText("42")
|
||||
}
|
||||
|
||||
application.messageBus.connect(disposable).subscribe(VirtualFileManager.VFS_CHANGES, object : BulkFileListener {
|
||||
override fun before(events: List<VFileEvent>) {
|
||||
assertThat(EDT.isCurrentThreadEdt()).isTrue
|
||||
counter.incrementAndGet()
|
||||
}
|
||||
|
||||
override fun after(events: List<VFileEvent>) {
|
||||
assertThat(EDT.isCurrentThreadEdt()).isTrue
|
||||
counter.incrementAndGet()
|
||||
}
|
||||
})
|
||||
|
||||
backgroundWriteAction {
|
||||
FileContentUtilCore.reparseFiles(virtualFile)
|
||||
}
|
||||
assertThat(counter.get()).isEqualTo(2)
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -3,7 +3,6 @@ package com.intellij.psi.impl
|
||||
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.application.backgroundWriteAction
|
||||
import com.intellij.openapi.application.impl.TransferredWriteActionService
|
||||
import com.intellij.openapi.application.invokeAndWaitIfNeeded
|
||||
import com.intellij.openapi.application.runReadAction
|
||||
import com.intellij.openapi.command.CommandProcessor
|
||||
@@ -28,6 +27,7 @@ import com.intellij.testFramework.junit5.fixture.projectFixture
|
||||
import com.intellij.testFramework.junit5.fixture.psiFileFixture
|
||||
import com.intellij.testFramework.junit5.fixture.sourceRootFixture
|
||||
import com.intellij.util.application
|
||||
import com.intellij.util.concurrency.TransferredWriteActionService
|
||||
import com.intellij.util.ui.EDT
|
||||
import org.junit.jupiter.api.Assertions.assertTrue
|
||||
import org.junit.jupiter.api.DynamicTest
|
||||
|
||||
Reference in New Issue
Block a user