Ensure that it's possible to subscribe via <projectListener> to an application-level topic

GitOrigin-RevId: dc955939689955763f5c3e092ad4751599f94c41
This commit is contained in:
Dmitry Jemerov
2019-12-20 18:32:07 +00:00
committed by intellij-monorepo-bot
parent 71f351610e
commit 895e6311d6
3 changed files with 34 additions and 34 deletions
@@ -71,6 +71,8 @@ public class MessageBusImpl implements MessageBus {
private final Map<PluginDescriptor, MessageBusConnectionImpl> myLazyConnections;
private boolean myIgnoreParentLazyListeners;
public MessageBusImpl(@NotNull MessageBusOwner owner, @NotNull MessageBusImpl parentBus) {
myOwner = owner;
myConnectionDisposable = createConnectionDisposable(owner);
@@ -102,6 +104,10 @@ public class MessageBusImpl implements MessageBus {
myParentBus = null;
}
public void setIgnoreParentLazyListeners(boolean ignoreParentLazyListeners) {
myIgnoreParentLazyListeners = ignoreParentLazyListeners;
}
/**
* Must be a concurrent map, because remove operation may be concurrently performed (synchronized only per topic).
*/
@@ -109,7 +115,7 @@ public class MessageBusImpl implements MessageBus {
public void setLazyListeners(@NotNull ConcurrentMap<String, List<ListenerDescriptor>> map) {
if (myTopicClassToListenerClass != Collections.<String, List<ListenerDescriptor>>emptyMap()) {
myTopicClassToListenerClass.putAll(map);
myPublishers.clear();
clearSubscriberCache();
}
else {
myTopicClassToListenerClass = map;
@@ -192,31 +198,14 @@ public class MessageBusImpl implements MessageBus {
Class<L> listenerClass = topic.getListenerClass();
if (myTopicClassToListenerClass.isEmpty()) {
Object newInstance = Proxy.newProxyInstance(listenerClass.getClassLoader(), new Class[]{listenerClass}, createTopicHandler(topic));
Object prev = myPublishers.putIfAbsent(topic, newInstance);
//noinspection unchecked
return (L)(prev == null ? newInstance : prev);
}
else {
// remove is atomic operation, so, even if topic concurrently created and our topic instance will be not used, still, listeners will be added,
// but problem is that if another topic will be returned earlier, then these listeners will not get fired event
//noinspection SynchronizationOnLocalVariableOrMethodParameter
synchronized (topic) {
return subscribeLazyListeners(topic, listenerClass);
}
}
Object newInstance = Proxy.newProxyInstance(listenerClass.getClassLoader(), new Class[]{listenerClass}, createTopicHandler(topic));
Object prev = myPublishers.putIfAbsent(topic, newInstance);
//noinspection unchecked
return (L)(prev == null ? newInstance : prev);
}
@NotNull
private <L> L subscribeLazyListeners(@NotNull Topic<L> topic, @NotNull Class<L> listenerClass) {
//noinspection unchecked
L publisher = (L)myPublishers.get(topic);
if (publisher != null) {
return publisher;
}
List<ListenerDescriptor> listenerDescriptors = myTopicClassToListenerClass.remove(listenerClass.getName());
private <L> void subscribeLazyListeners(@NotNull Topic<L> topic) {
List<ListenerDescriptor> listenerDescriptors = myTopicClassToListenerClass.remove(topic.getListenerClass().getName());
if (listenerDescriptors != null) {
MultiMap<PluginDescriptor, Object> listenerMap = new MultiMap<>();
for (ListenerDescriptor listenerDescriptor : listenerDescriptors) {
@@ -239,11 +228,6 @@ public class MessageBusImpl implements MessageBus {
}
}
}
//noinspection unchecked
publisher = (L)Proxy.newProxyInstance(listenerClass.getClassLoader(), new Class[]{listenerClass}, createTopicHandler(topic));
myPublishers.put(topic, publisher);
return publisher;
}
@ApiStatus.Internal
@@ -339,7 +323,12 @@ public class MessageBusImpl implements MessageBus {
return myOwner.toString();
}
private void calcSubscribers(@NotNull Topic<?> topic, @NotNull List<? super MessageBusConnectionImpl> result) {
private void calcSubscribers(@NotNull Topic<?> topic,
@NotNull List<? super MessageBusConnectionImpl> result,
boolean subscribeLazyListeners) {
if (subscribeLazyListeners) {
subscribeLazyListeners(topic);
}
final List<MessageBusConnectionImpl> topicSubscribers = mySubscribers.get(topic);
if (topicSubscribers != null) {
result.addAll(topicSubscribers);
@@ -349,12 +338,14 @@ public class MessageBusImpl implements MessageBus {
if (direction == Topic.BroadcastDirection.TO_CHILDREN) {
for (MessageBusImpl childBus : myChildBuses) {
childBus.calcSubscribers(topic, result);
if (!childBus.isDisposed()) {
childBus.calcSubscribers(topic, result, !childBus.myIgnoreParentLazyListeners);
}
}
}
if (direction == Topic.BroadcastDirection.TO_PARENT && myParentBus != null) {
myParentBus.calcSubscribers(topic, result);
myParentBus.calcSubscribers(topic, result, true);
}
}
@@ -383,7 +374,7 @@ public class MessageBusImpl implements MessageBus {
List<MessageBusConnectionImpl> topicSubscribers = mySubscriberCache.get(topic);
if (topicSubscribers == null) {
topicSubscribers = new ArrayList<>();
calcSubscribers(topic, topicSubscribers);
calcSubscribers(topic, topicSubscribers, true);
mySubscriberCache.put(topic, topicSubscribers);
myRootBus.myClearedSubscribersCache = false;
}
@@ -18,6 +18,7 @@ import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.project.ProjectStoreOwner;
import com.intellij.util.messages.MessageBus;
import com.intellij.util.messages.impl.MessageBusImpl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.SystemIndependent;
@@ -90,6 +91,14 @@ final class DefaultProject extends UserDataHolderBase implements Project, Projec
public int hashCode() {
return DEFAULT_HASH_CODE;
}
@NotNull
@Override
protected synchronized MessageBusImpl getOrCreateMessageBusUnderLock() {
MessageBusImpl messageBus = super.getOrCreateMessageBusUnderLock();
messageBus.setIgnoreParentLazyListeners(true);
return messageBus;
}
};
}
@@ -396,7 +396,7 @@ abstract class PlatformComponentManagerImpl @JvmOverloads constructor(internal v
}
@Synchronized
private fun getOrCreateMessageBusUnderLock(): MessageBusImpl {
protected open fun getOrCreateMessageBusUnderLock(): MessageBusImpl {
var messageBus = this.messageBus
if (messageBus != null) {
return messageBus