[AA] KT-58257 Remove timing guarantees of Kotlin modification events

- Kotlin modification events are published before or after the
  modification, depending on the underlying cause. For example, PSI tree
  change events in the IDE can occur both before and after the change,
  so module and global out-of-block modification events must not make
  timing guarantees. Similarly, module state modification events
  published by the IDE can both happen before and after a module change,
  with most events happening before the change.
This commit is contained in:
Marco Pennekamp
2023-06-22 15:08:01 +02:00
committed by Space Team
parent 9983abea4c
commit 2d279c5f25
8 changed files with 27 additions and 20 deletions
@@ -21,7 +21,7 @@ public abstract class KotlinGlobalModificationServiceBase(private val project: P
ApplicationManager.getApplication().assertWriteAccessAllowed()
incrementModificationTrackers(includeBinaryTrackers = true)
project.analysisMessageBus.syncPublisher(KotlinTopics.GLOBAL_MODULE_STATE_MODIFICATION).afterModification()
project.analysisMessageBus.syncPublisher(KotlinTopics.GLOBAL_MODULE_STATE_MODIFICATION).onModification()
}
@TestOnly
@@ -29,7 +29,7 @@ public abstract class KotlinGlobalModificationServiceBase(private val project: P
ApplicationManager.getApplication().assertWriteAccessAllowed()
incrementModificationTrackers(includeBinaryTrackers = true)
project.analysisMessageBus.syncPublisher(KotlinTopics.GLOBAL_OUT_OF_BLOCK_MODIFICATION).afterModification()
project.analysisMessageBus.syncPublisher(KotlinTopics.GLOBAL_OUT_OF_BLOCK_MODIFICATION).onModification()
}
@TestOnly
@@ -37,7 +37,7 @@ public abstract class KotlinGlobalModificationServiceBase(private val project: P
ApplicationManager.getApplication().assertWriteAccessAllowed()
incrementModificationTrackers(includeBinaryTrackers = false)
project.analysisMessageBus.syncPublisher(KotlinTopics.GLOBAL_SOURCE_MODULE_STATE_MODIFICATION).afterModification()
project.analysisMessageBus.syncPublisher(KotlinTopics.GLOBAL_SOURCE_MODULE_STATE_MODIFICATION).onModification()
}
@TestOnly
@@ -45,6 +45,6 @@ public abstract class KotlinGlobalModificationServiceBase(private val project: P
ApplicationManager.getApplication().assertWriteAccessAllowed()
incrementModificationTrackers(includeBinaryTrackers = false)
project.analysisMessageBus.syncPublisher(KotlinTopics.GLOBAL_SOURCE_OUT_OF_BLOCK_MODIFICATION).afterModification()
project.analysisMessageBus.syncPublisher(KotlinTopics.GLOBAL_SOURCE_OUT_OF_BLOCK_MODIFICATION).onModification()
}
}
@@ -9,10 +9,10 @@ import org.jetbrains.kotlin.analysis.project.structure.KtModule
public fun interface KotlinGlobalModuleStateModificationListener {
/**
* [afterModification] is invoked in a write action after global modification of the module state of all [KtModule]s, including binary
* modules.
* [onModification] is invoked in a write action before or after global modification of the module state of all [KtModule]s, including
* binary modules.
*
* This event is published after SDK removal and to invalidate caches during/between tests.
*/
public fun afterModification()
public fun onModification()
}
@@ -9,9 +9,10 @@ import org.jetbrains.kotlin.analysis.project.structure.KtModule
public fun interface KotlinGlobalOutOfBlockModificationListener {
/**
* [afterModification] is invoked in a write action after global out-of-block modification of all [KtModule]s, including binary modules.
* [onModification] is invoked in a write action before or after global out-of-block modification of all [KtModule]s, including binary
* modules.
*
* This event is published to invalidate caches during/between tests.
*/
public fun afterModification()
public fun onModification()
}
@@ -9,10 +9,10 @@ import org.jetbrains.kotlin.analysis.project.structure.KtModule
public fun interface KotlinGlobalSourceModuleStateModificationListener {
/**
* [afterModification] is invoked in a write action after global modification of the module state of all source [KtModule]s, excluding
* binary modules.
* [onModification] is invoked in a write action before or after global modification of the module state of all source [KtModule]s,
* excluding binary modules.
*
* This event is published to invalidate caches during/between tests.
*/
public fun afterModification()
public fun onModification()
}
@@ -9,10 +9,10 @@ import org.jetbrains.kotlin.analysis.project.structure.KtModule
public fun interface KotlinGlobalSourceOutOfBlockModificationListener {
/**
* [afterModification] is invoked in a write action after global out-of-block modification of all source [KtModule]s, excluding binary
* modules.
* [onModification] is invoked in a write action before or after global out-of-block modification of all source [KtModule]s, excluding
* binary modules.
*
* This event is published on global PSI changes.
*/
public fun afterModification()
public fun onModification()
}
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.analysis.providers.KotlinModificationTrackerFactory
public fun interface KotlinModuleOutOfBlockModificationListener {
/**
* [afterModification] is invoked in a write action after an out-of-block modification happened in [module]'s source code.
* [onModification] is invoked in a write action before or after an out-of-block modification happens in [module]'s source code.
*
* See [KotlinModificationTrackerFactory.createProjectWideOutOfBlockModificationTracker] for an explanation of out-of-block
* modifications.
@@ -18,5 +18,5 @@ public fun interface KotlinModuleOutOfBlockModificationListener {
* This event may be published for any and all source code changes, not just out-of-block modifications, to simplify the implementation
* of modification detection.
*/
public fun afterModification(module: KtModule)
public fun onModification(module: KtModule)
}
@@ -9,8 +9,8 @@ import org.jetbrains.kotlin.analysis.project.structure.KtModule
public fun interface KotlinModuleStateModificationListener {
/**
* [afterModification] is invoked in a write action after the [module] was moved, removed, or its structure changed. [isRemoval] signals
* if the module was removed.
* [onModification] is invoked in a write action before or after the [module] is moved, removed, or its structure is changed.
* [isRemoval] signals if the event is a removal.
*/
public fun afterModification(module: KtModule, isRemoval: Boolean)
public fun onModification(module: KtModule, isRemoval: Boolean)
}
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.analysis.providers.analysisMessageBus
* message bus: [analysisMessageBus].
*
* See the individual listener interfaces for documentation about the events described by these topics:
*
* - [KotlinModuleStateModificationListener]
* - [KotlinModuleOutOfBlockModificationListener]
* - [KotlinGlobalModuleStateModificationListener]
@@ -20,6 +21,11 @@ import org.jetbrains.kotlin.analysis.providers.analysisMessageBus
* - [KotlinGlobalSourceModuleStateModificationListener]
* - [KotlinGlobalSourceOutOfBlockModificationListener]
*
* Modification events may be published before or after a modification, so subscribers should not assume that the modification has or hasn't
* happened yet. The reason for this design decision is that the underlying events (such as PSI tree changes or workspace model events) are
* sometimes published before and sometimes after a change, or even both. Modification events published before the modification should
* however be published close to the modification.
*
* Care needs to be taken with the lack of interplay between different types of topics: Publishing a global modification event, for example,
* does not imply the corresponding module-level event. Similarly, publishing a module state modification event does not imply out-of-block
* modification.