diff --git a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionPointImpl.java b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionPointImpl.java index 95fdcf58be5f..62fe9e85d4a3 100644 --- a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionPointImpl.java +++ b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionPointImpl.java @@ -8,6 +8,7 @@ import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.EmptyRunnable; import com.intellij.util.ArrayUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.OpenTHashSet; @@ -247,6 +248,7 @@ public final class ExtensionPointImpl implements ExtensionPoint { myLoadedAdapters = Collections.emptyList(); boolean errorHappened = false; for (int i = 0; i < adapters.size(); i++) { + CHECK_CANCELED.run(); ExtensionComponentAdapter adapter = adapters.get(i); try { @SuppressWarnings("unchecked") T extension = (T)adapter.getExtension(); @@ -548,4 +550,35 @@ public final class ExtensionPointImpl implements ExtensionPoint { return myLoadingOrder; } } + + @SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized") + private static Runnable CHECK_CANCELED = EmptyRunnable.getInstance(); + + public static void setCheckCanceledAction(Runnable checkCanceled) { + CHECK_CANCELED = new Runnable() { + final Set reported = ContainerUtil.newConcurrentSet(); + + @Override + public void run() { + try { + checkCanceled.run(); + } + catch (ProcessCanceledException e) { + if (!isInsideClassInitializer(e.getStackTrace())) { // otherwise ExceptionInInitializerError happens and the class is screwed forever + throw e; + } + else { + Throwable throwable = new Throwable(); + if (reported.add(throwable)) { + LOG.warn("Don't instantiate extensions from class initializer", throwable); + } + } + } + } + }; + } + + private static boolean isInsideClassInitializer(StackTraceElement[] trace) { + return Arrays.stream(trace).anyMatch(s -> "".equals(s.getMethodName())); + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java index 5725d6706ebd..76ab98918073 100644 --- a/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/progress/impl/ProgressManagerImpl.java @@ -5,10 +5,8 @@ package com.intellij.openapi.progress.impl; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.progress.EmptyProgressIndicator; -import com.intellij.openapi.progress.ProcessCanceledException; -import com.intellij.openapi.progress.ProgressIndicator; -import com.intellij.openapi.progress.Task; +import com.intellij.openapi.extensions.impl.ExtensionPointImpl; +import com.intellij.openapi.progress.*; import com.intellij.openapi.progress.util.PingProgress; import com.intellij.openapi.progress.util.ProgressIndicatorUtils; import com.intellij.openapi.progress.util.ProgressWindow; @@ -58,6 +56,7 @@ public class ProgressManagerImpl extends CoreProgressManager implements Disposab } }, this); + ExtensionPointImpl.setCheckCanceledAction(ProgressManager::checkCanceled); } @Override