diff --git a/java/compiler/impl/src/com/intellij/compiler/ant/GenerateAntMain.java b/java/compiler/impl/src/com/intellij/compiler/ant/GenerateAntMain.java index 3ae1802b777c..b16b8bf1c658 100644 --- a/java/compiler/impl/src/com/intellij/compiler/ant/GenerateAntMain.java +++ b/java/compiler/impl/src/com/intellij/compiler/ant/GenerateAntMain.java @@ -5,10 +5,9 @@ import com.intellij.openapi.application.ApplicationStarter; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; -/** - * @author max - */ -public class GenerateAntMain implements ApplicationStarter { +import java.util.List; + +final class GenerateAntMain implements ApplicationStarter { private GenerateAntApplication myApplication; @Override @@ -18,12 +17,12 @@ public class GenerateAntMain implements ApplicationStarter { } @Override - public void premain(String[] args) { + public void premain(@NotNull List args) { System.setProperty("idea.load.plugins", "false"); myApplication = new GenerateAntApplication(); - myApplication.myProjectPath = args[1]; - myApplication.myOutPath = args[2]; + myApplication.myProjectPath = args.get(1); + myApplication.myOutPath = args.get(2); } @Override diff --git a/java/java-psi-impl/src/com/intellij/core/JavaCoreApplicationEnvironment.java b/java/java-psi-impl/src/com/intellij/core/JavaCoreApplicationEnvironment.java index 8ca5ab7439e6..c8f793ae0a43 100644 --- a/java/java-psi-impl/src/com/intellij/core/JavaCoreApplicationEnvironment.java +++ b/java/java-psi-impl/src/com/intellij/core/JavaCoreApplicationEnvironment.java @@ -1,4 +1,4 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.core; import com.intellij.codeInsight.ContainerProvider; @@ -10,7 +10,6 @@ import com.intellij.ide.highlighter.ArchiveFileType; import com.intellij.ide.highlighter.JavaClassFileType; import com.intellij.ide.highlighter.JavaFileType; import com.intellij.lang.LanguageASTFactory; -import com.intellij.lang.LanguageParserDefinitions; import com.intellij.lang.folding.LanguageFolding; import com.intellij.lang.java.JavaLanguage; import com.intellij.lang.java.JavaParserDefinition; @@ -53,13 +52,13 @@ public class JavaCoreApplicationEnvironment extends CoreApplicationEnvironment { registerFileType(PlainTextFileType.INSTANCE, "txt;sh;bat;cmd;policy;log;cgi;MF;jad;jam;htaccess"); addExplicitExtension(LanguageASTFactory.INSTANCE, PlainTextLanguage.INSTANCE, new PlainTextASTFactory()); - addExplicitExtension(LanguageParserDefinitions.INSTANCE, PlainTextLanguage.INSTANCE, new PlainTextParserDefinition()); + registerParserDefinition(new PlainTextParserDefinition()); addExplicitExtension(FileTypeFileViewProviders.INSTANCE, JavaClassFileType.INSTANCE, new ClassFileViewProviderFactory()); addExplicitExtension(BinaryFileStubBuilders.INSTANCE, JavaClassFileType.INSTANCE, new ClassFileStubBuilder()); addExplicitExtension(LanguageASTFactory.INSTANCE, JavaLanguage.INSTANCE, new JavaASTFactory()); - addExplicitExtension(LanguageParserDefinitions.INSTANCE, JavaLanguage.INSTANCE, new JavaParserDefinition()); + registerParserDefinition(new JavaParserDefinition()); addExplicitExtension(LanguageConstantExpressionEvaluator.INSTANCE, JavaLanguage.INSTANCE, new PsiExpressionEvaluator()); addExtension(ContainerProvider.EP_NAME, new JavaContainerProvider()); diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightAdvHighlightingPerformanceTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightAdvHighlightingPerformanceTest.java index a44f213df95a..0eb0d7321bf6 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightAdvHighlightingPerformanceTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/daemon/LightAdvHighlightingPerformanceTest.java @@ -41,7 +41,7 @@ public class LightAdvHighlightingPerformanceTest extends LightDaemonAnalyzerTest blockUntil(Extensions.getRootArea().getExtensionPoint(LanguageAnnotators.EP_NAME), getTestRootDisposable()); blockUntil(Extensions.getRootArea().getExtensionPoint(LineMarkerProviders.EP_NAME), getTestRootDisposable()); blockUntil(ConcatenationInjectorManager.CONCATENATION_INJECTOR_EP_NAME.getPoint(getProject()), getTestRootDisposable()); - blockUntil(Extensions.getArea(getProject()).getExtensionPoint(MultiHostInjector.MULTIHOST_INJECTOR_EP_NAME), getTestRootDisposable()); + blockUntil(getProject().getExtensionArea().getExtensionPoint(MultiHostInjector.MULTIHOST_INJECTOR_EP_NAME), getTestRootDisposable()); IntentionManager.getInstance().getAvailableIntentionActions(); // hack to avoid slowdowns in PyExtensionFactory PathManagerEx.getTestDataPath(); // to cache stuff diff --git a/json/tests/test/com/intellij/json/JsonSpellcheckerTest.java b/json/tests/test/com/intellij/json/JsonSpellcheckerTest.java index 0492d08744c8..7957b85d9d85 100644 --- a/json/tests/test/com/intellij/json/JsonSpellcheckerTest.java +++ b/json/tests/test/com/intellij/json/JsonSpellcheckerTest.java @@ -3,7 +3,6 @@ package com.intellij.json; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.IdeActions; -import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileTypes.LanguageFileType; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.vfs.VirtualFile; @@ -43,7 +42,7 @@ public class JsonSpellcheckerTest extends JsonTestCase { PsiFile[] files = myFixture.configureByFiles(getTestName(false) + ".json", "Schema.json"); JsonSchemaTestServiceImpl.setProvider(new JsonSchemaTestProvider(files[1].getVirtualFile(), getAvailabilityPredicate())); - MutablePicoContainer container = Extensions.getArea(getProject()).getPicoContainer(); + MutablePicoContainer container = (MutablePicoContainer)getProject().getPicoContainer(); String key = JsonSchemaService.class.getName(); container.unregisterComponent(key); container.registerComponentImplementation(key, JsonSchemaTestServiceImpl.class); diff --git a/json/tests/test/com/jetbrains/jsonSchema/JsonSchemaCrossReferencesTest.java b/json/tests/test/com/jetbrains/jsonSchema/JsonSchemaCrossReferencesTest.java index 3c3ae7f14e73..08eb6c66fea4 100644 --- a/json/tests/test/com/jetbrains/jsonSchema/JsonSchemaCrossReferencesTest.java +++ b/json/tests/test/com/jetbrains/jsonSchema/JsonSchemaCrossReferencesTest.java @@ -8,7 +8,6 @@ import com.intellij.json.JsonFileType; import com.intellij.json.psi.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Document; -import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.Trinity; @@ -236,7 +235,7 @@ public class JsonSchemaCrossReferencesTest extends JsonSchemaHeavyAbstractTest { public void registerSchemes() { final String moduleDir = getModuleDir(getProject()); - MutablePicoContainer container = Extensions.getArea(getProject()).getPicoContainer(); + MutablePicoContainer container = (MutablePicoContainer)getProject().getPicoContainer(); final String key = JsonSchemaMappingsProjectConfiguration.class.getName(); container.unregisterComponent(key); container.registerComponentImplementation(key, TestJsonSchemaMappingsProjectConfiguration.class); diff --git a/json/tests/test/com/jetbrains/jsonSchema/JsonSchemaHighlightingTestBase.java b/json/tests/test/com/jetbrains/jsonSchema/JsonSchemaHighlightingTestBase.java index eb0b6383510f..1d629bce1ed6 100644 --- a/json/tests/test/com/jetbrains/jsonSchema/JsonSchemaHighlightingTestBase.java +++ b/json/tests/test/com/jetbrains/jsonSchema/JsonSchemaHighlightingTestBase.java @@ -4,7 +4,6 @@ package com.jetbrains.jsonSchema; import com.intellij.codeInsight.daemon.DaemonAnalyzerTestCase; import com.intellij.codeInspection.InspectionProfileEntry; import com.intellij.openapi.Disposable; -import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.io.FileUtil; @@ -20,7 +19,6 @@ import java.io.File; import java.io.IOException; public abstract class JsonSchemaHighlightingTestBase extends DaemonAnalyzerTestCase { - protected abstract String getTestFileName(); protected abstract InspectionProfileEntry getInspectionProfile(); protected abstract Predicate getAvailabilityPredicate(); @@ -62,7 +60,7 @@ public abstract class JsonSchemaHighlightingTestBase extends DaemonAnalyzerTestC FileUtil.writeToFile(child, schema); VirtualFile schemaFile = getVirtualFile(child); JsonSchemaTestServiceImpl.setProvider(new JsonSchemaTestProvider(schemaFile, getAvailabilityPredicate())); - MutablePicoContainer container = Extensions.getArea(project).getPicoContainer(); + MutablePicoContainer container = (MutablePicoContainer)project.getPicoContainer(); String key = JsonSchemaService.class.getName(); container.unregisterComponent(key); container.registerComponentImplementation(key, JsonSchemaTestServiceImpl.class); diff --git a/platform/configuration-store-impl/src/ApplicationStoreImpl.kt b/platform/configuration-store-impl/src/ApplicationStoreImpl.kt index 49dbb8bfd0e4..3376514eda2f 100644 --- a/platform/configuration-store-impl/src/ApplicationStoreImpl.kt +++ b/platform/configuration-store-impl/src/ApplicationStoreImpl.kt @@ -3,6 +3,7 @@ package com.intellij.configurationStore import com.intellij.configurationStore.schemeManager.ROOT_CONFIG import com.intellij.openapi.application.Application +import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.PathManager import com.intellij.openapi.application.appSystemDir import com.intellij.openapi.components.* @@ -15,11 +16,16 @@ import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.launch import org.jetbrains.jps.model.serialization.JpsGlobalLoader -private class ApplicationPathMacroManager : PathMacroManager(null) +internal class ApplicationPathMacroManager : PathMacroManager(null) const val APP_CONFIG = "\$APP_CONFIG$" -class ApplicationStoreImpl(private val application: Application, pathMacroManager: PathMacroManager? = null) : ComponentStoreWithExtraComponents() { +class ApplicationStoreImpl(pathMacroManager: PathMacroManager?) : ComponentStoreWithExtraComponents() { + private val application = ApplicationManager.getApplication() + + @Suppress("unused") + constructor() : this(PathMacroManager.getInstance(ApplicationManager.getApplication())) + override val storageManager = ApplicationStorageManager(application, pathMacroManager) // number of app components require some state, so, we load default state in test mode diff --git a/platform/core-api/src/com/intellij/lang/LanguageExtensionPoint.java b/platform/core-api/src/com/intellij/lang/LanguageExtensionPoint.java index 75867633a611..c4a32533152b 100644 --- a/platform/core-api/src/com/intellij/lang/LanguageExtensionPoint.java +++ b/platform/core-api/src/com/intellij/lang/LanguageExtensionPoint.java @@ -3,7 +3,6 @@ package com.intellij.lang; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.extensions.CustomLoadingExtensionPointBean; -import com.intellij.openapi.util.NotNullLazyValue; import com.intellij.util.KeyedLazyInstance; import com.intellij.util.xmlb.annotations.Attribute; import org.jetbrains.annotations.NotNull; @@ -14,6 +13,13 @@ import org.jetbrains.annotations.NotNull; * @author yole */ public class LanguageExtensionPoint extends CustomLoadingExtensionPointBean implements KeyedLazyInstance { + public LanguageExtensionPoint() { + } + + public LanguageExtensionPoint(@NotNull T instance) { + myInstance = instance; + } + // these must be public for scrambling compatibility /** @@ -27,13 +33,28 @@ public class LanguageExtensionPoint extends CustomLoadingExtensionPointBean i @Attribute("implementationClass") public String implementationClass; - private final NotNullLazyValue myHandler = - NotNullLazyValue.createValue(() -> instantiateExtension(implementationClass, ApplicationManager.getApplication().getPicoContainer())); + private volatile T myInstance; @NotNull @Override public T getInstance() { - return myHandler.getValue(); + T result = myInstance; + if (result != null) { + return result; + } + + //noinspection SynchronizeOnThis + synchronized (this) { + result = myInstance; + if (result != null) { + return result; + } + + //noinspection NonPrivateFieldAccessedInSynchronizedContext + result = instantiateExtension(implementationClass, ApplicationManager.getApplication().getPicoContainer()); + myInstance = result; + } + return result; } @Override diff --git a/platform/core-api/src/com/intellij/lang/LanguageUtil.java b/platform/core-api/src/com/intellij/lang/LanguageUtil.java index ece7ad5c5f13..321990b585b0 100644 --- a/platform/core-api/src/com/intellij/lang/LanguageUtil.java +++ b/platform/core-api/src/com/intellij/lang/LanguageUtil.java @@ -35,7 +35,7 @@ public final class LanguageUtil { public static Language getLanguageForPsi(@NotNull Project project, @Nullable VirtualFile file) { Language language = getFileLanguage(file); if (language == null) return null; - return LanguageSubstitutors.INSTANCE.substituteLanguage(language, file, project); + return LanguageSubstitutors.getInstance().substituteLanguage(language, file, project); } @Nullable diff --git a/platform/core-api/src/com/intellij/openapi/components/ComponentManager.java b/platform/core-api/src/com/intellij/openapi/components/ComponentManager.java index 959f695bff59..85c5291b2dd1 100644 --- a/platform/core-api/src/com/intellij/openapi/components/ComponentManager.java +++ b/platform/core-api/src/com/intellij/openapi/components/ComponentManager.java @@ -4,9 +4,11 @@ package com.intellij.openapi.components; import com.intellij.openapi.Disposable; import com.intellij.openapi.extensions.AreaInstance; import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.extensions.ExtensionsArea; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.UserDataHolder; import com.intellij.util.messages.MessageBus; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.picocontainer.PicoContainer; @@ -19,7 +21,7 @@ import org.picocontainer.PicoContainer; * @see com.intellij.openapi.application.Application * @see com.intellij.openapi.project.Project */ -public interface ComponentManager extends UserDataHolder, Disposable { +public interface ComponentManager extends UserDataHolder, Disposable, AreaInstance { /** * @deprecated Use {@link #getComponent(Class)} instead. */ @@ -51,7 +53,7 @@ public interface ComponentManager extends UserDataHolder, Disposable { * @return {@code true} if there is a component with the specified interface class; * {@code false} otherwise */ - boolean hasComponent(@NotNull Class interfaceClass); + boolean hasComponent(@NotNull Class interfaceClass); /** * Gets all components whose implementation class is derived from {@code baseClass}. @@ -83,7 +85,9 @@ public interface ComponentManager extends UserDataHolder, Disposable { */ @NotNull @Deprecated - T[] getExtensions(@NotNull ExtensionPointName extensionPointName); + default T[] getExtensions(@NotNull ExtensionPointName extensionPointName) { + return getExtensionArea().getExtensionPoint(extensionPointName).getExtensions(); + } /** * @return condition for this component being disposed. @@ -94,4 +98,18 @@ public interface ComponentManager extends UserDataHolder, Disposable { default void initializeComponent(@NotNull Object component, @Nullable ServiceDescriptor serviceDescriptor) { } + + @ApiStatus.Internal + default T getService(@NotNull Class serviceClass, boolean isCreate) { + // default impl to keep backward compatibility + //noinspection unchecked + return (T)getPicoContainer().getComponentInstance(serviceClass.getName()); + } + + @NotNull + @Override + default ExtensionsArea getExtensionArea() { + // default impl to keep backward compatibility + throw new AbstractMethodError(); + } } \ No newline at end of file diff --git a/platform/core-api/src/com/intellij/openapi/components/ExtensionAreas.java b/platform/core-api/src/com/intellij/openapi/components/ExtensionAreas.java index f539a84ae79a..e6f282926fbb 100644 --- a/platform/core-api/src/com/intellij/openapi/components/ExtensionAreas.java +++ b/platform/core-api/src/com/intellij/openapi/components/ExtensionAreas.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2012 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.components; import org.jetbrains.annotations.NonNls; @@ -20,7 +6,7 @@ import org.jetbrains.annotations.NonNls; /** * @author yole */ -public class ExtensionAreas { +public final class ExtensionAreas { @NonNls public static final String IDEA_PROJECT = "IDEA_PROJECT"; @NonNls public static final String IDEA_MODULE = "IDEA_MODULE"; } diff --git a/platform/core-api/src/com/intellij/openapi/components/ServiceManager.java b/platform/core-api/src/com/intellij/openapi/components/ServiceManager.java index e97be3d550ea..6b74afa86a52 100644 --- a/platform/core-api/src/com/intellij/openapi/components/ServiceManager.java +++ b/platform/core-api/src/com/intellij/openapi/components/ServiceManager.java @@ -1,102 +1,35 @@ // Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.components; -import com.intellij.diagnostic.LoadingPhase; -import com.intellij.diagnostic.ParallelActivity; -import com.intellij.diagnostic.StartUpMeasurer; -import com.intellij.openapi.Disposable; -import com.intellij.openapi.application.AccessToken; -import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.progress.ProgressIndicatorProvider; -import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.NotNullLazyKey; -import com.intellij.openapi.util.Ref; -import com.intellij.util.ReflectionUtil; -import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.io.storage.HeavyProcessLatch; -import com.intellij.util.pico.DefaultPicoContainer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.picocontainer.PicoContainer; - -import java.lang.reflect.Modifier; -import java.util.concurrent.ConcurrentMap; /** * For old-style components, the contract specifies a lifecycle: the component gets created and notified during the project opening process. * For services, there's no such contract, so we don't even load the class implementing the service until someone requests it. */ public final class ServiceManager { - private static final Logger LOG = Logger.getInstance(ServiceManager.class); - - private static final ConcurrentMap, Object> ourAppServices = ContainerUtil.newConcurrentMap(); - private ServiceManager() { } public static T getService(@NotNull Class serviceClass) { - if (isLightService(serviceClass)) { - return getOrCreateLightService(serviceClass); - } - else { - return doGetService(ApplicationManager.getApplication(), serviceClass, true); - } + return ApplicationManager.getApplication().getService(serviceClass, true); } public static T getService(@NotNull Project project, @NotNull Class serviceClass) { - return doGetService(project, serviceClass, true); + return project.getService(serviceClass, true); } @Nullable public static T getServiceIfCreated(@NotNull Project project, @NotNull Class serviceClass) { - return doGetService(project, serviceClass, false); + return project.getService(serviceClass, false); } @Nullable public static T getServiceIfCreated(@NotNull Class serviceClass) { - if (isLightService(serviceClass)) { - //noinspection unchecked - return (T)ourAppServices.get(serviceClass); - } - return doGetService(ApplicationManager.getApplication(), serviceClass, false); - } - - @Nullable - private static T doGetService(@NotNull ComponentManager componentManager, @NotNull Class serviceClass, boolean isCreate) { - String componentKey = serviceClass.getName(); - - PicoContainer picoContainer = componentManager.getPicoContainer(); - if (!isCreate && picoContainer instanceof DefaultPicoContainer) { - return ((DefaultPicoContainer)picoContainer).getComponentInstanceIfInstantiated(componentKey); - } - - @SuppressWarnings("unchecked") T instance = (T)picoContainer.getComponentInstance(componentKey); - if (instance == null) { - ProgressManager.checkCanceled(); - instance = assertServiceNotRegisteredAsComponent(componentManager, serviceClass, componentKey); - } - return instance; - } - - private static T assertServiceNotRegisteredAsComponent(@NotNull ComponentManager componentManager, - @NotNull Class serviceClass, - @NotNull String componentKey) { - T instance = componentManager.getComponent(serviceClass); - if (instance != null) { - Application app = ApplicationManager.getApplication(); - String message = componentKey + " requested as a service, but it is a component - convert it to a service or change call to " + - (componentManager == app ? "ApplicationManager.getApplication().getComponent()" : "project.getComponent()"); - if (app.isUnitTestMode()) { - LOG.error(message); - } - else { - LOG.warn(message); - } - } - return instance; + return ApplicationManager.getApplication().getService(serviceClass, false); } /** @@ -110,59 +43,4 @@ public final class ServiceManager { public static NotNullLazyKey createLazyKey(@NotNull final Class serviceClass) { return NotNullLazyKey.create("Service: " + serviceClass.getName(), project -> getService(project, serviceClass)); } - - private static boolean isLightService(@NotNull Class serviceClass) { - return Modifier.isFinal(serviceClass.getModifiers()) && serviceClass.isAnnotationPresent(Service.class); - } - - @NotNull - private static T getOrCreateLightService(@NotNull Class serviceClass) { - @SuppressWarnings("unchecked") - T instance = (T)ourAppServices.get(serviceClass); - if (instance != null) { - return instance; - } - - LoadingPhase.COMPONENT_REGISTERED.assertAtLeast(); - - //noinspection SynchronizeOnThis - synchronized (serviceClass) { - //noinspection unchecked - instance = (T)ourAppServices.get(serviceClass); - if (instance != null) { - return instance; - } - - ComponentManager componentManager = ApplicationManager.getApplication(); - try (AccessToken ignore = HeavyProcessLatch.INSTANCE.processStarted("Creating service '" + serviceClass.getName() + "'")) { - if (ProgressIndicatorProvider.getGlobalProgressIndicator() == null) { - instance = createLightService(serviceClass, componentManager); - } - else { - Ref ref = new Ref<>(); - //noinspection CodeBlock2Expr - ProgressManager.getInstance().executeNonCancelableSection(() -> { - ref.set(createLightService(serviceClass, componentManager)); - }); - instance = ref.get(); - } - } - - Object prevValue = ourAppServices.put(serviceClass, instance); - LOG.assertTrue(prevValue == null); - return instance; - } - } - - @NotNull - private static T createLightService(@NotNull Class serviceClass, @NotNull ComponentManager componentManager) { - long startTime = StartUpMeasurer.getCurrentTime(); - T instance = ReflectionUtil.newInstance(serviceClass, false); - if (instance instanceof Disposable) { - Disposer.register(componentManager, (Disposable)instance); - } - componentManager.initializeComponent(instance, null); - ParallelActivity.SERVICE.record(startTime, instance.getClass(), StartUpMeasurer.Level.APPLICATION); - return instance; - } } diff --git a/platform/core-api/src/com/intellij/openapi/extensions/CustomLoadingExtensionPointBean.java b/platform/core-api/src/com/intellij/openapi/extensions/CustomLoadingExtensionPointBean.java index 88da67de84f0..82f6255d64b2 100644 --- a/platform/core-api/src/com/intellij/openapi/extensions/CustomLoadingExtensionPointBean.java +++ b/platform/core-api/src/com/intellij/openapi/extensions/CustomLoadingExtensionPointBean.java @@ -1,7 +1,6 @@ // Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.extensions; -import com.intellij.diagnostic.PluginException; import com.intellij.util.ExtensionInstantiator; import com.intellij.util.xmlb.annotations.Attribute; import org.jetbrains.annotations.NotNull; diff --git a/platform/core-api/src/com/intellij/openapi/fileTypes/FileTypeRegistry.java b/platform/core-api/src/com/intellij/openapi/fileTypes/FileTypeRegistry.java index f17d77aa2dff..88b2f453d84d 100644 --- a/platform/core-api/src/com/intellij/openapi/fileTypes/FileTypeRegistry.java +++ b/platform/core-api/src/com/intellij/openapi/fileTypes/FileTypeRegistry.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.fileTypes; import com.intellij.lang.Language; diff --git a/platform/core-api/src/com/intellij/openapi/util/KeyedExtensionCollector.java b/platform/core-api/src/com/intellij/openapi/util/KeyedExtensionCollector.java index a5667a469ea3..9611e1e3a894 100644 --- a/platform/core-api/src/com/intellij/openapi/util/KeyedExtensionCollector.java +++ b/platform/core-api/src/com/intellij/openapi/util/KeyedExtensionCollector.java @@ -14,15 +14,19 @@ import gnu.trove.THashMap; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; import java.util.*; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Predicate; public class KeyedExtensionCollector implements ModificationTracker { private static final Logger LOG = Logger.getInstance(KeyedExtensionCollector.class); protected final String myLock; + @Nullable + private final Disposable myParentDisposable; /** Guarded by {@link #myLock} */ @SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized") @@ -32,32 +36,7 @@ public class KeyedExtensionCollector implements ModificationTracker { private final String myEpName; private final SimpleModificationTracker myTracker = new SimpleModificationTracker(); - private final ExtensionPointAndAreaListener> myListener = new ExtensionPointAndAreaListener>() { - @Override - public void extensionAdded(@NotNull KeyedLazyInstance bean, @NotNull PluginDescriptor pluginDescriptor) { - synchronized (myLock) { - if (bean.getKey() == null) { - throw new PluginException("No key specified for extension of class " + bean.getInstance().getClass(), pluginDescriptor.getPluginId()); - } - myCache.remove(bean.getKey()); - myTracker.incModificationCount(); - } - } - - @Override - public void extensionRemoved(@NotNull KeyedLazyInstance bean, @NotNull PluginDescriptor pluginDescriptor) { - synchronized (myLock) { - myCache.remove(bean.getKey()); - myTracker.incModificationCount(); - } - } - - @Override - public void areaReplaced(@NotNull ExtensionsArea area) { - myCache.clear(); - myTracker.incModificationCount(); - } - }; + protected final AtomicBoolean myEpListenerAdded = new AtomicBoolean(); public KeyedExtensionCollector(@NotNull String epName) { this(epName, null); @@ -66,23 +45,46 @@ public class KeyedExtensionCollector implements ModificationTracker { public KeyedExtensionCollector(@NotNull String epName, @Nullable Disposable parentDisposable) { myEpName = epName; myLock = "lock for KeyedExtensionCollector " + epName; + myParentDisposable = parentDisposable; + } - Extensions.getRootArea().addAvailabilityListener(epName, new ExtensionPointAvailabilityListener() { + @TestOnly + public void clearCache() { + myCache.clear(); + myTracker.incModificationCount(); + } + + private void addExtensionPointListener(@NotNull ExtensionPoint> point) { + if (!myEpListenerAdded.compareAndSet(false, true)) { + return; + } + + point.addExtensionPointListener(new ExtensionPointAndAreaListener>() { @Override - public void extensionPointRegistered(@NotNull ExtensionPoint extensionPoint) { - if (extensionPoint.getName().equals(epName)) { - //noinspection unchecked - extensionPoint.addExtensionPointListener(myListener, false, parentDisposable); - myCache.clear(); + public void extensionAdded(@NotNull KeyedLazyInstance bean, @NotNull PluginDescriptor pluginDescriptor) { + synchronized (myLock) { + if (bean.getKey() == null) { + throw new PluginException("No key specified for extension of class " + bean.getInstance().getClass(), pluginDescriptor.getPluginId()); + } + myCache.remove(bean.getKey()); myTracker.incModificationCount(); } } @Override - public void extensionPointRemoved(@NotNull ExtensionPoint extensionPoint) { - // no need to remove myListener - it should unregister automatically + public void extensionRemoved(@NotNull KeyedLazyInstance bean, @NotNull PluginDescriptor pluginDescriptor) { + synchronized (myLock) { + myCache.remove(bean.getKey()); + myTracker.incModificationCount(); + } } - }, parentDisposable); + + @Override + public void areaReplaced(@NotNull ExtensionsArea area) { + myCache.clear(); + myTracker.incModificationCount(); + } + }, false, myParentDisposable); } public void addExplicitExtension(@NotNull KeyT key, @NotNull T t) { @@ -163,7 +165,13 @@ public class KeyedExtensionCollector implements ModificationTracker { @NotNull protected final List> getExtensions() { ExtensionPoint> point = getPoint(); - return point == null ? Collections.emptyList() : point.getExtensionList(); + if (point == null) { + return Collections.emptyList(); + } + else { + addExtensionPointListener(point); + return point.getExtensionList(); + } } @Nullable diff --git a/platform/core-api/src/com/intellij/psi/FileContextProvider.java b/platform/core-api/src/com/intellij/psi/FileContextProvider.java index 5de787eb246f..799540637ae9 100644 --- a/platform/core-api/src/com/intellij/psi/FileContextProvider.java +++ b/platform/core-api/src/com/intellij/psi/FileContextProvider.java @@ -1,4 +1,4 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.psi; @@ -12,7 +12,6 @@ import java.util.Collection; * @author Dmitry Avdeev */ public abstract class FileContextProvider { - public static final ExtensionPointName EP_NAME = new ExtensionPointName<>("com.intellij.fileContextProvider"); @Nullable diff --git a/platform/core-api/src/com/intellij/psi/LanguageSubstitutors.java b/platform/core-api/src/com/intellij/psi/LanguageSubstitutors.java index b05fb00a9b96..b6d0e6043f4f 100644 --- a/platform/core-api/src/com/intellij/psi/LanguageSubstitutors.java +++ b/platform/core-api/src/com/intellij/psi/LanguageSubstitutors.java @@ -6,6 +6,7 @@ import com.intellij.lang.Language; import com.intellij.lang.LanguageExtension; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.TransactionGuard; +import com.intellij.openapi.components.Service; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; @@ -24,13 +25,24 @@ import java.util.concurrent.atomic.AtomicBoolean; /** * A utility class used to query the language for PSI from {@link LanguageSubstitutor} extensions. */ +@Service public final class LanguageSubstitutors extends LanguageExtension { - public static final LanguageSubstitutors INSTANCE = new LanguageSubstitutors(); + /** + * @deprecated Use {@link #getInstance()} + */ + @Deprecated + public static final LanguageSubstitutors INSTANCE = getInstance(); + private static final Logger LOG = Logger.getInstance(LanguageSubstitutors.class); private static final Key> PROJECT_KEY_FOR_SUBSTITUTED_LANG_KEY = Key.create("PROJECT_KEY_FOR_SUBSTITUTED_LANG_KEY"); private static final AtomicBoolean REQUESTS_DRAIN_NEEDED = new AtomicBoolean(true); private static final ConcurrentMap ourReparsingRequests = ContainerUtil.newConcurrentMap(); + @NotNull + public static LanguageSubstitutors getInstance() { + return ApplicationManager.getApplication().getService(LanguageSubstitutors.class, true); + } + private LanguageSubstitutors() { super("com.intellij.lang.substitutor"); } diff --git a/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java b/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java index 78626ac987d1..2ce9fbc1bbef 100644 --- a/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java +++ b/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java @@ -16,7 +16,6 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.impl.ApplicationInfoImpl; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.command.impl.CoreCommandProcessor; -import com.intellij.openapi.components.ExtensionAreas; import com.intellij.openapi.editor.impl.DocumentImpl; import com.intellij.openapi.extensions.*; import com.intellij.openapi.fileEditor.FileDocumentManager; @@ -27,7 +26,6 @@ import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.impl.CoreProgressManager; import com.intellij.openapi.util.ClassExtension; import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.StaticGetter; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.VirtualFileSystem; import com.intellij.openapi.vfs.encoding.EncodingManager; @@ -86,14 +84,12 @@ public class CoreApplicationEnvironment { myApplication = createApplication(myParentDisposable); ApplicationManager.setApplication(myApplication, - new StaticGetter<>(myFileTypeRegistry), + () -> myFileTypeRegistry, myParentDisposable); myLocalFileSystem = createLocalFileSystem(); myJarFileSystem = createJarFileSystem(); myJrtFileSystem = createJrtFileSystem(); - Extensions.registerAreaClass(ExtensionAreas.IDEA_PROJECT, null); - final MutablePicoContainer appContainer = myApplication.getPicoContainer(); registerComponentInstance(appContainer, FileDocumentManager.class, new MockFileDocumentManagerImpl( charSequence -> new DocumentImpl(charSequence), null)); diff --git a/platform/core-impl/src/com/intellij/core/CoreProjectEnvironment.java b/platform/core-impl/src/com/intellij/core/CoreProjectEnvironment.java index a67eaf46285f..91484c99bbcc 100644 --- a/platform/core-impl/src/com/intellij/core/CoreProjectEnvironment.java +++ b/platform/core-impl/src/com/intellij/core/CoreProjectEnvironment.java @@ -8,7 +8,6 @@ import com.intellij.mock.MockProject; import com.intellij.mock.MockResolveScopeManager; import com.intellij.openapi.Disposable; import com.intellij.openapi.extensions.ExtensionPointName; -import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.roots.FileIndexFacade; import com.intellij.openapi.util.Disposer; @@ -97,7 +96,7 @@ public class CoreProjectEnvironment { public void registerProjectExtensionPoint(@NotNull ExtensionPointName extensionPointName, @NotNull Class aClass) { - CoreApplicationEnvironment.registerExtensionPoint(Extensions.getArea(myProject), extensionPointName, aClass); + CoreApplicationEnvironment.registerExtensionPoint(myProject.getExtensionArea(), extensionPointName, aClass); } public void addProjectExtension(@NotNull ExtensionPointName name, @NotNull final T extension) { diff --git a/platform/core-impl/src/com/intellij/ide/plugins/IdeaPluginDescriptorImpl.java b/platform/core-impl/src/com/intellij/ide/plugins/IdeaPluginDescriptorImpl.java index ba67b8604385..3da5b73a9302 100644 --- a/platform/core-impl/src/com/intellij/ide/plugins/IdeaPluginDescriptorImpl.java +++ b/platform/core-impl/src/com/intellij/ide/plugins/IdeaPluginDescriptorImpl.java @@ -10,8 +10,6 @@ import com.intellij.openapi.components.ComponentConfig; import com.intellij.openapi.components.OldComponentConfig; import com.intellij.openapi.components.ServiceDescriptor; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.extensions.ExtensionPoint; -import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.extensions.ExtensionsArea; import com.intellij.openapi.extensions.PluginId; import com.intellij.openapi.extensions.impl.ExtensionPointImpl; @@ -48,6 +46,10 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; public final class IdeaPluginDescriptorImpl implements IdeaPluginDescriptor { + public enum OS { + mac, linux, windows, unix, freebsd + } + public static final IdeaPluginDescriptorImpl[] EMPTY_ARRAY = new IdeaPluginDescriptorImpl[0]; private static final Logger LOG = Logger.getInstance("#com.intellij.ide.plugins.PluginDescriptor"); @@ -470,16 +472,22 @@ public final class IdeaPluginDescriptorImpl implements IdeaPluginDescriptor { return build; } - public void registerExtensionPoints(@NotNull ExtensionsArea area) { - ContainerDescriptor containerDescriptor = getContainerDescriptorByExtensionArea(area.getAreaClass()); - if (containerDescriptor == null) { - throw new IllegalStateException("Unknown area: " + area); + public void registerExtensionPoints(@NotNull ExtensionsArea area, @NotNull MutablePicoContainer picoContainer) { + ContainerDescriptor containerDescriptor; + if (picoContainer.getParent() == null) { + containerDescriptor = myAppContainerDescriptor; + } + else if (picoContainer.getParent().getParent() == null) { + containerDescriptor = myProjectContainerDescriptor; + } + else { + containerDescriptor = myModuleContainerDescriptor; } List extensionsPoints = containerDescriptor.extensionsPoints; if (extensionsPoints != null) { for (Element element : extensionsPoints) { - area.registerExtensionPoint(this, element); + area.registerExtensionPoint(this, element, picoContainer); } } } @@ -510,14 +518,6 @@ public final class IdeaPluginDescriptorImpl implements IdeaPluginDescriptor { } } - // made public for Upsource - public void registerExtensions(@NotNull ExtensionsArea area, @NotNull ExtensionPoint extensionPoint) { - if (myExtensions == null) { - return; - } - ((ExtensionPointImpl)extensionPoint).createAndRegisterAdapters(myExtensions.get(extensionPoint.getName()), this, area.getPicoContainer()); - } - @Override public String getDescription() { return myDescription.getValue(); @@ -841,19 +841,19 @@ public final class IdeaPluginDescriptorImpl implements IdeaPluginDescriptor { return true; } - if (os.equals(Extensions.OS.mac.name())) { + if (os.equals(OS.mac.name())) { return SystemInfo.isMac; } - else if (os.equals(Extensions.OS.linux.name())) { + else if (os.equals(OS.linux.name())) { return SystemInfo.isLinux; } - else if (os.equals(Extensions.OS.windows.name())) { + else if (os.equals(OS.windows.name())) { return SystemInfo.isWindows; } - else if (os.equals(Extensions.OS.unix.name())) { + else if (os.equals(OS.unix.name())) { return SystemInfo.isUnix; } - else if (os.equals(Extensions.OS.freebsd.name())) { + else if (os.equals(OS.freebsd.name())) { return SystemInfo.isFreeBSD; } else { diff --git a/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java b/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java index 04bd1822facc..9382cada2197 100644 --- a/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java +++ b/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java @@ -13,9 +13,11 @@ import com.intellij.openapi.application.JetBrainsProtocolHandler; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.application.ex.ApplicationInfoEx; import com.intellij.openapi.application.impl.ApplicationInfoImpl; -import com.intellij.openapi.components.ExtensionAreas; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.extensions.*; +import com.intellij.openapi.extensions.ExtensionInstantiationException; +import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.extensions.ExtensionsArea; +import com.intellij.openapi.extensions.PluginId; import com.intellij.openapi.extensions.impl.ExtensionPointImpl; import com.intellij.openapi.extensions.impl.ExtensionsAreaImpl; import com.intellij.openapi.project.Project; @@ -41,6 +43,7 @@ import gnu.trove.THashSet; import gnu.trove.TObjectIntHashMap; import org.jdom.JDOMException; import org.jetbrains.annotations.*; +import org.picocontainer.MutablePicoContainer; import java.io.*; import java.lang.invoke.MethodHandle; @@ -406,7 +409,7 @@ public class PluginManagerCore { @ApiStatus.Internal @NotNull public static PluginException createPluginException(@NotNull String errorMessage, @Nullable Throwable cause, - @NotNull Class pluginClass) { + @NotNull Class pluginClass) { ClassLoader classLoader = pluginClass.getClassLoader(); PluginId pluginId = classLoader instanceof PluginClassLoader ? ((PluginClassLoader)classLoader).getPluginId() : getPluginByClassName(pluginClass.getName()); @@ -532,11 +535,6 @@ public class PluginManagerCore { return loadPlugins == null || Boolean.TRUE.toString().equals(loadPlugins); } - public static void configureExtensions() { - Extensions.registerAreaClass(ExtensionAreas.IDEA_PROJECT, null); - Extensions.registerAreaClass(ExtensionAreas.IDEA_MODULE, ExtensionAreas.IDEA_PROJECT); - } - @Nullable private static ClassLoader createPluginClassLoader(@NotNull File[] classPath, @NotNull ClassLoader[] parentLoaders, @@ -1496,7 +1494,6 @@ public class PluginManagerCore { @NotNull private static IdeaPluginDescriptorImpl[] initializePlugins(@NotNull ClassLoader coreLoader) { Activity loadPluginsActivity = ParallelActivity.PREPARE_APP_INIT.start(ActivitySubNames.INIT_PLUGINS); - configureExtensions(); List errors = new ArrayList<>(); IdeaPluginDescriptorImpl[] pluginDescriptors = loadDescriptors(errors); @@ -1536,16 +1533,6 @@ public class PluginManagerCore { } loadPluginsActivity.end("plugin count: " + pluginDescriptors.length); - Activity registerExtensionsActivity = ParallelActivity.PREPARE_APP_INIT.start(ActivitySubNames.REGISTER_EXTENSIONS); - registerExtensionPointsAndExtensions((ExtensionsAreaImpl)Extensions.getRootArea(), result); - //noinspection deprecation - Extensions.AREA_LISTENER_EXTENSION_POINT.getPoint(null).registerExtension(new AreaListener() { - @Override - public void areaCreated(@NotNull String areaClass, @NotNull AreaInstance areaInstance) { - registerExtensionPointsAndExtensions((ExtensionsAreaImpl)Extensions.getArea(areaInstance), result); - } - }); - registerExtensionsActivity.end(); ourLoadedPlugins = Collections.unmodifiableList(result); ourPlugins.set(pluginDescriptors); @@ -1634,15 +1621,17 @@ public class PluginManagerCore { } } - private static void registerExtensionPointsAndExtensions(@NotNull ExtensionsAreaImpl area, - @NotNull List loadedPlugins) { + @ApiStatus.Internal + public static void registerExtensionPointsAndExtensions(@NotNull ExtensionsAreaImpl area, + @NotNull MutablePicoContainer container, + @NotNull List loadedPlugins) { for (IdeaPluginDescriptorImpl descriptor : loadedPlugins) { - descriptor.registerExtensionPoints(area); + descriptor.registerExtensionPoints(area, container); } - ExtensionPointImpl[] extensionPoints = area.getExtensionPoints(); + ExtensionPointImpl[] extensionPoints = area.getExtensionPoints(); for (IdeaPluginDescriptorImpl descriptor : loadedPlugins) { - descriptor.registerExtensions(extensionPoints, area.getPicoContainer()); + descriptor.registerExtensions(extensionPoints, container); } // to avoid clearing cache for each plugin on registration, cache is cleared only now @@ -1673,7 +1662,8 @@ public class PluginManagerCore { } if (descriptor != null) { - registerExtensionPointsAndExtensions((ExtensionsAreaImpl)area, Collections.singletonList(descriptor)); + registerExtensionPointsAndExtensions((ExtensionsAreaImpl)area, + (MutablePicoContainer)ApplicationManager.getApplication().getPicoContainer(), Collections.singletonList(descriptor)); } else { getLogger().error("Cannot load " + fileName + " from " + pluginRoot); @@ -1683,7 +1673,7 @@ public class PluginManagerCore { @NotNull private static synchronized IdeaPluginDescriptorImpl[] initPlugins(@Nullable ClassLoader coreLoader) { if (coreLoader == null) { - Class callerClass = ReflectionUtil.findCallerClass(1); + Class callerClass = ReflectionUtil.findCallerClass(1); assert callerClass != null; coreLoader = callerClass.getClassLoader(); } diff --git a/platform/core-impl/src/com/intellij/mock/MockApplication.java b/platform/core-impl/src/com/intellij/mock/MockApplication.java index d64603826894..1d2f5130c23f 100644 --- a/platform/core-impl/src/com/intellij/mock/MockApplication.java +++ b/platform/core-impl/src/com/intellij/mock/MockApplication.java @@ -1,32 +1,22 @@ -/* - * Copyright 2000-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.mock; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.*; import com.intellij.openapi.application.impl.AnyModalityState; +import com.intellij.openapi.components.Service; +import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.ThrowableComputable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; import org.jetbrains.ide.PooledThreadExecutor; import java.awt.*; +import java.lang.reflect.Modifier; import java.util.concurrent.Callable; import java.util.concurrent.Future; @@ -35,7 +25,36 @@ public class MockApplication extends MockComponentManager implements Application public MockApplication(@NotNull Disposable parentDisposable) { super(null, parentDisposable); + INSTANCES_CREATED++; + //noinspection TestOnlyProblems + Extensions.setRootArea(getExtensionArea(), parentDisposable); + } + + @NotNull + @TestOnly + public static MockApplication setUp(@NotNull Disposable parentDisposable) { + MockApplication app = new MockApplication(parentDisposable); + ApplicationManager.setApplication(app, parentDisposable); + return app; + } + + @Override + public T getService(@NotNull Class serviceClass, boolean isCreate) { + T service = super.getService(serviceClass, isCreate); + if (service == null && isCreate && Modifier.isFinal(serviceClass.getModifiers()) && serviceClass.isAnnotationPresent(Service.class)) { + //noinspection SynchronizeOnThis,SynchronizationOnLocalVariableOrMethodParameter + synchronized (serviceClass) { + service = super.getService(serviceClass, true); + if (service != null) { + return service; + } + + getPicoContainer().registerComponentImplementation(serviceClass.getName(), serviceClass); + return super.getService(serviceClass, true); + } + } + return service; } @Override diff --git a/platform/core-impl/src/com/intellij/mock/MockApplicationEx.java b/platform/core-impl/src/com/intellij/mock/MockApplicationEx.java index 055c8dbec1d4..79b5a5f2092e 100644 --- a/platform/core-impl/src/com/intellij/mock/MockApplicationEx.java +++ b/platform/core-impl/src/com/intellij/mock/MockApplicationEx.java @@ -3,7 +3,6 @@ package com.intellij.mock; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ex.ApplicationEx; -import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; @@ -14,12 +13,8 @@ import javax.swing.*; public class MockApplicationEx extends MockApplication implements ApplicationEx { public MockApplicationEx(@NotNull Disposable parentDisposable) { super(parentDisposable); - } - @NotNull - @Override - public String getName() { - return "mock"; + Extensions.setRootArea(getExtensionArea()); } @Override @@ -73,12 +68,6 @@ public class MockApplicationEx extends MockApplication implements ApplicationEx return false; } - @NotNull - @Override - public T[] getExtensions(@NotNull final ExtensionPointName extensionPointName) { - return Extensions.getRootArea().getExtensionPoint(extensionPointName).getExtensions(); - } - @Override public void assertIsDispatchThread(@Nullable final JComponent component) { } diff --git a/platform/core-impl/src/com/intellij/mock/MockComponentManager.java b/platform/core-impl/src/com/intellij/mock/MockComponentManager.java index dacbf2e1dc53..bf3f7d7cc87b 100644 --- a/platform/core-impl/src/com/intellij/mock/MockComponentManager.java +++ b/platform/core-impl/src/com/intellij/mock/MockComponentManager.java @@ -4,31 +4,30 @@ package com.intellij.mock; import com.intellij.openapi.Disposable; import com.intellij.openapi.components.BaseComponent; import com.intellij.openapi.components.ComponentManager; -import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.extensions.impl.ExtensionsAreaImpl; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Conditions; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.UserDataHolderBase; -import com.intellij.util.ArrayUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.messages.MessageBus; import com.intellij.util.messages.impl.MessageBusFactoryImpl; import com.intellij.util.pico.DefaultPicoContainer; +import gnu.trove.THashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.picocontainer.MutablePicoContainer; import org.picocontainer.PicoContainer; -import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.Set; public class MockComponentManager extends UserDataHolderBase implements ComponentManager { private final MessageBus myMessageBus = new MessageBusFactoryImpl().createMessageBus(this); - private final MutablePicoContainer myPicoContainer; + private final DefaultPicoContainer myPicoContainer; + private final ExtensionsAreaImpl myExtensionArea; - private final Map, Object> myComponents = new HashMap<>(); + private final Map, Object> myComponents = new THashMap<>(); private final Set myDisposableComponents = ContainerUtil.newConcurrentSet(); private boolean myDisposed; @@ -47,13 +46,19 @@ public class MockComponentManager extends UserDataHolderBase implements Componen }; myPicoContainer.registerComponentInstance(this); + myExtensionArea = new ExtensionsAreaImpl(myPicoContainer); Disposer.register(parentDisposable, this); } + @NotNull + @Override + public ExtensionsAreaImpl getExtensionArea() { + return myExtensionArea; + } + private void registerComponentInDisposer(@Nullable Object o) { - if (o instanceof Disposable && o != this && !(o instanceof MessageBus)) { - if (myDisposableComponents.add(o)) - Disposer.register(this, (Disposable)o); + if (o instanceof Disposable && o != this && !(o instanceof MessageBus) && myDisposableComponents.add(o)) { + Disposer.register(this, (Disposable)o); } } @@ -89,6 +94,13 @@ public class MockComponentManager extends UserDataHolderBase implements Componen return (T)(o != null ? o : myComponents.get(interfaceClass)); } + @Override + public T getService(@NotNull Class serviceClass, boolean isCreate) { + T result = myPicoContainer.getService(serviceClass, isCreate); + registerComponentInDisposer(result); + return result; + } + @Override public T getComponent(@NotNull Class interfaceClass, T defaultImplementation) { return getComponent(interfaceClass); @@ -99,12 +111,10 @@ public class MockComponentManager extends UserDataHolderBase implements Componen return false; } - @SuppressWarnings("unchecked") @Override @NotNull public T[] getComponents(@NotNull Class baseClass) { - final List list = myPicoContainer.getComponentInstancesOfType(baseClass); - return list.toArray(ArrayUtil.newArray(baseClass, 0)); + throw new UnsupportedOperationException(); } @Override @@ -130,12 +140,6 @@ public class MockComponentManager extends UserDataHolderBase implements Componen myDisposed = true; } - @NotNull - @Override - public T[] getExtensions(@NotNull final ExtensionPointName extensionPointName) { - throw new UnsupportedOperationException("getExtensions()"); - } - @NotNull @Override public Condition getDisposed() { diff --git a/platform/core-impl/src/com/intellij/mock/MockProject.java b/platform/core-impl/src/com/intellij/mock/MockProject.java index daa70fb4c102..958e3ef61382 100644 --- a/platform/core-impl/src/com/intellij/mock/MockProject.java +++ b/platform/core-impl/src/com/intellij/mock/MockProject.java @@ -1,29 +1,11 @@ -/* - * Copyright 2000-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.mock; import com.intellij.openapi.Disposable; -import com.intellij.openapi.components.ExtensionAreas; import com.intellij.openapi.components.ProjectComponent; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.extensions.ExtensionPointName; -import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; -import com.intellij.openapi.util.Disposer; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -40,13 +22,6 @@ public class MockProject extends MockComponentManager implements Project { public MockProject(PicoContainer parent, @NotNull Disposable parentDisposable) { super(parent, parentDisposable); - Extensions.instantiateArea(ExtensionAreas.IDEA_PROJECT, this, null); - Disposer.register(parentDisposable, new Disposable() { - @Override - public void dispose() { - Extensions.disposeArea(MockProject.this); - } - }); } @Override @@ -57,7 +32,7 @@ public class MockProject extends MockComponentManager implements Project { @NotNull @Override public Condition getDisposed() { - return (Condition)o -> isDisposed(); + return o -> isDisposed(); } @Override @@ -121,12 +96,6 @@ public class MockProject extends MockComponentManager implements Project { public void save() { } - @NotNull - @Override - public T[] getExtensions(@NotNull final ExtensionPointName extensionPointName) { - return Extensions.getArea(this).getExtensionPoint(extensionPointName).getExtensions(); - } - public void projectOpened() { final ProjectComponent[] components = getComponents(ProjectComponent.class); for (ProjectComponent component : components) { diff --git a/platform/core-impl/src/com/intellij/openapi/application/ex/ApplicationEx.java b/platform/core-impl/src/com/intellij/openapi/application/ex/ApplicationEx.java index f19e973ede96..b3c27edc81a3 100644 --- a/platform/core-impl/src/com/intellij/openapi/application/ex/ApplicationEx.java +++ b/platform/core-impl/src/com/intellij/openapi/application/ex/ApplicationEx.java @@ -38,9 +38,6 @@ public interface ApplicationEx extends Application { return LoadingPhase.COMPONENT_LOADED.isComplete(); } - @NotNull - String getName(); - /** * @return true if this thread is inside read action. * @see #runReadAction(Runnable) diff --git a/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java b/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java index 40baba5eac01..bbdc7e0ce2f4 100644 --- a/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java @@ -13,8 +13,11 @@ import com.intellij.openapi.components.ComponentConfig; import com.intellij.openapi.components.ComponentManager; import com.intellij.openapi.components.NamedComponent; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.extensions.ExtensionsArea; import com.intellij.openapi.extensions.PluginDescriptor; import com.intellij.openapi.extensions.PluginId; +import com.intellij.openapi.extensions.impl.ExtensionsAreaImpl; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; @@ -50,7 +53,9 @@ import java.util.Map; public abstract class ComponentManagerImpl extends UserDataHolderBase implements ComponentManager, Disposable { private static final Logger LOG = Logger.getInstance("#com.intellij.components.ComponentManager"); - private final MutablePicoContainer myPicoContainer; + private final DefaultPicoContainer myPicoContainer; + private final ExtensionsAreaImpl myExtensionArea; + private volatile boolean myDisposed; private volatile boolean myDisposeCompleted; @@ -66,16 +71,19 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements private final List myBaseComponents = new SmartList<>(); - private final ComponentManager myParentComponentManager; + private final ComponentManager myParent; - protected ComponentManagerImpl(@Nullable ComponentManager parentComponentManager) { - myParentComponentManager = parentComponentManager; - myPicoContainer = bootstrapPicoContainer(toString()); + protected ComponentManagerImpl(@Nullable ComponentManager parent) { + this(parent, new DefaultPicoContainer(parent == null ? null : parent.getPicoContainer())); } - protected ComponentManagerImpl(@Nullable ComponentManager parentComponentManager, @NotNull String name) { - myParentComponentManager = parentComponentManager; - myPicoContainer = bootstrapPicoContainer(name); + protected ComponentManagerImpl(@Nullable ComponentManager parent, @NotNull DefaultPicoContainer picoContainer) { + myParent = parent; + myPicoContainer = picoContainer; + myExtensionArea = new ExtensionsAreaImpl(myPicoContainer); + if (parent == null) { + Extensions.setRootArea(myExtensionArea); + } } @Nullable @@ -93,7 +101,7 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements String activityNamePrefix = activityNamePrefix(); Activity activity = activityNamePrefix == null ? null : StartUpMeasurer.start(activityNamePrefix + Phases.CREATE_COMPONENTS_SUFFIX); - DefaultPicoContainer picoContainer = (DefaultPicoContainer)getPicoContainer(); + DefaultPicoContainer picoContainer = getPicoContainer(); for (ComponentAdapter componentAdapter : picoContainer.getComponentAdapters()) { if (componentAdapter instanceof ComponentConfigComponentAdapter) { ((ComponentConfigComponentAdapter)componentAdapter).getComponentInstance(picoContainer, indicator); @@ -167,6 +175,7 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements } myBaseComponents.clear(); + //noinspection NonPrivateFieldAccessedInSynchronizedContext myComponentConfigCount = -1; } @@ -226,7 +235,7 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements } @Override - public boolean hasComponent(@NotNull Class interfaceClass) { + public boolean hasComponent(@NotNull Class interfaceClass) { return getPicoContainer().getComponentAdapter(interfaceClass) != null; } @@ -245,7 +254,7 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements public final List getComponentInstancesOfType(@NotNull Class baseClass, boolean createIfNotYet) { List result = null; // we must use instances only from our adapter (could be service or extension point or something else) - for (ComponentAdapter componentAdapter : ((DefaultPicoContainer)getPicoContainer()).getComponentAdapters()) { + for (ComponentAdapter componentAdapter : getPicoContainer().getComponentAdapters()) { if (componentAdapter instanceof ComponentConfigComponentAdapter && ReflectionUtil.isAssignable(baseClass, componentAdapter.getComponentImplementation())) { ComponentConfigComponentAdapter adapter = (ComponentConfigComponentAdapter)componentAdapter; @@ -264,14 +273,20 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements @Override @NotNull - public MutablePicoContainer getPicoContainer() { - MutablePicoContainer container = myPicoContainer; + public DefaultPicoContainer getPicoContainer() { + DefaultPicoContainer container = myPicoContainer; if (container == null || myDisposeCompleted) { throwAlreadyDisposed(); } return container; } + @NotNull + @Override + public ExtensionsArea getExtensionArea() { + return myExtensionArea; + } + @Contract("->fail") private void throwAlreadyDisposed() { ReadAction.run(() -> { @@ -280,11 +295,6 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements }); } - @NotNull - protected MutablePicoContainer createPicoContainer() { - return myParentComponentManager == null ? new DefaultPicoContainer() : new DefaultPicoContainer(myParentComponentManager.getPicoContainer()); - } - protected boolean isComponentSuitable(@NotNull ComponentConfig componentConfig) { Map options = componentConfig.options; return options == null || !Boolean.parseBoolean(options.get("internal")) || ApplicationManager.getApplication().isInternal(); @@ -311,10 +321,6 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements return myDisposed; } - protected MutablePicoContainer bootstrapPicoContainer(@NotNull String name) { - return createPicoContainer(); - } - protected void logMessageBusDelivery(Topic topic, String messageName, Object handler, long durationNanos) { if (!StartUpMeasurer.isMeasuringPluginStartupCosts()) { ((MessageBusImpl) myMessageBus).setMessageDeliveryListener(null); @@ -327,7 +333,7 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements } protected final ComponentManager getParentComponentManager() { - return myParentComponentManager; + return myParent; } @Nullable @@ -342,7 +348,7 @@ public abstract class ComponentManagerImpl extends UserDataHolderBase implements @Nullable private ComponentConfigComponentAdapter getComponentAdapter(@NotNull Class componentImplementation) { - for (ComponentAdapter componentAdapter : ((DefaultPicoContainer)getPicoContainer()).getComponentAdapters()) { + for (ComponentAdapter componentAdapter : getPicoContainer().getComponentAdapters()) { if (componentAdapter instanceof ComponentConfigComponentAdapter && componentAdapter.getComponentImplementation() == componentImplementation) { return (ComponentConfigComponentAdapter)componentAdapter; } diff --git a/platform/core-impl/src/com/intellij/psi/impl/PsiFileFactoryImpl.java b/platform/core-impl/src/com/intellij/psi/impl/PsiFileFactoryImpl.java index 6e16992b7540..275b89969298 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/PsiFileFactoryImpl.java +++ b/platform/core-impl/src/com/intellij/psi/impl/PsiFileFactoryImpl.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. /* * @author max @@ -99,7 +85,7 @@ public class PsiFileFactoryImpl extends PsiFileFactory { final LightVirtualFile virtualFile = new LightVirtualFile(name, fileType, text, modificationStamp); if(fileType instanceof LanguageFileType){ final Language language = - LanguageSubstitutors.INSTANCE.substituteLanguage(((LanguageFileType)fileType).getLanguage(), virtualFile, myManager.getProject()); + LanguageSubstitutors.getInstance().substituteLanguage(((LanguageFileType)fileType).getLanguage(), virtualFile, myManager.getProject()); final PsiFile file = trySetupPsiForFile(virtualFile, language, eventSystemEnabled, markAsCopy); if (file != null) return file; } diff --git a/platform/core-impl/src/com/intellij/util/indexing/FileContentImpl.java b/platform/core-impl/src/com/intellij/util/indexing/FileContentImpl.java index 906a5926416f..b536376a720c 100644 --- a/platform/core-impl/src/com/intellij/util/indexing/FileContentImpl.java +++ b/platform/core-impl/src/com/intellij/util/indexing/FileContentImpl.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2014 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.util.indexing; import com.intellij.lang.FileASTNode; @@ -30,7 +16,10 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.UserDataHolderBase; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.*; +import com.intellij.psi.LanguageSubstitutors; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiFileFactory; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; @@ -143,7 +132,7 @@ public class FileContentImpl extends UserDataHolderBase implements PsiDependentF public static PsiFile createFileFromText(@NotNull Project project, @NotNull CharSequence text, @NotNull LanguageFileType fileType, @NotNull VirtualFile file, @NotNull String fileName) { final Language language = fileType.getLanguage(); - final Language substitutedLanguage = LanguageSubstitutors.INSTANCE.substituteLanguage(language, file, project); + final Language substitutedLanguage = LanguageSubstitutors.getInstance().substituteLanguage(language, file, project); PsiFile psiFile = PsiFileFactory.getInstance(project).createFileFromText(fileName, substitutedLanguage, text, false, false, false, file); if (psiFile == null) { throw new IllegalStateException("psiFile is null. language = " + language.getID() + diff --git a/platform/core-impl/src/com/intellij/util/indexing/SubstitutedFileType.java b/platform/core-impl/src/com/intellij/util/indexing/SubstitutedFileType.java index 171ec0fb7d98..42bf69e724f3 100644 --- a/platform/core-impl/src/com/intellij/util/indexing/SubstitutedFileType.java +++ b/platform/core-impl/src/com/intellij/util/indexing/SubstitutedFileType.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2014 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.util.indexing; import com.intellij.lang.Language; @@ -48,7 +34,7 @@ public class SubstitutedFileType extends LanguageFileType{ } if (fileType instanceof LanguageFileType) { final Language language = ((LanguageFileType)fileType).getLanguage(); - final Language substitutedLanguage = LanguageSubstitutors.INSTANCE.substituteLanguage(language, file, project); + final Language substitutedLanguage = LanguageSubstitutors.getInstance().substituteLanguage(language, file, project); LanguageFileType substFileType; if (!substitutedLanguage.equals(language) && (substFileType = substitutedLanguage.getAssociatedFileType()) != null) { return new SubstitutedFileType(fileType, substFileType, substitutedLanguage); diff --git a/platform/diff-impl/src/com/intellij/diff/applications/DiffApplication.java b/platform/diff-impl/src/com/intellij/diff/applications/DiffApplication.java index 2ef894f9a78e..d3f67ad6fada 100644 --- a/platform/diff-impl/src/com/intellij/diff/applications/DiffApplication.java +++ b/platform/diff-impl/src/com/intellij/diff/applications/DiffApplication.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.diff.applications; import com.intellij.diff.DiffDialogHints; @@ -32,13 +18,12 @@ import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Arrays; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Future; -public class DiffApplication extends DiffApplicationBase { - public DiffApplication() { +final class DiffApplication extends DiffApplicationBase { + DiffApplication() { super("diff", 2, 3); } @@ -51,8 +36,8 @@ public class DiffApplication extends DiffApplicationBase { @NotNull @Override - public Future processCommand(@NotNull String[] args, @Nullable String currentDirectory) throws Exception { - List filePaths = Arrays.asList(args).subList(1, args.length); + public Future processCommand(@NotNull List args, @Nullable String currentDirectory) throws Exception { + List filePaths = args.subList(1, args.size()); List files = findFiles(filePaths, currentDirectory); Project project = guessProject(files); diff --git a/platform/diff-impl/src/com/intellij/diff/applications/MergeApplication.java b/platform/diff-impl/src/com/intellij/diff/applications/MergeApplication.java index a77cbc75c9a7..b82050354faf 100644 --- a/platform/diff-impl/src/com/intellij/diff/applications/MergeApplication.java +++ b/platform/diff-impl/src/com/intellij/diff/applications/MergeApplication.java @@ -22,8 +22,8 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicReference; -public class MergeApplication extends DiffApplicationBase { - public MergeApplication() { +class MergeApplication extends DiffApplicationBase { + MergeApplication() { super("merge", 3, 4); } @@ -36,8 +36,8 @@ public class MergeApplication extends DiffApplicationBase { @NotNull @Override - public Future processCommand(@NotNull String[] args, @Nullable String currentDirectory) throws Exception { - List filePaths = Arrays.asList(args).subList(1, args.length); + public Future processCommand(@NotNull List args, @Nullable String currentDirectory) throws Exception { + List filePaths = args.subList(1, args.size()); List files = findFiles(filePaths, currentDirectory); Project project = guessProject(files); diff --git a/platform/diff-impl/src/com/intellij/diff/lang/LangDiffIgnoredRangeProvider.java b/platform/diff-impl/src/com/intellij/diff/lang/LangDiffIgnoredRangeProvider.java index 02aa1342e075..cb5d6181c2b2 100644 --- a/platform/diff-impl/src/com/intellij/diff/lang/LangDiffIgnoredRangeProvider.java +++ b/platform/diff-impl/src/com/intellij/diff/lang/LangDiffIgnoredRangeProvider.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.diff.lang; import com.intellij.diff.contents.DiffContent; @@ -64,7 +50,7 @@ public abstract class LangDiffIgnoredRangeProvider implements DiffIgnoredRangePr if (language != null && content instanceof DocumentContent) { VirtualFile highlightFile = ((DocumentContent)content).getHighlightFile(); - if (highlightFile != null) language = LanguageSubstitutors.INSTANCE.substituteLanguage(language, highlightFile, project); + if (highlightFile != null) language = LanguageSubstitutors.getInstance().substituteLanguage(language, highlightFile, project); } return language; diff --git a/platform/dvcs-impl/testSrc/com.intellij.dvcs/VcsRepositoryManagerTest.java b/platform/dvcs-impl/testSrc/com.intellij.dvcs/VcsRepositoryManagerTest.java index 7d06d37c290e..53d0fd3a97ab 100644 --- a/platform/dvcs-impl/testSrc/com.intellij.dvcs/VcsRepositoryManagerTest.java +++ b/platform/dvcs-impl/testSrc/com.intellij.dvcs/VcsRepositoryManagerTest.java @@ -6,7 +6,6 @@ import com.intellij.dvcs.repo.VcsRepositoryCreator; import com.intellij.dvcs.repo.VcsRepositoryManager; import com.intellij.openapi.Disposable; import com.intellij.openapi.extensions.ExtensionPoint; -import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.vcs.ProjectLevelVcsManager; import com.intellij.openapi.vcs.VcsKey; @@ -55,7 +54,7 @@ public class VcsRepositoryManagerTest extends VcsPlatformTest { @NotNull private ExtensionPoint getExtensionPoint() { - return Extensions.getArea(myProject).getExtensionPoint(VcsRepositoryCreator.EXTENSION_POINT_NAME); + return VcsRepositoryCreator.EXTENSION_POINT_NAME.getPoint(myProject); } @Override diff --git a/platform/editor-ui-api/src/com/intellij/openapi/fileTypes/SyntaxHighlighterFactoryEP.java b/platform/editor-ui-api/src/com/intellij/openapi/fileTypes/SyntaxHighlighterFactoryEP.java index b7dce375ac29..9dbe5fe79de7 100644 --- a/platform/editor-ui-api/src/com/intellij/openapi/fileTypes/SyntaxHighlighterFactoryEP.java +++ b/platform/editor-ui-api/src/com/intellij/openapi/fileTypes/SyntaxHighlighterFactoryEP.java @@ -1,26 +1,10 @@ -/* - * Copyright 2000-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.fileTypes; import com.intellij.lang.LanguageExtensionPoint; import com.intellij.util.xmlb.annotations.Attribute; -public class SyntaxHighlighterFactoryEP extends LanguageExtensionPoint { - // For backward compatibility - +final class SyntaxHighlighterFactoryEP extends LanguageExtensionPoint { /** * @deprecated use "language" attribute instead */ @@ -30,12 +14,7 @@ public class SyntaxHighlighterFactoryEP extends LanguageExtensionPoint T findExtension(@NotNull BaseExtensionPointName pointName, @NotNull Class instanceOf, @Nullable AreaInstance areaInstance, boolean isRequired) { - ExtensionPointImpl point = ((ExtensionsAreaImpl)Extensions.getArea(areaInstance)).getExtensionPoint(pointName.getName()); + ExtensionPointImpl point = ((ExtensionsAreaImpl)(areaInstance == null ? Extensions.getRootArea() : areaInstance.getExtensionArea())).getExtensionPoint(pointName.getName()); return point.findExtension(instanceOf, isRequired); } } diff --git a/platform/extensions/src/com/intellij/openapi/extensions/EPAvailabilityListenerExtension.java b/platform/extensions/src/com/intellij/openapi/extensions/EPAvailabilityListenerExtension.java deleted file mode 100644 index a02367236b2c..000000000000 --- a/platform/extensions/src/com/intellij/openapi/extensions/EPAvailabilityListenerExtension.java +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -package com.intellij.openapi.extensions; - -import org.jetbrains.annotations.NotNull; - -/** - * @author AKireyev - */ -public class EPAvailabilityListenerExtension implements PluginAware { - public static final String EXTENSION_POINT_NAME = "com.intellij.openapi.extensions.epAvailabilityListener"; - - private String myExtensionPointName; - private String myListenerClass; - private PluginDescriptor myPluginDescriptor; - - public EPAvailabilityListenerExtension(@NotNull String extensionPointName, @NotNull String listenerClass) { - myExtensionPointName = extensionPointName; - myListenerClass = listenerClass; - } - - @NotNull - public String getExtensionPointName() { - return myExtensionPointName; - } - - public void setExtensionPointName(@NotNull String extensionPointName) { - myExtensionPointName = extensionPointName; - } - - @NotNull - public String getListenerClass() { - return myListenerClass; - } - - public void setListenerClass(@NotNull String listenerClass) { - myListenerClass = listenerClass; - } - - @Override - public void setPluginDescriptor(@NotNull PluginDescriptor pluginDescriptor) { - myPluginDescriptor = pluginDescriptor; - } - - public PluginDescriptor getPluginDescriptor() { - return myPluginDescriptor; - } - - @NotNull - public Class loadListenerClass() throws ClassNotFoundException { - if (myPluginDescriptor != null && myPluginDescriptor.getPluginClassLoader() != null) { - return Class.forName(getListenerClass(), true, myPluginDescriptor.getPluginClassLoader()); - } - return Class.forName(getListenerClass()); - } -} diff --git a/platform/extensions/src/com/intellij/openapi/extensions/ExtensionPointName.java b/platform/extensions/src/com/intellij/openapi/extensions/ExtensionPointName.java index 28fd04848dab..1509d6071040 100644 --- a/platform/extensions/src/com/intellij/openapi/extensions/ExtensionPointName.java +++ b/platform/extensions/src/com/intellij/openapi/extensions/ExtensionPointName.java @@ -50,7 +50,7 @@ public final class ExtensionPointName extends BaseExtensionPointName { @NotNull public List getExtensionsIfPointIsRegistered(@Nullable AreaInstance areaInstance) { - ExtensionPoint point = Extensions.getArea(areaInstance).getExtensionPointIfRegistered(getName()); + ExtensionPoint point = (areaInstance == null ? Extensions.getRootArea() : areaInstance.getExtensionArea()).getExtensionPointIfRegistered(getName()); return point == null ? Collections.emptyList() : point.getExtensionList(); } @@ -89,7 +89,8 @@ public final class ExtensionPointName extends BaseExtensionPointName { @NotNull public ExtensionPoint getPoint(@Nullable AreaInstance areaInstance) { - return Extensions.getArea(areaInstance).getExtensionPoint(getName()); + ExtensionsArea area = areaInstance == null ? Extensions.getRootArea() : areaInstance.getExtensionArea(); + return area.getExtensionPoint(getName()); } @Nullable diff --git a/platform/extensions/src/com/intellij/openapi/extensions/Extensions.java b/platform/extensions/src/com/intellij/openapi/extensions/Extensions.java index b7d29ea6c333..c31f1cec1149 100644 --- a/platform/extensions/src/com/intellij/openapi/extensions/Extensions.java +++ b/platform/extensions/src/com/intellij/openapi/extensions/Extensions.java @@ -3,67 +3,74 @@ package com.intellij.openapi.extensions; import com.intellij.openapi.Disposable; import com.intellij.openapi.extensions.impl.ExtensionsAreaImpl; -import com.intellij.openapi.extensions.impl.InterfaceExtensionPoint; import com.intellij.openapi.util.Disposer; -import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.pico.DefaultPicoContainer; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; -import java.util.List; -import java.util.Map; -import java.util.Objects; - public final class Extensions { - public static final ExtensionPointName AREA_LISTENER_EXTENSION_POINT = new ExtensionPointName<>("com.intellij.arealistener"); - private static final Map ourAreaInstance2area = ContainerUtil.newConcurrentMap(); - private static final Map ourAreaClass2Configuration = ContainerUtil.newConcurrentMap(); - - @NotNull - private static ExtensionsAreaImpl ourRootArea = createRootArea(); + private static ExtensionsAreaImpl ourRootArea; private Extensions() { } - @NotNull - private static ExtensionsAreaImpl createRootArea() { - ExtensionsAreaImpl rootArea = new ExtensionsAreaImpl(null, null, null); - rootArea.registerExtensionPoint(new InterfaceExtensionPoint<>(AREA_LISTENER_EXTENSION_POINT.getName(), AreaListener.class, rootArea.getPicoContainer())); - return rootArea; + public static void setRootArea(@NotNull ExtensionsAreaImpl area) { + ourRootArea = area; + } + + @TestOnly + public static void setRootArea(@NotNull ExtensionsAreaImpl area, @NotNull Disposable parentDisposable) { + ExtensionsAreaImpl oldRootArea = ourRootArea; + ourRootArea = area; + Disposer.register(parentDisposable, () -> { + ourRootArea.notifyAreaReplaced(oldRootArea); + ourRootArea = oldRootArea; + }); } /** * @return instance containing application-level extensions */ - @NotNull public static ExtensionsArea getRootArea() { return ourRootArea; } /** - * If {@code areaInstance} is a project returns instance containing project-level extensions for that project - * if {@code areaInstance} is a module returns instance containing module-level extensions for that module, - * if {@code areaInstance} is {@code null} returns instance containing application-level extensions. + * @deprecated Use {@link AreaInstance#getExtensionArea()} */ @NotNull + @Deprecated public static ExtensionsArea getArea(@Nullable("null means root") AreaInstance areaInstance) { - if (areaInstance == null) { - return ourRootArea; - } - ExtensionsAreaImpl area = ourAreaInstance2area.get(areaInstance); - if (area == null) { - throw new IllegalArgumentException("No area instantiated for: " + areaInstance); - } - return area; + return areaInstance == null ? ourRootArea : areaInstance.getExtensionArea(); } @TestOnly + private static final class TestAreaInstance implements AreaInstance { + private final DefaultPicoContainer container = new DefaultPicoContainer(); + private final ExtensionsAreaImpl extensionArea = new ExtensionsAreaImpl(container); + + @NotNull + @Override + public ExtensionsArea getExtensionArea() { + return extensionArea; + } + } + + /** + * @deprecated Extension area is a part of component manager, no need to clean extension area - dispose component manager instead. + */ + @TestOnly + @Deprecated public static void cleanRootArea(@NotNull Disposable parentDisposable) { - final ExtensionsAreaImpl oldRootArea = (ExtensionsAreaImpl)getRootArea(); - final ExtensionsAreaImpl newArea = createRootArea(); + ExtensionsAreaImpl oldRootArea = ourRootArea; + TestAreaInstance areaInstance = new TestAreaInstance(); + final ExtensionsAreaImpl newArea = new ExtensionsAreaImpl(areaInstance.container); ourRootArea = newArea; - oldRootArea.notifyAreaReplaced(newArea); + if (oldRootArea != null) { + oldRootArea.notifyAreaReplaced(newArea); + } Disposer.register(parentDisposable, () -> { ourRootArea = oldRootArea; newArea.notifyAreaReplaced(oldRootArea); @@ -116,94 +123,10 @@ public final class Extensions { } /** - * @deprecated Use {@link ExtensionPointName#findExtensionOrFail(Class)} + * @deprecated Not needed. */ + @SuppressWarnings("unused") @Deprecated - @NotNull - public static U findExtension(@NotNull ExtensionPointName extensionPointName, AreaInstance areaInstance, @NotNull Class extClass) { - return extensionPointName.findExtensionOrFail(extClass, areaInstance); - } - - public static void instantiateArea(@NonNls @NotNull String areaClass, @NotNull AreaInstance areaInstance, @Nullable("null means root") AreaInstance parentAreaInstance) { - AreaClassConfiguration configuration = ourAreaClass2Configuration.get(areaClass); - if (configuration == null) { - throw new IllegalArgumentException("Area class is not registered: " + areaClass); - } - ExtensionsArea parentArea = getArea(parentAreaInstance); - if (!Objects.equals(parentArea.getAreaClass(), configuration.getParentClassName())) { - throw new IllegalArgumentException("Wrong parent area. Expected class: " + configuration.getParentClassName() + " actual class: " + parentArea.getAreaClass()); - } - ExtensionsAreaImpl area = new ExtensionsAreaImpl(areaClass, areaInstance, parentArea.getPicoContainer()); - if (ourAreaInstance2area.put(areaInstance, area) != null) { - throw new IllegalArgumentException("Area already instantiated for: " + areaInstance); - } - for (AreaListener listener : getAreaListeners()) { - listener.areaCreated(areaClass, areaInstance); - } - } - - @NotNull - private static List getAreaListeners() { - return getRootArea().getExtensionPoint(AREA_LISTENER_EXTENSION_POINT).getExtensionList(); - } - public static void registerAreaClass(@NonNls @NotNull String areaClass, @Nullable @NonNls String parentAreaClass) { - if (ourAreaClass2Configuration.containsKey(areaClass)) { - // allow duplicate area class registrations if they are the same - fixing duplicate registration in tests is much more trouble - AreaClassConfiguration configuration = ourAreaClass2Configuration.get(areaClass); - if (!Objects.equals(configuration.getParentClassName(), parentAreaClass)) { - throw new RuntimeException("Area class already registered: " + areaClass + ", "+ configuration); - } - else { - return; - } - } - AreaClassConfiguration configuration = new AreaClassConfiguration(areaClass, parentAreaClass); - ourAreaClass2Configuration.put(areaClass, configuration); - } - - public static void disposeArea(@NotNull AreaInstance areaInstance) { - assert ourAreaInstance2area.containsKey(areaInstance); - - String areaClass = ourAreaInstance2area.get(areaInstance).getAreaClass(); - if (areaClass == null) { - throw new IllegalArgumentException("Area class is null (area never instantiated?). Instance: " + areaInstance); - } - try { - for (AreaListener listener : getAreaListeners()) { - listener.areaDisposing(areaClass, areaInstance); - } - } - finally { - ourAreaInstance2area.remove(areaInstance); - } - } - - private static class AreaClassConfiguration { - private final String myClassName; - private final String myParentClassName; - - private AreaClassConfiguration(@NotNull String className, String parentClassName) { - myClassName = className; - myParentClassName = parentClassName; - } - - @NotNull - public String getClassName() { - return myClassName; - } - - public String getParentClassName() { - return myParentClassName; - } - - @Override - public String toString() { - return "AreaClassConfiguration{myClassName='" + myClassName + '\'' + ", myParentClassName='" + myParentClassName + "'}"; - } - } - - public enum OS { - mac, linux, windows, unix, freebsd } } diff --git a/platform/extensions/src/com/intellij/openapi/extensions/ExtensionsArea.java b/platform/extensions/src/com/intellij/openapi/extensions/ExtensionsArea.java index 7b17ef4bdee1..e62a1a85f4aa 100644 --- a/platform/extensions/src/com/intellij/openapi/extensions/ExtensionsArea.java +++ b/platform/extensions/src/com/intellij/openapi/extensions/ExtensionsArea.java @@ -10,16 +10,9 @@ import org.jetbrains.annotations.TestOnly; import org.picocontainer.MutablePicoContainer; /** - * @see Extensions#getArea(AreaInstance) * @see Extensions#getRootArea() */ public interface ExtensionsArea { - @TestOnly - void registerExtensionPoint(@NotNull BaseExtensionPointName extensionPoint, - @NotNull String extensionPointBeanClass, - @NotNull ExtensionPoint.Kind kind, - @NotNull Disposable parentDisposable); - /** * @deprecated use {@link ExtensionsArea#registerExtensionPoint(BaseExtensionPointName, String, ExtensionPoint.Kind, Disposable)} */ @@ -48,28 +41,11 @@ public interface ExtensionsArea { ExtensionPoint getExtensionPoint(@NotNull ExtensionPointName extensionPointName); @NotNull - ExtensionPoint[] getExtensionPoints(); + ExtensionPoint[] getExtensionPoints(); - void addAvailabilityListener(@NotNull String extensionPointName, @NotNull ExtensionPointAvailabilityListener listener, @Nullable Disposable parentDisposable); - - /** - * @deprecated use {@link #addAvailabilityListener(String, ExtensionPointAvailabilityListener, Disposable)} - */ - @Deprecated - default void addAvailabilityListener(@NotNull String extensionPointName, @NotNull ExtensionPointAvailabilityListener listener) { - addAvailabilityListener(extensionPointName, listener, null); - } - - /** - * @deprecated use {@link #addAvailabilityListener(String, ExtensionPointAvailabilityListener, Disposable)} - */ - @Deprecated - void removeAvailabilityListener(@NotNull String extensionPointName, @NotNull ExtensionPointAvailabilityListener listener); - - @NotNull - MutablePicoContainer getPicoContainer(); - - void registerExtensionPoint(@NotNull PluginDescriptor pluginDescriptor, @NotNull Element extensionPointElement); + void registerExtensionPoint(@NotNull PluginDescriptor pluginDescriptor, + @NotNull Element extensionPointElement, + @NotNull MutablePicoContainer picoContainer); /** * Registers a new extension. @@ -80,7 +56,5 @@ public interface ExtensionsArea { @TestOnly void registerExtension(@NotNull PluginDescriptor pluginDescriptor, @NotNull Element extensionElement, @Nullable String extensionNs); - void registerExtension(@NotNull final ExtensionPoint extensionPoint, @NotNull final PluginDescriptor pluginDescriptor, @NotNull final Element extensionElement); - - String getAreaClass(); + void registerExtension(@NotNull ExtensionPoint extensionPoint, @NotNull PluginDescriptor pluginDescriptor, @NotNull Element extensionElement); } diff --git a/platform/extensions/src/com/intellij/openapi/extensions/ProjectExtensionPointName.java b/platform/extensions/src/com/intellij/openapi/extensions/ProjectExtensionPointName.java index 3eaf5b88c1d2..2c86a4735d0d 100644 --- a/platform/extensions/src/com/intellij/openapi/extensions/ProjectExtensionPointName.java +++ b/platform/extensions/src/com/intellij/openapi/extensions/ProjectExtensionPointName.java @@ -14,7 +14,7 @@ public final class ProjectExtensionPointName extends BaseExtensionPointName { @NotNull public ExtensionPoint getPoint(@NotNull AreaInstance areaInstance) { - return Extensions.getArea(areaInstance).getExtensionPoint(getName()); + return areaInstance.getExtensionArea().getExtensionPoint(getName()); } @NotNull 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 199a2c595102..a221e7ac3e44 100644 --- a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionPointImpl.java +++ b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionPointImpl.java @@ -38,6 +38,8 @@ public abstract class ExtensionPointImpl implements ExtensionPoint, Iterab // test-only private static Set> POINTS_IN_READONLY_MODE; + private static volatile Predicate> TYPE_CHECKER; + private final String myName; private final String myClassName; @@ -75,6 +77,20 @@ public abstract class ExtensionPointImpl implements ExtensionPoint, Iterab myDescriptor = pluginDescriptor; } + @TestOnly + public static boolean setTestTypeChecker(@NotNull Predicate> typeChecker, @NotNull Disposable parentDisposable) { + if (TYPE_CHECKER != null) { + return false; + } + + TYPE_CHECKER = typeChecker; + Disposer.register(parentDisposable, () -> { + TYPE_CHECKER = null; + }); + + return true; + } + @NotNull @Override public String getName() { @@ -194,6 +210,11 @@ public abstract class ExtensionPointImpl implements ExtensionPoint, Iterab private synchronized void checkExtensionType(@NotNull T extension, @NotNull Class extensionClass, @Nullable ExtensionComponentAdapter adapter) { if (!extensionClass.isInstance(extension)) { + Predicate> checker = TYPE_CHECKER; + if (checker != null && checker.test(extensionClass)) { + return; + } + String message = "Extension " + extension.getClass() + " does not implement " + extensionClass; if (adapter != null) { message += ". It came from " + adapter; @@ -686,7 +707,7 @@ public abstract class ExtensionPointImpl implements ExtensionPoint, Iterab } } - private static final ArrayFactory LISTENER_ARRAY_FACTORY = + private static final ArrayFactory> LISTENER_ARRAY_FACTORY = n -> n == 0 ? ExtensionPointListener.EMPTY_ARRAY : new ExtensionPointListener[n]; private static ArrayFactory> listenerArrayFactory() { //noinspection unchecked @@ -883,7 +904,7 @@ public abstract class ExtensionPointImpl implements ExtensionPoint, Iterab final synchronized void notifyAreaReplaced(@NotNull ExtensionsArea oldArea) { for (final ExtensionPointListener listener : myListeners) { if (listener instanceof ExtensionPointAndAreaListener) { - ((ExtensionPointAndAreaListener)listener).areaReplaced(oldArea); + ((ExtensionPointAndAreaListener)listener).areaReplaced(oldArea); } } } 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 37708b9015bc..c2cb96a9436c 100644 --- a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java +++ b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java @@ -8,8 +8,6 @@ import com.intellij.openapi.extensions.impl.InterfaceExtensionPoint.PicoContaine import com.intellij.openapi.util.Disposer; import com.intellij.util.SystemProperties; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.containers.MultiMap; -import com.intellij.util.pico.CachingConstructorInjectionComponentAdapter; import com.intellij.util.pico.DefaultPicoContainer; import gnu.trove.THashMap; import gnu.trove.THashSet; @@ -20,10 +18,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; import org.picocontainer.MutablePicoContainer; -import org.picocontainer.PicoContainer; -import java.util.Collection; -import java.util.Iterator; +import java.lang.reflect.Modifier; import java.util.Map; import java.util.Set; @@ -34,68 +30,37 @@ public final class ExtensionsAreaImpl implements ExtensionsArea { private static final boolean DEBUG_REGISTRATION = Boolean.FALSE.booleanValue(); // not compile-time constant to avoid yellow code - private final MutablePicoContainer myPicoContainer; - private final Map myExtensionPoints = ContainerUtil.newConcurrentMap(); + private final DefaultPicoContainer myPicoContainer; + private final Map> myExtensionPoints = ContainerUtil.newConcurrentMap(); private final Map myEPTraces = DEBUG_REGISTRATION ? new THashMap<>() : null; - private final MultiMap myAvailabilityListeners = MultiMap.createSmart(); // guarded by myAvailabilityListeners - private final AreaInstance myAreaInstance; - private final String myAreaClass; - public ExtensionsAreaImpl(@Nullable String areaClass, @Nullable AreaInstance areaInstance, PicoContainer parentPicoContainer) { - myAreaClass = areaClass; - myAreaInstance = areaInstance; - myPicoContainer = new DefaultPicoContainer(parentPicoContainer); - initialize(); + public ExtensionsAreaImpl(@NotNull DefaultPicoContainer picoContainer) { + myPicoContainer = picoContainer; } @TestOnly - public final void notifyAreaReplaced(@NotNull ExtensionsAreaImpl newArea) { + public final void notifyAreaReplaced(@Nullable ExtensionsAreaImpl newArea) { Set processedEPs = new THashSet<>(); - for (final ExtensionPointImpl point : myExtensionPoints.values()) { + for (ExtensionPointImpl point : myExtensionPoints.values()) { point.notifyAreaReplaced(this); processedEPs.add(point.getName()); } - // this code is required because we have a lot of static extensions e.g. LanguageExtension that are initialized only once - // for the extensions AvailabilityListeners will be broken if the initialization happened in a "fake" area, which doesn't have required EP - if (!myAvailabilityListeners.isEmpty()) { - for (Map.Entry> entry : myAvailabilityListeners.entrySet()) { - String key = entry.getKey(); - if (!processedEPs.contains(key)) { - boolean wasAdded = false; - //if listeners are "detached" for any EP we have to transfer them to the new area (otherwise it will affect area searching) - for (ExtensionPointAvailabilityListener listener : entry.getValue()) { - if (!newArea.hasAvailabilityListener(key, listener)) { - newArea.addAvailabilityListener(key, listener, null); - wasAdded = true; - } - } - if (wasAdded) { - processedEPs.add(key); - } - } - } + + if (newArea == null) { + return; } - for (ExtensionPointImpl point : newArea.myExtensionPoints.values()) { + for (ExtensionPointImpl point : newArea.myExtensionPoints.values()) { if (!processedEPs.contains(point.getName())) { point.notifyAreaReplaced(this); } } } - @NotNull @Override - public MutablePicoContainer getPicoContainer() { - return myPicoContainer; - } - - @Override - public String getAreaClass() { - return myAreaClass; - } - - @Override - public void registerExtensionPoint(@NotNull PluginDescriptor pluginDescriptor, @NotNull Element extensionPointElement) { + public void registerExtensionPoint(@NotNull PluginDescriptor pluginDescriptor, + @NotNull Element extensionPointElement, + @NotNull MutablePicoContainer picoContainer) { String pointName = extensionPointElement.getAttributeValue("qualifiedName"); if (pointName == null) { final String name = extensionPointElement.getAttributeValue("name"); @@ -118,7 +83,7 @@ public final class ExtensionsAreaImpl implements ExtensionsArea { ExtensionPointImpl point; if (interfaceClassName == null) { - point = new BeanExtensionPoint<>(pointName, beanClassName, myPicoContainer, pluginDescriptor); + point = new BeanExtensionPoint<>(pointName, beanClassName, picoContainer, pluginDescriptor); } else { boolean registerInPicoContainer; @@ -134,10 +99,10 @@ public final class ExtensionsAreaImpl implements ExtensionsArea { } if (registerInPicoContainer) { - point = new PicoContainerAwareInterfaceExtensionPoint<>(pointName, interfaceClassName, myPicoContainer, pluginDescriptor); + point = new PicoContainerAwareInterfaceExtensionPoint<>(pointName, interfaceClassName, picoContainer, pluginDescriptor); } else { - point = new InterfaceExtensionPoint<>(pointName, interfaceClassName, myPicoContainer, pluginDescriptor); + point = new InterfaceExtensionPoint<>(pointName, interfaceClassName, picoContainer, pluginDescriptor); } } registerExtensionPoint(point); @@ -152,12 +117,12 @@ public final class ExtensionsAreaImpl implements ExtensionsArea { // Used in Upsource @Override public void registerExtension(@NotNull final ExtensionPoint extensionPoint, @NotNull final PluginDescriptor pluginDescriptor, @NotNull final Element extensionElement) { - ((ExtensionPointImpl)extensionPoint).createAndRegisterAdapter(extensionElement, pluginDescriptor, myPicoContainer); + ((ExtensionPointImpl)extensionPoint).createAndRegisterAdapter(extensionElement, pluginDescriptor, myPicoContainer); } // don't want to expose clearCache directly - public void extensionsRegistered(@NotNull ExtensionPointImpl[] points) { - for (ExtensionPointImpl point : points) { + public void extensionsRegistered(@NotNull ExtensionPointImpl[] points) { + for (ExtensionPointImpl point : points) { point.clearCache(); } } @@ -177,85 +142,15 @@ public final class ExtensionsAreaImpl implements ExtensionsArea { return epName; } - private void initialize() { - InterfaceExtensionPoint point = - new InterfaceExtensionPoint<>(EPAvailabilityListenerExtension.EXTENSION_POINT_NAME, EPAvailabilityListenerExtension.class, myPicoContainer); - registerExtensionPoint(point); - point.addExtensionPointListener(new ExtensionPointListener() { - @Override - public void extensionRemoved(@NotNull EPAvailabilityListenerExtension extension, @NotNull PluginDescriptor pluginDescriptor) { - synchronized (myAvailabilityListeners) { - Collection listeners = myAvailabilityListeners.get(extension.getExtensionPointName()); - for (Iterator iterator = listeners.iterator(); iterator.hasNext(); ) { - ExtensionPointAvailabilityListener listener = iterator.next(); - if (listener.getClass().getName().equals(extension.getListenerClass())) { - iterator.remove(); - return; - } - } - } - LOG.warn("Failed to find EP availability listener: " + extension.getListenerClass()); - } - - @Override - public void extensionAdded(@NotNull EPAvailabilityListenerExtension extension, @NotNull PluginDescriptor pluginDescriptor) { - String epName = extension.getExtensionPointName(); - - ExtensionPointAvailabilityListener listener; - try { - listener = (ExtensionPointAvailabilityListener)instantiate(extension.loadListenerClass()); - } - catch (ClassNotFoundException e) { - throw new ExtensionInstantiationException(e, pluginDescriptor); - } - - addAvailabilityListener(epName, listener, null); - } - }, false, null); - } - - @NotNull - private Object instantiate(@NotNull Class clazz) { - CachingConstructorInjectionComponentAdapter adapter = - new CachingConstructorInjectionComponentAdapter(Integer.toString(System.identityHashCode(new Object())), clazz); - return adapter.getComponentInstance(getPicoContainer()); - } - - @Override - public void addAvailabilityListener(@NotNull String extensionPointName, @NotNull ExtensionPointAvailabilityListener listener, @Nullable Disposable parentDisposable) { - synchronized (myAvailabilityListeners) { - myAvailabilityListeners.putValue(extensionPointName, listener); - } - ExtensionPointImpl ep = myExtensionPoints.get(extensionPointName); - if (ep != null) { - listener.extensionPointRegistered(ep); - } - - if (parentDisposable != null) { - Disposer.register(parentDisposable, () -> removeAvailabilityListener(extensionPointName, listener)); - } - } - - @Override - public void removeAvailabilityListener(@NotNull String extensionPointName, @NotNull ExtensionPointAvailabilityListener listener) { - synchronized (myAvailabilityListeners) { - myAvailabilityListeners.remove(extensionPointName, listener); - } - } - - private boolean hasAvailabilityListener(@NotNull String extensionPointName, @NotNull ExtensionPointAvailabilityListener listener) { - Collection listeners = myAvailabilityListeners.get(extensionPointName); - return ContainerUtil.containsIdentity(listeners, listener); - } - @Override + @TestOnly public void registerExtensionPoint(@NotNull @NonNls String extensionPointName, @NotNull String extensionPointBeanClass, @NotNull ExtensionPoint.Kind kind) { doRegisterExtensionPoint(extensionPointName, extensionPointBeanClass, kind); } - @Override + @TestOnly public void registerExtensionPoint(@NotNull BaseExtensionPointName extensionPoint, @NotNull String extensionPointBeanClass, @NotNull ExtensionPoint.Kind kind, @@ -277,6 +172,33 @@ public final class ExtensionsAreaImpl implements ExtensionsArea { registerExtensionPoint(point); } + @TestOnly + public ExtensionPointImpl registerPoint(@NotNull String name, + @NotNull Class extensionClass, + @NotNull PluginDescriptor pluginDescriptor) { + ExtensionPointImpl point; + if (extensionClass.isInterface() || (extensionClass.getModifiers() & Modifier.ABSTRACT) != 0) { + point = new PicoContainerAwareInterfaceExtensionPoint<>(name, extensionClass.getName(), myPicoContainer, pluginDescriptor); + } + else { + point = new BeanExtensionPoint<>(name, extensionClass.getName(), myPicoContainer, pluginDescriptor); + } + registerExtensionPoint(point); + return point; + } + + /** + * To register extensions for {@link com.intellij.openapi.util.KeyedExtensionCollector} for test purposes, where extension instance can be KeyedLazyInstance and not a real bean class, + * because often it is not possible to use one (for example, {@link com.intellij.lang.LanguageExtensionPoint}). + */ + @TestOnly + public ExtensionPointImpl registerFakeBeanPoint(@NotNull String name, @NotNull PluginDescriptor pluginDescriptor) { + // any object name can be used, because EP must not create any instance + ExtensionPointImpl point = new BeanExtensionPoint<>(name, Object.class.getName(), myPicoContainer, pluginDescriptor); + registerExtensionPoint(point); + return point; + } + @Nullable private static PluginId id(@NotNull PluginDescriptor descriptor) { return descriptor instanceof UndefinedPluginDescriptor ? null : descriptor.getPluginId(); @@ -300,28 +222,18 @@ public final class ExtensionsAreaImpl implements ExtensionsArea { String name = point.getName(); checkThatPointNotDuplicated(name, point.getDescriptor()); myExtensionPoints.put(name, point); - notifyPointRegistered(point); if (DEBUG_REGISTRATION) { myEPTraces.put(name, new Throwable("Original registration for " + name)); } } - private void notifyPointRegistered(@NotNull ExtensionPoint extensionPoint) { - Collection listeners; - synchronized (myAvailabilityListeners) { - listeners = myAvailabilityListeners.get(extensionPoint.getName()); - } - for (final ExtensionPointAvailabilityListener listener : listeners) { - listener.extensionPointRegistered(extensionPoint); - } - } - @NotNull @Override public ExtensionPointImpl getExtensionPoint(@NotNull String extensionPointName) { - @SuppressWarnings("unchecked") ExtensionPointImpl extensionPoint = myExtensionPoints.get(extensionPointName); + @SuppressWarnings("unchecked") + ExtensionPointImpl extensionPoint = (ExtensionPointImpl)myExtensionPoints.get(extensionPointName); if (extensionPoint == null) { - throw new IllegalArgumentException("Missing extension point: " + extensionPointName + " in area " + myAreaInstance); + throw new IllegalArgumentException("Missing extension point: " + extensionPointName + " in container " + myPicoContainer); } return extensionPoint; } @@ -329,7 +241,8 @@ public final class ExtensionsAreaImpl implements ExtensionsArea { @Nullable @Override public ExtensionPoint getExtensionPointIfRegistered(@NotNull String extensionPointName) { - @SuppressWarnings("unchecked") ExtensionPointImpl extensionPoint = myExtensionPoints.get(extensionPointName); + @SuppressWarnings("unchecked") + ExtensionPointImpl extensionPoint = (ExtensionPointImpl)myExtensionPoints.get(extensionPointName); return extensionPoint; } @@ -341,27 +254,16 @@ public final class ExtensionsAreaImpl implements ExtensionsArea { @NotNull @Override - public ExtensionPointImpl[] getExtensionPoints() { + public ExtensionPointImpl[] getExtensionPoints() { return myExtensionPoints.values().toArray(new ExtensionPointImpl[0]); } @Override public void unregisterExtensionPoint(@NotNull final String extensionPointName) { - ExtensionPoint extensionPoint = myExtensionPoints.get(extensionPointName); + ExtensionPoint extensionPoint = myExtensionPoints.get(extensionPointName); if (extensionPoint != null) { extensionPoint.reset(); myExtensionPoints.remove(extensionPointName); - notifyEPRemoved(extensionPoint); - } - } - - private void notifyEPRemoved(@NotNull ExtensionPoint extensionPoint) { - Collection listeners; - synchronized (myAvailabilityListeners) { - listeners = myAvailabilityListeners.get(extensionPoint.getName()); - } - for (final ExtensionPointAvailabilityListener listener : listeners) { - listener.extensionPointRemoved(extensionPoint); } } @@ -377,6 +279,6 @@ public final class ExtensionsAreaImpl implements ExtensionsArea { @Override public String toString() { - return (myAreaClass == null ? "Root" : myAreaClass)+" Area"; + return myPicoContainer.toString(); } } \ No newline at end of file diff --git a/platform/extensions/src/com/intellij/openapi/extensions/impl/InterfaceExtensionPoint.java b/platform/extensions/src/com/intellij/openapi/extensions/impl/InterfaceExtensionPoint.java index 301521f74c96..ea906563cd9f 100644 --- a/platform/extensions/src/com/intellij/openapi/extensions/impl/InterfaceExtensionPoint.java +++ b/platform/extensions/src/com/intellij/openapi/extensions/impl/InterfaceExtensionPoint.java @@ -1,16 +1,15 @@ // Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.extensions.impl; -import com.intellij.openapi.extensions.*; +import com.intellij.openapi.extensions.ExtensionInstantiationException; +import com.intellij.openapi.extensions.LoadingOrder; +import com.intellij.openapi.extensions.PluginDescriptor; import org.jdom.Attribute; import org.jdom.Element; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.picocontainer.ComponentAdapter; import org.picocontainer.MutablePicoContainer; -import java.util.List; - public class InterfaceExtensionPoint extends ExtensionPointImpl { public InterfaceExtensionPoint(@NotNull String name, @NotNull Class clazz, @NotNull MutablePicoContainer picoContainer) { super(name, clazz.getName(), picoContainer, new UndefinedPluginDescriptor()); @@ -63,32 +62,6 @@ public class InterfaceExtensionPoint extends ExtensionPointImpl { return false; } - @Nullable - protected static T findExtension(@NotNull BaseExtensionPointName pointName, - @NotNull Class instanceOf, - @Nullable AreaInstance areaInstance, - boolean isRequired) { - ExtensionPoint point = Extensions.getArea(areaInstance).getExtensionPoint(pointName.getName()); - - List list = point.getExtensionList(); - //noinspection ForLoopReplaceableByForEach - for (int i = 0, size = list.size(); i < size; i++) { - T object = list.get(i); - if (instanceOf.isInstance(object)) { - return object; - } - } - - if (isRequired) { - String message = "could not find extension implementation " + instanceOf; - if (((ExtensionPointImpl)point).isInReadOnlyMode()) { - message += " (point in read-only mode)"; - } - throw new IllegalArgumentException(message); - } - return null; - } - static final class PicoContainerAwareInterfaceExtensionPoint extends InterfaceExtensionPoint { PicoContainerAwareInterfaceExtensionPoint(@NotNull String name, @NotNull String className, diff --git a/platform/extensions/src/com/intellij/openapi/extensions/impl/UndefinedPluginDescriptor.java b/platform/extensions/src/com/intellij/openapi/extensions/impl/UndefinedPluginDescriptor.java index 8911749f7e06..4166686fc024 100644 --- a/platform/extensions/src/com/intellij/openapi/extensions/impl/UndefinedPluginDescriptor.java +++ b/platform/extensions/src/com/intellij/openapi/extensions/impl/UndefinedPluginDescriptor.java @@ -6,6 +6,9 @@ import com.intellij.openapi.extensions.PluginId; import org.jetbrains.annotations.NotNull; final class UndefinedPluginDescriptor implements PluginDescriptor { + UndefinedPluginDescriptor() { + } + @NotNull @Override public PluginId getPluginId() { diff --git a/platform/extensions/src/com/intellij/util/pico/DefaultPicoContainer.java b/platform/extensions/src/com/intellij/util/pico/DefaultPicoContainer.java index a8e51e925d90..e08fed5a11d8 100644 --- a/platform/extensions/src/com/intellij/util/pico/DefaultPicoContainer.java +++ b/platform/extensions/src/com/intellij/util/pico/DefaultPicoContainer.java @@ -39,7 +39,7 @@ public class DefaultPicoContainer implements MutablePicoContainer { return componentAdapters.getImmutableSet(); } - private void appendNonAssignableAdaptersOfType(@NotNull Class componentType, @NotNull List result) { + private void appendNonAssignableAdaptersOfType(@NotNull Class componentType, @NotNull List result) { List comp = new ArrayList<>(); for (final ComponentAdapter componentAdapter : nonAssignableComponentAdapters.get()) { if (ReflectionUtil.isAssignable(componentType, componentAdapter.getComponentImplementation())) { @@ -69,7 +69,7 @@ public class DefaultPicoContainer implements MutablePicoContainer { } if (componentKey instanceof Class) { - return componentKeyToAdapterCache.get(((Class)componentKey).getName()); + return componentKeyToAdapterCache.get(((Class)componentKey).getName()); } return null; @@ -92,7 +92,7 @@ public class DefaultPicoContainer implements MutablePicoContainer { return parent == null ? null : parent.getComponentAdapterOfType(componentType); } - Class[] foundClasses = new Class[found.size()]; + Class[] foundClasses = new Class[found.size()]; for (int i = 0; i < foundClasses.length; i++) { foundClasses[i] = found.get(i).getComponentImplementation(); } @@ -165,24 +165,13 @@ public class DefaultPicoContainer implements MutablePicoContainer { } @Override - public List getComponentInstances() { - return getComponentInstancesOfType(Object.class); + public List getComponentInstances() { + throw new UnsupportedOperationException("Do not use"); } @Override public List getComponentInstancesOfType(@Nullable Class componentType) { - if (componentType == null) { - return Collections.emptyList(); - } - - List result = new ArrayList<>(); - for (ComponentAdapter componentAdapter : getComponentAdapters()) { - if (ReflectionUtil.isAssignable(componentType, componentAdapter.getComponentImplementation())) { - // may be null in the case of the "implicit" adapter representing "this". - ContainerUtil.addIfNotNull(result, getInstance(componentAdapter)); - } - } - return result; + throw new UnsupportedOperationException("use ComponentManagerImpl.getComponentInstancesOfType"); } @FunctionalInterface @@ -190,27 +179,12 @@ public class DefaultPicoContainer implements MutablePicoContainer { boolean isComponentInstantiated(); } - @Nullable - public T getComponentInstanceIfInstantiated(@NotNull String componentKey) { - ComponentAdapter adapter = getFromCache(componentKey); - if (!(adapter instanceof LazyComponentAdapter)) { - //noinspection unchecked - return (T)getComponentInstance(componentKey); - } - - if (((LazyComponentAdapter)adapter).isComponentInstantiated()) { - //noinspection unchecked - return (T)getLocalInstance(adapter); - } - return null; - } - @Override @Nullable public Object getComponentInstance(Object componentKey) { ComponentAdapter adapter = getFromCache(componentKey); if (adapter != null) { - return getLocalInstance(adapter); + return adapter.getComponentInstance(this); } if (parent != null) { adapter = parent.getComponentAdapter(componentKey); @@ -221,6 +195,22 @@ public class DefaultPicoContainer implements MutablePicoContainer { return null; } + @Nullable + public T getService(@NotNull Class serviceClass, boolean isCreate) { + ComponentAdapter adapter = componentKeyToAdapterCache.get(serviceClass.getName()); + if (adapter == null) { + return null; + } + + if (!isCreate && adapter instanceof LazyComponentAdapter && !((LazyComponentAdapter)adapter).isComponentInstantiated()) { + return null; + } + else { + //noinspection unchecked + return (T)adapter.getComponentInstance(this); + } + } + @Override @Nullable public Object getComponentInstanceOfType(Class componentType) { @@ -231,7 +221,7 @@ public class DefaultPicoContainer implements MutablePicoContainer { @Nullable private Object getInstance(@NotNull ComponentAdapter componentAdapter) { if (getComponentAdapters().contains(componentAdapter)) { - return getLocalInstance(componentAdapter); + return componentAdapter.getComponentInstance(this); } if (parent != null) { return parent.getComponentInstance(componentAdapter.getComponentKey()); @@ -240,40 +230,23 @@ public class DefaultPicoContainer implements MutablePicoContainer { return null; } - private Object getLocalInstance(@NotNull ComponentAdapter componentAdapter) { - PicoException firstLevelException; - try { - return componentAdapter.getComponentInstance(this); - } - catch (PicoInitializationException | PicoIntrospectionException e) { - firstLevelException = e; - } - - if (parent != null) { - Object instance = parent.getComponentInstance(componentAdapter.getComponentKey()); - if (instance != null) { - return instance; - } - } - - throw firstLevelException; - } - + /** + * @deprecated Do not use. + */ @Override + @Deprecated @Nullable public ComponentAdapter unregisterComponentByInstance(@NotNull Object componentInstance) { - for (ComponentAdapter adapter : getComponentAdapters()) { - Object o = getInstance(adapter); - if (componentInstance.equals(o)) { - return unregisterComponent(adapter.getComponentKey()); - } - } - return null; + throw new UnsupportedOperationException("Do not use"); } + /** + * @deprecated Do not use. + */ @Override + @Deprecated public void verify() { - new VerifyingVisitor().traverse(this); + throw new UnsupportedOperationException("Do not use"); } @Override @@ -356,7 +329,7 @@ public class DefaultPicoContainer implements MutablePicoContainer { * A linked hash set that's copied on write operations. * @param */ - private static class LinkedHashSetWrapper { + private static final class LinkedHashSetWrapper { private final Object lock = new Object(); private volatile Set immutableSet; private LinkedHashSet synchronizedSet = new LinkedHashSet<>(); diff --git a/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionsAreaTest.java b/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionsAreaTest.java deleted file mode 100644 index c23a9580e6c2..000000000000 --- a/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionsAreaTest.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2000-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.openapi.extensions.impl; - -import org.junit.Test; -import org.picocontainer.MutablePicoContainer; -import org.picocontainer.defaults.DefaultPicoContainer; - -import java.util.List; - -import static org.junit.Assert.assertEquals; - -/** - * @author mike - */ -public class ExtensionsAreaTest { - @Test - public void testGetComponentAdapterDoesntDuplicateAdapters() { - MutablePicoContainer picoContainer = - new ExtensionsAreaImpl("foo", null, new DefaultPicoContainer()).getPicoContainer(); - picoContainer.registerComponentImplementation("runnable", ExtensionsAreaTest.class); - - List adapters = picoContainer.getComponentAdaptersOfType(ExtensionsAreaTest.class); - assertEquals(1, adapters.size()); - } -} 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 013b0d7511b7..f21a0268e92b 100644 --- a/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionsImplTest.java +++ b/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionsImplTest.java @@ -5,13 +5,13 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.extensions.*; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.JDOMUtil; +import com.intellij.util.pico.DefaultPicoContainer; import org.jdom.Element; import org.jdom.JDOMException; import org.jetbrains.annotations.NotNull; import org.junit.After; import org.junit.Test; import org.picocontainer.MutablePicoContainer; -import org.picocontainer.defaults.DefaultPicoContainer; import java.io.IOException; import java.util.Arrays; @@ -21,9 +21,6 @@ import static org.assertj.core.api.AssertionsForClassTypes.fail; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -/** - * @author AKireyev - */ public class ExtensionsImplTest { static final String EXTENSION_POINT_NAME_1 = "ext.point.one"; @@ -36,7 +33,7 @@ public class ExtensionsImplTest { @Test public void testCreateAndAccess() { - ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(null, null, null); + ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(new DefaultPicoContainer()); int numEP = extensionsArea.getExtensionPoints().length; registerInterfaceExtension(extensionsArea); assertEquals("Additional EP available", numEP + 1, extensionsArea.getExtensionPoints().length); @@ -49,7 +46,7 @@ public class ExtensionsImplTest { @Test(expected = Throwable.class) public void testInvalidActions() { - ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(null, null, null); + ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(new DefaultPicoContainer()); registerInterfaceExtension(extensionsArea); extensionsArea.doRegisterExtensionPoint(EXTENSION_POINT_NAME_1, Boolean.class.getName(), ExtensionPoint.Kind.INTERFACE); fail("Should not allow duplicate registration"); @@ -57,7 +54,7 @@ public class ExtensionsImplTest { @Test public void testUnregisterEP() { - ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(null, null, null); + ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(new DefaultPicoContainer()); int numEP = extensionsArea.getExtensionPoints().length; registerInterfaceExtension(extensionsArea); @@ -80,51 +77,6 @@ public class ExtensionsImplTest { assertThat(removed[0]).withFailMessage("Extension point disposed").isTrue(); } - @Test - public void testAvailabilityListener() { - ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(null, null, null); - MyListener.reset(); - extensionsArea.getExtensionPoint(EPAvailabilityListenerExtension.EXTENSION_POINT_NAME).registerExtension( - new EPAvailabilityListenerExtension(EXTENSION_POINT_NAME_1, MyListener.class.getName())); - assertEquals(0, MyListener.regCount); - assertEquals(0, MyListener.remCount); - registerInterfaceExtension(extensionsArea); - assertEquals(1, MyListener.regCount); - assertEquals(0, MyListener.remCount); - MyListener.reset(); - extensionsArea.unregisterExtensionPoint(EXTENSION_POINT_NAME_1); - assertEquals(1, MyListener.remCount); - assertEquals(0, MyListener.regCount); - } - - @Test - public void testAvailability2Listeners() { - ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(null, null, null); - MyListener.reset(); - registerInterfaceExtension(extensionsArea); - extensionsArea.getExtensionPoint(EPAvailabilityListenerExtension.EXTENSION_POINT_NAME).registerExtension( - new EPAvailabilityListenerExtension(EXTENSION_POINT_NAME_1, MyListener.class.getName())); - extensionsArea.getExtensionPoint(EPAvailabilityListenerExtension.EXTENSION_POINT_NAME).registerExtension( - new EPAvailabilityListenerExtension(EXTENSION_POINT_NAME_1, MyListener.class.getName())); - assertEquals(2, MyListener.regCount); - assertEquals(0, MyListener.remCount); - MyListener.reset(); - extensionsArea.unregisterExtensionPoint(EXTENSION_POINT_NAME_1); - assertEquals(2, MyListener.remCount); - assertEquals(0, MyListener.regCount); - } - - @Test - public void testAvailabilityListenerAfter() { - ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(null, null, null); - registerInterfaceExtension(extensionsArea); - MyListener.reset(); - extensionsArea.getExtensionPoint(EPAvailabilityListenerExtension.EXTENSION_POINT_NAME).registerExtension( - new EPAvailabilityListenerExtension(EXTENSION_POINT_NAME_1, MyListener.class.getName())); - assertEquals(1, MyListener.regCount); - assertEquals(0, MyListener.remCount); - } - @Test public void testTryPicoContainer() { DefaultPicoContainer rootContainer = new DefaultPicoContainer(); @@ -178,7 +130,7 @@ public class ExtensionsImplTest { @Test public void testExtensionsNamespaces() throws IOException, JDOMException { - ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(null, null, new DefaultPicoContainer()); + ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(new DefaultPicoContainer()); extensionsArea.doRegisterExtensionPoint("plugin.ep1", TestExtensionClassOne.class.getName(), ExtensionPoint.Kind.BEAN_CLASS); registerExtension(extensionsArea, "plugin", JDOMUtil.load( "3")); @@ -186,7 +138,7 @@ public class ExtensionsImplTest { "1")); registerExtension(extensionsArea, "plugin", JDOMUtil.load( "2")); - ExtensionPoint extensionPoint = extensionsArea.getExtensionPoint("plugin.ep1"); + ExtensionPoint extensionPoint = extensionsArea.getExtensionPoint("plugin.ep1"); TestExtensionClassOne[] extensions = (TestExtensionClassOne[]) extensionPoint.getExtensions(); assertEquals(3, extensions.length); assertEquals("1", extensions[0].getText()); @@ -196,7 +148,7 @@ public class ExtensionsImplTest { @Test public void testExtensionsWithOrdering() throws IOException, JDOMException { - ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(null, null, new DefaultPicoContainer()); + ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(new DefaultPicoContainer()); extensionsArea.doRegisterExtensionPoint("ep1", TestExtensionClassOne.class.getName(), ExtensionPoint.Kind.BEAN_CLASS); registerExtension(extensionsArea, "", JDOMUtil.load( "3")); @@ -204,7 +156,7 @@ public class ExtensionsImplTest { "1")); registerExtension(extensionsArea, "", JDOMUtil.load( "2")); - ExtensionPoint extensionPoint = extensionsArea.getExtensionPoint("ep1"); + ExtensionPoint extensionPoint = extensionsArea.getExtensionPoint("ep1"); TestExtensionClassOne[] extensions = (TestExtensionClassOne[]) extensionPoint.getExtensions(); assertEquals(3, extensions.length); assertEquals("1", extensions[0].getText()); @@ -214,7 +166,7 @@ public class ExtensionsImplTest { @Test public void testExtensionsWithOrderingUpdate() throws IOException, JDOMException { - ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(null, null, new DefaultPicoContainer()); + ExtensionsAreaImpl extensionsArea = new ExtensionsAreaImpl(new DefaultPicoContainer()); extensionsArea.doRegisterExtensionPoint("ep1", TestExtensionClassOne.class.getName(), ExtensionPoint.Kind.BEAN_CLASS); registerExtension(extensionsArea, "", JDOMUtil.load("7")); registerExtension(extensionsArea, "", JDOMUtil.load("1")); diff --git a/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsTopHitProvider.java b/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsTopHitProvider.java index df06bacf5409..5d93683312ec 100644 --- a/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsTopHitProvider.java +++ b/platform/lang-impl/src/com/intellij/application/options/editor/EditorOptionsTopHitProvider.java @@ -1,4 +1,4 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.application.options.editor; import com.intellij.openapi.application.ApplicationBundle; @@ -8,10 +8,7 @@ import com.intellij.openapi.project.Project; import javax.swing.*; -/** - * @author Sergey.Malenkov - */ -public class EditorOptionsTopHitProvider extends EditorOptionsTopHitProviderBase.NoPrefix { +final class EditorOptionsTopHitProvider extends EditorOptionsTopHitProviderBase.NoPrefix { @Override protected Configurable getConfigurable(Project project) { return new EditorOptionsPanel(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java index dec301688a7e..22b608d8c147 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java @@ -1,23 +1,8 @@ -/* - * Copyright 2000-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.codeInsight.actions; import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.openapi.command.CommandProcessor; -import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.SelectionModel; @@ -108,7 +93,7 @@ public class RearrangeCodeProcessor extends AbstractLayoutCodeProcessor { @NotNull private Runnable prepareRearrangeCommand(@NotNull final PsiFile file, @NotNull final Collection ranges) { - final ArrangementEngine engine = ServiceManager.getService(myProject, ArrangementEngine.class); + ArrangementEngine engine = ArrangementEngine.getInstance(); return () -> { engine.arrange(file, ranges); if (getInfoCollector() != null) { diff --git a/platform/lang-impl/src/com/intellij/codeInspection/AbstractInspectionToolStarter.java b/platform/lang-impl/src/com/intellij/codeInspection/AbstractInspectionToolStarter.java index e5fe75861582..9a9650dc477c 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/AbstractInspectionToolStarter.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/AbstractInspectionToolStarter.java @@ -3,10 +3,12 @@ package com.intellij.codeInspection; import com.intellij.execution.configurations.ParametersList; import com.intellij.openapi.application.ApplicationStarter; -import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.ArrayUtilRt; import com.sampullara.cli.Args; import org.jetbrains.annotations.NotNull; +import java.util.List; + /** * @author Roman.Chernyatchik */ @@ -18,10 +20,10 @@ public abstract class AbstractInspectionToolStarter implements ApplicationStarte protected abstract AbstractInspectionCmdlineOptions createCmdlineOptions(); @Override - public void premain(String[] args) { + public void premain(@NotNull List args) { myOptions = createCmdlineOptions(); try { - Args.parse(myOptions, args); + Args.parse(myOptions, ArrayUtilRt.toStringArray(args)); } catch (Exception e) { printHelpAndExit(args, myOptions); @@ -80,17 +82,16 @@ public abstract class AbstractInspectionToolStarter implements ApplicationStarte return opts.getVerboseLevelProperty() > 0; } - protected void printArgs(String[] args, StringBuilder buff) { - if (args.length < 2) { + protected void printArgs(@NotNull List args, @NotNull StringBuilder buff) { + if (args.size() < 2) { buff.append(" no arguments"); } else { - final String argString = ParametersList.join(ContainerUtil.newArrayList(args, 1, args.length)); - buff.append(argString); + buff.append(ParametersList.join(args.subList(1, args.size()))); } } - protected void printHelpAndExit(final String[] args, final InspectionToolCmdlineOptions opts) { + protected void printHelpAndExit(@NotNull List args, final InspectionToolCmdlineOptions opts) { final StringBuilder buff = new StringBuilder(); buff.append("\n"); buff.append("Invalid options or syntax:"); diff --git a/platform/lang-impl/src/com/intellij/codeInspection/InspectionMain.java b/platform/lang-impl/src/com/intellij/codeInspection/InspectionMain.java index bec8576b7bbf..c90dd42f4df7 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/InspectionMain.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/InspectionMain.java @@ -4,7 +4,7 @@ package com.intellij.codeInspection; import com.intellij.openapi.application.ApplicationStarter; import org.jetbrains.annotations.NotNull; -import java.util.Arrays; +import java.util.List; public class InspectionMain implements ApplicationStarter { private InspectionApplication myApplication; @@ -16,9 +16,9 @@ public class InspectionMain implements ApplicationStarter { @Override @SuppressWarnings({"HardCodedStringLiteral"}) - public void premain(String[] args) { - if (args.length < 4) { - System.err.println("invalid args:" + Arrays.toString(args)); + public void premain(@NotNull List args) { + if (args.size() < 4) { + System.err.println("invalid args:" + args); printHelp(); } @@ -31,9 +31,9 @@ public class InspectionMain implements ApplicationStarter { printHelp(); } }; - myApplication.myProjectPath = args[1]; - myApplication.myStubProfile = args[2]; - myApplication.myOutPath = args[3]; + myApplication.myProjectPath = args.get(1); + myApplication.myStubProfile = args.get(2); + myApplication.myOutPath = args.get(3); if (myApplication.myProjectPath == null || myApplication.myOutPath == null @@ -43,16 +43,16 @@ public class InspectionMain implements ApplicationStarter { } try { - for (int i = 4; i < args.length; i++) { - String arg = args[i]; + for (int i = 4; i < args.size(); i++) { + String arg = args.get(i); if ("-profileName".equals(arg)) { - myApplication.myProfileName = args[++i]; + myApplication.myProfileName = args.get(++i); } else if ("-profilePath".equals(arg)) { - myApplication.myProfilePath = args[++i]; + myApplication.myProfilePath = args.get(++i); } else if ("-d".equals(arg)) { - myApplication.mySourceDirectory = args[++i]; + myApplication.mySourceDirectory = args.get(++i); } else if ("-v0".equals(arg)) { myApplication.setVerboseLevel(0); diff --git a/platform/lang-impl/src/com/intellij/ide/scratch/ScratchFileServiceImpl.java b/platform/lang-impl/src/com/intellij/ide/scratch/ScratchFileServiceImpl.java index 9cfbb2331774..abb6971ee8df 100644 --- a/platform/lang-impl/src/com/intellij/ide/scratch/ScratchFileServiceImpl.java +++ b/platform/lang-impl/src/com/intellij/ide/scratch/ScratchFileServiceImpl.java @@ -187,7 +187,7 @@ public class ScratchFileServiceImpl extends ScratchFileService implements Persis Language language = rootType.substituteLanguage(project, file); Language adjusted = language != null ? language : getLanguageByFileName(file); return adjusted != null && adjusted != ScratchFileType.INSTANCE.getLanguage() ? - LanguageSubstitutors.INSTANCE.substituteLanguage(adjusted, file, project) : adjusted; + LanguageSubstitutors.getInstance().substituteLanguage(adjusted, file, project) : adjusted; } } diff --git a/platform/lang-impl/src/com/intellij/ide/ui/search/TraverseUIStarter.java b/platform/lang-impl/src/com/intellij/ide/ui/search/TraverseUIStarter.java index 89abf229feda..a4c0142a25c3 100644 --- a/platform/lang-impl/src/com/intellij/ide/ui/search/TraverseUIStarter.java +++ b/platform/lang-impl/src/com/intellij/ide/ui/search/TraverseUIStarter.java @@ -68,9 +68,9 @@ public class TraverseUIStarter implements ApplicationStarter { } @Override - public void premain(String[] args) { - OUTPUT_PATH = args[1]; - SPLIT_BY_RESOURCE_PATH = args.length > 2 && Boolean.valueOf(args[2]); + public void premain(@NotNull List args) { + OUTPUT_PATH = args.get(1); + SPLIT_BY_RESOURCE_PATH = args.size() > 2 && Boolean.valueOf(args.get(2)); } @Override diff --git a/platform/lang-impl/src/com/intellij/internal/DumpExtensionsAction.java b/platform/lang-impl/src/com/intellij/internal/DumpExtensionsAction.java index 0ea3577948f1..5390c0eee089 100644 --- a/platform/lang-impl/src/com/intellij/internal/DumpExtensionsAction.java +++ b/platform/lang-impl/src/com/intellij/internal/DumpExtensionsAction.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2010 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.internal; import com.intellij.openapi.actionSystem.AnActionEvent; @@ -41,15 +27,15 @@ public class DumpExtensionsAction extends DumbAwareAction { areas.add(Extensions.getRootArea()); final Project project = e.getData(CommonDataKeys.PROJECT); if (project != null) { - areas.add(Extensions.getArea(project)); + areas.add(project.getExtensionArea()); final Module[] modules = ModuleManager.getInstance(project).getModules(); if (modules.length > 0) { - areas.add(Extensions.getArea(modules[0])); + areas.add(modules[0].getExtensionArea()); } } System.out.print(areas.size() + " extension areas: "); for (ExtensionsArea area : areas) { - System.out.print(area.getAreaClass() + " "); + System.out.print(area.toString() + " "); } System.out.println("\n"); diff --git a/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleImpl.java b/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleImpl.java index 322a5d3ac14f..fc298dbde12b 100644 --- a/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleImpl.java @@ -9,9 +9,6 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.*; import com.intellij.openapi.components.impl.PlatformComponentManagerImpl; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.extensions.AreaInstance; -import com.intellij.openapi.extensions.ExtensionPointName; -import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleComponent; import com.intellij.openapi.module.ModuleServiceManager; @@ -33,7 +30,6 @@ import com.intellij.util.xmlb.annotations.Property; import gnu.trove.THashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.picocontainer.MutablePicoContainer; import java.util.List; import java.util.Map; @@ -53,7 +49,7 @@ public class ModuleImpl extends PlatformComponentManagerImpl implements ModuleEx private final ModuleScopeProvider myModuleScopeProvider; ModuleImpl(@NotNull String name, @NotNull Project project, @NotNull String filePath) { - super(project, "Module " + name); + super(project); getPicoContainer().registerComponentInstance(Module.class, this); @@ -64,12 +60,6 @@ public class ModuleImpl extends PlatformComponentManagerImpl implements ModuleEx myImlFilePointer = VirtualFilePointerManager.getInstance().create(VfsUtilCore.pathToUrl(filePath), this, null); } - @Override - protected MutablePicoContainer bootstrapPicoContainer(@NotNull String name) { - Extensions.instantiateArea(ExtensionAreas.IDEA_MODULE, this, (AreaInstance)getParentComponentManager()); - return super.bootstrapPicoContainer(name); - } - @Override public void init(@Nullable Runnable beforeComponentCreation) { // do not measure (activityNamePrefix method not overridden by this class) @@ -149,7 +139,6 @@ public class ModuleImpl extends PlatformComponentManagerImpl implements ModuleEx public synchronized void dispose() { isModuleAdded = false; disposeComponents(); - Extensions.disposeArea(this); super.dispose(); } @@ -307,18 +296,6 @@ public class ModuleImpl extends PlatformComponentManagerImpl implements ModuleEx return "Module: '" + getName() + "'"; } - @NotNull - @Override - public T[] getExtensions(@NotNull final ExtensionPointName extensionPointName) { - return Extensions.getArea(this).getExtensionPoint(extensionPointName).getExtensions(); - } - - @NotNull - @Override - protected MutablePicoContainer createPicoContainer() { - return Extensions.getArea(this).getPicoContainer(); - } - @Override public long getOptionsModificationCount() { return getOptionManager().getModificationCount(); diff --git a/platform/lang-impl/src/com/intellij/psi/codeStyle/arrangement/engine/ArrangementEngine.java b/platform/lang-impl/src/com/intellij/psi/codeStyle/arrangement/engine/ArrangementEngine.java index cc5ee3c19a25..f97bb1717176 100644 --- a/platform/lang-impl/src/com/intellij/psi/codeStyle/arrangement/engine/ArrangementEngine.java +++ b/platform/lang-impl/src/com/intellij/psi/codeStyle/arrangement/engine/ArrangementEngine.java @@ -5,6 +5,8 @@ import com.intellij.application.options.CodeStyle; import com.intellij.codeInsight.actions.FormatChangedTextUtil; import com.intellij.lang.Language; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.components.Service; +import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.ex.DocumentEx; @@ -41,12 +43,15 @@ import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Se *

* I.e. the general idea is to have a language-specific rules hidden by generic arrangement API and common arrangement * engine which works on top of that API and performs the arrangement. - * - * @author Denis Zhdanov */ -public class ArrangementEngine { +@Service +public final class ArrangementEngine { private boolean myCodeChanged; + public static ArrangementEngine getInstance() { + return ServiceManager.getService(ArrangementEngine.class); + } + @Nullable public String getUserNotificationInfo() { if (myCodeChanged) { diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java index 51a1b3cba6a3..171a1987421b 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.psi.impl.source.tree.injected; @@ -784,7 +770,8 @@ public class InjectedLanguageUtil { .getCachedInjectedDocumentsInRange(containingFile, element.getTextRange()) .stream() .map(documentWindow -> PsiDocumentManager.getInstance(containingFile.getProject()).getPsiFile(documentWindow)) - .filter(file -> file != null && file.getLanguage() == LanguageSubstitutors.INSTANCE.substituteLanguage(language, file.getVirtualFile(), file.getProject())) + .filter(file -> file != null && file.getLanguage() == LanguageSubstitutors.getInstance() + .substituteLanguage(language, file.getVirtualFile(), file.getProject())) .max(Comparator.comparingInt(PsiElement::getTextLength)) .orElse(null); } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectionRegistrarImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectionRegistrarImpl.java index 34f4ed34ab43..fb317b7fed9b 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectionRegistrarImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectionRegistrarImpl.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.psi.impl.source.tree.injected; @@ -370,7 +356,7 @@ class InjectionRegistrarImpl extends MultiHostRegistrarImpl implements MultiHost resultReferences.add(Pair.create(injector, place)); clear(); } - + // returns true if shreds were set, false if old ones were reused private static boolean cacheEverything(@NotNull Place place, @NotNull DocumentWindowImpl documentWindow, @@ -532,7 +518,7 @@ class InjectionRegistrarImpl extends MultiHostRegistrarImpl implements MultiHost * and corresponding injected {@code oldInjectedPsi} (along with {@code oldDocumentWindow} and {@code oldInjectedVirtualFile}) were created. * Then the user came along and changed the host document in {@code hostVirtualFile}. * Document commit started and produced PSI diff {@code oldRoot} -> {@code newRoot} in the host PSI. - * + * * Now we try to produce similar diff for the injected fragment PSI. * To do that, we: *

@@ -665,7 +651,7 @@ class InjectionRegistrarImpl extends MultiHostRegistrarImpl implements MultiHost
                                    @NotNull StringBuilder decodedChars,
                                    @NotNull String fileName, @NotNull PsiDocumentManagerBase documentManager) {
     VirtualFileWindowImpl virtualFile = new VirtualFileWindowImpl(fileName, hostVirtualFile, documentWindow, language, decodedChars);
-    Language finalLanguage = forcedLanguage == null ? LanguageSubstitutors.INSTANCE.substituteLanguage(language, virtualFile, project) : forcedLanguage;
+    Language finalLanguage = forcedLanguage == null ? LanguageSubstitutors.getInstance().substituteLanguage(language, virtualFile, project) : forcedLanguage;
     InjectedFileViewProvider viewProvider = new InjectedFileViewProvider(PsiManager.getInstance(project), virtualFile, documentWindow, finalLanguage);
     ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(finalLanguage);
     assert parserDefinition != null : "Parser definition for language " + finalLanguage + " is null";
diff --git a/platform/platform-api/src/com/intellij/openapi/application/ApplicationStarter.java b/platform/platform-api/src/com/intellij/openapi/application/ApplicationStarter.java
index 1730e56185c4..ba4eeaa7f443 100644
--- a/platform/platform-api/src/com/intellij/openapi/application/ApplicationStarter.java
+++ b/platform/platform-api/src/com/intellij/openapi/application/ApplicationStarter.java
@@ -3,9 +3,11 @@ package com.intellij.openapi.application;
 
 import com.intellij.ide.CliResult;
 import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.util.ArrayUtilRt;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import java.util.List;
 import java.util.concurrent.Future;
 
 /**
@@ -24,12 +26,21 @@ public interface ApplicationStarter {
    */
   String getCommandName();
 
+  /**
+   * @deprecated Use {@link #premain(List)}
+   */
+  @SuppressWarnings("DeprecatedIsStillUsed")
+  @Deprecated
+  default void premain(@SuppressWarnings("unused") @NotNull String[] args) { }
+
   /**
    * Called before application initialization. Invoked in event dispatch thread.
    *
    * @param args program arguments (including the selector)
    */
-  default void premain(String[] args) { }
+  default void premain(@NotNull List args) {
+    premain(ArrayUtilRt.toStringArray(args));
+  }
 
   /**
    * 

Called when application has been initialized. Invoked in event dispatch thread.

@@ -67,7 +78,7 @@ public interface ApplicationStarter { /** @see #canProcessExternalCommandLine */ @NotNull - default Future processExternalCommandLineAsync(@NotNull String[] args, @Nullable String currentDirectory) { + default Future processExternalCommandLineAsync(@NotNull List args, @Nullable String currentDirectory) { throw new UnsupportedOperationException("Class " + getClass().getName() + " must implement `processExternalCommandLineAsync()`"); } } \ No newline at end of file diff --git a/platform/platform-api/src/com/intellij/openapi/application/ApplicationStarterEx.java b/platform/platform-api/src/com/intellij/openapi/application/ApplicationStarterEx.java index 6a20a7ff41ea..03c72bd1ceac 100644 --- a/platform/platform-api/src/com/intellij/openapi/application/ApplicationStarterEx.java +++ b/platform/platform-api/src/com/intellij/openapi/application/ApplicationStarterEx.java @@ -2,10 +2,12 @@ package com.intellij.openapi.application; import com.intellij.ide.CliResult; +import com.intellij.util.ArrayUtilRt; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.List; import java.util.concurrent.Future; /** @deprecated override {@link ApplicationStarter} instead */ @@ -14,8 +16,8 @@ import java.util.concurrent.Future; public abstract class ApplicationStarterEx implements ApplicationStarter { @NotNull @Override - public final Future processExternalCommandLineAsync(@NotNull String[] args, @Nullable String currentDirectory) { - processExternalCommandLine(args, currentDirectory); + public final Future processExternalCommandLineAsync(@NotNull List args, @Nullable String currentDirectory) { + processExternalCommandLine(ArrayUtilRt.toStringArray(args), currentDirectory); return CliResult.ok(); } diff --git a/platform/platform-api/src/com/intellij/openapi/fileTypes/FileTypeManager.java b/platform/platform-api/src/com/intellij/openapi/fileTypes/FileTypeManager.java index 1ff718644db7..d3e53a881c43 100644 --- a/platform/platform-api/src/com/intellij/openapi/fileTypes/FileTypeManager.java +++ b/platform/platform-api/src/com/intellij/openapi/fileTypes/FileTypeManager.java @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2019 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.fileTypes; import com.intellij.openapi.application.Application; diff --git a/platform/platform-impl/src/com/intellij/ide/CommandLineProcessor.java b/platform/platform-impl/src/com/intellij/ide/CommandLineProcessor.java index ba12189ffdde..3d4ad3a98cb0 100644 --- a/platform/platform-impl/src/com/intellij/ide/CommandLineProcessor.java +++ b/platform/platform-impl/src/com/intellij/ide/CommandLineProcessor.java @@ -21,7 +21,6 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.openapi.wm.IdeFrame; import com.intellij.platform.CommandLineProjectOpenProcessor; -import com.intellij.util.ArrayUtilRt; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -105,7 +104,7 @@ public final class CommandLineProcessor { @NotNull public static Pair> processExternalCommandLine(@NotNull List args, - @Nullable String currentDirectory) { + @Nullable String currentDirectory) { LOG.info("External command line:"); LOG.info("Dir: " + currentDirectory); for (String arg : args) LOG.info(arg); @@ -121,7 +120,7 @@ public final class CommandLineProcessor { if (command.equals(starter.getCommandName())) { if (starter.canProcessExternalCommandLine()) { LOG.info("Processing command with " + starter); - return pair(null, starter.processExternalCommandLineAsync(ArrayUtilRt.toStringArray(args), currentDirectory)); + return pair(null, starter.processExternalCommandLineAsync(args, currentDirectory)); } else { String title = "Cannot execute command '" + command + "'"; diff --git a/platform/platform-impl/src/com/intellij/idea/ApplicationLoader.kt b/platform/platform-impl/src/com/intellij/idea/ApplicationLoader.kt index 2dced46f1f51..9696c6cdbfa5 100644 --- a/platform/platform-impl/src/com/intellij/idea/ApplicationLoader.kt +++ b/platform/platform-impl/src/com/intellij/idea/ApplicationLoader.kt @@ -15,7 +15,6 @@ import com.intellij.ide.plugins.* import com.intellij.ide.ui.customization.CustomActionsSchema import com.intellij.openapi.actionSystem.IdeActions import com.intellij.openapi.application.* -import com.intellij.openapi.application.ex.ApplicationManagerEx import com.intellij.openapi.application.impl.ApplicationImpl import com.intellij.openapi.components.stateStore import com.intellij.openapi.diagnostic.Logger @@ -51,7 +50,6 @@ import java.awt.EventQueue import java.beans.PropertyChangeListener import java.io.File import java.nio.file.Paths -import java.util.* import java.util.concurrent.CompletableFuture import java.util.concurrent.Future import java.util.concurrent.atomic.AtomicReference @@ -72,21 +70,43 @@ private fun executeInitAppInEdt(rawArgs: Array, pluginDescriptorsFuture: CompletableFuture>) { val args = processProgramArguments(rawArgs) StartupUtil.patchSystem(LOG) - val starter = createAppStarter(args, pluginDescriptorsFuture) val headless = Main.isHeadless() val app = initAppActivity.runChild("create app") { - ApplicationImpl(java.lang.Boolean.getBoolean(PluginManagerCore.IDEA_IS_INTERNAL_PROPERTY), false, headless, Main.isCommandLine(), - ApplicationManagerEx.IDEA_APPLICATION) + ApplicationImpl(java.lang.Boolean.getBoolean(PluginManagerCore.IDEA_IS_INTERNAL_PROPERTY), false, headless, Main.isCommandLine()) } - starter.premain(args) + val registerFuture = pluginDescriptorsFuture.thenAccept { + initAppActivity.runChild("app component registration") { + app.registerComponents(it) + } + } + if (args.isEmpty()) { + startApp(app, IdeStarter(), initAppActivity, registerFuture, args) + return + } + + // ApplicationStarter it is extension, so, to find starter, extensions must be registered prior to that + registerFuture.thenRunOrHandleError { + val starter = findStarter(args.first()) ?: IdeStarter() + if (Main.isHeadless() && !starter.isHeadless) { + Main.showMessage("Startup Error", "Application cannot start in headless mode", true) + exitProcess(Main.NO_GRAPHICS) + } + + starter.premain(args) + startApp(app, starter, initAppActivity, registerFuture, args) + } +} + +private fun startApp(app: ApplicationImpl, starter: ApplicationStarter, initAppActivity: Activity, registerFuture: CompletableFuture, args: List) { // this code is here for one simple reason - here we have application, // and after plugin loading we don't have - ApplicationManager.getApplication() can be used, but it doesn't matter // but it is very important to call registerRegistryAndMessageBusAndComponent immediately after application creation // and do not place any time-consuming code in between (e.g. showLicenseeInfoOnSplash) - var future = registerRegistryAndContainerAndInitStore(pluginDescriptorsFuture, app, initAppActivity) + var future = registerRegistryAndInitStore(registerFuture, app) + val headless = app.isHeadlessEnvironment if (!headless) { initAppActivity.runChild("icon loader activation") { // todo investigate why in test mode dummy icon manager is not suitable @@ -139,7 +159,7 @@ private fun executeInitAppInEdt(rawArgs: Array, WeakFocusStackManager.getInstance() } - future.thenRun(Runnable { + future.thenRunOrHandleError { // this invokeLater() call is needed not only because current thread maybe not EDT, but to place the app starting code on a freshly minted IdeEventQueue instance val placeOnEventQueueActivity = initAppActivity.startChild(Phases.PLACE_ON_EVENT_QUEUE) EventQueue.invokeLater { @@ -153,7 +173,7 @@ private fun executeInitAppInEdt(rawArgs: Array, } (TransactionGuard.getInstance() as TransactionGuardImpl).performUserActivity { - starter.main(args) + starter.main(ArrayUtilRt.toStringArray(args)) } if (PluginManagerCore.isRunningFromSources()) { @@ -168,25 +188,19 @@ private fun executeInitAppInEdt(rawArgs: Array, ParallelActivity.PREPARE_APP_INIT.run("init system properties") { SystemPropertyBean.initSystemProperties() } - }) + } } @ApiStatus.Internal -fun registerRegistryAndContainerAndInitStore(pluginDescriptorsFuture: CompletableFuture>, - app: ApplicationImpl, - initAppActivity: Activity?): CompletableFuture { - return pluginDescriptorsFuture - .thenCompose { pluginDescriptors -> +fun registerRegistryAndInitStore(registerFuture: CompletableFuture<*>, app: ApplicationImpl): CompletableFuture { + return registerFuture + .thenCompose { val future = CompletableFuture.runAsync(Runnable { ParallelActivity.PREPARE_APP_INIT.run("add registry keys") { RegistryKeyBean.addKeysFromPlugins() } }, AppExecutorUtil.getAppExecutorService()) - initAppActivity.runChild("app component registration") { - app.registerComponents(pluginDescriptors) - } - // yes, at this moment initSystemProperties or RegistryKeyBean.addKeysFromPlugins maybe not yet performed, but it doesn't affect because not used. initConfigurationStore(app, null) @@ -237,21 +251,6 @@ private fun addActivateAndWindowsCliListeners(app: ApplicationImpl) { } } -private fun createAppStarter(args: Array, pluginsLoaded: Future<*>): ApplicationStarter { - if (args.isEmpty()) { - return IdeStarter() - } - - pluginsLoaded.get() - - val starter = findStarter(args[0]) ?: IdeStarter() - if (Main.isHeadless() && !starter.isHeadless) { - Main.showMessage("Startup Error", "Application cannot start in headless mode", true) - exitProcess(Main.NO_GRAPHICS) - } - return starter -} - fun initApplication(rawArgs: Array) { val initAppActivity = MainRunner.startupStart.endAndStart(Phases.INIT_APP) val pluginDescriptorsFuture = CompletableFuture>() @@ -272,7 +271,7 @@ fun initApplication(rawArgs: Array) { pluginDescriptorsFuture.complete(plugins) } -fun findStarter(key: String?): ApplicationStarter? { +fun findStarter(key: String): ApplicationStarter? { for (starter in ApplicationStarter.EP_NAME.iterable) { if (starter == null) { break @@ -323,7 +322,7 @@ open class IdeStarter : ApplicationStarter { override fun canProcessExternalCommandLine() = true - override fun processExternalCommandLineAsync(args: Array, currentDirectory: String?): Future { + override fun processExternalCommandLineAsync(args: List, currentDirectory: String?): Future { LOG.info("Request to open in $currentDirectory with parameters: ${args.joinToString(separator = ",")}") if (args.isEmpty()) { return CliResult.ok() @@ -470,8 +469,12 @@ open class IdeStarter : ApplicationStarter { * @see SAFE_JAVA_ENV_PARAMETERS */ @Suppress("SpellCheckingInspection") -private fun processProgramArguments(args: Array): Array { - val arguments = ArrayList() +private fun processProgramArguments(args: Array): List { + if (args.isEmpty()) { + return emptyList() + } + + val arguments = mutableListOf() val safeKeys = SAFE_JAVA_ENV_PARAMETERS.toList() for (arg in args) { if (arg.startsWith("-D")) { @@ -487,7 +490,7 @@ private fun processProgramArguments(args: Array): Array { arguments.add(arg) } - return ArrayUtilRt.toStringArray(arguments) + return arguments } @ApiStatus.Internal @@ -519,4 +522,12 @@ fun preloadServices(app: ApplicationImpl): CompletableFuture { } }, appExecutorService) }) +} + +private fun CompletableFuture.thenRunOrHandleError(handler: () -> Unit): CompletableFuture? { + return thenRun(handler) + .exceptionally { + MainRunner.processException(it) + null + } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/idea/CommandLineApplication.java b/platform/platform-impl/src/com/intellij/idea/CommandLineApplication.java deleted file mode 100644 index a95339086f04..000000000000 --- a/platform/platform-impl/src/com/intellij/idea/CommandLineApplication.java +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -package com.intellij.idea; - -import com.intellij.openapi.application.ex.ApplicationManagerEx; -import com.intellij.openapi.application.impl.ApplicationImpl; -import com.intellij.openapi.diagnostic.Logger; -import org.jetbrains.annotations.ApiStatus; - -/** @deprecated obsolete; use {@link com.intellij.ide.impl.HeadlessDataManager} and {@code com.intellij.idea.IdeaTestApplication} instead */ -@Deprecated -@ApiStatus.ScheduledForRemoval(inVersion = "2019.3") -public class CommandLineApplication { - private static final Logger LOG = Logger.getInstance("#com.intellij.idea.CommandLineApplication"); - - protected static CommandLineApplication ourInstance; - - protected CommandLineApplication(boolean isInternal, boolean isUnitTestMode, boolean isHeadless) { - LOG.assertTrue(ourInstance == null, "Only one instance allowed."); - //noinspection AssignmentToStaticFieldFromInstanceMethod - ourInstance = this; - new ApplicationImpl(isInternal, isUnitTestMode, isHeadless, true, ApplicationManagerEx.IDEA_APPLICATION); - } -} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/jps/impl/JpsIdePluginManagerImpl.java b/platform/platform-impl/src/com/intellij/jps/impl/JpsIdePluginManagerImpl.java index a6a6de52e3a5..59110a2f503f 100644 --- a/platform/platform-impl/src/com/intellij/jps/impl/JpsIdePluginManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/jps/impl/JpsIdePluginManagerImpl.java @@ -17,11 +17,15 @@ import java.util.concurrent.CopyOnWriteArrayList; /** * @author nik */ -public class JpsIdePluginManagerImpl extends JpsPluginManager { +public final class JpsIdePluginManagerImpl extends JpsPluginManager { private final List myExternalBuildPlugins = new CopyOnWriteArrayList<>(); public JpsIdePluginManagerImpl() { ExtensionsArea rootArea = Extensions.getRootArea(); + if (rootArea == null) { + return; + } + //todo[nik] get rid of this check: currently this class is used in intellij.platform.jps.build tests instead of JpsPluginManagerImpl because intellij.platform.ide.impl module is added to classpath via testFramework if (rootArea.hasExtensionPoint(JpsPluginBean.EP_NAME)) { JpsPluginBean.EP_NAME.getPoint(null).addExtensionPointListener(new ExtensionPointListener() { diff --git a/platform/platform-impl/src/com/intellij/openapi/application/ApplicationStarterBase.java b/platform/platform-impl/src/com/intellij/openapi/application/ApplicationStarterBase.java index 0383da935e01..38e52de7cd09 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/ApplicationStarterBase.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/ApplicationStarterBase.java @@ -9,6 +9,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Arrays; +import java.util.List; import java.util.concurrent.Future; /** @@ -41,7 +42,7 @@ public abstract class ApplicationStarterBase implements ApplicationStarter { @NotNull @Override - public Future processExternalCommandLineAsync(@NotNull String[] args, @Nullable String currentDirectory) { + public Future processExternalCommandLineAsync(@NotNull List args, @Nullable String currentDirectory) { if (!checkArguments(args)) { Messages.showMessageDialog(getUsageMessage(), StringUtil.toTitleCase(getCommandName()), Messages.getInformationIcon()); return CliResult.error(1, getUsageMessage()); @@ -64,17 +65,17 @@ public abstract class ApplicationStarterBase implements ApplicationStarter { ApplicationManager.getApplication().saveSettings(); } - private boolean checkArguments(String[] args) { - return Arrays.binarySearch(myArgsCount, args.length - 1) != -1 && getCommandName().equals(args[0]); + private boolean checkArguments(@NotNull List args) { + return Arrays.binarySearch(myArgsCount, args.size() - 1) != -1 && getCommandName().equals(args.get(0)); } public abstract String getUsageMessage(); @NotNull - protected abstract Future processCommand(@NotNull String[] args, @Nullable String currentDirectory) throws Exception; + protected abstract Future processCommand(@NotNull List args, @Nullable String currentDirectory) throws Exception; @Override - public void premain(String[] args) { + public void premain(@NotNull List args) { if (!checkArguments(args)) { System.err.println(getUsageMessage()); System.exit(1); @@ -85,7 +86,7 @@ public abstract class ApplicationStarterBase implements ApplicationStarter { public void main(@NotNull String[] args) { int exitCode = 0; try { - Future commandFuture = processCommand(args, null); + Future commandFuture = processCommand(Arrays.asList(args), null); CliResult result = commandFuture.get(); if (result.getMessage() != null) { System.out.println(result.getMessage()); diff --git a/platform/platform-impl/src/com/intellij/openapi/application/SaveStarter.java b/platform/platform-impl/src/com/intellij/openapi/application/SaveStarter.java index 3308b4894f0e..0dab049a4c5d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/SaveStarter.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/SaveStarter.java @@ -5,9 +5,10 @@ import com.intellij.ide.CliResult; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.List; import java.util.concurrent.Future; -public final class SaveStarter extends ApplicationStarterBase { +final class SaveStarter extends ApplicationStarterBase { private SaveStarter() { super("save", 0); } @@ -19,7 +20,7 @@ public final class SaveStarter extends ApplicationStarterBase { @NotNull @Override - protected Future processCommand(@NotNull String[] args, @Nullable String currentDirectory) { + protected Future processCommand(@NotNull List args, @Nullable String currentDirectory) { saveAll(); return CliResult.ok(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/application/ex/DecodeDefaultsUtil.java b/platform/platform-impl/src/com/intellij/openapi/application/ex/DecodeDefaultsUtil.java index 546e11497feb..afc2761fbc52 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/ex/DecodeDefaultsUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/ex/DecodeDefaultsUtil.java @@ -26,7 +26,7 @@ public class DecodeDefaultsUtil { url = getResource(appendExt(componentResourcePath), requestor); } else { - url = getResource(appendExt('/' + ApplicationManagerEx.getApplicationEx().getName() + '/' + componentResourcePath), requestor); + url = getResource(appendExt("/idea/" + componentResourcePath), requestor); if (url == null) { url = getResource(appendExt('/' + componentResourcePath), requestor); } diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java index adf988ef27b8..334af78793c6 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java @@ -27,7 +27,6 @@ import com.intellij.openapi.components.impl.PlatformComponentManagerImpl; import com.intellij.openapi.diagnostic.Attachment; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.diagnostic.RuntimeExceptionWithAttachments; -import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.extensions.impl.ExtensionsAreaImpl; import com.intellij.openapi.progress.*; @@ -83,7 +82,6 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App private final boolean myCommandLineMode; private final boolean myIsInternal; - private final String myName; // contents modified in write action, read in read action private final Stack> myWriteActionsStack = new Stack<>(); @@ -103,10 +101,9 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App private static final String WAS_EVER_SHOWN = "was.ever.shown"; public ApplicationImpl(boolean isInternal, - boolean isUnitTestMode, - boolean isHeadless, - boolean isCommandLine, - @NotNull String appName) { + boolean isUnitTestMode, + boolean isHeadless, + boolean isCommandLine) { super(null); ApplicationManager.setApplication(this, myLastDisposable); // reset back to null only when all components already disposed @@ -121,8 +118,6 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App Disposer.setDebugMode(isInternal || isUnitTestMode || Disposer.isDebugDisposerOn()); - myName = appName; - myIsInternal = isInternal; myTestModeFlag = isUnitTestMode; myHeadlessMode = isHeadless; @@ -213,23 +208,11 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App return true; } - @Override - @NotNull - public String getName() { - return myName; - } - @Override public boolean holdsReadLock() { return myLock.isReadLockedByThisThread(); } - @NotNull - @Override - protected MutablePicoContainer createPicoContainer() { - return Extensions.getRootArea().getPicoContainer(); - } - @Override public boolean isInternal() { return myIsInternal; @@ -1349,12 +1332,6 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App return mySaveAllowed; } - @NotNull - @Override - public T[] getExtensions(@NotNull final ExtensionPointName extensionPointName) { - return Extensions.getRootArea().getExtensionPoint(extensionPointName).getExtensions(); - } - @Override public boolean isDisposeInProgress() { return myDisposeInProgress || ShutDownTracker.isShutdownHookRunning(); diff --git a/platform/platform-impl/src/com/intellij/openapi/command/impl/DummyProject.java b/platform/platform-impl/src/com/intellij/openapi/command/impl/DummyProject.java index 0b709f9a67b1..e3e7484363d1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/command/impl/DummyProject.java +++ b/platform/platform-impl/src/com/intellij/openapi/command/impl/DummyProject.java @@ -2,17 +2,17 @@ package com.intellij.openapi.command.impl; import com.intellij.openapi.components.BaseComponent; -import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.extensions.ExtensionsArea; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.UserDataHolderBase; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ArrayUtilRt; import com.intellij.util.messages.MessageBus; +import com.intellij.util.pico.DefaultPicoContainer; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.SystemIndependent; -import org.picocontainer.PicoContainer; /** * @author max @@ -79,6 +79,11 @@ public class DummyProject extends UserDataHolderBase implements Project { return null; } + @Override + public T getService(@NotNull Class serviceClass, boolean isCreate) { + return null; + } + @Nullable @Override public T getComponent(@NotNull Class interfaceClass) { @@ -99,10 +104,16 @@ public class DummyProject extends UserDataHolderBase implements Project { @Override @NotNull - public PicoContainer getPicoContainer() { + public DefaultPicoContainer getPicoContainer() { throw new UnsupportedOperationException("getPicoContainer is not implement in : " + getClass()); } + @NotNull + @Override + public ExtensionsArea getExtensionArea() { + throw new UnsupportedOperationException("getExtensionArea is not implement in : " + getClass()); + } + @Override public T getComponent(@NotNull Class interfaceClass, T defaultImplementation) { return null; @@ -142,10 +153,4 @@ public class DummyProject extends UserDataHolderBase implements Project { @Override public void dispose() { } - - @NotNull - @Override - public T[] getExtensions(@NotNull final ExtensionPointName extensionPointName) { - throw new UnsupportedOperationException("getExtensions()"); - } } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/command/impl/UpdatePluginsApp.java b/platform/platform-impl/src/com/intellij/openapi/command/impl/UpdatePluginsApp.java index eeb254a4e9e0..d629a8db3000 100644 --- a/platform/platform-impl/src/com/intellij/openapi/command/impl/UpdatePluginsApp.java +++ b/platform/platform-impl/src/com/intellij/openapi/command/impl/UpdatePluginsApp.java @@ -11,6 +11,7 @@ import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import java.util.Collection; +import java.util.List; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -30,7 +31,7 @@ public class UpdatePluginsApp implements ApplicationStarter { } @Override - public void premain(String[] args) { + public void premain(@NotNull List args) { System.setProperty("idea.skip.indices.initialization", "true"); } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/PlatformComponentManagerImpl.kt b/platform/platform-impl/src/com/intellij/openapi/components/impl/PlatformComponentManagerImpl.kt index cc535134f4aa..5f3f16a6177d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/PlatformComponentManagerImpl.kt +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/PlatformComponentManagerImpl.kt @@ -1,36 +1,55 @@ // Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.components.impl +import com.intellij.diagnostic.ActivitySubNames import com.intellij.diagnostic.LoadingPhase -import com.intellij.ide.plugins.ContainerDescriptor -import com.intellij.ide.plugins.IdeaPluginDescriptor -import com.intellij.ide.plugins.IdeaPluginDescriptorImpl -import com.intellij.ide.plugins.PluginManager +import com.intellij.diagnostic.ParallelActivity +import com.intellij.diagnostic.run +import com.intellij.ide.plugins.* import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.components.ComponentManager import com.intellij.openapi.components.PathMacroManager import com.intellij.openapi.components.ServiceDescriptor import com.intellij.openapi.components.impl.stores.IComponentStore import com.intellij.openapi.components.stateStore +import com.intellij.openapi.diagnostic.logger +import com.intellij.openapi.extensions.AreaInstance import com.intellij.openapi.extensions.PluginId +import com.intellij.openapi.extensions.impl.ExtensionsAreaImpl +import com.intellij.openapi.progress.ProgressManager +import com.intellij.serviceContainer.ServiceContainer import com.intellij.util.SmartList import com.intellij.util.containers.ContainerUtil import com.intellij.util.messages.ListenerDescriptor import com.intellij.util.messages.MessageBusFactory import com.intellij.util.messages.impl.MessageBusImpl +import com.intellij.util.pico.DefaultPicoContainer +import org.jetbrains.annotations.ApiStatus import java.util.concurrent.ConcurrentMap -abstract class PlatformComponentManagerImpl : ComponentManagerImpl { +private val LOG = logger() + +private fun createPicoContainer(parent: ComponentManager?): DefaultPicoContainer { + return when (parent) { + null -> ServiceContainer(null) + else -> DefaultPicoContainer(parent.picoContainer) + } +} + +abstract class PlatformComponentManagerImpl(parent: ComponentManager?) : ComponentManagerImpl(parent, createPicoContainer(parent)), AreaInstance { private var handlingInitComponentError = false private val componentStore: IComponentStore get() = this.stateStore - protected constructor(parent: ComponentManager?) : super(parent) - - protected constructor(parent: ComponentManager?, name: String) : super(parent, name) - protected open fun registerComponents(plugins: List) { + ParallelActivity.PREPARE_APP_INIT.run(ActivitySubNames.REGISTER_EXTENSIONS) { + @Suppress("UNCHECKED_CAST") + PluginManagerCore.registerExtensionPointsAndExtensions(extensionArea as ExtensionsAreaImpl, picoContainer, + plugins as MutableList) + } + + val app = ApplicationManager.getApplication() val headless = app == null || app.isHeadlessEnvironment @@ -107,4 +126,27 @@ abstract class PlatformComponentManagerImpl : ComponentManagerImpl { } protected abstract fun getContainerDescriptor(pluginDescriptor: IdeaPluginDescriptorImpl): ContainerDescriptor -} + + @ApiStatus.Internal + override fun getService(serviceClass: Class, isCreate: Boolean): T? { + val componentKey = serviceClass.name + var instance = picoContainer.getService(serviceClass, isCreate) + if (instance == null && isCreate) { + ProgressManager.checkCanceled() + + if (parentComponentManager != null) { + instance = parentComponentManager.getService(serviceClass, isCreate) + if (instance != null) { + LOG.error("$componentKey is registered as application service, but requested as project one") + return instance + } + } + + instance = getComponent(serviceClass) ?: return null + LOG.error("$componentKey requested as a service, but it is a component - convert it to a service or " + + "change call to ${if (parentComponentManager == null) "ApplicationManager.getApplication().getComponent()" else "project.getComponent()"}") + return instance + } + return instance + } +} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/ServiceManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/ServiceManagerImpl.java index bcf9ffb990ab..a102aa2bac1a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/ServiceManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/ServiceManagerImpl.java @@ -268,8 +268,7 @@ public final class ServiceManagerImpl implements Disposable { } @Override - public void verify(final PicoContainer container) throws PicoIntrospectionException { - getDelegate().verify(container); + public void verify(PicoContainer container) { } @Override diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableWrapper.java b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableWrapper.java index d4947e4a8702..b4e0a01f3e9e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableWrapper.java +++ b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableWrapper.java @@ -1,10 +1,12 @@ // Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.options.ex; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.ExtensionPointName; -import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.extensions.ExtensionsArea; import com.intellij.openapi.options.*; +import com.intellij.openapi.project.Project; import com.intellij.util.ArrayUtil; import com.intellij.util.NullableFunction; import com.intellij.util.containers.ContainerUtil; @@ -87,10 +89,10 @@ public class ConfigurableWrapper implements SearchableConfigurable, Weighted { : null; } - private final ConfigurableEP myEp; + private final ConfigurableEP myEp; int myWeight; // see ConfigurableExtensionPointUtil.getConfigurableToReplace - private ConfigurableWrapper(@NotNull ConfigurableEP ep) { + private ConfigurableWrapper(@NotNull ConfigurableEP ep) { myEp = ep; myWeight = ep.groupWeight; } @@ -202,7 +204,7 @@ public class ConfigurableWrapper implements SearchableConfigurable, Weighted { } @NotNull - public ConfigurableEP getExtensionPoint() { + public ConfigurableEP getExtensionPoint() { return myEp; } @@ -249,53 +251,57 @@ public class ConfigurableWrapper implements SearchableConfigurable, Weighted { @NotNull @Override public Configurable[] getConfigurables() { - if (!isInitialized) { - long time = System.currentTimeMillis(); - ArrayList list = new ArrayList<>(); - if (super.myEp.dynamic) { - Composite composite = cast(Composite.class, this); - if (composite != null) { - Collections.addAll(list, composite.getConfigurables()); - } - } - if (super.myEp.children != null) { - for (ConfigurableEP ep : super.myEp.getChildren()) { - if (ep.isAvailable()) { - list.add((Configurable)wrapConfigurable(ep)); - } - } - } - if (super.myEp.childrenEPName != null) { - Object[] extensions = Extensions.getArea(super.myEp.getProject()).getExtensionPoint(super.myEp.childrenEPName).getExtensions(); - if (extensions.length > 0) { - if (extensions[0] instanceof ConfigurableEP) { - for (Object object : extensions) { - list.add((Configurable)wrapConfigurable((ConfigurableEP)object)); - } - } - else if (!super.myEp.dynamic) { - Composite composite = cast(Composite.class, this); - if (composite != null) { - Collections.addAll(list, composite.getConfigurables()); - } - } - } - } - Collections.addAll(list, myKids); - // sort configurables is needed - for (Configurable configurable : list) { - if (configurable instanceof Weighted) { - if (((Weighted)configurable).getWeight() != 0) { - myComparator = COMPARATOR; - Collections.sort(list, myComparator); - break; - } - } - } - myKids = list.toArray(new Configurable[0]); - isInitialized = true; - ConfigurableCardPanel.warn(this, "children", time); + if (isInitialized) { + return myKids; } + + long time = System.currentTimeMillis(); + ArrayList list = new ArrayList<>(); + if (super.myEp.dynamic) { + Composite composite = cast(Composite.class, this); + if (composite != null) { + Collections.addAll(list, composite.getConfigurables()); + } + } + if (super.myEp.children != null) { + for (ConfigurableEP ep : super.myEp.getChildren()) { + if (ep.isAvailable()) { + list.add((Configurable)wrapConfigurable(ep)); + } + } + } + if (super.myEp.childrenEPName != null) { + Project project = super.myEp.getProject(); + ExtensionsArea area = project == null ? ApplicationManager.getApplication().getExtensionArea() : project.getExtensionArea(); + List extensions = area.getExtensionPoint(super.myEp.childrenEPName).getExtensionList(); + if (!extensions.isEmpty()) { + if (extensions.get(0) instanceof ConfigurableEP) { + for (Object object : extensions) { + list.add((Configurable)wrapConfigurable((ConfigurableEP)object)); + } + } + else if (!super.myEp.dynamic) { + Composite composite = cast(Composite.class, this); + if (composite != null) { + Collections.addAll(list, composite.getConfigurables()); + } + } + } + } + Collections.addAll(list, myKids); + // sort configurables is needed + for (Configurable configurable : list) { + if (configurable instanceof Weighted) { + if (((Weighted)configurable).getWeight() != 0) { + myComparator = COMPARATOR; + Collections.sort(list, myComparator); + break; + } + } + } + myKids = list.toArray(new Configurable[0]); + isInitialized = true; + ConfigurableCardPanel.warn(this, "children", time); return myKids; } diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/DefaultProject.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/DefaultProject.java index c0dc86c23236..d2622fc2a7b6 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/DefaultProject.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/DefaultProject.java @@ -7,7 +7,7 @@ import com.intellij.openapi.components.BaseComponent; import com.intellij.openapi.components.ComponentConfig; import com.intellij.openapi.components.impl.stores.IComponentStore; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.extensions.ExtensionsArea; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ex.ProjectEx; @@ -35,18 +35,6 @@ final class DefaultProject extends UserDataHolderBase implements ProjectEx, Proj Project compute() { LOG.assertTrue(!ApplicationManager.getApplication().isDisposeInProgress(), "Application is being disposed!"); return new ProjectImpl() { - private MutablePicoContainer myPicoContainer; - @Override - protected MutablePicoContainer bootstrapPicoContainer(@NotNull String name) { - return null; - } - - @NotNull - @Override - public MutablePicoContainer getPicoContainer() { - return myPicoContainer; - } - @Override public boolean isDefault() { return true; @@ -73,7 +61,6 @@ final class DefaultProject extends UserDataHolderBase implements ProjectEx, Proj @Override public void init(@Nullable ProgressIndicator indicator) { - myPicoContainer = super.bootstrapPicoContainer(TEMPLATE_PROJECT_NAME); MutablePicoContainer picoContainer = getPicoContainer(); // do not leak internal delegate, use DefaultProject everywhere instead picoContainer.registerComponentInstance(Project.class, DefaultProject.this); @@ -213,6 +200,11 @@ final class DefaultProject extends UserDataHolderBase implements ProjectEx, Proj return getDelegate().getComponent(name); } + @Override + public T getService(@NotNull Class serviceClass, boolean isCreate) { + return getDelegate().getService(serviceClass, isCreate); + } + @Override public T getComponent(@NotNull Class interfaceClass) { return getDelegate().getComponent(interfaceClass); @@ -241,6 +233,12 @@ final class DefaultProject extends UserDataHolderBase implements ProjectEx, Proj return getDelegate().getPicoContainer(); } + @NotNull + @Override + public ExtensionsArea getExtensionArea() { + return getDelegate().getExtensionArea(); + } + @Override @NotNull public MessageBus getMessageBus() { @@ -252,13 +250,6 @@ final class DefaultProject extends UserDataHolderBase implements ProjectEx, Proj return ApplicationManager.getApplication().isDisposed(); } - @Override - @Deprecated - @NotNull - public T[] getExtensions(@NotNull ExtensionPointName extensionPointName) { - return getDelegate().getExtensions(extensionPointName); - } - @Override @NotNull public Condition getDisposed() { diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java index 0e4a74987f46..dc3e6668e3f4 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java @@ -13,17 +13,12 @@ import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.application.impl.LaterInvocator; -import com.intellij.openapi.components.ExtensionAreas; -import com.intellij.openapi.components.PathMacroManager; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.components.StorageScheme; import com.intellij.openapi.components.impl.PlatformComponentManagerImpl; -import com.intellij.openapi.components.impl.ProjectPathMacroManager; import com.intellij.openapi.components.impl.stores.IComponentStore; import com.intellij.openapi.components.impl.stores.IProjectStore; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.extensions.ExtensionPointName; -import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileEditor.impl.EditorsSplitters; import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl; @@ -47,7 +42,6 @@ import com.intellij.psi.impl.DebugUtil; import com.intellij.util.PathUtil; import com.intellij.util.TimedReference; import org.jetbrains.annotations.*; -import org.picocontainer.MutablePicoContainer; import javax.swing.*; import java.nio.file.Path; @@ -77,7 +71,7 @@ public class ProjectImpl extends PlatformComponentManagerImpl implements Project }); protected ProjectImpl(@NotNull Path filePath, @Nullable String projectName) { - super(ApplicationManager.getApplication(), "Project " + (projectName == null ? filePath.toString() : projectName)); + super(ApplicationManager.getApplication()); putUserData(CREATION_TIME, System.nanoTime()); creationTrace = ApplicationManager.getApplication().isUnitTestMode() ? DebugUtil.currentStackTrace() : null; @@ -93,7 +87,7 @@ public class ProjectImpl extends PlatformComponentManagerImpl implements Project static final String TEMPLATE_PROJECT_NAME = "Default (Template) Project"; // default project constructor ProjectImpl() { - super(ApplicationManager.getApplication(), TEMPLATE_PROJECT_NAME); + super(ApplicationManager.getApplication()); putUserData(CREATION_TIME, System.nanoTime()); if (ApplicationManager.getApplication().isUnitTestMode()) { @@ -144,14 +138,6 @@ public class ProjectImpl extends PlatformComponentManagerImpl implements Project } } - @Override - protected MutablePicoContainer bootstrapPicoContainer(@NotNull String name) { - Extensions.instantiateArea(ExtensionAreas.IDEA_PROJECT, this, null); - MutablePicoContainer container = super.bootstrapPicoContainer(name); - container.registerComponentImplementation(PathMacroManager.class, ProjectPathMacroManager.class); - return container; - } - // do not call for default project @NotNull public final IProjectStore getStateStore() { @@ -323,7 +309,6 @@ public class ProjectImpl extends PlatformComponentManagerImpl implements Project // we use super here, because temporarilyDisposed will be true if project closed LOG.assertTrue(!super.isDisposed(), this + " is disposed already"); disposeComponents(); - Extensions.disposeArea(this); super.dispose(); @@ -336,18 +321,6 @@ public class ProjectImpl extends PlatformComponentManagerImpl implements Project LaterInvocator.purgeExpiredItems(); } - @NotNull - @Override - public T[] getExtensions(@NotNull final ExtensionPointName extensionPointName) { - return Extensions.getArea(this).getExtensionPoint(extensionPointName).getExtensions(); - } - - @NotNull - @Override - protected MutablePicoContainer createPicoContainer() { - return Extensions.getArea(this).getPicoContainer(); - } - @Override public boolean isDefault() { return false; diff --git a/platform/platform-impl/src/com/intellij/serviceContainer/ServiceContainer.kt b/platform/platform-impl/src/com/intellij/serviceContainer/ServiceContainer.kt new file mode 100644 index 000000000000..79b3a7c0b335 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/serviceContainer/ServiceContainer.kt @@ -0,0 +1,90 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.serviceContainer + +import com.intellij.diagnostic.LoadingPhase +import com.intellij.diagnostic.ParallelActivity +import com.intellij.diagnostic.StartUpMeasurer +import com.intellij.diagnostic.StartUpMeasurer.Level +import com.intellij.openapi.Disposable +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.components.ComponentManager +import com.intellij.openapi.components.Service +import com.intellij.openapi.components.ServiceManager +import com.intellij.openapi.diagnostic.logger +import com.intellij.openapi.progress.ProgressIndicatorProvider +import com.intellij.openapi.progress.ProgressManager +import com.intellij.openapi.util.Disposer +import com.intellij.util.ReflectionUtil +import com.intellij.util.containers.ContainerUtil +import com.intellij.util.io.storage.HeavyProcessLatch +import com.intellij.util.pico.DefaultPicoContainer +import org.picocontainer.PicoContainer +import java.lang.reflect.Modifier +import java.util.concurrent.ConcurrentMap + +private val LOG = logger() + +// used only for Application for now +internal class ServiceContainer(parent: PicoContainer?) : DefaultPicoContainer(parent) { + private val lightServices: ConcurrentMap, Any>? = if (parent == null) ContainerUtil.newConcurrentMap() else null + + override fun getService(serviceClass: Class, isCreate: Boolean): T? { + val lightServices = lightServices + if (lightServices == null || !isLightService(serviceClass)) { + return super.getService(serviceClass, isCreate) + } + else { + @Suppress("UNCHECKED_CAST") + val result = lightServices.get(serviceClass) as T? + if (result != null || !isCreate) { + return result + } + else { + synchronized(serviceClass) { + return getOrCreateLightService(serviceClass, lightServices) + } + } + } + } +} + +private fun getOrCreateLightService(serviceClass: Class, cache: ConcurrentMap, Any>): T { + LoadingPhase.COMPONENT_REGISTERED.assertAtLeast() + + @Suppress("UNCHECKED_CAST") + var instance = cache.get(serviceClass) as T? + if (instance != null) { + return instance + } + + val componentManager = ApplicationManager.getApplication() + HeavyProcessLatch.INSTANCE.processStarted("Creating service '${serviceClass.name}'").use { + if (ProgressIndicatorProvider.getGlobalProgressIndicator() == null) { + instance = createLightService(serviceClass, componentManager) + } + else { + ProgressManager.getInstance().executeNonCancelableSection { + instance = createLightService(serviceClass, componentManager) + } + } + } + + val prevValue = cache.put(serviceClass, instance) + LOG.assertTrue(prevValue == null) + return instance!! +} + +private fun createLightService(serviceClass: Class, componentManager: ComponentManager): T { + val startTime = StartUpMeasurer.getCurrentTime() + val instance = ReflectionUtil.newInstance(serviceClass, false) + if (instance is Disposable) { + Disposer.register(componentManager, instance as Disposable) + } + componentManager.initializeComponent(instance, null) + ParallelActivity.SERVICE.record(startTime, instance.javaClass, Level.APPLICATION) + return instance +} + +private fun isLightService(serviceClass: Class): Boolean { + return Modifier.isFinal(serviceClass.modifiers) && serviceClass.isAnnotationPresent(Service::class.java) +} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/ui/PathChooserDialogHelper.kt b/platform/platform-impl/src/com/intellij/ui/PathChooserDialogHelper.kt index da03739d63c1..210da38239cd 100644 --- a/platform/platform-impl/src/com/intellij/ui/PathChooserDialogHelper.kt +++ b/platform/platform-impl/src/com/intellij/ui/PathChooserDialogHelper.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.ui import com.intellij.core.CoreFileTypeRegistry @@ -7,7 +7,6 @@ import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.fileChooser.FileChooserDescriptor import com.intellij.openapi.fileChooser.impl.FileChooserUtil import com.intellij.openapi.fileTypes.FileTypeRegistry -import com.intellij.openapi.fileTypes.FileTypes import com.intellij.openapi.util.Getter import com.intellij.openapi.util.io.FileUtilRt import com.intellij.openapi.vfs.LocalFileSystem diff --git a/platform/platform-impl/src/com/intellij/ui/docking/impl/DockManagerImpl.java b/platform/platform-impl/src/com/intellij/ui/docking/impl/DockManagerImpl.java index da14c3cab32c..44c0e1e24d7a 100644 --- a/platform/platform-impl/src/com/intellij/ui/docking/impl/DockManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/ui/docking/impl/DockManagerImpl.java @@ -11,7 +11,6 @@ import com.intellij.openapi.components.PersistentStateComponent; import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; import com.intellij.openapi.components.StoragePathMacros; -import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileEditor.FileEditor; import com.intellij.openapi.fileEditor.FileEditorProvider; import com.intellij.openapi.fileEditor.impl.*; @@ -474,10 +473,8 @@ public final class DockManagerImpl extends DockManager implements PersistentStat && !(myContainer instanceof DockContainer.Dialog) && !UISettings.getInstance().getPresentationMode()); - IdeRootPaneNorthExtension[] extensions = - Extensions.getArea(myProject).getExtensionPoint(IdeRootPaneNorthExtension.EP_NAME).getExtensions(); - HashSet processedKeys = new HashSet<>(); - for (IdeRootPaneNorthExtension each : extensions) { + Set processedKeys = new HashSet<>(); + for (IdeRootPaneNorthExtension each : IdeRootPaneNorthExtension.EP_NAME.getExtensionList(myProject)) { processedKeys.add(each.getKey()); if (myNorthExtensions.containsKey(each.getKey())) continue; IdeRootPaneNorthExtension toInstall = each.copy(); diff --git a/platform/platform-impl/src/com/intellij/ui/win/RecentProjectApplication.java b/platform/platform-impl/src/com/intellij/ui/win/RecentProjectApplication.java index b8aace7be611..abdafc076f4e 100644 --- a/platform/platform-impl/src/com/intellij/ui/win/RecentProjectApplication.java +++ b/platform/platform-impl/src/com/intellij/ui/win/RecentProjectApplication.java @@ -7,13 +7,11 @@ import com.intellij.openapi.application.ApplicationStarterBase; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.List; import java.util.concurrent.Future; -/** - * @author Denis Fokin - */ -public final class RecentProjectApplication extends ApplicationStarterBase { - public RecentProjectApplication() { +final class RecentProjectApplication extends ApplicationStarterBase { + RecentProjectApplication() { super("reopen", 1); } @@ -24,8 +22,8 @@ public final class RecentProjectApplication extends ApplicationStarterBase { @NotNull @Override - protected Future processCommand(@NotNull String[] args, @Nullable String currentDirectory) { - ProjectUtil.openProject(args[1], null, false); + protected Future processCommand(@NotNull List args, @Nullable String currentDirectory) { + ProjectUtil.openProject(args.get(1), null, false); return CliResult.ok(); } } \ No newline at end of file diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index 981e839283b7..ebcafededf5b 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -183,7 +183,6 @@ - + + diff --git a/platform/platform-tests/testSrc/com/intellij/ide/ui/TopHitProvidersTest.java b/platform/platform-tests/testSrc/com/intellij/ide/ui/TopHitProvidersTest.java index 5de1b7507b7d..de643344a5f8 100644 --- a/platform/platform-tests/testSrc/com/intellij/ide/ui/TopHitProvidersTest.java +++ b/platform/platform-tests/testSrc/com/intellij/ide/ui/TopHitProvidersTest.java @@ -1,27 +1,17 @@ -/* - * Copyright 2000-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.ide.ui; import com.intellij.ide.SearchTopHitProvider; import com.intellij.ide.ui.search.BooleanOptionDescription; import com.intellij.ide.ui.search.NotABooleanOptionDescription; import com.intellij.ide.ui.search.OptionDescription; -import com.intellij.testFramework.LightPlatformTestCase; +import com.intellij.testFramework.EdtRule; +import com.intellij.testFramework.ProjectRule; +import com.intellij.testFramework.RunsInEdt; import one.util.streamex.StreamEx; import org.jetbrains.annotations.NotNull; +import org.junit.Rule; +import org.junit.Test; import java.util.ArrayList; import java.util.Collection; @@ -30,10 +20,16 @@ import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; -/** - * @author Konstantin Bulenkov - */ -public class TopHitProvidersTest extends LightPlatformTestCase { +import static com.intellij.testFramework.assertions.Assertions.assertThat; + +@RunsInEdt +public class TopHitProvidersTest { + @Rule + public final ProjectRule projectRule = new ProjectRule(); + @Rule + public final EdtRule edtRule = new EdtRule(); + + @Test public void testUiSettings() { List errors = new ArrayList<>(); @@ -61,7 +57,7 @@ public class TopHitProvidersTest extends LightPlatformTestCase { } } - assertEmpty(errors); + assertThat(errors).isEmpty(); } private static List getProviders() { @@ -72,13 +68,13 @@ public class TopHitProvidersTest extends LightPlatformTestCase { private Collection getOptions(@NotNull OptionsSearchTopHitProvider provider) { if (provider instanceof OptionsSearchTopHitProvider.ProjectLevelProvider) { - return ((OptionsSearchTopHitProvider.ProjectLevelProvider)provider).getOptions(getProject()); + return ((OptionsSearchTopHitProvider.ProjectLevelProvider)provider).getOptions(projectRule.getProject()); } else if (provider instanceof OptionsSearchTopHitProvider.ApplicationLevelProvider) { return ((OptionsSearchTopHitProvider.ApplicationLevelProvider)provider).getOptions(); } else if (provider instanceof OptionsTopHitProvider) { - return ((OptionsTopHitProvider)provider).getOptions(getProject()); + return ((OptionsTopHitProvider)provider).getOptions(projectRule.getProject()); } return Collections.emptyList(); } diff --git a/platform/platform-tests/testSrc/com/intellij/lang/LanguageExtensionCacheTest.kt b/platform/platform-tests/testSrc/com/intellij/lang/LanguageExtensionCacheTest.kt index 94104d312e9d..92a2b8ea5e4c 100644 --- a/platform/platform-tests/testSrc/com/intellij/lang/LanguageExtensionCacheTest.kt +++ b/platform/platform-tests/testSrc/com/intellij/lang/LanguageExtensionCacheTest.kt @@ -2,17 +2,17 @@ package com.intellij.lang import com.intellij.openapi.Disposable +import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.extensions.DefaultPluginDescriptor -import com.intellij.openapi.extensions.Extensions import com.intellij.openapi.extensions.ExtensionsArea import com.intellij.openapi.extensions.PluginId import com.intellij.openapi.fileTypes.PlainTextLanguage import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.JDOMUtil import com.intellij.testFramework.LightPlatformTestCase +import org.picocontainer.MutablePicoContainer class LanguageExtensionCacheTest : LightPlatformTestCase() { - private val myExtensionPointName = "testLangExt" private val myExtensionPointXML = """ @@ -26,8 +26,8 @@ class LanguageExtensionCacheTest : LightPlatformTestCase() { override fun setUp() { super.setUp() - myArea = Extensions.getRootArea() - myArea.registerExtensionPoint(myDescriptor, JDOMUtil.load(myExtensionPointXML)) + myArea = ApplicationManager.getApplication().extensionArea + myArea.registerExtensionPoint(myDescriptor, JDOMUtil.load(myExtensionPointXML), ApplicationManager.getApplication ().picoContainer as MutablePicoContainer) Disposer.register(testRootDisposable, Disposable { myArea.unregisterExtensionPoint(myExtensionPointName) }) diff --git a/platform/platform-tests/testSrc/com/intellij/lang/LanguageExtensionOrderTest.groovy b/platform/platform-tests/testSrc/com/intellij/lang/LanguageExtensionOrderTest.groovy index d0232ddce42e..bdd71b5e8377 100644 --- a/platform/platform-tests/testSrc/com/intellij/lang/LanguageExtensionOrderTest.groovy +++ b/platform/platform-tests/testSrc/com/intellij/lang/LanguageExtensionOrderTest.groovy @@ -1,12 +1,17 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.lang -import com.intellij.openapi.extensions.* +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.extensions.DefaultPluginDescriptor +import com.intellij.openapi.extensions.ExtensionsArea +import com.intellij.openapi.extensions.PluginDescriptor +import com.intellij.openapi.extensions.PluginId import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.JDOMUtil import com.intellij.testFramework.LightPlatformTestCase import com.intellij.testFramework.PlatformTestUtil import groovy.transform.CompileStatic +import org.picocontainer.MutablePicoContainer @CompileStatic class LanguageExtensionOrderTest extends LightPlatformTestCase { @@ -16,7 +21,7 @@ class LanguageExtensionOrderTest extends LightPlatformTestCase { void setUp() { super.setUp() - myArea = Extensions.rootArea + myArea = ApplicationManager.getApplication().getExtensionArea() myLanguageExtension = new LanguageExtension("langExt") registerMetaLanguage() registerLanguageEP() @@ -27,11 +32,11 @@ class LanguageExtensionOrderTest extends LightPlatformTestCase { } private void registerLanguageEP() { - myArea.registerExtensionPoint myDescriptor, JDOMUtil.load('''\ + myArea.registerExtensionPoint(myDescriptor, JDOMUtil.load('''\ -''') +'''), (MutablePicoContainer)ApplicationManager.getApplication().picoContainer) Disposer.register(testRootDisposable) { myArea.unregisterExtensionPoint("langExt") } diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/components/impl/PathMacroManagerTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/components/impl/PathMacroManagerTest.java index 280106a6ae56..9679cb31f523 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/components/impl/PathMacroManagerTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/components/impl/PathMacroManagerTest.java @@ -4,16 +4,13 @@ package com.intellij.openapi.components.impl; import com.intellij.application.options.PathMacrosCollector; import com.intellij.application.options.PathMacrosImpl; import com.intellij.application.options.ReplacePathToMacroMap; +import com.intellij.mock.MockApplication; import com.intellij.openapi.Disposable; -import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.application.PathMacroFilter; -import com.intellij.openapi.application.PathMacros; import com.intellij.openapi.application.PathManager; -import com.intellij.openapi.application.ex.ApplicationEx; import com.intellij.openapi.extensions.ExtensionPoint; import com.intellij.openapi.extensions.ExtensionPointName; -import com.intellij.openapi.extensions.Extensions; -import com.intellij.openapi.extensions.ExtensionsArea; +import com.intellij.openapi.extensions.impl.ExtensionsAreaImpl; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.ex.ProjectEx; import com.intellij.openapi.util.Disposer; @@ -21,12 +18,8 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.SystemProperties; -import org.hamcrest.Description; -import org.jetbrains.annotations.Nullable; import org.jmock.Expectations; import org.jmock.Mockery; -import org.jmock.api.Action; -import org.jmock.api.Invocation; import org.jmock.integration.junit4.JMock; import org.jmock.integration.junit4.JUnit4Mockery; import org.jmock.lib.legacy.ClassImposteriser; @@ -37,9 +30,6 @@ import org.junit.runner.RunWith; import static org.junit.Assert.assertEquals; -/** - * @author mike - */ @RunWith(JMock.class) public class PathMacroManagerTest { private static final String APP_HOME = FileUtil.toSystemIndependentName(PathManager.getHomePath()); @@ -50,41 +40,16 @@ public class PathMacroManagerTest { private PathMacrosImpl myPathMacros; private Mockery context; - protected ApplicationEx myApplication; + protected MockApplication myApplication; private final Disposable myRootDisposable = Disposer.newDisposable(); @Before public final void setupApplication() { context = new JUnit4Mockery(); context.setImposteriser(ClassImposteriser.INSTANCE); - myApplication = context.mock(ApplicationEx.class, "application"); + myApplication = MockApplication.setUp(myRootDisposable); - context.checking(new Expectations() { - { - allowing(myApplication).isUnitTestMode(); will(returnValue(false)); - allowing(myApplication).getName(); will(returnValue("IDEA")); - - // some tests leave invokeLater()'s after them - allowing(myApplication).invokeLater(with(any(Runnable.class)), with(any(ModalityState.class))); - - allowing(myApplication).runReadAction(with(any(Runnable.class))); - will(new Action() { - @Override - public void describeTo(final Description description) { - description.appendText("runs runnable"); - } - - @Override - @Nullable - public Object invoke(final Invocation invocation) { - ((Runnable)invocation.getParameter(0)).run(); - return null; - } - }); - } - }); - - final ExtensionsArea area = Extensions.getRootArea(); + ExtensionsAreaImpl area = myApplication.getExtensionArea(); final ExtensionPointName epName = PathMacrosCollector.MACRO_FILTER_EXTENSION_POINT_NAME; if (!area.hasExtensionPoint(epName)) { area.registerExtensionPoint(epName, "com.intellij.openapi.application.PathMacroFilter", ExtensionPoint.Kind.INTERFACE, myRootDisposable); @@ -111,7 +76,6 @@ public class PathMacroManagerTest { final String moduleFilePath = projectPath + "/module/module.iml"; - allowing(myApplication).getComponent(with(equal(PathMacros.class))); will(returnValue(myPathMacros)); allowing(myPathMacros).addMacroReplacements(with(any(ReplacePathToMacroMap.class))); allowing(myPathMacros).getModificationCount(); diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/NonProjectFileAccessTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/NonProjectFileAccessTest.java index da6e4fcb4c7f..8c9e525b9478 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/NonProjectFileAccessTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/NonProjectFileAccessTest.java @@ -11,7 +11,6 @@ import com.intellij.openapi.components.impl.ComponentManagerImpl; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.actionSystem.EditorActionManager; import com.intellij.openapi.editor.actionSystem.TypedAction; -import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx; import com.intellij.openapi.fileEditor.impl.NonProjectFileWritingAccessExtension; import com.intellij.openapi.fileEditor.impl.NonProjectFileWritingAccessProvider; @@ -318,7 +317,7 @@ public class NonProjectFileAccessTest extends HeavyFileEditorManagerTestCase { private Set registerWriteAccessProvider(final VirtualFile... filesToDeny) { final Set requested = new LinkedHashSet<>(); - PlatformTestUtil.registerExtension(Extensions.getArea(getProject()), WritingAccessProvider.EP_NAME, new WritingAccessProvider() { + PlatformTestUtil.registerExtension(getProject().getExtensionArea(), WritingAccessProvider.EP_NAME, new WritingAccessProvider() { @NotNull @Override public Collection requestWriting(@NotNull Collection files) { @@ -332,7 +331,7 @@ public class NonProjectFileAccessTest extends HeavyFileEditorManagerTestCase { } private void registerAccessCheckExtension(Collection filesToAllow, Collection filesToDeny) { - PlatformTestUtil.registerExtension(Extensions.getArea(getProject()), NonProjectFileWritingAccessExtension.EP_NAME, + PlatformTestUtil.registerExtension(getProject().getExtensionArea(), NonProjectFileWritingAccessExtension.EP_NAME, new NonProjectFileWritingAccessExtension() { @Override public boolean isWritable(@NotNull VirtualFile file) { diff --git a/platform/platform-tests/testSrc/com/intellij/usages/impl/UsageViewTest.java b/platform/platform-tests/testSrc/com/intellij/usages/impl/UsageViewTest.java index 228350119455..191fb34bc169 100644 --- a/platform/platform-tests/testSrc/com/intellij/usages/impl/UsageViewTest.java +++ b/platform/platform-tests/testSrc/com/intellij/usages/impl/UsageViewTest.java @@ -1,4 +1,4 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.usages.impl; import com.intellij.find.FindManager; @@ -15,6 +15,7 @@ import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.command.impl.UndoManagerImpl; import com.intellij.openapi.command.undo.UndoManager; import com.intellij.openapi.editor.Document; +import com.intellij.openapi.extensions.impl.ExtensionsAreaImpl; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.fileTypes.BinaryFileDecompiler; import com.intellij.openapi.fileTypes.BinaryFileTypeDecompilers; @@ -30,9 +31,10 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiNamedElement; import com.intellij.psi.impl.source.PsiFileImpl; +import com.intellij.testFramework.ExtensionTestUtil; +import com.intellij.testFramework.HeavyPlatformTestCase; import com.intellij.testFramework.LeakHunter; import com.intellij.testFramework.LightPlatformTestCase; -import com.intellij.testFramework.HeavyPlatformTestCase; import com.intellij.testFramework.fixtures.BasePlatformTestCase; import com.intellij.usageView.UsageInfo; import com.intellij.usages.*; @@ -303,7 +305,9 @@ public class UsageViewTest extends BasePlatformTestCase { BinaryFileDecompiler decompiler = file -> { throw new IllegalStateException("oh no"); }; - BinaryFileTypeDecompilers.INSTANCE.addExplicitExtension(ArchiveFileType.INSTANCE, decompiler, getTestRootDisposable()); + + ExtensionTestUtil.addExtension((ExtensionsAreaImpl)ApplicationManager.getApplication().getExtensionArea(), + BinaryFileTypeDecompilers.INSTANCE, ArchiveFileType.INSTANCE.getName(), decompiler); PsiFile psiFile = myFixture.addFileToProject("X.jar", "xxx"); assertEquals(ArchiveFileType.INSTANCE, psiFile.getFileType()); diff --git a/platform/projectModel-impl/src/com/intellij/core/CoreModule.java b/platform/projectModel-impl/src/com/intellij/core/CoreModule.java index 6c8a37a6149d..996bed8c10e9 100644 --- a/platform/projectModel-impl/src/com/intellij/core/CoreModule.java +++ b/platform/projectModel-impl/src/com/intellij/core/CoreModule.java @@ -4,12 +4,9 @@ package com.intellij.core; import com.intellij.ide.highlighter.ModuleFileType; import com.intellij.mock.MockComponentManager; import com.intellij.openapi.Disposable; -import com.intellij.openapi.application.PathMacros; -import com.intellij.openapi.components.ExtensionAreas; import com.intellij.openapi.components.PathMacroManager; import com.intellij.openapi.components.impl.ModulePathMacroManager; import com.intellij.openapi.extensions.ExtensionPointName; -import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.module.impl.ModuleEx; import com.intellij.openapi.module.impl.ModuleScopeProvider; import com.intellij.openapi.project.Project; @@ -43,13 +40,6 @@ public class CoreModule extends MockComponentManager implements ModuleEx { myProject = project; myPath = moduleFilePath; - Extensions.instantiateArea(ExtensionAreas.IDEA_MODULE, this, null); - Disposer.register(parentDisposable, new Disposable() { - @Override - public void dispose() { - Extensions.disposeArea(CoreModule.this); - } - }); initModuleExtensions(); final ModuleRootManagerImpl moduleRootManager = @@ -82,7 +72,7 @@ public class CoreModule extends MockComponentManager implements ModuleEx { // used by Upsource protected PathMacroManager createModulePathMacroManager(@SuppressWarnings("unused") @NotNull Project project) { - return new ModulePathMacroManager(PathMacros.getInstance(), this); + return new ModulePathMacroManager(this); } protected ModuleFileIndex createModuleFileIndex(@NotNull Project project) { diff --git a/platform/projectModel-impl/src/com/intellij/openapi/components/PathMacroManager.java b/platform/projectModel-impl/src/com/intellij/openapi/components/PathMacroManager.java index 12d5392ec39e..57572d6ab4d4 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/components/PathMacroManager.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/components/PathMacroManager.java @@ -1,4 +1,4 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.components; import com.intellij.application.options.PathMacrosCollector; @@ -18,11 +18,12 @@ import org.jetbrains.annotations.SystemIndependent; import org.jetbrains.jps.model.serialization.PathMacroUtil; import java.util.Map; +import java.util.Objects; public class PathMacroManager implements PathMacroSubstitutor { @NotNull public static PathMacroManager getInstance(@NotNull ComponentManager componentManager) { - return (PathMacroManager)componentManager.getPicoContainer().getComponentInstance(PathMacroManager.class); + return Objects.requireNonNull(componentManager.getService(PathMacroManager.class, true)); } private static class Holder { diff --git a/platform/projectModel-impl/src/com/intellij/openapi/components/impl/ModulePathMacroManager.java b/platform/projectModel-impl/src/com/intellij/openapi/components/impl/ModulePathMacroManager.java index 0c38e6d498f0..38d3e95d6796 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/components/impl/ModulePathMacroManager.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/components/impl/ModulePathMacroManager.java @@ -1,4 +1,4 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.components.impl; import com.intellij.application.options.ReplacePathToMacroMap; @@ -7,11 +7,18 @@ import com.intellij.openapi.components.ExpandMacroToPathMap; import com.intellij.openapi.components.PathMacroManager; import com.intellij.openapi.module.Module; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.TestOnly; import org.jetbrains.jps.model.serialization.PathMacroUtil; public class ModulePathMacroManager extends PathMacroManager { private final Module myModule; + public ModulePathMacroManager(@NotNull Module module) { + super(PathMacros.getInstance()); + myModule = module; + } + + @TestOnly public ModulePathMacroManager(@NotNull PathMacros pathMacros, @NotNull Module module) { super(pathMacros); diff --git a/platform/projectModel-impl/src/com/intellij/openapi/components/impl/ProjectPathMacroManager.java b/platform/projectModel-impl/src/com/intellij/openapi/components/impl/ProjectPathMacroManager.java index 5330e6159634..ff4788240d82 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/components/impl/ProjectPathMacroManager.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/components/impl/ProjectPathMacroManager.java @@ -1,4 +1,4 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.components.impl; import com.intellij.application.options.ReplacePathToMacroMap; @@ -7,12 +7,20 @@ import com.intellij.openapi.components.ExpandMacroToPathMap; import com.intellij.openapi.components.PathMacroManager; import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.TestOnly; import org.jetbrains.jps.model.serialization.PathMacroUtil; -public class ProjectPathMacroManager extends PathMacroManager { +public final class ProjectPathMacroManager extends PathMacroManager { private final Project myProject; - public ProjectPathMacroManager(PathMacros pathMacros, Project project) { + @SuppressWarnings("unused") + public ProjectPathMacroManager(@NotNull Project project) { + super(PathMacros.getInstance()); + myProject = project; + } + + @TestOnly + public ProjectPathMacroManager(@NotNull PathMacros pathMacros, @NotNull Project project) { super(pathMacros); myProject = project; } diff --git a/platform/testFramework/src/com/intellij/idea/IdeaTestApplication.java b/platform/testFramework/src/com/intellij/idea/IdeaTestApplication.java index 3854db457660..2fcc8a704bd3 100644 --- a/platform/testFramework/src/com/intellij/idea/IdeaTestApplication.java +++ b/platform/testFramework/src/com/intellij/idea/IdeaTestApplication.java @@ -11,7 +11,6 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.DataProvider; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.application.impl.ApplicationImpl; import com.intellij.openapi.util.Disposer; import com.intellij.testFramework.HeavyPlatformTestCase; @@ -94,10 +93,10 @@ public final class IdeaTestApplication implements Disposable { }, AppExecutorUtil.getAppExecutorService()); ApplicationImpl.patchSystem(); - ApplicationImpl app = new ApplicationImpl(true, true, true, true, ApplicationManagerEx.IDEA_APPLICATION); + ApplicationImpl app = new ApplicationImpl(true, true, true, true); IconManager.activate(); try { - ApplicationLoader.registerRegistryAndContainerAndInitStore(loadedPluginFuture, app, null) + ApplicationLoader.registerRegistryAndInitStore(loadedPluginFuture.thenAccept(it -> app.registerComponents(it)), app) .thenCompose(aVoid -> ApplicationLoader.preloadServices(app)) .get(20, TimeUnit.SECONDS); } diff --git a/platform/testFramework/src/com/intellij/psi/codeStyle/arrangement/AbstractRearrangerTest.java b/platform/testFramework/src/com/intellij/psi/codeStyle/arrangement/AbstractRearrangerTest.java index 94d0bda0dfb1..9d6d0d83d3a6 100644 --- a/platform/testFramework/src/com/intellij/psi/codeStyle/arrangement/AbstractRearrangerTest.java +++ b/platform/testFramework/src/com/intellij/psi/codeStyle/arrangement/AbstractRearrangerTest.java @@ -4,7 +4,6 @@ package com.intellij.psi.codeStyle.arrangement; import com.intellij.application.options.CodeStyle; import com.intellij.lang.Language; import com.intellij.openapi.command.CommandProcessor; -import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.editor.FoldRegion; import com.intellij.openapi.editor.FoldingModel; import com.intellij.openapi.fileTypes.FileType; @@ -131,9 +130,9 @@ public abstract class AbstractRearrangerTest extends BasePlatformTestCase { @SuppressWarnings("unchecked") List aliases = ObjectUtils.coalesce((List)args.get("aliases"), Collections.emptyList()); - + final StdArrangementSettings arrangementSettings = new StdArrangementExtendableSettings(groupingRules, sectionRules, aliases); - + String text = (String)args.get("initial"); String expected = (String)args.get("expected"); @SuppressWarnings("unchecked") List ranges = (List)args.get("ranges"); @@ -143,7 +142,7 @@ public abstract class AbstractRearrangerTest extends BasePlatformTestCase { protected void doTestWithSettings(@NotNull String text, @NotNull String expected, - @Nullable ArrangementSettings arrangementSettings, + @Nullable ArrangementSettings arrangementSettings, @Nullable List ranges) { Info info = parse(text); if (!isEmpty(ranges) && !isEmpty(info.ranges)) { @@ -167,7 +166,7 @@ public abstract class AbstractRearrangerTest extends BasePlatformTestCase { CommonCodeStyleSettings settings = CodeStyle.getSettings(myFixture.getProject()).getCommonSettings(language); settings.setArrangementSettings(arrangementSettings); } - ArrangementEngine engine = ServiceManager.getService(myFixture.getProject(), ArrangementEngine.class); + ArrangementEngine engine = ArrangementEngine.getInstance(); CommandProcessor.getInstance().executeCommand(getProject(), ()-> engine.arrange(myFixture.getEditor(), myFixture.getFile(), info.ranges), null, null); diff --git a/platform/testFramework/src/com/intellij/testFramework/ExtensionTestUtil.kt b/platform/testFramework/src/com/intellij/testFramework/ExtensionTestUtil.kt new file mode 100644 index 000000000000..41d4e697a0c8 --- /dev/null +++ b/platform/testFramework/src/com/intellij/testFramework/ExtensionTestUtil.kt @@ -0,0 +1,37 @@ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.testFramework + +import com.intellij.lang.Language +import com.intellij.lang.LanguageExtension +import com.intellij.mock.MockApplication +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.extensions.impl.ExtensionPointImpl +import com.intellij.openapi.extensions.impl.ExtensionsAreaImpl +import com.intellij.openapi.util.KeyedExtensionCollector +import com.intellij.util.KeyedLazyInstance +import java.util.function.Predicate + +object ExtensionTestUtil { + @JvmStatic + fun addExtension(area: ExtensionsAreaImpl, collector: LanguageExtension, language: Language, instance: T) { + addExtension(area, collector, language.id, instance) + } + + @JvmStatic + fun addExtension(area: ExtensionsAreaImpl, collector: KeyedExtensionCollector, key: String, instance: T) { + val point = area.getExtensionPoint>(collector.name) + + if (ApplicationManager.getApplication() !is MockApplication) { + // if not MockApplication, it means that extension point is not registered as fake bean + ExtensionPointImpl.setTestTypeChecker(Predicate { KeyedLazyInstance::class.java.isAssignableFrom(it) }, ApplicationManager.getApplication()) + } + + @Suppress("DEPRECATION") + point.registerExtension(object : KeyedLazyInstance { + override fun getKey() = key + + override fun getInstance() = instance + }) + collector.clearCache() + } +} \ No newline at end of file diff --git a/platform/testFramework/src/com/intellij/testFramework/ParsingTestCase.java b/platform/testFramework/src/com/intellij/testFramework/ParsingTestCase.java index af71101314d6..c1eba609c90a 100644 --- a/platform/testFramework/src/com/intellij/testFramework/ParsingTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/ParsingTestCase.java @@ -9,8 +9,12 @@ import com.intellij.lang.injection.MultiHostInjector; import com.intellij.mock.*; import com.intellij.openapi.application.ex.PathManagerEx; import com.intellij.openapi.editor.EditorFactory; +import com.intellij.openapi.extensions.DefaultPluginDescriptor; +import com.intellij.openapi.extensions.ExtensionPoint; import com.intellij.openapi.extensions.ExtensionPointName; -import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.extensions.PluginDescriptor; +import com.intellij.openapi.extensions.impl.ExtensionPointImpl; +import com.intellij.openapi.extensions.impl.ExtensionsAreaImpl; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl; import com.intellij.openapi.fileEditor.impl.LoadTextUtil; @@ -21,7 +25,6 @@ import com.intellij.openapi.progress.EmptyProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.impl.ProgressManagerImpl; import com.intellij.openapi.startup.StartupManager; -import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.LineColumn; @@ -37,24 +40,25 @@ import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry import com.intellij.psi.impl.source.tree.injected.InjectedLanguageManagerImpl; import com.intellij.psi.util.CachedValuesManager; import com.intellij.util.CachedValuesManagerImpl; +import com.intellij.util.KeyedLazyInstance; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.messages.MessageBus; import org.jetbrains.annotations.NotNull; -import org.picocontainer.*; -import org.picocontainer.defaults.AbstractComponentAdapter; +import org.picocontainer.ComponentAdapter; +import org.picocontainer.MutablePicoContainer; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.Set; - -import static java.util.Objects.requireNonNull; +import java.util.*; /** @noinspection JUnitTestCaseWithNonTrivialConstructors*/ -public abstract class ParsingTestCase extends PlatformLiteFixture { +public abstract class ParsingTestCase extends UsefulTestCase { + private PluginDescriptor myPluginDescriptor; + + private MockApplication myApp; + protected MockProjectEx myProject; + protected String myFilePrefix = ""; protected String myFileExt; protected final String myFullDataPath; @@ -64,6 +68,7 @@ public abstract class ParsingTestCase extends PlatformLiteFixture { protected Language myLanguage; private final ParserDefinition[] myDefinitions; private final boolean myLowercaseFirstLetter; + private ExtensionPointImpl> myLangParserDefinition; protected ParsingTestCase(@NotNull String dataPath, @NotNull String fileExt, @NotNull ParserDefinition... definitions) { this(dataPath, fileExt, false, definitions); @@ -76,49 +81,52 @@ public abstract class ParsingTestCase extends PlatformLiteFixture { myLowercaseFirstLetter = lowercaseFirstLetter; } + @NotNull + protected MockApplication getApplication() { + return myApp; + } + @Override protected void setUp() throws Exception { super.setUp(); - initApplication(); - ComponentAdapter component = getApplication().getPicoContainer().getComponentAdapter(ProgressManager.class.getName()); - if (component == null) { - getApplication().getPicoContainer().registerComponent(new AbstractComponentAdapter(ProgressManager.class.getName(), Object.class) { - @Override - public Object getComponentInstance(PicoContainer container) throws PicoInitializationException, PicoIntrospectionException { - return new ProgressManagerImpl(); - } - @Override - public void verify(PicoContainer container) throws PicoIntrospectionException { } - }); + MockApplication app = MockApplication.setUp(getTestRootDisposable()); + myApp = app; + MutablePicoContainer appContainer = app.getPicoContainer(); + ComponentAdapter component = appContainer.getComponentAdapter(ProgressManager.class.getName()); + if (component == null) { + appContainer.registerComponentInstance(ProgressManager.class.getName(), new ProgressManagerImpl()); } - Extensions.registerAreaClass("IDEA_PROJECT", null); + myProject = new MockProjectEx(getTestRootDisposable()); myPsiManager = new MockPsiManager(myProject); myFileFactory = new PsiFileFactoryImpl(myPsiManager); - MutablePicoContainer appContainer = getApplication().getPicoContainer(); - registerComponentInstance(appContainer, MessageBus.class, getApplication().getMessageBus()); - registerComponentInstance(appContainer, SchemeManagerFactory.class, new MockSchemeManagerFactory()); + appContainer.registerComponentInstance(MessageBus.class, app.getMessageBus()); + appContainer.registerComponentInstance(SchemeManagerFactory.class, new MockSchemeManagerFactory()); MockEditorFactory editorFactory = new MockEditorFactory(); - registerComponentInstance(appContainer, EditorFactory.class, editorFactory); - registerComponentInstance(appContainer, FileDocumentManager.class, new MockFileDocumentManagerImpl( - charSequence -> editorFactory.createDocument(charSequence), FileDocumentManagerImpl.HARD_REF_TO_DOCUMENT_KEY)); - registerComponentInstance(appContainer, PsiDocumentManager.class, new MockPsiDocumentManager()); + appContainer.registerComponentInstance(EditorFactory.class, editorFactory); + appContainer.registerComponentInstance(FileDocumentManager.class, new MockFileDocumentManagerImpl(charSequence -> { + return editorFactory.createDocument(charSequence); + }, FileDocumentManagerImpl.HARD_REF_TO_DOCUMENT_KEY)); + appContainer.registerComponentInstance(PsiDocumentManager.class, new MockPsiDocumentManager()); - registerApplicationService(PsiBuilderFactory.class, new PsiBuilderFactoryImpl()); - registerApplicationService(DefaultASTFactory.class, new DefaultASTFactoryImpl()); - registerApplicationService(ReferenceProvidersRegistry.class, new ReferenceProvidersRegistryImpl()); + app.registerService(PsiBuilderFactory.class, new PsiBuilderFactoryImpl()); + app.registerService(DefaultASTFactory.class, new DefaultASTFactoryImpl()); + app.registerService(ReferenceProvidersRegistry.class, new ReferenceProvidersRegistryImpl()); myProject.registerService(CachedValuesManager.class, new CachedValuesManagerImpl(myProject, new PsiCachedValuesFactory(myPsiManager))); myProject.registerService(PsiManager.class, myPsiManager); myProject.registerService(StartupManager.class, new StartupManagerImpl(myProject)); - registerExtensionPoint(FileTypeFactory.FILE_TYPE_FACTORY_EP, FileTypeFactory.class); - registerExtensionPoint(MetaLanguage.EP_NAME, MetaLanguage.class); + registerExtensionPoint(app.getExtensionArea(), FileTypeFactory.FILE_TYPE_FACTORY_EP, FileTypeFactory.class); + registerExtensionPoint(app.getExtensionArea(), MetaLanguage.EP_NAME, MetaLanguage.class); + + myLangParserDefinition = app.getExtensionArea().registerFakeBeanPoint(LanguageParserDefinitions.INSTANCE.getName(), getPluginDescriptor()); - for (ParserDefinition definition : myDefinitions) { - addExplicitExtension(LanguageParserDefinitions.INSTANCE, definition.getFileNodeType().getLanguage(), definition); - } if (myDefinitions.length > 0) { configureFromParserDefinition(myDefinitions[0], myFileExt); + // first definition is registered by configureFromParserDefinition + for (int i = 1, length = myDefinitions.length; i < length; i++) { + registerParserDefinition(myDefinitions[i]); + } } // That's for reparse routines @@ -127,22 +135,82 @@ public abstract class ParsingTestCase extends PlatformLiteFixture { new TreeAspect(pomModel); } - public void configureFromParserDefinition(ParserDefinition definition, String extension) { + protected final void registerParserDefinition(@NotNull ParserDefinition definition) { + myLangParserDefinition.registerExtension(new KeyedLazyInstance() { + @Override + public String getKey() { + return definition.getFileNodeType().getLanguage().getID(); + } + + @NotNull + @Override + public ParserDefinition getInstance() { + return definition; + } + }); + LanguageParserDefinitions.INSTANCE.clearCache(); + } + + public void configureFromParserDefinition(@NotNull ParserDefinition definition, String extension) { myLanguage = definition.getFileNodeType().getLanguage(); myFileExt = extension; - addExplicitExtension(LanguageParserDefinitions.INSTANCE, myLanguage, definition); - registerComponentInstance(getApplication().getPicoContainer(), FileTypeManager.class, - new MockFileTypeManager(new MockLanguageFileType(myLanguage, myFileExt))); + registerParserDefinition(definition); + myApp.getPicoContainer().registerComponentInstance(FileTypeManager.class, new MockFileTypeManager(new MockLanguageFileType(myLanguage, myFileExt))); } - protected void addExplicitExtension(LanguageExtension instance, Language language, T object) { - instance.addExplicitExtension(language, object, myProject); + protected final void registerExtension(@NotNull ExtensionPointName name, @NotNull T extension) { + //noinspection unchecked + registerExtensions(name, (Class)extension.getClass(), Collections.singletonList(extension)); } - @Override - protected void registerExtensionPoint(@NotNull ExtensionPointName extensionPointName, @NotNull Class aClass) { - super.registerExtensionPoint(extensionPointName, aClass); - Disposer.register(getTestRootDisposable(), () -> Extensions.getRootArea().unregisterExtensionPoint(extensionPointName.getName())); + protected final void registerExtensions(@NotNull ExtensionPointName name, @NotNull Class extensionClass, @NotNull List extensions) { + ExtensionsAreaImpl area = myApp.getExtensionArea(); + ExtensionPoint point = area.getExtensionPointIfRegistered(name.getName()); + if (point == null) { + point = registerExtensionPoint(area, name, extensionClass); + } + + for (T extension : extensions) { + // no need to specify disposable because ParsingTestCase in any case clean area for each test + //noinspection deprecation + point.registerExtension(extension); + } + } + + protected final void addExplicitExtension(@NotNull LanguageExtension collector, @NotNull Language language, @NotNull T object) { + ExtensionsAreaImpl area = myApp.getExtensionArea(); + if (!area.hasExtensionPoint(collector.getName())) { + area.registerFakeBeanPoint(collector.getName(), getPluginDescriptor()); + } + ExtensionTestUtil.addExtension(area, collector, language, object); + } + + protected final void registerExtensionPoint(@NotNull ExtensionPointName extensionPointName, @NotNull Class aClass) { + registerExtensionPoint(myApp.getExtensionArea(), extensionPointName, aClass); + } + + protected ExtensionPointImpl registerExtensionPoint(@NotNull ExtensionsAreaImpl extensionArea, + @NotNull ExtensionPointName extensionPointName, + @NotNull Class extensionClass) { + // todo get rid of it - registerExtensionPoint should be not called several times + String name = extensionPointName.getName(); + if (extensionArea.hasExtensionPoint(name)) { + return extensionArea.getExtensionPoint(name); + } + else { + return extensionArea.registerPoint(name, extensionClass, getPluginDescriptor()); + } + } + + @NotNull + // easy debug of not disposed extension + private PluginDescriptor getPluginDescriptor() { + PluginDescriptor pluginDescriptor = myPluginDescriptor; + if (pluginDescriptor == null) { + pluginDescriptor = new DefaultPluginDescriptor(getClass().getName() + "." + getName()); + myPluginDescriptor = pluginDescriptor; + } + return pluginDescriptor; } @NotNull @@ -226,7 +294,7 @@ public abstract class ParsingTestCase extends PlatformLiteFixture { ensureParsed(myFile); assertEquals("light virtual file text mismatch", text, ((LightVirtualFile)myFile.getVirtualFile()).getContent().toString()); assertEquals("virtual file text mismatch", text, LoadTextUtil.loadText(myFile.getVirtualFile())); - assertEquals("doc text mismatch", text, requireNonNull(myFile.getViewProvider().getDocument()).getText()); + assertEquals("doc text mismatch", text, Objects.requireNonNull(myFile.getViewProvider().getDocument()).getText()); assertEquals("psi text mismatch", text, myFile.getText()); ensureCorrectReparse(myFile); if (checkResult) { @@ -378,9 +446,9 @@ public abstract class ParsingTestCase extends PlatformLiteFixture { } public void registerMockInjectedLanguageManager() { - registerExtensionPoint(Extensions.getArea(myProject), MultiHostInjector.MULTIHOST_INJECTOR_EP_NAME, MultiHostInjector.class); + registerExtensionPoint(myProject.getExtensionArea(), MultiHostInjector.MULTIHOST_INJECTOR_EP_NAME, MultiHostInjector.class); - registerExtensionPoint(LanguageInjector.EXTENSION_POINT_NAME, LanguageInjector.class); + registerExtensionPoint(myApp.getExtensionArea(), LanguageInjector.EXTENSION_POINT_NAME, LanguageInjector.class); myProject.registerService(InjectedLanguageManager.class, new InjectedLanguageManagerImpl(myProject, new MockDumbService(myProject))); } } \ No newline at end of file diff --git a/platform/testFramework/src/com/intellij/testFramework/PlatformLiteFixture.java b/platform/testFramework/src/com/intellij/testFramework/PlatformLiteFixture.java index c2989467d1c2..451ff2469952 100644 --- a/platform/testFramework/src/com/intellij/testFramework/PlatformLiteFixture.java +++ b/platform/testFramework/src/com/intellij/testFramework/PlatformLiteFixture.java @@ -1,6 +1,7 @@ // Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.testFramework; +import com.intellij.mock.MockApplication; import com.intellij.mock.MockApplicationEx; import com.intellij.mock.MockProjectEx; import com.intellij.openapi.application.ApplicationManager; @@ -9,6 +10,7 @@ import com.intellij.openapi.extensions.ExtensionPoint; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.extensions.ExtensionsArea; +import com.intellij.openapi.extensions.impl.ExtensionsAreaImpl; import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.vfs.encoding.EncodingManager; @@ -24,24 +26,19 @@ import java.lang.reflect.Modifier; public abstract class PlatformLiteFixture extends UsefulTestCase { protected MockProjectEx myProject; - @Override - protected void setUp() throws Exception { - super.setUp(); - Extensions.cleanRootArea(getTestRootDisposable()); - } - @NotNull public static MockApplicationEx getApplication() { return (MockApplicationEx)ApplicationManager.getApplication(); } - public void initApplication() { - //if (ApplicationManager.getApplication() instanceof MockApplicationEx) return; - final MockApplicationEx instance = new MockApplicationEx(getTestRootDisposable()); - ApplicationManager.setApplication(instance, + @NotNull + public MockApplication initApplication() { + MockApplicationEx app = new MockApplicationEx(getTestRootDisposable()); + ApplicationManager.setApplication(app, () -> FileTypeManager.getInstance(), getTestRootDisposable()); - getApplication().registerService(EncodingManager.class, EncodingManagerImpl.class); + app.registerService(EncodingManager.class, EncodingManagerImpl.class); + return app; } @Override @@ -74,7 +71,7 @@ public abstract class PlatformLiteFixture extends UsefulTestCase { @NotNull Class aClass) { if (!area.hasExtensionPoint(extensionPointName)) { ExtensionPoint.Kind kind = aClass.isInterface() || (aClass.getModifiers() & Modifier.ABSTRACT) != 0 ? ExtensionPoint.Kind.INTERFACE : ExtensionPoint.Kind.BEAN_CLASS; - area.registerExtensionPoint(extensionPointName, aClass.getName(), kind, getTestRootDisposable()); + ((ExtensionsAreaImpl)area).registerExtensionPoint(extensionPointName, aClass.getName(), kind, getTestRootDisposable()); } } diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/LightIdeaTestFixtureImpl.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/LightIdeaTestFixtureImpl.java index b76d49f4aa55..07cb3a584a58 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/LightIdeaTestFixtureImpl.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/LightIdeaTestFixtureImpl.java @@ -1,5 +1,4 @@ // Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. - package com.intellij.testFramework.fixtures.impl; import com.intellij.application.options.CodeStyle; @@ -19,11 +18,8 @@ import org.jetbrains.annotations.NotNull; import java.util.concurrent.TimeUnit; -/** - * @author mike - */ @SuppressWarnings("TestOnlyProblems") -public class LightIdeaTestFixtureImpl extends BaseFixture implements LightIdeaTestFixture { +public final class LightIdeaTestFixtureImpl extends BaseFixture implements LightIdeaTestFixture { private final LightProjectDescriptor myProjectDescriptor; private SdkLeakTracker myOldSdks; private CodeStyleSettingsTracker myCodeStyleSettingsTracker; @@ -100,7 +96,7 @@ public class LightIdeaTestFixtureImpl extends BaseFixture implements LightIdeaTe return myProject; } - protected CodeStyleSettings getCurrentCodeStyleSettings() { + private CodeStyleSettings getCurrentCodeStyleSettings() { if (CodeStyleSchemes.getInstance().getCurrentScheme() == null) return new CodeStyleSettings(); return CodeStyle.getSettings(getProject()); } diff --git a/platform/testGuiFramework/src/com/intellij/testGuiFramework/impl/GuiTestStarter.kt b/platform/testGuiFramework/src/com/intellij/testGuiFramework/impl/GuiTestStarter.kt index d75d22cba6e6..a2b5287dbb2a 100644 --- a/platform/testGuiFramework/src/com/intellij/testGuiFramework/impl/GuiTestStarter.kt +++ b/platform/testGuiFramework/src/com/intellij/testGuiFramework/impl/GuiTestStarter.kt @@ -24,7 +24,7 @@ class GuiTestStarter : IdeStarter() { override fun getCommandName() = COMMAND_NAME - override fun premain(args: Array) { + override fun premain(args: List) { val guiTestThread = GuiTestThread() processArgs(args) LOG.info("Starting GuiTest activity") @@ -39,7 +39,7 @@ class GuiTestStarter : IdeStarter() { /** * We assume next argument string model: main.app guitest testName1,testName2,testName3 host="localhost" port=5009 */ - private fun processArgs(args: Array) { + private fun processArgs(args: List) { val guiTestList = args[1].removeSurrounding("\"") System.setProperty(GUI_TEST_LIST, guiTestList) val hostArg: String? = args.find { arg -> arg.toLowerCase().startsWith("host") }?.substringAfter("host=") ?: HOST_LOCALHOST diff --git a/plugins/devkit/devkit-core/src/dom/Extension.java b/plugins/devkit/devkit-core/src/dom/Extension.java index 254e067e6f96..b20c1a84b85b 100644 --- a/plugins/devkit/devkit-core/src/dom/Extension.java +++ b/plugins/devkit/devkit-core/src/dom/Extension.java @@ -1,22 +1,8 @@ -/* - * Copyright 2000-2019 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.idea.devkit.dom; +import com.intellij.ide.plugins.IdeaPluginDescriptorImpl; import com.intellij.ide.presentation.Presentation; -import com.intellij.openapi.extensions.Extensions; import com.intellij.psi.xml.XmlTag; import com.intellij.util.xml.*; import org.jetbrains.annotations.NotNull; @@ -47,7 +33,7 @@ public interface Extension extends DomElement { @NotNull @Attribute(OS_ATTRIBUTE) - GenericAttributeValue getOs(); + GenericAttributeValue getOs(); @Nullable ExtensionPoint getExtensionPoint(); diff --git a/plugins/settings-repository/src/git/CommitMessageFormatter.kt b/plugins/settings-repository/src/git/CommitMessageFormatter.kt index ca2751e10869..b3e4d9d3da3f 100644 --- a/plugins/settings-repository/src/git/CommitMessageFormatter.kt +++ b/plugins/settings-repository/src/git/CommitMessageFormatter.kt @@ -1,6 +1,7 @@ // Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.settingsRepository.git +import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.ApplicationNamesInfo import com.intellij.openapi.application.ex.ApplicationInfoEx import org.eclipse.jgit.lib.Ref @@ -31,7 +32,7 @@ class IdeaCommitMessageFormatter : CommitMessageFormatter { builder.appendAppName() } - if (icsManager.settings.includeHostIntoCommitMessage) { + if (!ApplicationManager.getApplication()!!.isUnitTestMode && icsManager.settings.includeHostIntoCommitMessage) { builder.append(' ').append('<').append(System.getProperty("user.name", "unknown-user")) builder.append('@').append(InetAddress.getLocalHost().hostName) } diff --git a/plugins/settings-repository/testSrc/GitTest.kt b/plugins/settings-repository/testSrc/GitTest.kt index f821cc61b81b..cffdf98b6683 100644 --- a/plugins/settings-repository/testSrc/GitTest.kt +++ b/plugins/settings-repository/testSrc/GitTest.kt @@ -3,7 +3,6 @@ package org.jetbrains.settingsRepository.test import com.intellij.configurationStore.ApplicationStoreImpl import com.intellij.configurationStore.write -import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.vcs.merge.MergeSession import com.intellij.testFramework.file import com.intellij.util.PathUtilRt @@ -370,7 +369,7 @@ internal class GitTest : GitTestCase() { repositoryManager.createRepositoryIfNeeded() repositoryManager.setUpstream(remoteRepository.workTree.absolutePath) - val store = ApplicationStoreImpl(ApplicationManager.getApplication()!!) + val store = ApplicationStoreImpl(null) val localConfigPath = tempDirManager.newPath("local_config", refreshVfs = true) val lafData = """ diff --git a/spellchecker/src/com/intellij/spellchecker/SpellCheckerManager.java b/spellchecker/src/com/intellij/spellchecker/SpellCheckerManager.java index 60ff038823ba..52cb4eea5a01 100644 --- a/spellchecker/src/com/intellij/spellchecker/SpellCheckerManager.java +++ b/spellchecker/src/com/intellij/spellchecker/SpellCheckerManager.java @@ -173,7 +173,7 @@ public class SpellCheckerManager implements Disposable { } private void initUserDictionaries() { - final CachedDictionaryState cachedDictionaryState = ServiceManager.getService(project, CachedDictionaryState.class); + CachedDictionaryState cachedDictionaryState = CachedDictionaryState.getInstance(); cachedDictionaryState.addCachedDictListener((dict) -> restartInspections()); if (cachedDictionaryState.getDictionary() == null) { cachedDictionaryState.setDictionary(new UserDictionary(CachedDictionaryState.DEFAULT_NAME)); diff --git a/spellchecker/src/com/intellij/spellchecker/state/CachedDictionaryState.java b/spellchecker/src/com/intellij/spellchecker/state/CachedDictionaryState.java index 3f65a9775ed8..b60f0f402940 100644 --- a/spellchecker/src/com/intellij/spellchecker/state/CachedDictionaryState.java +++ b/spellchecker/src/com/intellij/spellchecker/state/CachedDictionaryState.java @@ -1,13 +1,10 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.spellchecker.state; -import com.intellij.openapi.components.PersistentStateComponent; -import com.intellij.openapi.components.RoamingType; -import com.intellij.openapi.components.State; -import com.intellij.openapi.components.Storage; +import com.intellij.openapi.components.*; import com.intellij.spellchecker.dictionary.EditableDictionary; -import org.jetbrains.annotations.NotNull; import com.intellij.util.EventDispatcher; +import org.jetbrains.annotations.NotNull; @State( name = "CachedDictionaryState", @@ -21,6 +18,11 @@ public class CachedDictionaryState extends DictionaryState implements Persistent name = DEFAULT_NAME; } + @NotNull + public static CachedDictionaryState getInstance() { + return ServiceManager.getService(CachedDictionaryState.class); + } + public CachedDictionaryState(EditableDictionary dictionary) { super(dictionary); name = DEFAULT_NAME; diff --git a/uast/uast-common/src/org/jetbrains/uast/evaluation/UEvaluator.kt b/uast/uast-common/src/org/jetbrains/uast/evaluation/UEvaluator.kt index 65f336577b1a..fcc788ef1ead 100644 --- a/uast/uast-common/src/org/jetbrains/uast/evaluation/UEvaluator.kt +++ b/uast/uast-common/src/org/jetbrains/uast/evaluation/UEvaluator.kt @@ -1,21 +1,6 @@ -/* - * Copyright 2000-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.uast.evaluation -import com.intellij.openapi.extensions.Extensions import com.intellij.psi.PsiElement import org.jetbrains.uast.* import org.jetbrains.uast.values.UDependency @@ -23,15 +8,10 @@ import org.jetbrains.uast.values.UValue // Role: at the current state, evaluate expression(s) interface UEvaluator { - val context: UastLanguagePlugin val languageExtensions: List - get() { - val rootArea = Extensions.getRootArea() - if (!rootArea.hasExtensionPoint(UEvaluatorExtension.EXTENSION_POINT_NAME.name)) return listOf() - return rootArea.getExtensionPoint(UEvaluatorExtension.EXTENSION_POINT_NAME).extensions.toList() - } + get() = UEvaluatorExtension.EXTENSION_POINT_NAME.extensionsIfPointIsRegistered fun PsiElement.languageExtension(): UEvaluatorExtension? = languageExtensions.firstOrNull { it.language == language } diff --git a/uast/uast-common/src/org/jetbrains/uast/evaluation/UEvaluatorExtension.kt b/uast/uast-common/src/org/jetbrains/uast/evaluation/UEvaluatorExtension.kt index b25c4d24de54..9a3fcfe09d33 100644 --- a/uast/uast-common/src/org/jetbrains/uast/evaluation/UEvaluatorExtension.kt +++ b/uast/uast-common/src/org/jetbrains/uast/evaluation/UEvaluatorExtension.kt @@ -1,18 +1,4 @@ -/* - * Copyright 2000-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package org.jetbrains.uast.evaluation import com.intellij.lang.Language @@ -24,8 +10,7 @@ import org.jetbrains.uast.values.UValue interface UEvaluatorExtension { companion object { - val EXTENSION_POINT_NAME: ExtensionPointName = - ExtensionPointName.create("org.jetbrains.uast.evaluation.UEvaluatorExtension") + val EXTENSION_POINT_NAME = ExtensionPointName("org.jetbrains.uast.evaluation.UEvaluatorExtension") } val language: Language diff --git a/uast/uast-tests/src/org/jetbrains/uast/test/env/TestCoreEnvironment.java b/uast/uast-tests/src/org/jetbrains/uast/test/env/TestCoreEnvironment.java deleted file mode 100644 index 27e12521d168..000000000000 --- a/uast/uast-tests/src/org/jetbrains/uast/test/env/TestCoreEnvironment.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.uast.test.env; - -import com.intellij.codeInsight.ContainerProvider; -import com.intellij.codeInsight.runner.JavaMainMethodProvider; -import com.intellij.core.CoreApplicationEnvironment; -import com.intellij.core.CoreJavaFileManager; -import com.intellij.core.JavaCoreApplicationEnvironment; -import com.intellij.core.JavaCoreProjectEnvironment; -import com.intellij.lang.MetaLanguage; -import com.intellij.mock.MockProject; -import com.intellij.openapi.Disposable; -import com.intellij.openapi.components.ServiceManager; -import com.intellij.openapi.extensions.Extensions; -import com.intellij.openapi.extensions.ExtensionsArea; -import com.intellij.openapi.fileTypes.FileTypeExtensionPoint; -import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.vfs.StandardFileSystems; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.VirtualFileSystem; -import com.intellij.openapi.vfs.impl.ZipHandler; -import com.intellij.psi.FileContextProvider; -import com.intellij.psi.PsiElementFinder; -import com.intellij.psi.augment.PsiAugmentProvider; -import com.intellij.psi.compiled.ClassFileDecompilers; -import com.intellij.psi.impl.JavaClassSupersImpl; -import com.intellij.psi.impl.PsiElementFinderImpl; -import com.intellij.psi.impl.PsiTreeChangePreprocessor; -import com.intellij.psi.impl.file.impl.JavaFileManager; -import com.intellij.psi.meta.MetaDataContributor; -import com.intellij.psi.stubs.BinaryFileStubBuilders; -import com.intellij.psi.util.JavaClassSupers; -import org.jetbrains.annotations.NotNull; - -import java.io.File; -import java.io.IOException; - -public class TestCoreEnvironment extends AbstractCoreEnvironment { - private static final Object APPLICATION_LOCK = new Object(); - private static volatile JavaCoreApplicationEnvironment sEnvironment = null; - - private final Disposable mDisposable; - private volatile JavaCoreProjectEnvironment mProjectEnvironment = null; - - public TestCoreEnvironment(@NotNull Disposable disposable) { - mDisposable = disposable; - } - - @Override - public void dispose() { - Disposer.dispose(mDisposable); - } - - @Override - public MockProject getProject() { - JavaCoreProjectEnvironment projectEnvironment = getProjectEnvironment(); - if (projectEnvironment == null) { - return null; - } - return projectEnvironment.getProject(); - } - - @Override - public void addJavaSourceRoot(@NotNull File root) { - VirtualFileSystem vfs = StandardFileSystems.local(); - try { - addDirectoryToClassPath(vfs, root); - } - catch (IOException e) { - throw new RuntimeException(e); - } - } - - private void addDirectoryToClassPath(VirtualFileSystem vfs, File root) throws IOException { - VirtualFile virtualFile = vfs.findFileByPath(root.getCanonicalPath()); - assert virtualFile != null; - getProjectEnvironment().addSourcesToClasspath(virtualFile); - } - - @Override - public void addJar(@NotNull File root) { - getProjectEnvironment().addJarToClassPath(root); - } - - public JavaCoreProjectEnvironment getProjectEnvironment() { - if (mProjectEnvironment != null) { - return mProjectEnvironment; - } - synchronized (APPLICATION_LOCK) { - if (mProjectEnvironment != null) { - return mProjectEnvironment; - } - JavaCoreApplicationEnvironment coreEnvironment = getCoreEnvironment(); - - mProjectEnvironment = new TestJavaCoreProjectEnvironment(coreEnvironment); - - Disposer.register(mDisposable, new Disposable() { - @Override - public void dispose() { - mProjectEnvironment = null; - } - }); - - return mProjectEnvironment; - } - } - - private static JavaCoreApplicationEnvironment getCoreEnvironment() { - if (sEnvironment != null) { - return sEnvironment; - } - synchronized (APPLICATION_LOCK) { - if (sEnvironment != null) { - return sEnvironment; - } - Disposable parentDisposable = Disposer.newDisposable(); - Extensions.cleanRootArea(parentDisposable); - registerAppExtensionPoints(); - JavaCoreApplicationEnvironment coreEnvironment = new JavaCoreApplicationEnvironment(parentDisposable); - coreEnvironment.registerApplicationService(JavaClassSupers.class, new JavaClassSupersImpl()); - - sEnvironment = coreEnvironment; - - Disposer.register(parentDisposable, new Disposable() { - @Override - public void dispose() { - synchronized (APPLICATION_LOCK) { - JavaCoreApplicationEnvironment environment = sEnvironment; - sEnvironment = null; - Disposer.dispose(environment.getParentDisposable()); - ZipHandler.clearFileAccessorCache(); - } - } - }); - return sEnvironment; - } - } - - private static void registerAppExtensionPoints() { - CoreApplicationEnvironment.registerExtensionPoint( - Extensions.getRootArea(), BinaryFileStubBuilders.EP_NAME, FileTypeExtensionPoint.class); - CoreApplicationEnvironment.registerExtensionPoint( - Extensions.getRootArea(), FileContextProvider.EP_NAME, FileContextProvider.class); - // - CoreApplicationEnvironment.registerExtensionPoint( - Extensions.getRootArea(), MetaDataContributor.EP_NAME, MetaDataContributor.class); - CoreApplicationEnvironment.registerExtensionPoint( - Extensions.getRootArea(), PsiAugmentProvider.EP_NAME, PsiAugmentProvider.class); - CoreApplicationEnvironment.registerExtensionPoint( - Extensions.getRootArea(), JavaMainMethodProvider.EP_NAME, JavaMainMethodProvider.class); - // - CoreApplicationEnvironment.registerExtensionPoint( - Extensions.getRootArea(), ContainerProvider.EP_NAME, ContainerProvider.class); - CoreApplicationEnvironment.registerExtensionPoint( - Extensions.getRootArea(), ClassFileDecompilers.EP_NAME, ClassFileDecompilers.Decompiler.class); - CoreApplicationEnvironment.registerExtensionPoint( - Extensions.getRootArea(), MetaLanguage.EP_NAME, MetaLanguage.class); - } - - private class TestJavaCoreProjectEnvironment extends JavaCoreProjectEnvironment { - TestJavaCoreProjectEnvironment(@NotNull JavaCoreApplicationEnvironment coreEnvironment) { - super(mDisposable, coreEnvironment); - - registerProjectExtensions(); - } - - @Override - protected void preregisterServices() { - registerProjectExtensionPoints(); - } - - private void registerProjectExtensionPoints() { - ExtensionsArea area = Extensions.getArea(myProject); - CoreApplicationEnvironment.registerExtensionPoint(area, PsiTreeChangePreprocessor.EP, PsiTreeChangePreprocessor.class); - CoreApplicationEnvironment.registerExtensionPoint( - area, PsiElementFinder.EP, PsiElementFinder.class); - } - - private void registerProjectExtensions() { - myProject.registerService(CoreJavaFileManager.class, - ((CoreJavaFileManager)ServiceManager.getService(myProject, JavaFileManager.class))); - - //noinspection TestOnlyProblems - PsiElementFinder.EP.getPoint(myProject).registerExtension(new PsiElementFinderImpl(myProject), mDisposable); - } - } -} diff --git a/xml/tests/src/com/intellij/xml/XmlParsingTest.java b/xml/tests/src/com/intellij/xml/XmlParsingTest.java index 2886ef25cf13..7a5e41cfece1 100644 --- a/xml/tests/src/com/intellij/xml/XmlParsingTest.java +++ b/xml/tests/src/com/intellij/xml/XmlParsingTest.java @@ -1,4 +1,4 @@ -// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.xml; import com.intellij.lang.*; @@ -27,11 +27,7 @@ import org.jetbrains.annotations.Nullable; import java.io.File; -/** - * @author Mike, ik - */ public class XmlParsingTest extends ParsingTestCase { - public XmlParsingTest() { super("psi/xml", "xml", new XMLParserDefinition()); } @@ -533,7 +529,7 @@ public class XmlParsingTest extends ParsingTestCase { return null; } }); - addExplicitExtension(LanguageParserDefinitions.INSTANCE, HTMLLanguage.INSTANCE, new HTMLParserDefinition()); + registerParserDefinition(new HTMLParserDefinition()); addExplicitExtension(LanguageASTFactory.INSTANCE, HTMLLanguage.INSTANCE, new XmlASTFactory()); registerExtensionPoint(EmbeddedTokenTypesProvider.EXTENSION_POINT_NAME, EmbeddedTokenTypesProvider.class); myLanguage = HTMLLanguage.INSTANCE;