diff --git a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionComponentAdapter.java b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionComponentAdapter.java index 7d231b181587..49b5f4701783 100644 --- a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionComponentAdapter.java +++ b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionComponentAdapter.java @@ -47,13 +47,6 @@ public class ExtensionComponentAdapter implements LoadingOrder.Orderable, Assign myOrder = order; } - public ExtensionComponentAdapter(@NotNull String implementationClassName, - @Nullable Element extensionElement, - PicoContainer container, - PluginDescriptor pluginDescriptor) { - this(implementationClassName, container, pluginDescriptor, null, LoadingOrder.ANY, extensionElement); - } - @Override public Object getComponentKey() { return this; @@ -66,21 +59,22 @@ public class ExtensionComponentAdapter implements LoadingOrder.Orderable, Assign @Override public Object getComponentInstance(final PicoContainer container) throws PicoException, ProcessCanceledException { - if (myComponentInstance == null) { + Object instance = myComponentInstance; + if (instance == null) { try { Class impl = loadImplementationClass(); - Object componentInstance = new CachingConstructorInjectionComponentAdapter(getComponentKey(), impl, null, true).getComponentInstance(container); + instance = new CachingConstructorInjectionComponentAdapter(getComponentKey(), impl, null, true).getComponentInstance(container); if (myExtensionElement != null) { try { - XmlSerializer.deserializeInto(componentInstance, myExtensionElement); + XmlSerializer.deserializeInto(instance, myExtensionElement); } catch (Exception e) { throw new PicoInitializationException(e); } } - myComponentInstance = componentInstance; + myComponentInstance = instance; } catch (ProcessCanceledException e) { throw e; @@ -90,13 +84,13 @@ public class ExtensionComponentAdapter implements LoadingOrder.Orderable, Assign throw new PicoPluginExtensionInitializationException(t.getMessage(), t, pluginId); } - if (myComponentInstance instanceof PluginAware) { - PluginAware pluginAware = (PluginAware)myComponentInstance; + if (instance instanceof PluginAware) { + PluginAware pluginAware = (PluginAware)instance; pluginAware.setPluginDescriptor(myPluginDescriptor); } } - return myComponentInstance; + return instance; } @Override @@ -162,8 +156,8 @@ public class ExtensionComponentAdapter implements LoadingOrder.Orderable, Assign return myNotificationSent; } - void setNotificationSent(boolean notificationSent) { - myNotificationSent = notificationSent; + void setNotificationSent() { + myNotificationSent = true; } @Override 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 abdbfac62398..2715d9597c9b 100644 --- a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionPointImpl.java +++ b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionPointImpl.java @@ -10,6 +10,7 @@ import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Disposer; import com.intellij.util.ArrayUtil; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.OpenTHashSet; import com.intellij.util.containers.StringInterner; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -152,7 +153,7 @@ public final class ExtensionPointImpl implements ExtensionPoint { } notifyListenersOnAdd(extension, adapter.getPluginDescriptor()); - adapter.setNotificationSent(true); + adapter.setNotificationSent(); } } } @@ -199,9 +200,7 @@ public final class ExtensionPointImpl implements ExtensionPoint { //noinspection unchecked return (T[])Array.newInstance(getExtensionClass(), 0); } - else { - return myExtensionsCacheAsArray.clone(); - } + return myExtensionsCacheAsArray.clone(); } @NotNull @@ -243,6 +242,7 @@ public final class ExtensionPointImpl implements ExtensionPoint { myExtensionAdapters = new LinkedHashSet<>(adapters); Set loaded = ContainerUtil.newHashOrEmptySet(myLoadedAdapters); + OpenTHashSet duplicates = new OpenTHashSet<>(adapters.size()); myLoadedAdapters = Collections.emptyList(); boolean errorHappened = false; @@ -254,11 +254,12 @@ public final class ExtensionPointImpl implements ExtensionPoint { errorHappened = true; LOG.error("null extension in: " + adapter + ";\ngetExtensionClass(): " + getExtensionClass() + ";\n" ); } - if (i > 0 && extension == result[i - 1]) { + if (!duplicates.add(extension)) { errorHappened = true; + T duplicate = duplicates.get(extension); LOG.error("Duplicate extension found: " + extension + "; " + - " Adapter: " + adapter + ";\n" + - " Prev adapter: " + adapters.get(i-1) + ";\n" + + " Prev extension: " + duplicate + ";\n" + + " Adapter: " + adapter + ";\n" + " getExtensionClass(): " + getExtensionClass() + ";\n" + " result:" + Arrays.asList(result)); } @@ -268,6 +269,7 @@ public final class ExtensionPointImpl implements ExtensionPoint { continue; } result[i] = extension; + registerExtension(extension, adapter, myLoadedAdapters.size(), !loaded.contains(adapter)); } catch (ProcessCanceledException e) { @@ -331,7 +333,7 @@ public final class ExtensionPointImpl implements ExtensionPoint { } @Override - public void unregisterExtension(@NotNull Class extensionClass) { + public synchronized void unregisterExtension(@NotNull Class extensionClass) { for (ExtensionComponentAdapter adapter : ContainerUtil.concat(myExtensionAdapters, myLoadedAdapters)) { if (adapter.getAssignableToClassName().equals(extensionClass.getCanonicalName())) { unregisterExtensionAdapter(adapter); @@ -479,6 +481,7 @@ public final class ExtensionPointImpl implements ExtensionPoint { return extensionClass; } + @Override public String toString() { return getName(); } @@ -528,7 +531,7 @@ public final class ExtensionPointImpl implements ExtensionPoint { private final LoadingOrder myLoadingOrder; private ObjectComponentAdapter(@NotNull Object extension, @NotNull LoadingOrder loadingOrder) { - super(extension.getClass().getName(), null, null, null); + super(extension.getClass().getName(), null, null, null, LoadingOrder.ANY, null); myExtension = extension; myLoadingOrder = loadingOrder; } diff --git a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java index bcee0c07368f..278681924b0d 100644 --- a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java +++ b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java @@ -144,10 +144,6 @@ public class ExtensionsAreaImpl implements ExtensionsArea { registerExtensionPoint(epName, className, pluginDescriptor, kind); } - public void registerExtension(@NotNull final String pluginName, @NotNull final Element extensionElement) { - registerExtension(new DefaultPluginDescriptor(PluginId.getId(pluginName)), extensionElement, null); - } - @Override public void registerExtension(@NotNull final PluginDescriptor pluginDescriptor, @NotNull final Element extensionElement, String extensionNs) { String epName = extractEPName(extensionElement, extensionNs); diff --git a/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionComponentAdapterTest.java b/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionComponentAdapterTest.java index 143fb898ab51..f606c36bcf85 100644 --- a/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionComponentAdapterTest.java +++ b/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionComponentAdapterTest.java @@ -33,7 +33,7 @@ public class ExtensionComponentAdapterTest { Element element = JDOMUtil.load(""); DefaultPicoContainer container = new DefaultPicoContainer(); DefaultPluginDescriptor descriptor = new DefaultPluginDescriptor("test"); - new ExtensionComponentAdapter(name, element, container, descriptor).getComponentInstance(container); + new ExtensionComponentAdapter(name, container, descriptor, null, LoadingOrder.ANY, element).getComponentInstance(container); } @NotNull diff --git a/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionPointImplTest.java b/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionPointImplTest.java index f2363240e9c7..6c15372200b3 100644 --- a/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionPointImplTest.java +++ b/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionPointImplTest.java @@ -262,7 +262,7 @@ public class ExtensionPointImplTest { private boolean myFire; MyShootingComponentAdapter(@NotNull String implementationClass) { - super(implementationClass, null, new DefaultPicoContainer(), new DefaultPluginDescriptor("test")); + super(implementationClass, new DefaultPicoContainer(), new DefaultPluginDescriptor("test"), null, LoadingOrder.ANY, null); } public void setFire(boolean fire) { diff --git a/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionsComplexTest.java b/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionsComplexTest.java index 59ffe6c60479..e0659abb3b40 100644 --- a/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionsComplexTest.java +++ b/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionsComplexTest.java @@ -110,7 +110,7 @@ public class ExtensionsComplexTest { private static void initExtensions(@NonNls String data, AreaInstance instance) throws IOException, JDOMException { final Element element = JDOMUtil.load(data); for (final Element child : element.getChildren()) { - ((ExtensionsAreaImpl)Extensions.getArea(instance)).registerExtension(element.getNamespaceURI(), child); + ExtensionsImplTest.registerExtension(((ExtensionsAreaImpl)Extensions.getArea(instance)), element.getNamespaceURI(), child); } } diff --git a/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionsImplTest.java b/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionsImplTest.java index 795133a50861..99297014ac6d 100644 --- a/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionsImplTest.java +++ b/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionsImplTest.java @@ -3,6 +3,7 @@ package com.intellij.openapi.extensions.impl; import com.intellij.openapi.extensions.*; import com.intellij.openapi.util.JDOMUtil; +import org.jdom.Element; import org.jdom.JDOMException; import org.jetbrains.annotations.NotNull; import org.junit.Test; @@ -156,11 +157,11 @@ public class ExtensionsImplTest { public void testExtensionsNamespaces() throws IOException, JDOMException { ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(new DefaultPicoContainer()); extensionsArea.registerExtensionPoint("plugin.ep1", TestExtensionClassOne.class.getName(), ExtensionPoint.Kind.BEAN_CLASS); - extensionsArea.registerExtension("plugin", JDOMUtil.load( + registerExtension(extensionsArea, "plugin", JDOMUtil.load( "3")); - extensionsArea.registerExtension("plugin", JDOMUtil.load( + registerExtension(extensionsArea, "plugin", JDOMUtil.load( "1")); - extensionsArea.registerExtension("plugin", JDOMUtil.load( + registerExtension(extensionsArea, "plugin", JDOMUtil.load( "2")); ExtensionPoint extensionPoint = extensionsArea.getExtensionPoint("plugin.ep1"); TestExtensionClassOne[] extensions = (TestExtensionClassOne[]) extensionPoint.getExtensions(); @@ -174,11 +175,11 @@ public class ExtensionsImplTest { public void testExtensionsWithOrdering() throws IOException, JDOMException { ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(new DefaultPicoContainer()); extensionsArea.registerExtensionPoint("ep1", TestExtensionClassOne.class.getName(), ExtensionPoint.Kind.BEAN_CLASS); - extensionsArea.registerExtension("", JDOMUtil.load( + registerExtension(extensionsArea, "", JDOMUtil.load( "3")); - extensionsArea.registerExtension("", JDOMUtil.load( + registerExtension(extensionsArea, "", JDOMUtil.load( "1")); - extensionsArea.registerExtension("", JDOMUtil.load( + registerExtension(extensionsArea, "", JDOMUtil.load( "2")); ExtensionPoint extensionPoint = extensionsArea.getExtensionPoint("ep1"); TestExtensionClassOne[] extensions = (TestExtensionClassOne[]) extensionPoint.getExtensions(); @@ -192,9 +193,9 @@ public class ExtensionsImplTest { public void testExtensionsWithOrderingUpdate() throws IOException, JDOMException { ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(new DefaultPicoContainer()); extensionsArea.registerExtensionPoint("ep1", TestExtensionClassOne.class.getName(), ExtensionPoint.Kind.BEAN_CLASS); - extensionsArea.registerExtension("", JDOMUtil.load("7")); - extensionsArea.registerExtension("", JDOMUtil.load("1")); - extensionsArea.registerExtension("", JDOMUtil.load("3")); + registerExtension(extensionsArea, "", JDOMUtil.load("7")); + registerExtension(extensionsArea, "", JDOMUtil.load("1")); + registerExtension(extensionsArea, "", JDOMUtil.load("3")); ExtensionPoint extensionPoint = extensionsArea.getExtensionPoint("ep1"); TestExtensionClassOne[] extensions = extensionPoint.getExtensions(); assertEquals(3, extensions.length); @@ -204,10 +205,10 @@ public class ExtensionsImplTest { TestExtensionClassOne extension = new TestExtensionClassOne("xxx"); extensionPoint.registerExtension(extension); extensionPoint.unregisterExtension(extension); - extensionsArea.registerExtension("", JDOMUtil.load("2")); - extensionsArea.registerExtension("", JDOMUtil.load("4")); - extensionsArea.registerExtension("", JDOMUtil.load("8")); - extensionsArea.registerExtension("", JDOMUtil.load("5")); + registerExtension(extensionsArea, "", JDOMUtil.load("2")); + registerExtension(extensionsArea, "", JDOMUtil.load("4")); + registerExtension(extensionsArea, "", JDOMUtil.load("8")); + registerExtension(extensionsArea, "", JDOMUtil.load("5")); extensionPoint.registerExtension(new TestExtensionClassOne("6")); extensions = extensionPoint.getExtensions(); assertEquals(8, extensions.length); @@ -221,6 +222,10 @@ public class ExtensionsImplTest { assertEquals("8", extensions[7].getText()); } + public static void registerExtension(ExtensionsAreaImpl area, @NotNull final String pluginName, @NotNull final Element extensionElement) { + area.registerExtension(new DefaultPluginDescriptor(PluginId.getId(pluginName)), extensionElement, null); + } + public interface MyInterface1 extends Runnable { }