IJPL-196089 annotate and document ModuleRootListener

GitOrigin-RevId: f01b3424f2f8686115e69f5175047b7344ab79bf
This commit is contained in:
Andrei.Kuznetsov
2025-08-06 13:27:19 +00:00
committed by intellij-monorepo-bot
parent abc178a85a
commit 7f48fa3c8f
@@ -3,6 +3,7 @@ package com.intellij.openapi.roots;
import com.intellij.openapi.project.RootsChangeRescanningInfo;
import com.intellij.openapi.roots.ex.ProjectRootManagerEx;
import com.intellij.util.concurrency.annotations.RequiresWriteLock;
import com.intellij.util.messages.Topic;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
@@ -12,26 +13,44 @@ import java.util.EventListener;
/**
* Project root changes.
* <p>
* Instead of events with {@link ModuleRootEvent#isCausedByWorkspaceModelChangesOnly()} one may use
* {@link com.intellij.platform.backend.workspace.WorkspaceModelChangeListener} and get more fine-grained incremental events.
* For more fine-grained, incremental updates related specifically to workspace model changes,
* consider using {@link com.intellij.platform.backend.workspace.WorkspaceModelChangeListener}.
* <p>
* {@link ModuleRootEvent#isCausedByWorkspaceModelChangesOnly()} is always {@code false} in the {@linkplain #beforeRootsChange(ModuleRootEvent)}.
* This is because {@linkplain ModuleRootListener} will de-duplicate nested {@linkplain ModuleRootEvent} events, and at the moment of the
* {@linkplain #beforeRootsChange(ModuleRootEvent)} invocation we don't know if all the events (including de-duplicated) are from WSM or not.
* <p>
* {@linkplain com.intellij.platform.backend.workspace.WorkspaceModelChangeListener} is not a direct replacement for {@linkplain ModuleRootListener},
* because {@linkplain ModuleRootListener} may generate events that are not related to the workspace model. For example, there will be an
* event on a filetype change, roots validity change (VirtualFileUrl validity change like when a jar file is downloaded), and
* out of thin air events caused by {@link ProjectRootManagerEx#makeRootsChange(Runnable, RootsChangeRescanningInfo)}
* Note that unlike {@link com.intellij.platform.backend.workspace.WorkspaceModelChangeListener} {@link ModuleRootListener}
* may produce events unrelated to the workspace model.
* For example, events may be triggered by:
* <ul>
* <li>File type changes</li>
* <li>Manual invocations via {@link ProjectRootManagerEx#makeRootsChange(Runnable, RootsChangeRescanningInfo)}</li>
* </ul>
*
* Both {@link com.intellij.platform.backend.workspace.WorkspaceModelChangeListener} and {@link ModuleRootListener} will
* generate events when roots validity changes (e.g., when a JAR file is downloaded and the corresponding VirtualFile becomes valid)
*/
@ApiStatus.OverrideOnly
public interface ModuleRootListener extends EventListener {
@Topic.ProjectLevel
Topic<ModuleRootListener> TOPIC = new Topic<>(ModuleRootListener.class);
/**
* Called within the same write action that triggers the change, but before the change is actually applied.
* <p>
* @param event An approximate representation of the upcoming "roots change" event, as estimated by the IDE.
* In most cases, the IDE cannot provide precise information in this "before" event.
* <p>
* Note that {@link ModuleRootEvent#isCausedByWorkspaceModelChangesOnly()} always returns {@code false} in this method.
* This is because nested {@linkplain ModuleRootEvent} events are de-duplicated by the IDE, and at the time
* {@code beforeRootsChange} is called, it's not yet known whether all events (including de-duplicated ones)
* were caused exclusively by workspace model (WSM) changes.
*/
@RequiresWriteLock
default void beforeRootsChange(@NotNull ModuleRootEvent event) {
}
/**
* Called within the same write action that triggers the change, after the change is actually applied.
*/
@RequiresWriteLock
default void rootsChanged(@NotNull ModuleRootEvent event) {
}
}