diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/CaptureConfigurable.java b/java/debugger/impl/src/com/intellij/debugger/settings/CaptureConfigurable.java index 56157e461952..7f8476d0a039 100644 --- a/java/debugger/impl/src/com/intellij/debugger/settings/CaptureConfigurable.java +++ b/java/debugger/impl/src/com/intellij/debugger/settings/CaptureConfigurable.java @@ -1,4 +1,4 @@ -// Copyright 2000-2020 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-2021 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.debugger.settings; import com.intellij.CommonBundle; @@ -267,7 +267,7 @@ public class CaptureConfigurable implements SearchableConfigurable, NoScroll { } }); try { - JDOMUtil.write(rootElement, wrapper.getFile()); + JDOMUtil.write(rootElement, wrapper.getFile().toPath()); } catch (Exception ex) { final String msg = ex.getLocalizedMessage(); diff --git a/java/idea-ui/testSrc/com/intellij/ui/DeferredIconTest.java b/java/idea-ui/testSrc/com/intellij/ui/DeferredIconTest.java index 471171efa8d1..16fda425ba89 100644 --- a/java/idea-ui/testSrc/com/intellij/ui/DeferredIconTest.java +++ b/java/idea-ui/testSrc/com/intellij/ui/DeferredIconTest.java @@ -1,4 +1,4 @@ -// Copyright 2000-2020 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-2021 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.openapi.command.WriteCommandAction; @@ -11,6 +11,10 @@ import com.intellij.util.ui.UIUtil; import javax.swing.*; public class DeferredIconTest extends LightJavaCodeInsightFixtureTestCase { + @Override + protected boolean isIconRequired() { + return true; + } public void test_icons_before_and_after_computation_are_equal() { PsiFile file = myFixture.addFileToProject("a.java", "class C {}"); diff --git a/java/java-impl/src/com/intellij/psi/impl/JavaDirectoryIconProvider.java b/java/java-impl/src/com/intellij/psi/impl/JavaDirectoryIconProvider.java index a7a83259bb36..52eab3f16d35 100644 --- a/java/java-impl/src/com/intellij/psi/impl/JavaDirectoryIconProvider.java +++ b/java/java-impl/src/com/intellij/psi/impl/JavaDirectoryIconProvider.java @@ -1,4 +1,4 @@ -// Copyright 2000-2020 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-2021 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; import com.intellij.icons.AllIcons; @@ -27,45 +27,44 @@ import javax.swing.*; final class JavaDirectoryIconProvider extends IconProvider implements DumbAware { @Override - @Nullable - public Icon getIcon(@NotNull PsiElement element, int flags) { - if (element instanceof PsiDirectory) { - final PsiDirectory psiDirectory = (PsiDirectory)element; - final VirtualFile vFile = psiDirectory.getVirtualFile(); - final Project project = psiDirectory.getProject(); - - SourceFolder sourceFolder; - Icon symbolIcon; - if (vFile.getParent() == null && vFile.getFileSystem() instanceof ArchiveFileSystem) { - symbolIcon = PlatformIcons.JAR_ICON; - } - else if (ProjectRootsUtil.isModuleContentRoot(vFile, project)) { - Module module = ProjectRootManager.getInstance(project).getFileIndex().getModuleForFile(vFile); - symbolIcon = module == null || module.isDisposed() ? PlatformIcons.CONTENT_ROOT_ICON_CLOSED : ModuleType.get(module).getIcon(); - } - else if (ProjectRootsUtil.findUnloadedModuleByContentRoot(vFile, project) != null) { - symbolIcon = AllIcons.Modules.UnloadedModule; - } - else if ((sourceFolder = ProjectRootsUtil.getModuleSourceRoot(vFile, project)) != null) { - symbolIcon = SourceRootPresentation.getSourceRootIcon(sourceFolder); - } - else if (JrtFileSystem.isModuleRoot(vFile)) { - symbolIcon = AllIcons.Nodes.Module; - } - else if (isValidPackage(psiDirectory)) { - symbolIcon = IconManager.getInstance().tooltipOnlyIfComposite(PlatformIcons.PACKAGE_ICON); - } - else if (!Registry.is("ide.hide.excluded.files") && ProjectRootManager.getInstance(project).getFileIndex().isExcluded(vFile)) { - symbolIcon = AllIcons.Modules.ExcludeRoot; - } - else { - symbolIcon = PlatformIcons.FOLDER_ICON; - } - - return IconManager.getInstance().createLayeredIcon(element, symbolIcon, 0); + public @Nullable Icon getIcon(@NotNull PsiElement element, int flags) { + if (!(element instanceof PsiDirectory)) { + return null; } - return null; + final PsiDirectory psiDirectory = (PsiDirectory)element; + final VirtualFile vFile = psiDirectory.getVirtualFile(); + final Project project = psiDirectory.getProject(); + + SourceFolder sourceFolder; + Icon symbolIcon; + if (vFile.getParent() == null && vFile.getFileSystem() instanceof ArchiveFileSystem) { + symbolIcon = PlatformIcons.JAR_ICON; + } + else if (ProjectRootsUtil.isModuleContentRoot(vFile, project)) { + Module module = ProjectRootManager.getInstance(project).getFileIndex().getModuleForFile(vFile); + symbolIcon = module == null || module.isDisposed() ? PlatformIcons.CONTENT_ROOT_ICON_CLOSED : ModuleType.get(module).getIcon(); + } + else if (ProjectRootsUtil.findUnloadedModuleByContentRoot(vFile, project) != null) { + symbolIcon = AllIcons.Modules.UnloadedModule; + } + else if ((sourceFolder = ProjectRootsUtil.getModuleSourceRoot(vFile, project)) != null) { + symbolIcon = SourceRootPresentation.getSourceRootIcon(sourceFolder); + } + else if (JrtFileSystem.isModuleRoot(vFile)) { + symbolIcon = AllIcons.Nodes.Module; + } + else if (isValidPackage(psiDirectory)) { + IconManager iconManager = IconManager.getInstance(); + symbolIcon = iconManager.createLayeredIcon(element, iconManager.tooltipOnlyIfComposite(PlatformIcons.PACKAGE_ICON), 0); + } + else if (!Registry.is("ide.hide.excluded.files") && ProjectRootManager.getInstance(project).getFileIndex().isExcluded(vFile)) { + symbolIcon = AllIcons.Modules.ExcludeRoot; + } + else { + symbolIcon = PlatformIcons.FOLDER_ICON; + } + return IconManager.getInstance().createLayeredIcon(element, symbolIcon, 0); } /** diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/ServiceLineMarkerTest.kt b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/ServiceLineMarkerTest.kt index 6c3a2398ac4e..c4d63284cf1d 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/ServiceLineMarkerTest.kt +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/ServiceLineMarkerTest.kt @@ -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. +// Copyright 2000-2021 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.daemon.impl -import com.intellij.codeInsight.daemon.DaemonBundle import com.intellij.codeInsight.daemon.LineMarkerInfo import com.intellij.codeInsight.daemon.impl.JavaServiceUtil.ServiceNavigationHandler import com.intellij.icons.AllIcons @@ -10,10 +9,9 @@ import com.intellij.psi.* import com.intellij.psi.util.PsiTreeUtil import com.intellij.testFramework.LightProjectDescriptor import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase +import com.intellij.ui.IconTestUtil +import org.assertj.core.api.Assertions.assertThat -/** - * @author Pavel.Dolgov - */ class ServiceLineMarkerTest : LightJavaCodeInsightFixtureTestCase() { override fun getProjectDescriptor(): LightProjectDescriptor = JAVA_9 @@ -30,40 +28,45 @@ class ServiceLineMarkerTest : LightJavaCodeInsightFixtureTestCase() { @Override public void doWork() {} }""".trimIndent()) - fun testProvidesWithMethod() = + fun testProvidesWithMethod() { doTestImplementer(""" - public class MyServiceImpl { - public static MyService provider() { - return new MyService() { @Override public void doWork() {} }; - } - }""".trimIndent()) + public class MyServiceImpl { + public static MyService provider() { + return new MyService() { @Override public void doWork() {} }; + } + }""".trimIndent()) + } - fun testLoadWithLiteral() = + fun testLoadWithLiteral() { doTestLoader(""" - void foo() { - ServiceLoader loader = ServiceLoader.load(MyService.class); - }""".trimIndent()) + void foo() { + ServiceLoader loader = ServiceLoader.load(MyService.class); + }""".trimIndent()) + } - fun testLoadWithVariable() = + fun testLoadWithVariable() { doTestLoader(""" - void foo() { - Class service = MyService.class; - ServiceLoader loader = ServiceLoader.load(service); - }""".trimIndent()) + void foo() { + Class service = MyService.class; + ServiceLoader loader = ServiceLoader.load(service); + }""".trimIndent()) + } - fun testLoadWithClassForName() = + fun testLoadWithClassForName() { doTestLoader(""" - void foo() throws ClassNotFoundException { - ServiceLoader loader = - ServiceLoader.load(Class.forName("foo.bar.MyService"), Main.class.getClassLoader()); - }""".trimIndent()) + void foo() throws ClassNotFoundException { + ServiceLoader loader = + ServiceLoader.load(Class.forName("foo.bar.MyService"), Main.class.getClassLoader()); + }""".trimIndent()) + } - fun testLoadWithConstant() = + fun testLoadWithConstant() { doTestLoader(""" - static final Class SERVICE = MyService.class; - void foo() { - ServiceLoader loader = ServiceLoader.load(SERVICE); - }""".trimIndent()) + static final Class SERVICE = MyService.class; + void foo() { + ServiceLoader loader = ServiceLoader.load(SERVICE); + }""".trimIndent()) + } private fun doTestLoader(text: String) { val module = addModule("module foo.bar { uses foo.bar.MyService; provides foo.bar.MyService with foo.bar.impl.MyServiceImpl; }") @@ -83,10 +86,10 @@ class ServiceLineMarkerTest : LightJavaCodeInsightFixtureTestCase() { private fun doTest(file: PsiFile, module: PsiJavaModule, message: String, fqn: String, parentType: Class) { myFixture.configureFromExistingVirtualFile(file.virtualFile!!) - val atCaret = myFixture.findGuttersAtCaret().filter { it.icon === AllIcons.Gutter.Java9Service } - assertEquals("atCaret", 1, atCaret.size) - val all = myFixture.findAllGutters().filter { it.icon === AllIcons.Gutter.Java9Service } - assertEquals("all", atCaret, all) + val atCaret = myFixture.findGuttersAtCaret().filter { IconTestUtil.unwrapIcon(it.icon) == AllIcons.Gutter.Java9Service } + assertThat(atCaret).hasSize(1) + val all = myFixture.findAllGutters().filter { IconTestUtil.unwrapIcon(it.icon) == AllIcons.Gutter.Java9Service } + assertThat(all).isEqualTo(atCaret) val mark = atCaret[0] assertEquals(message, mark.tooltipText) @@ -99,18 +102,21 @@ class ServiceLineMarkerTest : LightJavaCodeInsightFixtureTestCase() { assertEquals(fqn, targetReference.qualifiedName) } - private fun addModule(text: String): PsiJavaModule = - (myFixture.addFileToProject("module-info.java", text) as PsiJavaFile).moduleDeclaration!! + private fun addModule(text: String): PsiJavaModule { + return (myFixture.addFileToProject("module-info.java", text) as PsiJavaFile).moduleDeclaration!! + } - private fun addImplementer(text: String) = - myFixture.addFileToProject("foo/bar/impl/MyServiceImpl.java", "package foo.bar.impl;\nimport foo.bar.MyService;\n${text}") + private fun addImplementer(text: String): PsiFile { + return myFixture.addFileToProject("foo/bar/impl/MyServiceImpl.java", "package foo.bar.impl;\nimport foo.bar.MyService;\n${text}") + } - private fun addMain(method: String) = - myFixture.addFileToProject("foo/bar/main/Main.java", """ - package foo.bar.main; - import foo.bar.MyService; - import java.util.ServiceLoader; - public class Main { - [METHOD] - }""".trimIndent().replace("[METHOD]", method.prependIndent(" "))) + private fun addMain(method: String): PsiFile { + return myFixture.addFileToProject("foo/bar/main/Main.java", """ + package foo.bar.main; + import foo.bar.MyService; + import java.util.ServiceLoader; + public class Main { + [METHOD] + }""".trimIndent().replace("[METHOD]", method.prependIndent(" "))) + } } \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/JavaIconTest.java b/java/java-tests/testSrc/com/intellij/java/JavaIconTest.java index 457d0d159e9c..76b060e4bc69 100644 --- a/java/java-tests/testSrc/com/intellij/java/JavaIconTest.java +++ b/java/java-tests/testSrc/com/intellij/java/JavaIconTest.java @@ -1,6 +1,7 @@ -// Copyright 2000-2020 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-2021 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.java; +import com.intellij.icons.AllIcons; import com.intellij.ide.projectView.impl.nodes.AbstractPsiBasedNode; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.util.Iconable; @@ -9,28 +10,32 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiJavaFile; +import com.intellij.testFramework.PlatformTestUtil; import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase; import com.intellij.ui.IconTestUtil; -import com.intellij.util.PlatformIcons; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.ui.UIUtil; import javax.swing.*; import java.io.IOException; import java.util.List; public class JavaIconTest extends LightJavaCodeInsightFixtureTestCase { + @Override + protected boolean isIconRequired() { + return true; + } + public void testOnlyOneIconForLockedJavaClass() throws IOException { PsiFile psiFile = myFixture.configureByText("a.java", "class A {}"); VirtualFile file = myFixture.getFile().getVirtualFile(); setFileWritable(file, false); - UIUtil.dispatchAllInvocationEvents(); // write actions - UIUtil.dispatchAllInvocationEvents(); + PlatformTestUtil.dispatchAllInvocationEventsInIdeEventQueue(); // write actions + PlatformTestUtil.dispatchAllInvocationEventsInIdeEventQueue(); try { PsiClass psiClass = ((PsiJavaFile) psiFile).getClasses()[0]; Icon icon = AbstractPsiBasedNode.patchIcon(getProject(), psiClass.getIcon(Iconable.ICON_FLAG_READ_STATUS), file); List icons = IconTestUtil.renderDeferredIcon(icon); - assertOneElement(ContainerUtil.filter(icons, ic -> ic == IconTestUtil.unwrapRetrievableIcon(PlatformIcons.LOCKED_ICON))); + assertOneElement(ContainerUtil.filter(icons, ic -> IconTestUtil.unwrapIcon(ic) == AllIcons.Nodes.Locked)); } finally { setFileWritable(file, true); diff --git a/java/java-tests/testSrc/com/intellij/projectView/CustomScopePaneTest.kt b/java/java-tests/testSrc/com/intellij/projectView/CustomScopePaneTest.kt index 2311686728a1..880726280a55 100644 --- a/java/java-tests/testSrc/com/intellij/projectView/CustomScopePaneTest.kt +++ b/java/java-tests/testSrc/com/intellij/projectView/CustomScopePaneTest.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2020 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-2021 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.projectView import com.intellij.ide.projectView.ProjectViewNode @@ -16,6 +16,8 @@ import com.intellij.util.io.directoryContent import com.intellij.util.io.generateInVirtualTempDir class CustomScopePaneTest : AbstractProjectViewTest() { + override fun isIconRequired() = true + override fun tearDown() { NamedScopeManager.getInstance(project).removeAllSets() super.tearDown() diff --git a/platform/analysis-api/src/com/intellij/codeInsight/lookup/LookupElementBuilder.java b/platform/analysis-api/src/com/intellij/codeInsight/lookup/LookupElementBuilder.java index ac256706c942..0e90c1da5046 100644 --- a/platform/analysis-api/src/com/intellij/codeInsight/lookup/LookupElementBuilder.java +++ b/platform/analysis-api/src/com/intellij/codeInsight/lookup/LookupElementBuilder.java @@ -1,4 +1,4 @@ -// Copyright 2000-2020 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-2021 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.lookup; @@ -405,7 +405,8 @@ public final class LookupElementBuilder extends LookupElement { } else if (myHardcodedPresentation != null) { presentation.copyFrom(myHardcodedPresentation); - } else { + } + else { presentation.setItemText(myLookupString); } } diff --git a/platform/core-api/src/com/intellij/openapi/project/DumbService.java b/platform/core-api/src/com/intellij/openapi/project/DumbService.java index e4cc10121674..62715e730d9f 100644 --- a/platform/core-api/src/com/intellij/openapi/project/DumbService.java +++ b/platform/core-api/src/com/intellij/openapi/project/DumbService.java @@ -5,8 +5,10 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.application.ReadAction; +import com.intellij.openapi.extensions.ExtensionPoint; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.extensions.ProjectExtensionPointName; +import com.intellij.openapi.extensions.impl.ExtensionPointImpl; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.util.*; @@ -19,10 +21,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; +import java.util.*; /** * A service managing the IDE's 'dumb' mode: when indexes are updated in the background, and the functionality is very much limited. @@ -60,13 +59,23 @@ public abstract class DumbService { } public static @NotNull List getDumbAwareExtensions(@NotNull Project project, @NotNull ExtensionPointName extensionPoint) { - List list = extensionPoint.getExtensionList(); - if (list.isEmpty()) { - return list; + ExtensionPoint point = extensionPoint.getPoint(); + int size = point.size(); + if (size == 0) { + return Collections.emptyList(); } - DumbService dumbService = getInstance(project); - return dumbService.filterByDumbAwareness(list); + if (!getInstance(project).isDumb()) { + return point.getExtensionList(); + } + + List result = new ArrayList<>(size); + for (T element : ((ExtensionPointImpl)point)) { + if (isDumbAware(element)) { + result.add(element); + } + } + return result; } public static @NotNull List getDumbAwareExtensions(@NotNull Project project, @NotNull ProjectExtensionPointName extensionPoint) { diff --git a/platform/core-api/src/com/intellij/util/PlatformIcons.java b/platform/core-api/src/com/intellij/util/PlatformIcons.java index e34b51dae612..fc068afe8b4a 100644 --- a/platform/core-api/src/com/intellij/util/PlatformIcons.java +++ b/platform/core-api/src/com/intellij/util/PlatformIcons.java @@ -1,4 +1,4 @@ -// Copyright 2000-2020 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-2021 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; import com.intellij.icons.AllIcons; @@ -70,11 +70,6 @@ public interface PlatformIcons { Icon CHECK_ICON_SMALL = AllIcons.Actions.Checked; Icon CHECK_ICON_SMALL_SELECTED = AllIcons.Actions.Checked_selected; - /** @deprecated to be removed in IDEA 2021.1 (use expandable text field instead, see https://jetbrains.design/intellij/controls/built_in_button/) */ - @SuppressWarnings("unused") - @Deprecated - @ApiStatus.ScheduledForRemoval(inVersion = "2021.1") - Icon OPEN_EDIT_DIALOG_ICON = AllIcons.Actions.ShowViewer; Icon FLATTEN_PACKAGES_ICON = AllIcons.ObjectBrowser.FlattenPackages; Icon EDIT_IN_SECTION_ICON = AllIcons.Actions.Edit; Icon CLASS_INITIALIZER = AllIcons.Nodes.ClassInitializer; diff --git a/platform/core-api/src/com/intellij/util/PsiIconUtil.java b/platform/core-api/src/com/intellij/util/PsiIconUtil.java index c8913507cde9..b26bbef4f6b4 100644 --- a/platform/core-api/src/com/intellij/util/PsiIconUtil.java +++ b/platform/core-api/src/com/intellij/util/PsiIconUtil.java @@ -1,4 +1,4 @@ -// Copyright 2000-2020 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-2021 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; import com.intellij.ide.IconProvider; @@ -11,11 +11,17 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; public final class PsiIconUtil { - @Nullable - public static Icon getProvidersIcon(@NotNull PsiElement element, @Iconable.IconFlags int flags) { - for (IconProvider provider : DumbService.getDumbAwareExtensions(element.getProject(), IconProvider.EXTENSION_POINT_NAME)) { + public static @Nullable Icon getProvidersIcon(@NotNull PsiElement element, @Iconable.IconFlags int flags) { + boolean isDumb = DumbService.getInstance(element.getProject()).isDumb(); + for (IconProvider provider : IconProvider.EXTENSION_POINT_NAME.getIterable()) { + if (isDumb && !DumbService.isDumbAware(provider)) { + continue; + } + Icon icon = provider.getIcon(element, flags); - if (icon != null) return icon; + if (icon != null) { + return icon; + } } return null; } diff --git a/platform/core-impl/src/com/intellij/ide/plugins/PluginDescriptorLoader.kt b/platform/core-impl/src/com/intellij/ide/plugins/PluginDescriptorLoader.kt index fc842b0fc8d5..f79190236d5a 100644 --- a/platform/core-impl/src/com/intellij/ide/plugins/PluginDescriptorLoader.kt +++ b/platform/core-impl/src/com/intellij/ide/plugins/PluginDescriptorLoader.kt @@ -379,18 +379,38 @@ object PluginDescriptorLoader { bundledPluginDir: Path?, isRunningFromSources: Boolean) { val classLoader = PluginDescriptorLoader::class.java.classLoader - val urlsFromClassPath = LinkedHashMap() - var activity = StartUpMeasurer.startActivity("platform plugin collecting", ActivityCategory.APP_INIT) - val platformPluginURL = computePlatformPluginUrlAndCollectPluginUrls(classLoader, urlsFromClassPath, isRunningFromSources) - val pool = ForkJoinPool.commonPool() + var activity = StartUpMeasurer.startActivity("platform plugin collecting", ActivityCategory.APP_INIT) + val platformPrefix = System.getProperty(PlatformUtils.PLATFORM_PREFIX_KEY) + // should be the only plugin in lib (only for Ultimate and WebStorm for now) + val pathResolver = ClassPathXmlPathResolver(classLoader) + if ((platformPrefix == null || platformPrefix == PlatformUtils.IDEA_PREFIX || platformPrefix == PlatformUtils.WEB_PREFIX) && + (java.lang.Boolean.getBoolean("idea.use.dev.build.server") || !isRunningFromSources)) { + val factory = context.xmlFactory + val element = JDOMUtil.load(classLoader.getResourceAsStream(PluginManagerCore.PLUGIN_XML_PATH)!!, factory) - if (urlsFromClassPath.isNotEmpty()) { - activity = activity.endAndStart("plugin from classpath loading") - pool.invoke(LoadDescriptorsFromClassPathAction(urls = urlsFromClassPath, - context = context, - platformPluginURL = platformPluginURL, - pathResolver = ClassPathXmlPathResolver(classLoader))) + val descriptor = IdeaPluginDescriptorImpl(Paths.get(PathManager.getLibPath()), true) + descriptor.readExternal(element, pathResolver, context, descriptor, object : DataLoader { + override val pool: ZipFilePool + get() = throw IllegalStateException("must be not called") + + override fun load(path: String) = throw IllegalStateException("must be not called") + + override fun toString() = "product classpath" + }) + descriptor.setUseCoreClassLoader() + context.result.add(descriptor, /* overrideUseIfCompatible = */false) + } + else { + val urlsFromClassPath = LinkedHashMap() + val platformPluginURL = computePlatformPluginUrlAndCollectPluginUrls(classLoader, urlsFromClassPath, platformPrefix) + if (!urlsFromClassPath.isEmpty()) { + activity = activity.endAndStart("plugin from classpath loading") + pool.invoke(LoadDescriptorsFromClassPathAction(urls = urlsFromClassPath, + context = context, + platformPluginURL = platformPluginURL, + pathResolver = pathResolver)) + } } activity = activity.endAndStart("plugin from user dir loading") @@ -404,16 +424,7 @@ object PluginDescriptorLoader { private fun computePlatformPluginUrlAndCollectPluginUrls(loader: ClassLoader, urls: MutableMap, - isRunningFromSources: Boolean): URL? { - val platformPrefix = System.getProperty(PlatformUtils.PLATFORM_PREFIX_KEY) - - // should be the only plugin in lib (only for Ultimate and WebStorm for now) - if ((platformPrefix == null || platformPrefix == PlatformUtils.IDEA_PREFIX || platformPrefix == PlatformUtils.WEB_PREFIX) && - (java.lang.Boolean.getBoolean("idea.use.dev.build.server") || !isRunningFromSources)) { - urls.put(loader.getResource(PluginManagerCore.PLUGIN_XML_PATH)!!, PluginManagerCore.PLUGIN_XML) - return null - } - + platformPrefix: String?): URL? { var result: URL? = null if (platformPrefix != null) { val fileName = "${platformPrefix}Plugin.xml" diff --git a/platform/core-ui/src/ui/CoreIconManager.java b/platform/core-ui/src/ui/CoreIconManager.java index b186b3776193..401446bdd4da 100644 --- a/platform/core-ui/src/ui/CoreIconManager.java +++ b/platform/core-ui/src/ui/CoreIconManager.java @@ -43,9 +43,8 @@ public final class CoreIconManager implements IconManager, CoreAwareIconManager return AllIcons.Actions.Stub; } - @NotNull @Override - public Icon getIcon(@NotNull String path, @NotNull Class aClass) { + public @NotNull Icon getIcon(@NotNull String path, @NotNull Class aClass) { Icon icon = IconLoader.getIcon(path, aClass); Supplier tooltip = new IconDescriptionLoader(path); if (icon instanceof ScalableIcon) { @@ -103,16 +102,14 @@ public final class CoreIconManager implements IconManager, CoreAwareIconManager } } - @NotNull @Override - public Icon createEmptyIcon(@NotNull Icon icon) { + public @NotNull Icon createEmptyIcon(@NotNull Icon icon) { return EmptyIcon.create(icon); } - @NotNull @Override - public Icon createDeferredIcon(@Nullable Icon base, T param, @NotNull Function f) { - return IconDeferrer.getInstance().defer(base, param, f); + public @NotNull Icon createDeferredIcon(@Nullable Icon base, T param, @NotNull Function iconProducer) { + return IconDeferrer.getInstance().defer(base, param, iconProducer); } @Override @@ -130,24 +127,21 @@ public final class CoreIconManager implements IconManager, CoreAwareIconManager return new IconWrapperWithToolTipComposite(icon); } - @NotNull @Override - public com.intellij.ui.icons.RowIcon createRowIcon(int iconCount, com.intellij.ui.icons.RowIcon.Alignment alignment) { + public @NotNull com.intellij.ui.icons.RowIcon createRowIcon(int iconCount, com.intellij.ui.icons.RowIcon.Alignment alignment) { return new RowIcon(iconCount, alignment); } - @NotNull @Override - public com.intellij.ui.icons.RowIcon createRowIcon(Icon @NotNull ... icons) { + public @NotNull com.intellij.ui.icons.RowIcon createRowIcon(Icon @NotNull ... icons) { return new RowIcon(icons); } - @NotNull @Override - public RowIcon createLayeredIcon(@NotNull Iconable instance, Icon icon, int flags) { + public @NotNull RowIcon createLayeredIcon(@NotNull Iconable instance, Icon icon, int flags) { List layersFromProviders = new ArrayList<>(); for (IconLayerProvider provider : IconLayerProvider.EP_NAME.getExtensionList()) { - final Icon layerIcon = provider.getLayerIcon(instance, BitUtil.isSet(flags, FLAGS_LOCKED)); + Icon layerIcon = provider.getLayerIcon(instance, BitUtil.isSet(flags, FLAGS_LOCKED)); if (layerIcon != null) { layersFromProviders.add(layerIcon); } @@ -174,21 +168,18 @@ public final class CoreIconManager implements IconManager, CoreAwareIconManager return baseIcon; } - @NotNull @Override - public Icon createOffsetIcon(@NotNull Icon icon) { + public @NotNull Icon createOffsetIcon(@NotNull Icon icon) { return new OffsetIcon(icon); } - @NotNull @Override - public Icon colorize(Graphics2D g, @NotNull Icon source, @NotNull Color color) { + public @NotNull Icon colorize(Graphics2D g, @NotNull Icon source, @NotNull Color color) { return IconUtil.colorize(g, source, color); } - @NotNull @Override - public Icon createLayered(Icon @NotNull ... icons) { + public @NotNull Icon createLayered(Icon @NotNull ... icons) { return new LayeredIcon(icons); } @@ -204,8 +195,7 @@ public final class CoreIconManager implements IconManager, CoreAwareIconManager private static final class IconLayer { private final int flagMask; - @NotNull - private final Icon icon; + private final @NotNull Icon icon; private IconLayer(final int flagMask, @NotNull Icon icon) { BitUtil.assertOneBitMask(flagMask); diff --git a/platform/core-ui/src/ui/IconWrapperWithToolTipComposite.java b/platform/core-ui/src/ui/IconWrapperWithToolTipComposite.java index 9bbaca2c8b3c..fbe9b9baed29 100644 --- a/platform/core-ui/src/ui/IconWrapperWithToolTipComposite.java +++ b/platform/core-ui/src/ui/IconWrapperWithToolTipComposite.java @@ -1,4 +1,4 @@ -// Copyright 2000-2020 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-2021 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.ui.icons.CopyableIcon; @@ -9,10 +9,10 @@ import javax.swing.*; import java.awt.*; import java.util.Objects; -public class IconWrapperWithToolTipComposite implements IconWithToolTip, CopyableIcon, RetrievableIcon { +final class IconWrapperWithToolTipComposite implements IconWithToolTip, CopyableIcon, RetrievableIcon { private final Icon myIcon; - public IconWrapperWithToolTipComposite(Icon icon) { + IconWrapperWithToolTipComposite(Icon icon) { myIcon = icon; } diff --git a/platform/core-ui/src/ui/RowIcon.java b/platform/core-ui/src/ui/RowIcon.java index b93cb0a3e4d1..e483c46a6579 100644 --- a/platform/core-ui/src/ui/RowIcon.java +++ b/platform/core-ui/src/ui/RowIcon.java @@ -1,35 +1,24 @@ -// 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. +// Copyright 2000-2021 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.openapi.util.IconLoader; -import com.intellij.util.ArrayUtil; +import com.intellij.ui.scale.ScaleType; import com.intellij.util.IconUtil; -import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.JBCachingScalableIcon; -import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import static com.intellij.ui.scale.ScaleType.OBJ_SCALE; -import static java.lang.Math.ceil; - public class RowIcon extends JBCachingScalableIcon implements com.intellij.ui.icons.RowIcon, IconWithToolTip { - private final com.intellij.ui.icons.RowIcon.Alignment myAlignment; + private final Alignment myAlignment; private int myWidth; private int myHeight; - /** - * @use {@link com.intellij.ui.icons.RowIcon.Alignment instead} - */ - @Deprecated - @ApiStatus.ScheduledForRemoval(inVersion = "2021.2") - public enum Alignment {TOP, CENTER, BOTTOM} - private final Icon @NotNull [] myIcons; private Icon[] myScaledIcons; @@ -39,30 +28,10 @@ public class RowIcon extends JBCachingScalableIcon implements com.intel } public RowIcon(int iconCount/*, int orientation*/) { - this(iconCount, com.intellij.ui.icons.RowIcon.Alignment.TOP); + this(iconCount, Alignment.TOP); } - /** - * @deprecated use {@link #RowIcon(int, com.intellij.ui.icons.RowIcon.Alignment)} instead - */ - @Deprecated - @ApiStatus.ScheduledForRemoval(inVersion = "2021.2") public RowIcon(int iconCount, Alignment alignment) { - com.intellij.ui.icons.RowIcon.Alignment a = null; - if (alignment == Alignment.TOP) { - a = com.intellij.ui.icons.RowIcon.Alignment.TOP; - } - else if (alignment == Alignment.BOTTOM) { - a = com.intellij.ui.icons.RowIcon.Alignment.BOTTOM; - } - else if (alignment == Alignment.CENTER) { - a = com.intellij.ui.icons.RowIcon.Alignment.CENTER; - } - myAlignment = a; - myIcons = new Icon[iconCount]; - } - - public RowIcon(int iconCount, com.intellij.ui.icons.RowIcon.Alignment alignment) { myAlignment = alignment; myIcons = new Icon[iconCount]; } @@ -79,19 +48,17 @@ public class RowIcon extends JBCachingScalableIcon implements com.intel myAlignment = icon.myAlignment; myWidth = icon.myWidth; myHeight = icon.myHeight; - myIcons = ArrayUtil.copyOf(icon.myIcons); + myIcons = icon.myIcons.clone(); myScaledIcons = null; } - @NotNull @Override - public RowIcon copy() { + public @NotNull RowIcon copy() { return new RowIcon(this); } - @NotNull @Override - public com.intellij.ui.icons.RowIcon deepCopy() { + public @NotNull com.intellij.ui.icons.RowIcon deepCopy() { RowIcon icon = new RowIcon(this); for (int i = 0; i < icon.myIcons.length; i++) { icon.myIcons[i] = IconUtil.copy(icon.myIcons[i], null); @@ -119,8 +86,13 @@ public class RowIcon extends JBCachingScalableIcon implements com.intel @Override public Icon @NotNull [] getAllIcons() { - List icons = ContainerUtil.packNullables(myIcons); - return icons.toArray(new Icon[0]); + List list = new ArrayList<>(myIcons.length); + for (Icon element : myIcons) { + if (element != null) { + list.add(element); + } + } + return list.toArray(new Icon[0]); } public int hashCode() { @@ -128,7 +100,7 @@ public class RowIcon extends JBCachingScalableIcon implements com.intel } public boolean equals(Object obj) { - return obj instanceof RowIcon && Arrays.equals(((RowIcon)obj).myIcons, myIcons); + return obj == this || (obj instanceof RowIcon && Arrays.equals(((RowIcon)obj).myIcons, myIcons)); } @Override @@ -172,13 +144,13 @@ public class RowIcon extends JBCachingScalableIcon implements com.intel @Override public int getIconWidth() { getScaleContext().update(); - return (int)ceil(scaleVal(myWidth, OBJ_SCALE)); + return (int)Math.ceil(scaleVal(myWidth, ScaleType.OBJ_SCALE)); } @Override public int getIconHeight() { getScaleContext().update(); - return (int)ceil(scaleVal(myHeight, OBJ_SCALE)); + return (int)Math.ceil(scaleVal(myHeight, ScaleType.OBJ_SCALE)); } private void updateSize() { @@ -194,9 +166,8 @@ public class RowIcon extends JBCachingScalableIcon implements com.intel myHeight = height; } - @NotNull @Override - public Icon getDarkIcon(boolean isDark) { + public @NotNull Icon getDarkIcon(boolean isDark) { RowIcon newIcon = copy(); for (int i=0; i() - internal const val VERSION = "28" + internal const val VERSION = "29" internal fun sortItems(items: MutableList) { items.sortWith(Comparator { o1, o2 -> 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 5a793b04fa19..9325449ff820 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 @@ -92,13 +92,11 @@ public class ModuleImpl extends ComponentManagerImpl implements ModuleEx { public void init(@Nullable Runnable beforeComponentCreation) { // do not measure (activityNamePrefix method not overridden by this class) // because there are a lot of modules and no need to measure each one - //noinspection unchecked - registerComponents((List)PluginManagerCore.getLoadedPlugins(), null); + registerComponents(PluginManagerCore.getLoadedPlugins(null), ApplicationManager.getApplication(), null); if (!isPersistent()) { registerService(IComponentStore.class, NonPersistentModuleStore.class, - Objects.requireNonNull(PluginManagerCore.getPlugin(PluginManagerCore.CORE_ID), - "Could not find plugin by id: " + PluginManagerCore.CORE_ID), + ComponentManagerImpl.getFakeCorePluginDescriptor(), true); } if (beforeComponentCreation != null) { diff --git a/platform/lang-impl/src/com/intellij/workspaceModel/ide/impl/legacyBridge/module/ModuleBridgeImpl.kt b/platform/lang-impl/src/com/intellij/workspaceModel/ide/impl/legacyBridge/module/ModuleBridgeImpl.kt index 2f8f9c0e314e..a74b4433819f 100644 --- a/platform/lang-impl/src/com/intellij/workspaceModel/ide/impl/legacyBridge/module/ModuleBridgeImpl.kt +++ b/platform/lang-impl/src/com/intellij/workspaceModel/ide/impl/legacyBridge/module/ModuleBridgeImpl.kt @@ -5,6 +5,7 @@ import com.intellij.facet.FacetFromExternalSourcesStorage import com.intellij.facet.FacetManager import com.intellij.ide.plugins.IdeaPluginDescriptorImpl import com.intellij.ide.plugins.PluginManagerCore +import com.intellij.openapi.application.Application import com.intellij.openapi.application.WriteAction import com.intellij.openapi.module.Module import com.intellij.openapi.module.impl.ModuleImpl @@ -63,8 +64,8 @@ internal class ModuleBridgeImpl( super.rename(newName, notifyStorage) } - override fun registerComponents(plugins: List, listenerCallbacks: MutableList?) { - super.registerComponents(plugins, null) + override fun registerComponents(plugins: List, app: Application?, listenerCallbacks: MutableList?) { + super.registerComponents(plugins, app, null) val corePlugin = plugins.find { it.pluginId == PluginManagerCore.CORE_ID } ?: return registerComponent(ModuleRootManager::class.java, ModuleRootComponentBridge::class.java, corePlugin, true) diff --git a/platform/platform-api/src/com/intellij/ui/AnimatedIcon.java b/platform/platform-api/src/com/intellij/ui/AnimatedIcon.java index 0e70f28bbeb3..c0b9ce6ddbee 100644 --- a/platform/platform-api/src/com/intellij/ui/AnimatedIcon.java +++ b/platform/platform-api/src/com/intellij/ui/AnimatedIcon.java @@ -1,4 +1,4 @@ -// Copyright 2000-2020 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-2021 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.icons.AllIcons; @@ -7,19 +7,17 @@ import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.Key; import com.intellij.util.concurrency.EdtScheduledExecutorService; import com.intellij.util.ui.UIUtil; -import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; +import java.util.Collections; +import java.util.IdentityHashMap; import java.util.List; import java.util.Set; - -import static com.intellij.util.containers.ContainerUtil.immutableList; -import static java.awt.AlphaComposite.SrcAtop; -import static java.util.concurrent.TimeUnit.MILLISECONDS; +import java.util.concurrent.TimeUnit; public class AnimatedIcon implements Icon { private static final Logger LOG = Logger.getInstance(AnimatedIcon.class); @@ -50,7 +48,7 @@ public class AnimatedIcon implements Icon { } public static final int DELAY = 130; - public static final List ICONS = immutableList( + public static final List ICONS = List.of( AllIcons.Process.Step_1, AllIcons.Process.Step_2, AllIcons.Process.Step_3, @@ -69,7 +67,7 @@ public class AnimatedIcon implements Icon { } public static final int DELAY = 130; - public static final List ICONS = immutableList( + public static final List ICONS = List.of( AllIcons.Process.Big.Step_1, AllIcons.Process.Big.Step_2, AllIcons.Process.Big.Step_3, @@ -82,13 +80,13 @@ public class AnimatedIcon implements Icon { public static final AnimatedIcon INSTANCE = new Big(); } - public static class Recording extends AnimatedIcon { + public static final class Recording extends AnimatedIcon { public Recording() { super(DELAY, ICONS.toArray(new Icon[0])); } public static final int DELAY = 250; - public static final List ICONS = immutableList( + public static final List ICONS = List.of( AllIcons.Ide.Macro.Recording_1, AllIcons.Ide.Macro.Recording_2, AllIcons.Ide.Macro.Recording_3, @@ -96,13 +94,13 @@ public class AnimatedIcon implements Icon { } @ApiStatus.Internal - public static class FS extends AnimatedIcon { + public static final class FS extends AnimatedIcon { public FS() { super(DELAY, ICONS.toArray(new Icon[0])); } public static final int DELAY = 50; - public static final List ICONS = immutableList( + public static final List ICONS = List.of( AllIcons.Process.FS.Step_1, AllIcons.Process.FS.Step_2, AllIcons.Process.FS.Step_3, @@ -124,7 +122,7 @@ public class AnimatedIcon implements Icon { } @ApiStatus.Internal - public static class Blinking extends AnimatedIcon { + public static final class Blinking extends AnimatedIcon { public Blinking(@NotNull Icon icon) { this(1000, icon); } @@ -135,7 +133,7 @@ public class AnimatedIcon implements Icon { } @ApiStatus.Internal - public static class Fading extends AnimatedIcon { + public static final class Fading extends AnimatedIcon { public Fading(@NotNull Icon icon) { this(1000, icon); } @@ -163,7 +161,7 @@ public class AnimatedIcon implements Icon { if (alpha < 1 && g instanceof Graphics2D) { Graphics2D g2d = (Graphics2D)g.create(); try { - g2d.setComposite(SrcAtop.derive(alpha)); + g2d.setComposite(AlphaComposite.SrcAtop.derive(alpha)); icon.paintIcon(c, g2d, x, y); } finally { @@ -181,7 +179,7 @@ public class AnimatedIcon implements Icon { private final Frame[] frames; - private final Set requested = new ReferenceOpenHashSet<>(); + private final Set requested = Collections.newSetFromMap(new IdentityHashMap<>()); private long time; private int index; @@ -239,21 +237,23 @@ public class AnimatedIcon implements Icon { } private void requestRefresh(@Nullable Component c) { - if (c != null && !requested.contains(c) && canRefresh(c)) { - Frame frame = frames[index]; - int delay = frame.getDelay(); - if (delay > 0) { - requested.add(c); - EdtScheduledExecutorService.getInstance().schedule(() -> { - requested.remove(c); - if (canRefresh(c)) { - doRefresh(c); - } - }, delay, MILLISECONDS); - } - else { - doRefresh(c); - } + if (c == null || requested.contains(c) || !canRefresh(c)) { + return; + } + + Frame frame = frames[index]; + int delay = frame.getDelay(); + if (delay > 0) { + requested.add(c); + EdtScheduledExecutorService.getInstance().schedule(() -> { + requested.remove(c); + if (canRefresh(c)) { + doRefresh(c); + } + }, delay, TimeUnit.MILLISECONDS); + } + else { + doRefresh(c); } } @@ -285,12 +285,12 @@ public class AnimatedIcon implements Icon { } protected void doRefresh(@NotNull Component component) { - Runnable delegate = UIUtil.getClientProperty(component, REFRESH_DELEGATE); - if (delegate != null) { - delegate.run(); + Runnable delegate = component instanceof JComponent ? (Runnable)((JComponent)component).getClientProperty(REFRESH_DELEGATE) : null; + if (delegate == null) { + component.repaint(); } else { - component.repaint(); + delegate.run(); } } diff --git a/platform/platform-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java b/platform/platform-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java index ab51090bdac9..0e813811aea0 100644 --- a/platform/platform-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java +++ b/platform/platform-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java @@ -1,4 +1,4 @@ -// Copyright 2000-2020 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-2021 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.colors; @@ -1260,7 +1260,7 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract metaInfo = JDOMUtil.load(JDOMUtil.writeElement(metaInfo)); scheme.addContent(0, metaInfo); } - JDOMUtil.write(scheme, path.toFile()); + JDOMUtil.write(scheme, path); VirtualFileManager.getInstance().syncRefresh(); } catch (Exception e) { diff --git a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java index bf38e1adf454..9eee37752471 100644 --- a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java +++ b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java @@ -82,8 +82,7 @@ public final class IdeEventQueue extends EventQueue { private static final Logger TYPEAHEAD_LOG = Logger.getInstance(IdeEventQueue.class.getName() + ".typeahead"); private static final Logger FOCUS_AWARE_RUNNABLES_LOG = Logger.getInstance(IdeEventQueue.class.getName() + ".runnables"); private static final boolean ourActionAwareTypeaheadEnabled = !SystemInfoRt.isMac && Boolean.getBoolean("action.aware.typeAhead"); - private static final boolean ourTypeAheadSearchEverywhereEnabled = - SystemProperties.getBooleanProperty("action.aware.typeAhead.searchEverywhere", false); + private static final boolean ourTypeAheadSearchEverywhereEnabled = Boolean.getBoolean("action.aware.typeAhead.searchEverywhere"); private static final boolean ourSkipMetaPressOnLinux = Boolean.getBoolean("keymap.skip.meta.press.on.linux"); private static TransactionGuardImpl ourTransactionGuard; private static ProgressManager ourProgressManager; diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/DynamicPlugins.kt b/platform/platform-impl/src/com/intellij/ide/plugins/DynamicPlugins.kt index 112c2a86005e..fefcc7e02078 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/DynamicPlugins.kt +++ b/platform/platform-impl/src/com/intellij/ide/plugins/DynamicPlugins.kt @@ -1146,11 +1146,11 @@ private fun loadPluginDescriptor(pluginDescriptor: IdeaPluginDescriptorImpl, updateDependenciesStatus(pluginDescriptor, pluginStateChecker) val list = listOf(pluginDescriptor) - app.registerComponents(list, listenerCallbacks) + app.registerComponents(list, ApplicationManager.getApplication(), listenerCallbacks) for (openProject in ProjectUtil.getOpenProjects()) { - (openProject as ComponentManagerImpl).registerComponents(list, listenerCallbacks) + (openProject as ComponentManagerImpl).registerComponents(list, ApplicationManager.getApplication(), listenerCallbacks) for (module in ModuleManager.getInstance(openProject).modules) { - (module as ComponentManagerImpl).registerComponents(list, listenerCallbacks) + (module as ComponentManagerImpl).registerComponents(list, ApplicationManager.getApplication(), listenerCallbacks) } } diff --git a/platform/platform-impl/src/com/intellij/idea/ApplicationLoader.kt b/platform/platform-impl/src/com/intellij/idea/ApplicationLoader.kt index bae5ff964704..b8ed59a7d57b 100644 --- a/platform/platform-impl/src/com/intellij/idea/ApplicationLoader.kt +++ b/platform/platform-impl/src/com/intellij/idea/ApplicationLoader.kt @@ -1,5 +1,6 @@ // Copyright 2000-2021 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. @file:JvmName("ApplicationLoader") +@file:ApiStatus.Internal package com.intellij.idea import com.intellij.diagnostic.* @@ -41,6 +42,7 @@ import java.awt.Font import java.awt.GraphicsEnvironment import java.awt.dnd.DragSource import java.io.IOException +import java.nio.charset.StandardCharsets import java.nio.file.Files import java.nio.file.Path import java.util.concurrent.* @@ -55,19 +57,56 @@ private fun executeInitAppInEdt(args: List, initAppActivity: Activity, pluginDescriptorFuture: CompletableFuture>) { StartupUtil.patchSystem(LOG) + val registerComponentFuture = CompletableFuture>() val app = runActivity("create app") { ApplicationImpl(java.lang.Boolean.getBoolean(PluginManagerCore.IDEA_IS_INTERNAL_PROPERTY), false, Main.isHeadless(), - Main.isCommandLine()) + Main.isCommandLine()) { app -> + ForkJoinPool.commonPool().execute { + pluginDescriptorFuture + .thenApply { + if (!app.isHeadlessEnvironment) { + ForkJoinPool.commonPool().execute { + runActivity("icons preloading") { + if (app.isInternal) { + IconLoader.setStrictGlobally(true) + } + + AsyncProcessIcon("") + AnimatedIcon.Blinking(AllIcons.Ide.FatalError) + AnimatedIcon.FS() + } + + runActivity("migLayout") { + // IDEA-170295 + PlatformDefaults.setLogicalPixelBase(PlatformDefaults.BASE_FONT_SIZE) + } + } + } + + runMainActivity("app component registration") { + app.registerComponents(it, app, null) + } + it + } + .whenComplete { result, error -> + if (error == null) { + registerComponentFuture.complete(result) + } + else { + registerComponentFuture.completeExceptionally(error) + } + } + } + } } - val registerFuture = registerAppComponents(pluginDescriptorFuture, app) if (args.isEmpty()) { - startApp(app, IdeStarter(), initAppActivity, registerFuture, args) + startApp(app, IdeStarter(), initAppActivity, registerComponentFuture, args) return } // `ApplicationStarter` is an extension, so to find a starter extensions must be registered first - registerFuture + registerComponentFuture .thenRun { val starter = findStarter(args.first()) ?: IdeStarter() if (Main.isHeadless() && !starter.isHeadless) { @@ -89,7 +128,7 @@ private fun executeInitAppInEdt(args: List, } starter.premain(args) - startApp(app, starter, initAppActivity, registerFuture, args) + startApp(app, starter, initAppActivity, registerComponentFuture, args) } .exceptionally { StartupAbortedException.processException(it) @@ -97,59 +136,35 @@ private fun executeInitAppInEdt(args: List, } } -@ApiStatus.Internal -fun registerAppComponents(pluginFuture: CompletableFuture>, - app: ApplicationImpl): CompletableFuture> { - return pluginFuture.thenApply { - runMainActivity("app component registration") { - app.registerComponents(it, null) - } - it - } -} - private fun startApp(app: ApplicationImpl, starter: ApplicationStarter, initAppActivity: Activity, - registerFuture: CompletableFuture>, + registerComponentFuture: 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 - val registerRegistryAndInitStoreFuture = registerRegistryAndInitStore(registerFuture, app) - - val headless = app.isHeadlessEnvironment - if (!headless) { - runActivity("icon loader activation") { - // todo investigate why in test mode dummy icon manager is not suitable - IconLoader.activate() - IconLoader.setStrictGlobally(app.isInternal) - } + val initStoreFuture = registerComponentFuture.thenApply { plugins -> + // initSystemProperties or RegistryKeyBean.addKeysFromPlugins maybe not yet performed, + // but it is ok because registry is not and should be not used + initConfigurationStore(app) + plugins } - val nonEdtExecutor = Executor { - if (app.isDispatchThread) { - ForkJoinPool.commonPool().execute(it) - } - else { - it.run() - } + val preloadSyncServiceFuture = initStoreFuture.thenAccept { + preloadServices(it, app, activityPrefix = "") } - // preload services only after icon activation - val preloadSyncServiceFuture = registerRegistryAndInitStoreFuture - .thenComposeAsync({ - preloadServices(it, app, activityPrefix = "") - }, nonEdtExecutor) + initStoreFuture.thenRunAsync({ + runActivity("add registry keys") { + RegistryKeyBean.addKeysFromPlugins() + } + }, ForkJoinPool.commonPool()) - if (!headless) { + if (!app.isHeadlessEnvironment) { if (SystemInfoRt.isMac) { runActivity("mac app init") { MacOSApplicationProvider.initApplication() } - registerFuture.thenRunAsync(Runnable { + initStoreFuture.thenRunAsync(Runnable { // ensure that TouchBarsManager is loaded before WelcomeFrame/project // do not wait completion - it is thread safe and not required for application start runActivity("mac touchbar") { @@ -167,69 +182,47 @@ private fun startApp(app: ApplicationImpl, } WeakFocusStackManager.getInstance() - - ForkJoinPool.commonPool().execute { - runActivity("migLayout") { - // IDEA-170295 - PlatformDefaults.setLogicalPixelBase(PlatformDefaults.BASE_FONT_SIZE) - } - } - - ForkJoinPool.commonPool().execute { - runActivity("icons preloading") { - AsyncProcessIcon("") - AnimatedIcon.Blinking(AllIcons.Ide.FatalError) - AnimatedIcon.FS() - } - } } - @Suppress("RemoveExplicitTypeArguments") - CompletableFuture.allOf(registerRegistryAndInitStoreFuture, StartupUtil.getServerFuture()) + initStoreFuture .thenCompose { // `invokeLater()` is needed to place the app starting code on a freshly minted `IdeEventQueue` instance val placeOnEventQueueActivity = initAppActivity.startChild(Activities.PLACE_ON_EVENT_QUEUE) val loadComponentInEdtFuture = CompletableFuture.runAsync({ - placeOnEventQueueActivity.end() + placeOnEventQueueActivity.end() - val indicator = if (SplashManager.SPLASH_WINDOW == null) { - null - } - else object : EmptyProgressIndicator() { - override fun setFraction(fraction: Double) { - SplashManager.SPLASH_WINDOW.showProgress(fraction) - } - } - app.loadComponents(indicator) - }, Executor { ApplicationManager.getApplication().invokeLater(it) }) - - CompletableFuture.allOf(loadComponentInEdtFuture, preloadSyncServiceFuture) - } - .thenRunAsync({ - val activity = initAppActivity.startChild("app initialized callback") - val tasks = callAppInitialized(app) - - // should be after scheduling all app initialized listeners (because this activity is not important) - if (!Main.isLightEdit()) { - ForkJoinPool.commonPool().execute { - // execute in parallel to component loading - this functionality should be used only by plugin functionality that is used after start-up - runActivity("system properties setting") { - SystemPropertyBean.initSystemProperties() + val indicator = if (SplashManager.SPLASH_WINDOW == null) { + null + } + else object : EmptyProgressIndicator() { + override fun setFraction(fraction: Double) { + SplashManager.SPLASH_WINDOW.showProgress(fraction) } } + app.loadComponents(indicator) + }, Executor { ApplicationManager.getApplication().invokeLater(it) }) + + CompletableFuture.allOf(loadComponentInEdtFuture, preloadSyncServiceFuture, StartupUtil.getServerFuture()) + } + .thenRunAsync({ + initAppActivity.runChild("app initialized callback") { + ForkJoinTask.invokeAll(callAppInitialized(app)) } - - ForkJoinTask.invokeAll(tasks) - - activity.end() - if (!headless) { + if (!app.isHeadlessEnvironment) { addActivateAndWindowsCliListeners() } - initAppActivity.end() - }, nonEdtExecutor /* if `loadComponentInEdtFuture` is completed after `preloadSyncServiceFuture`, - then this task will be executed in EDT, so force execution out of EDT */) + }, Executor { + // if `loadComponentInEdtFuture` is completed after `preloadSyncServiceFuture`, + // then this task will be executed in EDT, so force execution out of EDT + if (app.isDispatchThread) { + ForkJoinPool.commonPool().execute(it) + } + else { + it.run() + } + }) .thenRun { if (starter.requiredModality == ApplicationStarter.NOT_IN_EDT) { starter.main(args) @@ -251,7 +244,6 @@ private fun startApp(app: ApplicationImpl, } } -@ApiStatus.Internal @JvmOverloads fun preloadServices(plugins: List, container: ComponentManagerImpl, @@ -272,27 +264,6 @@ fun preloadServices(plugins: List, return logError(result.syncPreloadedServices) } -@ApiStatus.Internal -fun registerRegistryAndInitStore(registerFuture: CompletableFuture>, - app: ApplicationImpl): CompletableFuture> { - // async because register task is executed in EDT - force execution in a pooled thread - return registerFuture.thenComposeAsync({ plugins -> - val future = CompletableFuture.runAsync({ - runActivity("add registry keys") { - RegistryKeyBean.addKeysFromPlugins() - } - }, ForkJoinPool.commonPool()) - - // initSystemProperties or RegistryKeyBean.addKeysFromPlugins maybe not yet performed, - // but it is ok because registry is not and should be not used - initConfigurationStore(app) - - future.thenApply { - plugins - } - }, ForkJoinPool.commonPool()) -} - private fun addActivateAndWindowsCliListeners() { StartupUtil.addExternalInstanceListener { rawArgs -> LOG.info("External instance command received") @@ -395,10 +366,8 @@ private fun loadSystemFonts() { GraphicsEnvironment.getLocalGraphicsEnvironment().availableFontFamilyNames } -@ApiStatus.Internal fun findStarter(key: String) = ApplicationStarter.EP_NAME.iterable.find { it == null || it.commandName == key } -@ApiStatus.Internal fun initConfigurationStore(app: ApplicationImpl) { var activity = StartUpMeasurer.startMainActivity("beforeApplicationLoaded") val configPath = PathManager.getConfigDir() @@ -450,7 +419,6 @@ private fun processProgramArguments(args: List): List { return arguments } -@ApiStatus.Internal fun callAppInitialized(app: Application): List { val extensionArea = app.extensionArea as ExtensionsAreaImpl val extensionPoint = extensionArea.getExtensionPoint("com.intellij.applicationInitializedListener") @@ -471,18 +439,33 @@ fun callAppInitialized(app: Application): List { } extensionPoint.reset() - ForkJoinPool.commonPool().execute { - runActivity("create locator file") { - val locatorFile = Path.of(PathManager.getSystemPath(), ApplicationEx.LOCATOR_FILE_NAME) - try { - locatorFile.parent?.createDirectories() - Files.writeString(locatorFile, PathManager.getHomePath(), Charsets.UTF_8) + // should be after scheduling all app initialized listeners (because this activity is not important) + result.add(object : RecursiveAction() { + override fun compute() { + val pool = ForkJoinPool.commonPool() + pool.execute { + runActivity("create locator file") { + val locatorFile = Path.of(PathManager.getSystemPath(), ApplicationEx.LOCATOR_FILE_NAME) + try { + locatorFile.parent?.createDirectories() + Files.writeString(locatorFile, PathManager.getHomePath(), StandardCharsets.UTF_8) + } + catch (e: IOException) { + LOG.warn("Can't store a location in '$locatorFile'", e) + } + } } - catch (e: IOException) { - LOG.warn("Can't store a location in '$locatorFile'", e) + + if (!Main.isLightEdit()) { + // this functionality should be used only by plugin functionality that is used after start-up + pool.execute { + runActivity("system properties setting") { + SystemPropertyBean.initSystemProperties() + } + } } } - } + }) return result } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/idea/StartupUtil.java b/platform/platform-impl/src/com/intellij/idea/StartupUtil.java index 248256fba599..2ae870f30209 100644 --- a/platform/platform-impl/src/com/intellij/idea/StartupUtil.java +++ b/platform/platform-impl/src/com/intellij/idea/StartupUtil.java @@ -29,12 +29,12 @@ import com.intellij.openapi.application.ConfigImportHelper; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.application.impl.ApplicationInfoImpl; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.ShutDownTracker; import com.intellij.openapi.util.SystemInfoRt; import com.intellij.openapi.util.io.win32.IdeaWin32; import com.intellij.openapi.wm.impl.X11UiUtil; import com.intellij.ui.AppUIUtil; +import com.intellij.ui.CoreIconManager; import com.intellij.ui.IconManager; import com.intellij.ui.scale.JBUIScale; import com.intellij.util.EnvironmentUtil; @@ -187,14 +187,17 @@ public final class StartupUtil { private static void runPreAppClass(@NotNull Logger log) { String classBeforeAppProperty = System.getProperty(IDEA_CLASS_BEFORE_APPLICATION_PROPERTY); if (classBeforeAppProperty != null) { + Activity activity = StartUpMeasurer.startActivity("pre app class running", ActivityCategory.APP_INIT); try { Class clazz = Class.forName(classBeforeAppProperty); Method invokeMethod = clazz.getDeclaredMethod("invoke"); + invokeMethod.setAccessible(true); invokeMethod.invoke(null); } catch (Exception e) { log.error("Failed pre-app class init for class " + classBeforeAppProperty, e); } + activity.end(); } } @@ -770,6 +773,10 @@ public final class StartupUtil { "\n " + PathManager.PROPERTY_LOG_PATH + '=' + logPath(PathManager.getLogPath()) ); + log.info("CPU cores: " + Runtime.getRuntime().availableProcessors() + + "; ForkJoinPool.commonPool: " + ForkJoinPool.commonPool() + + "; factory: " + ForkJoinPool.commonPool().getFactory()); + activity.end(); } @@ -814,11 +821,13 @@ public final class StartupUtil { Class dialogClass = Class.forName(stepsDialogName); Constructor constr = dialogClass.getConstructor(AppStarter.class); ((CommonCustomizeIDEWizardDialog) constr.newInstance(appStarter)).showIfNeeded(); - } catch (Throwable e) { + } + catch (Throwable e) { Main.showMessage(BootstrapBundle.message("bootstrap.error.title.configuration.wizard.failed"), e); return; } - } else if (Boolean.parseBoolean(System.getProperty("idea.show.customize.ide.wizard"))) { + } + else if (Boolean.parseBoolean(System.getProperty("idea.show.customize.ide.wizard"))) { new CustomizeIDEWizardDialog(provider, appStarter, true, false).showIfNeeded(); } @@ -827,47 +836,38 @@ public final class StartupUtil { } // must be called from EDT - public static boolean patchSystem(@NotNull Logger log) { + public static boolean patchSystem(@NotNull Logger log) throws Throwable { if (!ourSystemPatched.compareAndSet(false, true)) { return false; } Activity activity = StartUpMeasurer.startActivity("event queue replacing", ActivityCategory.APP_INIT); - replaceSystemEventQueue(log); + // replace system event queue + //noinspection ResultOfMethodCallIgnored + IdeEventQueue.getInstance(); + if (!Main.isHeadless()) { - patchSystemForUi(log); + if ("true".equals(System.getProperty("idea.check.swing.threading"))) { + activity = activity.endAndStart("repaint manager set"); + RepaintManager.setCurrentManager(new AssertiveRepaintManager()); + } + + if (SystemInfoRt.isXWindow) { + activity = activity.endAndStart("linux wm set"); + String wmName = X11UiUtil.getWmName(); + log.info("WM detected: " + wmName); + if (wmName != null) { + X11UiUtil.patchDetectedWm(wmName); + } + } + + activity = activity.endAndStart("icon manager activation"); + IconManager.activate(new CoreIconManager()); } activity.end(); return true; } - @ApiStatus.Internal - public static void replaceSystemEventQueue(@NotNull Logger log) { - log.info("CPU cores: " + Runtime.getRuntime().availableProcessors() + - "; ForkJoinPool.commonPool: " + ForkJoinPool.commonPool() + - "; factory: " + ForkJoinPool.commonPool().getFactory()); - - // replaces system event queue - //noinspection ResultOfMethodCallIgnored - IdeEventQueue.getInstance(); - } - - private static void patchSystemForUi(@NotNull Logger log) { - if ("true".equals(System.getProperty("idea.check.swing.threading"))) { - RepaintManager.setCurrentManager(new AssertiveRepaintManager()); - } - - if (SystemInfoRt.isXWindow) { - String wmName = X11UiUtil.getWmName(); - log.info("WM detected: " + wmName); - if (wmName != null) { - X11UiUtil.patchDetectedWm(wmName); - } - } - - IconManager.activate(); - } - private static boolean showUserAgreementAndConsentsIfNeeded(@NotNull Logger log, @NotNull CompletableFuture initUiTask, @NotNull EndUserAgreement.Document agreement) { @@ -889,18 +889,17 @@ public final class StartupUtil { try { if (!ourSystemPatched.get()) { EventQueue.invokeAndWait(() -> { - if (!patchSystem(log)) { - return; - } - try { + if (!patchSystem(log)) { + return; + } + UIManager.setLookAndFeel(IntelliJLaf.class.getName()); - IconManager.activate(); - // todo investigate why in test mode dummy icon manager is not suitable - IconLoader.activate(); // we don't set AppUIUtil.updateForDarcula(false) because light is default } - catch (Exception ignore) { } + catch (Throwable e) { + log.warn(e); + } }); } 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 752e0d2adea5..de3c591599dc 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 @@ -59,6 +59,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; +@ApiStatus.Internal public class ApplicationImpl extends ComponentManagerImpl implements ApplicationEx { // do not use PluginManager.processException() because it can force app to exit, but we want just log error and continue private static final Logger LOG = Logger.getInstance(ApplicationImpl.class); @@ -110,6 +111,10 @@ public class ApplicationImpl extends ComponentManagerImpl implements Application } public ApplicationImpl(boolean isInternal, boolean isUnitTestMode, boolean isHeadless, boolean isCommandLine) { + this(isInternal, isUnitTestMode, isHeadless, isCommandLine, null); + } + + public ApplicationImpl(boolean isInternal, boolean isUnitTestMode, boolean isHeadless, boolean isCommandLine, Consumer initTask) { super(null); // reset back to null only when all components already disposed @@ -119,8 +124,14 @@ public class ApplicationImpl extends ComponentManagerImpl implements Application registerServiceInstance(ApplicationInfo.class, ApplicationInfoImpl.getShadowInstance(), ComponentManagerImpl.getFakeCorePluginDescriptor()); registerServiceInstance(Application.class, this, ComponentManagerImpl.getFakeCorePluginDescriptor()); - boolean strictMode = isUnitTestMode || isInternal; - BundleBase.assertOnMissedKeys(strictMode); + if (initTask != null) { + // myLock is a final field, we cannot do init in EDT and set it later + initTask.accept(this); + } + + if (isUnitTestMode || isInternal) { + BundleBase.assertOnMissedKeys(true); + } // do not crash AWT on exceptions AWTExceptionHandler.register(); @@ -141,18 +152,16 @@ public class ApplicationImpl extends ComponentManagerImpl implements Application Activity activity = StartUpMeasurer.startActivity("AppDelayQueue instantiation", ActivityCategory.APP_INIT); AtomicReference edtThread = new AtomicReference<>(); - Runnable runnable = () -> { + EdtInvocationManager.invokeAndWaitIfNeeded(() -> { // instantiate AppDelayQueue which starts "Periodic task thread" which we'll mark busy to prevent this EDT to die // that thread was chosen because we know for sure it's running - AppScheduledExecutorService service = (AppScheduledExecutorService)AppExecutorUtil.getAppScheduledExecutorService(); - Thread thread = service.getPeriodicTasksThread(); + Thread thread = ((AppScheduledExecutorService)AppExecutorUtil.getAppScheduledExecutorService()).getPeriodicTasksThread(); AWTAutoShutdown.getInstance().notifyThreadBusy(thread); // needed for EDT not to exit suddenly Disposer.register(this, () -> { AWTAutoShutdown.getInstance().notifyThreadFree(thread); // allow for EDT to exit - needed for Upsource }); edtThread.set(Thread.currentThread()); - }; - EdtInvocationManager.invokeAndWaitIfNeeded(runnable); + }); myLock = new ReadMostlyRWLock(edtThread.get()); // Acquire IW lock on EDT indefinitely in legacy mode if (!USE_SEPARATE_WRITE_THREAD || isUnitTestMode) { @@ -348,14 +357,13 @@ public class ApplicationImpl extends ComponentManagerImpl implements Application @Override public final void load() { List plugins = PluginManagerCore.getLoadedPlugins(null); - registerComponents(plugins, null); + registerComponents(plugins, this, null); ApplicationLoader.initConfigurationStore(this); preloadServices(plugins, "", false).getSyncPreloadedServices().join(); loadComponents(null); ForkJoinTask.invokeAll(ApplicationLoader.callAppInitialized(this)); } - @ApiStatus.Internal public final void loadComponents(@Nullable ProgressIndicator indicator) { if (indicator == null) { // no splash, no need to to use progress manager @@ -632,7 +640,6 @@ public class ApplicationImpl extends ComponentManagerImpl implements Application return !ProgressManager.getInstance().hasProgressIndicator(); } - @ApiStatus.Internal public final @NotNull CompletableFuture<@NotNull ProgressWindow> createProgressWindowAsyncIfNeeded(@NotNull @NlsContexts.ProgressTitle String progressTitle, boolean canBeCanceled, boolean shouldShowModalWindow, @@ -1300,7 +1307,6 @@ public class ApplicationImpl extends ComponentManagerImpl implements Application * so that background threads with read actions don't see half-baked PSI/VFS/etc. The runnable may perform write actions itself, * callers should be ready for those. */ - @ApiStatus.Internal public void executeSuspendingWriteAction(@Nullable Project project, @NotNull @NlsContexts.DialogTitle String title, @NotNull Runnable runnable) { assertIsWriteThread(); if (!myLock.isWriteLocked()) { @@ -1393,7 +1399,6 @@ public class ApplicationImpl extends ComponentManagerImpl implements Application (isCommandLine() ? " (Command line)" : ""); } - @ApiStatus.Internal @Override public @NotNull String activityNamePrefix() { return "app "; @@ -1425,7 +1430,6 @@ public class ApplicationImpl extends ComponentManagerImpl implements Application myDispatcher.neuterMultiCasterWhilePerformanceTestIsRunningUntil(disposable); } - @ApiStatus.Internal public boolean getComponentCreated() { return getContainerState().get().compareTo(ContainerState.COMPONENT_CREATED) >= 0; } diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ReadMostlyRWLock.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ReadMostlyRWLock.java index af10faff7cba..3b6f66afa954 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ReadMostlyRWLock.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ReadMostlyRWLock.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-2021 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.application.impl; import com.intellij.openapi.application.AccessToken; @@ -43,7 +29,7 @@ import java.util.concurrent.locks.LockSupport; * Read lock: flips {@link Reader#readRequested} bit in its own thread local {@link Reader} structure and waits for writer to release its lock by checking {@link #writeRequested}.
* Write lock: sets global {@link #writeRequested} bit and waits for all readers (in global {@link #readers} list) to release their locks by checking {@link Reader#readRequested} for all readers. */ -class ReadMostlyRWLock { +final class ReadMostlyRWLock { final Thread writeThread; @VisibleForTesting volatile boolean writeRequested; // this writer is requesting or obtained the write access 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 6bb678179fab..58601bbc756c 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 @@ -313,7 +313,7 @@ final class DefaultProjectImpl extends ComponentManagerImpl implements Project { registerServiceInstance(Project.class, actualContainerInstance, ComponentManagerImpl.getFakeCorePluginDescriptor()); //noinspection unchecked - registerComponents((List)PluginManagerCore.getLoadedPlugins(), null); + registerComponents((List)PluginManagerCore.getLoadedPlugins(), ApplicationManager.getApplication(), null); createComponents(null); Disposer.register(actualContainerInstance, this); } diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerExImpl.kt b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerExImpl.kt index ccc8eb2541d3..8bd445c56afb 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerExImpl.kt +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerExImpl.kt @@ -1,4 +1,5 @@ // Copyright 2000-2021 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. +@file:Suppress("ReplaceNegatedIsEmptyWithIsNotEmpty") package com.intellij.openapi.project.impl import com.intellij.conversion.ConversionResult @@ -85,7 +86,7 @@ open class ProjectManagerExImpl : ProjectManagerImpl() { val activity = StartUpMeasurer.startMainActivity("project opening preparation") if (!options.forceOpenInNewFrame) { val openProjects = openProjects - if (!openProjects.isNullOrEmpty()) { + if (!openProjects.isEmpty()) { var projectToClose = options.projectToClose if (projectToClose == null) { // if several projects are opened, ask to reuse not last opened project frame, but last focused (to avoid focus switching) diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/projectLoader.kt b/platform/platform-impl/src/com/intellij/openapi/project/impl/projectLoader.kt index ac62eefef908..f19f15df72c7 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/projectLoader.kt +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/projectLoader.kt @@ -9,7 +9,6 @@ import com.intellij.diagnostic.PluginException import com.intellij.diagnostic.StartUpMeasurer import com.intellij.diagnostic.StartUpMeasurer.Activities import com.intellij.diagnostic.StartUpMeasurer.startActivity -import com.intellij.ide.plugins.IdeaPluginDescriptorImpl import com.intellij.ide.plugins.PluginManagerCore import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.diagnostic.logger @@ -23,8 +22,7 @@ import org.jetbrains.annotations.ApiStatus internal fun registerComponents(project: ProjectImpl) { var activity = createActivity(project) { "project ${Activities.REGISTER_COMPONENTS_SUFFIX}" } // at this point of time plugins are already loaded by application - no need to pass indicator to getLoadedPlugins call - @Suppress("UNCHECKED_CAST") - project.registerComponents(PluginManagerCore.getLoadedPlugins() as List, null) + project.registerComponents(PluginManagerCore.getLoadedPlugins(null), ApplicationManager.getApplication(), null) activity = activity?.endAndStart("projectComponentRegistered") runOnlyCorePluginExtensions( diff --git a/platform/platform-impl/src/com/intellij/openapi/util/SystemPropertyBean.java b/platform/platform-impl/src/com/intellij/openapi/util/SystemPropertyBean.java index fed8810aa9fa..dd0170c953d8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/util/SystemPropertyBean.java +++ b/platform/platform-impl/src/com/intellij/openapi/util/SystemPropertyBean.java @@ -13,12 +13,10 @@ import org.jetbrains.annotations.Nullable; * @author gregsh */ public final class SystemPropertyBean implements PluginAware { - private static final ExtensionPointName EP_NAME = new ExtensionPointName<>("com.intellij.systemProperty"); - private PluginDescriptor myPluginDescriptor; public static void initSystemProperties() { - EP_NAME.forEachExtensionSafe(bean -> { + new ExtensionPointName("com.intellij.systemProperty").forEachExtensionSafe(bean -> { if (System.getProperty(bean.name) == null) { System.setProperty(bean.name, bean.value); } diff --git a/platform/platform-impl/src/com/intellij/openapi/util/registry/RegistryExtensionCollector.kt b/platform/platform-impl/src/com/intellij/openapi/util/registry/RegistryExtensionCollector.kt index e3cd662710d3..2513e882de4a 100644 --- a/platform/platform-impl/src/com/intellij/openapi/util/registry/RegistryExtensionCollector.kt +++ b/platform/platform-impl/src/com/intellij/openapi/util/registry/RegistryExtensionCollector.kt @@ -8,6 +8,7 @@ import com.intellij.openapi.extensions.* import com.intellij.openapi.util.text.StringUtil import com.intellij.util.xmlb.annotations.Attribute import com.intellij.util.xmlb.annotations.Transient +import org.jetbrains.annotations.ApiStatus import org.jetbrains.annotations.Nls import org.jetbrains.annotations.NonNls @@ -26,14 +27,14 @@ class RegistryKeyBean : PluginAware { private val pendingRemovalKeys = HashSet() @JvmStatic - internal fun addKeysFromPlugins() { + @ApiStatus.Internal + fun addKeysFromPlugins() { val epName = ExtensionPointName("com.intellij.registryKey") - - Registry.addKeys(epName.iterable.map { createRegistryKeyDescriptor(it) }) + Registry.addKeys(epName.iterable.asSequence().map { createRegistryKeyDescriptor(it) }.iterator()) epName.addExtensionPointListener(object : ExtensionPointListener, ExtensionPointPriorityListener { override fun extensionAdded(extension: RegistryKeyBean, pluginDescriptor: PluginDescriptor) { - Registry.addKeys(listOf(createRegistryKeyDescriptor(extension))) + Registry.addKeys(listOf(createRegistryKeyDescriptor(extension)).iterator()) } }, null) diff --git a/platform/platform-tests/testSrc/com/intellij/ui/IconUtilTest.java b/platform/platform-tests/testSrc/com/intellij/ui/IconUtilTest.java index d116dd461e5d..a29172529b98 100644 --- a/platform/platform-tests/testSrc/com/intellij/ui/IconUtilTest.java +++ b/platform/platform-tests/testSrc/com/intellij/ui/IconUtilTest.java @@ -1,39 +1,43 @@ -// Copyright 2000-2020 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-2021 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.openapi.command.WriteCommandAction; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.util.Iconable; +import com.intellij.openapi.util.LastComputedIconCache; import com.intellij.openapi.util.ThrowableComputable; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.testFramework.HeavyPlatformTestCase; +import com.intellij.testFramework.PlatformTestUtil; import com.intellij.testFramework.PsiTestUtil; import com.intellij.util.FileContentUtilCore; import com.intellij.util.IconUtil; import com.intellij.util.PlatformIcons; import com.intellij.util.TimeoutUtil; -import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.util.ArrayList; import java.util.List; +import static org.assertj.core.api.Assertions.assertThat; + public class IconUtilTest extends HeavyPlatformTestCase { @Override protected boolean isIconRequired() { - return false; + return true; } @Override protected void setUp() throws Exception { super.setUp(); while (DumbService.isDumb(getProject())) { - UIUtil.dispatchAllInvocationEvents(); + PlatformTestUtil.dispatchAllInvocationEventsInIdeEventQueue(); } } @@ -65,26 +69,32 @@ public class IconUtilTest extends HeavyPlatformTestCase { assertJustOneLockedIcon(file); } - private void assertJustOneLockedIcon(VirtualFile file) throws IOException { - WriteCommandAction.runWriteCommandAction(getProject(), - (ThrowableComputable)() -> { - file.setBinaryContent("class X {}".getBytes(StandardCharsets.UTF_8)); - file.setWritable(false); - return null; - }); - UIUtil.dispatchAllInvocationEvents(); // write actions - UIUtil.dispatchAllInvocationEvents(); + private void assertJustOneLockedIcon(@NotNull VirtualFile file) throws IOException { + LastComputedIconCache.clear(file); + + WriteCommandAction.runWriteCommandAction(getProject(), (ThrowableComputable)() -> { + file.setBinaryContent("class X {}".getBytes(StandardCharsets.UTF_8)); + file.setWritable(false); + return null; + }); + // write actions + PlatformTestUtil.dispatchAllInvocationEventsInIdeEventQueue(); + PlatformTestUtil.dispatchAllInvocationEventsInIdeEventQueue(); try { - Icon icon = IconUtil.getIcon(file, -1, getProject()); - List icons = IconTestUtil.renderDeferredIcon(icon); - assertOneElement(ContainerUtil.filter(icons, ic -> ic == IconTestUtil.unwrapRetrievableIcon(PlatformIcons.LOCKED_ICON))); + List icons = IconTestUtil.renderDeferredIcon(IconUtil.getIcon(file, -1, getProject())); + List result = new ArrayList<>(); + for (Icon icon : icons) { + if (IconTestUtil.unwrapIcon(icon) == PlatformIcons.LOCKED_ICON) { + result.add(icon); + } + } + assertThat(result).hasSize(1); } finally { - WriteCommandAction.runWriteCommandAction(getProject(), - (ThrowableComputable)() -> { - file.setWritable(true); - return null; - }); + WriteCommandAction.runWriteCommandAction(getProject(), (ThrowableComputable)() -> { + file.setWritable(true); + return null; + }); } } diff --git a/platform/platform-tests/testSrc/com/intellij/ui/UiTestRule.kt b/platform/platform-tests/testSrc/com/intellij/ui/UiTestRule.kt index 429d4474e34b..47f2451a4bf1 100644 --- a/platform/platform-tests/testSrc/com/intellij/ui/UiTestRule.kt +++ b/platform/platform-tests/testSrc/com/intellij/ui/UiTestRule.kt @@ -1,4 +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. +// Copyright 2000-2021 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.openapi.util.IconLoader @@ -22,7 +22,7 @@ class UiTestRule(private val testDataRoot: Path) : RequireHeadlessMode() { override fun before() { super.before() - IconManager.activate() + IconManager.activate(null) IconLoader.activate() } diff --git a/platform/platform-util-io/src/org/jetbrains/io/ChannelRegistrar.java b/platform/platform-util-io/src/org/jetbrains/io/ChannelRegistrar.java index d9a5c32df2e5..cd6b6c353c1d 100644 --- a/platform/platform-util-io/src/org/jetbrains/io/ChannelRegistrar.java +++ b/platform/platform-util-io/src/org/jetbrains/io/ChannelRegistrar.java @@ -1,8 +1,7 @@ -// Copyright 2000-2020 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-2021 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.io; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.util.containers.ContainerUtil; import io.netty.channel.*; import io.netty.util.concurrent.GenericFutureListener; import org.jetbrains.annotations.NotNull; @@ -20,7 +19,9 @@ public final class ChannelRegistrar extends ChannelInboundHandlerAdapter { private static final Logger LOG = Logger.getInstance(ChannelRegistrar.class); private final AtomicReference serverChannel = new AtomicReference<>(); - private final Set clientChannels = ContainerUtil.newConcurrentSet(); + // don't use ContainerUtil here! + @SuppressWarnings("SSBasedInspection") + private final Set clientChannels = Collections.newSetFromMap(new ConcurrentHashMap<>()); private boolean isEventLoopGroupOwner; diff --git a/platform/service-container/src/com/intellij/serviceContainer/BaseComponentAdapter.kt b/platform/service-container/src/com/intellij/serviceContainer/BaseComponentAdapter.kt index 705712ca2302..1133774630e6 100644 --- a/platform/service-container/src/com/intellij/serviceContainer/BaseComponentAdapter.kt +++ b/platform/service-container/src/com/intellij/serviceContainer/BaseComponentAdapter.kt @@ -173,14 +173,4 @@ internal abstract class BaseComponentAdapter(internal val componentManager: Comp @Suppress("UNCHECKED_CAST") return old as T? } - - // used in LinkedHashSetWrapper - override fun equals(other: Any?): Boolean { - if (this === other) { - return true - } - return other is ComponentAdapter && componentKey == other.componentKey - } - - override fun hashCode() = componentKey.hashCode() } \ No newline at end of file diff --git a/platform/service-container/src/com/intellij/serviceContainer/ComponentManagerImpl.kt b/platform/service-container/src/com/intellij/serviceContainer/ComponentManagerImpl.kt index 3ff814e54333..a605a0030bf7 100644 --- a/platform/service-container/src/com/intellij/serviceContainer/ComponentManagerImpl.kt +++ b/platform/service-container/src/com/intellij/serviceContainer/ComponentManagerImpl.kt @@ -234,15 +234,15 @@ abstract class ComponentManagerImpl @JvmOverloads constructor(internal val paren final override fun getExtensionArea() = extensionArea @Internal - open fun registerComponents(plugins: List, listenerCallbacks: MutableList?) { + open fun registerComponents(plugins: List, + app: Application?, + listenerCallbacks: MutableList?) { val activityNamePrefix = activityNamePrefix() - val app = getApplication() - val headless = app == null || app.isHeadlessEnvironment var newComponentConfigCount = 0 var map: ConcurrentMap>? = null - val isHeadlessMode = app?.isHeadlessEnvironment == true - val isUnitTestMode = app?.isUnitTestMode == true + val isHeadless = app == null || app.isHeadlessEnvironment + val isUnitTestMode = app?.isUnitTestMode ?: false val clonePoint = parent != null @@ -257,7 +257,7 @@ abstract class ComponentManagerImpl @JvmOverloads constructor(internal val paren } executeRegisterTask(mainPlugin, mainContainerDescriptor, this) { pluginDescriptor, containerDescriptor -> - newComponentConfigCount += registerComponents(pluginDescriptor, containerDescriptor, headless) + newComponentConfigCount += registerComponents(pluginDescriptor, containerDescriptor, isHeadless) } executeRegisterTask(mainPlugin, mainContainerDescriptor, this) { _, containerDescriptor -> @@ -268,7 +268,7 @@ abstract class ComponentManagerImpl @JvmOverloads constructor(internal val paren map = m } for (listener in listeners) { - if ((isUnitTestMode && !listener.activeInTestMode) || (isHeadlessMode && !listener.activeInHeadlessMode)) { + if ((isUnitTestMode && !listener.activeInTestMode) || (isHeadless && !listener.activeInHeadlessMode)) { continue } @@ -535,10 +535,10 @@ abstract class ComponentManagerImpl @JvmOverloads constructor(internal val paren val result = getComponent(serviceClass) ?: return null PluginException.logPluginError(LOG, - "$key requested as a service, but it is a component - " + - "convert it to a service or change call to " + - if (parent == null) "ApplicationManager.getApplication().getComponent()" else "project.getComponent()", - null, serviceClass) + "$key requested as a service, but it is a component - " + + "convert it to a service or change call to " + + if (parent == null) "ApplicationManager.getApplication().getComponent()" else "project.getComponent()", + null, serviceClass) return result } @@ -668,12 +668,11 @@ abstract class ComponentManagerImpl @JvmOverloads constructor(internal val paren fun registerServiceInstance(serviceInterface: Class, instance: T, pluginDescriptor: PluginDescriptor) { val serviceKey = serviceInterface.name checkState() - componentKeyToAdapter.remove(serviceKey) val descriptor = ServiceDescriptor() descriptor.serviceInterface = serviceKey descriptor.serviceImplementation = instance.javaClass.name - registerAdapter(ServiceComponentAdapter(descriptor, pluginDescriptor, this, instance.javaClass, instance), pluginDescriptor) + componentKeyToAdapter.put(serviceKey, ServiceComponentAdapter(descriptor, pluginDescriptor, this, instance.javaClass, instance)) } @TestOnly @@ -937,15 +936,15 @@ abstract class ComponentManagerImpl @JvmOverloads constructor(internal val paren return ServicePreloadingResult( asyncPreloadedServices = CompletableFuture.runAsync({ - runActivity("${activityPrefix}service async preloading") { - ForkJoinTask.invokeAll(asyncPreloadedServices) - } - }, ForkJoinPool.commonPool()), + runActivity("${activityPrefix}service async preloading") { + ForkJoinTask.invokeAll(asyncPreloadedServices) + } + }, ForkJoinPool.commonPool()), syncPreloadedServices = CompletableFuture.runAsync({ - runActivity("${activityPrefix}service sync preloading") { - ForkJoinTask.invokeAll(syncPreloadedServices) - } - }, ForkJoinPool.commonPool()) + runActivity("${activityPrefix}service sync preloading") { + ForkJoinTask.invokeAll(syncPreloadedServices) + } + }, ForkJoinPool.commonPool()) ) } diff --git a/platform/service-container/src/com/intellij/serviceContainer/MyComponentAdapter.kt b/platform/service-container/src/com/intellij/serviceContainer/MyComponentAdapter.kt index 7cd157696510..51c5d7ef2dd9 100644 --- a/platform/service-container/src/com/intellij/serviceContainer/MyComponentAdapter.kt +++ b/platform/service-container/src/com/intellij/serviceContainer/MyComponentAdapter.kt @@ -6,6 +6,7 @@ import com.intellij.openapi.Disposable import com.intellij.openapi.extensions.PluginDescriptor import com.intellij.openapi.progress.ProgressIndicator import com.intellij.openapi.util.Disposer +import org.picocontainer.ComponentAdapter internal class MyComponentAdapter(private val componentKey: Class<*>, override val implementationClassName: String, @@ -62,4 +63,14 @@ internal class MyComponentAdapter(private val componentKey: Class<*>, } override fun toString() = "ComponentAdapter(key=${getComponentKey()}, implementation=${componentImplementation}, plugin=$pluginId)" + + // used in LinkedHashSetWrapper + override fun equals(other: Any?): Boolean { + if (this === other) { + return true + } + return other is ComponentAdapter && componentKey == other.componentKey + } + + override fun hashCode() = componentKey.hashCode() } \ No newline at end of file diff --git a/platform/testFramework/src/com/intellij/simpleApplicationBootstrapper.kt b/platform/testFramework/src/com/intellij/simpleApplicationBootstrapper.kt index 02d9488d11cf..7c8c35220b5a 100644 --- a/platform/testFramework/src/com/intellij/simpleApplicationBootstrapper.kt +++ b/platform/testFramework/src/com/intellij/simpleApplicationBootstrapper.kt @@ -6,16 +6,18 @@ import com.intellij.diagnostic.ThreadDumper import com.intellij.ide.IdeEventQueue import com.intellij.ide.plugins.IdeaPluginDescriptorImpl import com.intellij.ide.plugins.PluginManagerCore -import com.intellij.idea.* +import com.intellij.idea.Main +import com.intellij.idea.callAppInitialized +import com.intellij.idea.initConfigurationStore +import com.intellij.idea.preloadServices import com.intellij.openapi.application.PathManager import com.intellij.openapi.application.impl.ApplicationImpl import com.intellij.openapi.util.RecursionManager import com.intellij.openapi.util.registry.Registry +import com.intellij.openapi.util.registry.RegistryKeyBean import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS import com.intellij.openapi.vfs.newvfs.persistent.PersistentFSImpl -import com.intellij.ui.IconManager import com.intellij.util.SystemProperties -import com.intellij.util.concurrency.AppExecutorUtil import java.awt.EventQueue import java.util.concurrent.* import java.util.function.Supplier @@ -43,7 +45,7 @@ internal fun doLoadApp(setupEventQueue: () -> Unit) { val loadedPluginFuture = CompletableFuture.supplyAsync(Supplier { PluginManagerCore.getLoadedPlugins(PathManager::class.java.classLoader) - }, AppExecutorUtil.getAppExecutorService()) + }, ForkJoinPool.commonPool()) setupEventQueue() @@ -53,13 +55,13 @@ internal fun doLoadApp(setupEventQueue: () -> Unit) { RecursionManager.assertOnMissedCache(app) } - IconManager.activate() val plugins: List try { // 40 seconds - tests maybe executed on cloud agents where IO speed is a very slow - plugins = registerRegistryAndInitStore(registerAppComponents(loadedPluginFuture, app), app) - .get(40, TimeUnit.SECONDS) - + plugins = loadedPluginFuture.get(40, TimeUnit.SECONDS) + app.registerComponents(plugins, app, null) + initConfigurationStore(app) + RegistryKeyBean.addKeysFromPlugins() Registry.getInstance().markAsLoaded() val preloadServiceFuture = preloadServices(plugins, app, activityPrefix = "") app.loadComponents(null) diff --git a/platform/testFramework/src/com/intellij/testFramework/TestApplicationManager.kt b/platform/testFramework/src/com/intellij/testFramework/TestApplicationManager.kt index 1e63e0195b6b..a268f56e0978 100644 --- a/platform/testFramework/src/com/intellij/testFramework/TestApplicationManager.kt +++ b/platform/testFramework/src/com/intellij/testFramework/TestApplicationManager.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2020 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-2021 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. @file:Suppress("JAVA_MODULE_DOES_NOT_EXPORT_PACKAGE") package com.intellij.testFramework @@ -17,10 +17,8 @@ import com.intellij.ide.impl.HeadlessDataManager import com.intellij.ide.startup.impl.StartupManagerImpl import com.intellij.ide.structureView.StructureViewFactory import com.intellij.ide.structureView.impl.StructureViewFactoryImpl -import com.intellij.idea.StartupUtil import com.intellij.openapi.Disposable import com.intellij.openapi.actionSystem.DataProvider -import com.intellij.openapi.actionSystem.ex.ActionUtil import com.intellij.openapi.application.Application import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.impl.ApplicationImpl @@ -31,7 +29,6 @@ import com.intellij.openapi.command.impl.UndoManagerImpl import com.intellij.openapi.command.undo.DocumentReferenceManager import com.intellij.openapi.command.undo.UndoManager import com.intellij.openapi.components.serviceIfCreated -import com.intellij.openapi.diagnostic.logger import com.intellij.openapi.fileEditor.FileDocumentManager import com.intellij.openapi.fileEditor.impl.EditorHistoryManager import com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl @@ -119,7 +116,8 @@ class TestApplicationManager private constructor() { HeavyPlatformTestCase.doAutodetectPlatformPrefix() doLoadApp { if (EventQueue.isDispatchThread()) { - StartupUtil.replaceSystemEventQueue(logger()) + // replaces system event queue + IdeEventQueue.getInstance() } else { replaceIdeEventQueueSafely() diff --git a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java index 9ea6578ff651..6de31ecbf45a 100644 --- a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java @@ -29,6 +29,8 @@ import com.intellij.psi.impl.source.PostprocessReformattingAspect; import com.intellij.rt.execution.junit.FileComparisonFailure; import com.intellij.testFramework.exceptionCases.AbstractExceptionCase; import com.intellij.testFramework.fixtures.IdeaTestExecutionPolicy; +import com.intellij.ui.CoreIconManager; +import com.intellij.ui.IconManager; import com.intellij.util.*; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.PeekableIterator; @@ -226,7 +228,7 @@ public abstract class UsefulTestCase extends TestCase { setupTempDir(); boolean isStressTest = isStressTest(); - ApplicationManagerEx.setInStressTest(isStressTest);; + ApplicationManagerEx.setInStressTest(isStressTest); if (isPerformanceTest()) { Timings.getStatistics(); } @@ -236,8 +238,15 @@ public abstract class UsefulTestCase extends TestCase { if (isIconRequired()) { // ensure that IconLoader will use dummy empty icon - IconLoader.deactivate(); - //IconManager.activate(); + try { + IconManager.activate(new CoreIconManager()); + } + catch (Exception e) { + throw e; + } + catch (Throwable e) { + throw new RuntimeException(e); + } } } @@ -293,6 +302,12 @@ public abstract class UsefulTestCase extends TestCase { // don't use method references here to make stack trace reading easier //noinspection Convert2MethodRef new RunAll( + () -> { + if (isIconRequired()) { + IconManager.deactivate(); + IconLoader.clearCacheInTests(); + } + }, () -> disposeRootDisposable(), () -> cleanupSwingDataStructures(), () -> cleanupDeleteOnExitHookList(), @@ -466,7 +481,7 @@ public abstract class UsefulTestCase extends TestCase { } } - protected void invokeSetUp() throws Exception { + protected final void invokeSetUp() throws Exception { long setupStart = System.nanoTime(); setUp(); long setupCost = (System.nanoTime() - setupStart) / 1000000; diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/BasePlatformTestCase.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/BasePlatformTestCase.java index fa2a48ebda71..f662a1038075 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/BasePlatformTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/BasePlatformTestCase.java @@ -1,4 +1,4 @@ -// Copyright 2000-2020 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-2021 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; import com.intellij.lang.Language; @@ -18,8 +18,6 @@ import com.intellij.testFramework.UsefulTestCase; import com.intellij.testFramework.fixtures.impl.LightTempDirTestFixtureImpl; import com.intellij.util.ThrowableRunnable; import org.jetbrains.annotations.NotNull; -import org.junit.Rule; -import org.junit.rules.TestRule; /** * Base class for light tests. diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/TestLookupElementPresentation.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/TestLookupElementPresentation.java index c85662647d79..fb3a43bb0056 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/TestLookupElementPresentation.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/TestLookupElementPresentation.java @@ -1,4 +1,4 @@ -// Copyright 2000-2020 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-2021 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; import com.intellij.codeInsight.lookup.LookupElement; @@ -6,6 +6,7 @@ import com.intellij.codeInsight.lookup.LookupElementPresentation; import com.intellij.codeInsight.lookup.LookupElementRenderer; import com.intellij.ui.DeferredIcon; import com.intellij.ui.LayeredIcon; +import com.intellij.ui.icons.CompositeIcon; import com.intellij.ui.icons.RowIcon; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -16,8 +17,7 @@ import javax.swing.*; * @author peter */ public final class TestLookupElementPresentation extends LookupElementPresentation { - @NotNull - public static TestLookupElementPresentation renderReal(@NotNull LookupElement e) { + public static @NotNull TestLookupElementPresentation renderReal(@NotNull LookupElement e) { TestLookupElementPresentation p = new TestLookupElementPresentation(); //noinspection rawtypes LookupElementRenderer renderer = e.getExpensiveRenderer(); @@ -30,13 +30,25 @@ public final class TestLookupElementPresentation extends LookupElementPresentati return p; } - @Nullable - public static Icon unwrapIcon(@Nullable Icon icon) { + public static @Nullable Icon unwrapIcon(@Nullable Icon icon) { while (true) { - if (icon instanceof RowIcon) icon = ((RowIcon)icon).getIcon(0); - else if (icon instanceof DeferredIcon) icon = ((DeferredIcon)icon).evaluate(); - else if (icon instanceof LayeredIcon) icon = ((LayeredIcon)icon).getIcon(0); - else return icon; + if (icon instanceof RowIcon) { + if (((CompositeIcon)icon).getIconCount() == 0) { + return icon; + } + else { + icon = ((RowIcon)icon).getIcon(0); + } + } + else if (icon instanceof DeferredIcon) { + icon = ((DeferredIcon)icon).evaluate(); + } + else if (icon instanceof LayeredIcon) { + icon = ((LayeredIcon)icon).getIcon(0); + } + else { + return icon; + } } } } diff --git a/platform/testFramework/src/com/intellij/ui/IconTestUtil.java b/platform/testFramework/src/com/intellij/ui/IconTestUtil.java index c628725d8567..9263d710e307 100644 --- a/platform/testFramework/src/com/intellij/ui/IconTestUtil.java +++ b/platform/testFramework/src/com/intellij/ui/IconTestUtil.java @@ -1,7 +1,8 @@ -// Copyright 2000-2020 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-2021 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.openapi.util.IconLoader; +import com.intellij.ui.icons.CompositeIcon; import com.intellij.util.TimeoutUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.UIUtil; @@ -16,19 +17,37 @@ import java.util.Collections; import java.util.List; public final class IconTestUtil { - @Nullable - public static String getIconPath(Icon icon) { + public static @Nullable String getIconPath(@NotNull Icon icon) { icon = unwrapRetrievableIcon(icon); - return ((IconLoader.CachedImageIcon)icon).getOriginalPath(); + if (icon instanceof IconLoader.CachedImageIcon) { + return ((IconLoader.CachedImageIcon)icon).getOriginalPath(); + } + else { + // DummyIcon + return icon.toString(); + } } - public static Icon unwrapRetrievableIcon(Icon icon) { + public static @NotNull Icon unwrapRetrievableIcon(@NotNull Icon icon) { while (icon instanceof RetrievableIcon) { icon = ((RetrievableIcon)icon).retrieveIcon(); } return icon; } + public static @NotNull Icon unwrapIcon(@NotNull Icon icon) { + while (icon instanceof CompositeIcon) { + CompositeIcon compositeIcon = (CompositeIcon)icon; + if (compositeIcon.getIconCount() == 0) { + break; + } + + icon = compositeIcon.getIcon(0); + } + assert icon != null; + return unwrapRetrievableIcon(icon); + } + @NotNull static List autopsyIconsFrom(@NotNull Icon icon) { if (icon instanceof RetrievableIcon) { diff --git a/platform/util-ex/src/com/intellij/util/containers/util.kt b/platform/util-ex/src/com/intellij/util/containers/util.kt index 40d593d6914b..a320d3b48fca 100644 --- a/platform/util-ex/src/com/intellij/util/containers/util.kt +++ b/platform/util-ex/src/com/intellij/util/containers/util.kt @@ -18,7 +18,7 @@ fun MutableMap>.remove(key: K, value: V) { fun MutableMap>.putValue(key: K, value: V) { val list = get(key) if (list == null) { - put(key, SmartList(value)) + put(key, SmartList(value)) } else { list.add(value) @@ -88,11 +88,7 @@ inline fun Iterator.forEachGuaranteed(operation: (T) -> Unit) { } inline fun Collection.forEachLoggingErrors(logger: Logger, operation: (T) -> Unit) { - return asSequence().forEachLoggingErrors(logger, operation) -} - -inline fun Sequence.forEachLoggingErrors(logger: Logger, operation: (T) -> Unit) { - forEach { + asSequence().forEach { try { operation(it) } @@ -100,6 +96,7 @@ inline fun Sequence.forEachLoggingErrors(logger: Logger, operation: (T) - logger.error(e) } } + return } inline fun Collection.mapNotNullLoggingErrors(logger: Logger, operation: (T) -> R?): List { @@ -190,7 +187,7 @@ inline fun Collection.mapSmartSet(transform: (T) -> R): Set { inline fun Collection.mapSmartNotNull(transform: (T) -> R?): List { val size = size return if (size == 1) { - transform(first())?.let { SmartList(it) } ?: SmartList() + transform(first())?.let { SmartList(it) } ?: SmartList() } else { mapNotNullTo(ArrayList(size), transform) @@ -219,7 +216,7 @@ inline fun Collection.filterSmartMutable(predicate: (T) -> Boolean): Muta return filterTo(if (size <= 1) SmartList() else ArrayList(), predicate) } -inline fun , V> enumMapOf(): MutableMap = EnumMap(E::class.java) +inline fun , V> enumMapOf(): MutableMap = EnumMap(E::class.java) fun Collection.toArray(empty: Array): Array { @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST") diff --git a/platform/util/src/com/intellij/openapi/application/PathManager.java b/platform/util/src/com/intellij/openapi/application/PathManager.java index abee55dec330..8816be933cd2 100644 --- a/platform/util/src/com/intellij/openapi/application/PathManager.java +++ b/platform/util/src/com/intellij/openapi/application/PathManager.java @@ -2,7 +2,6 @@ package com.intellij.openapi.application; import com.intellij.diagnostic.StartUpMeasurer; -import com.intellij.openapi.util.PropertiesUtil; import com.intellij.openapi.util.SystemInfoRt; import com.intellij.openapi.util.text.StringUtilRt; import com.intellij.openapi.util.text.Strings; @@ -56,7 +55,7 @@ public final class PathManager { private static final String SYSTEM_DIRECTORY = "system"; private static final String PATHS_SELECTOR = System.getProperty(PROPERTY_PATHS_SELECTOR); - private static class Lazy { + private static final class Lazy { private static final Pattern PROPERTY_REF = Pattern.compile("\\$\\{(.+?)}"); } @@ -550,16 +549,19 @@ public final class PathManager { Path file = path == null ? null : Paths.get(path); if (file != null) { try (Reader reader = Files.newBufferedReader(file)) { - Map properties = PropertiesUtil.loadProperties(reader); - for (Map.Entry entry : properties.entrySet()) { - String key = entry.getKey(); - if (PROPERTY_HOME_PATH.equals(key) || PROPERTY_HOME.equals(key)) { - log(path + ": '" + key + "' cannot be redefined"); + //noinspection NonSynchronizedMethodOverridesSynchronizedMethod + new Properties() { + @Override + public Object put(Object key, Object value) { + if (PROPERTY_HOME_PATH.equals(key) || PROPERTY_HOME.equals(key)) { + log(path + ": '" + key + "' cannot be redefined"); + } + else if (!sysProperties.containsKey(key)) { + sysProperties.setProperty(String.valueOf(key), substituteVars(String.valueOf(value))); + } + return null; } - else if (!sysProperties.containsKey(key)) { - sysProperties.setProperty(key, substituteVars(entry.getValue())); - } - } + }.load(reader); } catch (NoSuchFileException | AccessDeniedException ignore) { } catch (IOException e) { diff --git a/platform/util/src/com/intellij/openapi/util/JDOMUtil.java b/platform/util/src/com/intellij/openapi/util/JDOMUtil.java index af1123bc1ca6..af9906de98ba 100644 --- a/platform/util/src/com/intellij/openapi/util/JDOMUtil.java +++ b/platform/util/src/com/intellij/openapi/util/JDOMUtil.java @@ -1,9 +1,8 @@ -// Copyright 2000-2020 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-2021 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.util; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.io.FileUtil; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.util.text.Strings; import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.util.io.URLUtil; @@ -76,9 +75,11 @@ public final class JDOMUtil { } } - // avoid loading of SystemInfo class - if (Strings.indexOfIgnoreCase(System.getProperty("java.vm.vendor", ""), "IBM", 0) < 0) { + // avoid loading of SystemInfo and Strings classes + String jvmVendor = System.getProperty("java.vm.vendor", ""); + if (!jvmVendor.contains("IBM") && !jvmVendor.contains("ibm")) { try { + //noinspection HttpUrlsUsage factory.setProperty("http://java.sun.com/xml/stream/properties/report-cdata-event", true); } catch (Exception e) { @@ -184,7 +185,7 @@ public final class JDOMUtil { sb.append(each == '<' ? "<" : ">"); } else if (!Verifier.isXMLCharacter(each)) { - sb.append("0x").append(StringUtil.toUpperCase(Long.toHexString(each))); + sb.append("0x").append(Strings.toUpperCase(Long.toHexString(each))); } else { sb.append(each); @@ -410,14 +411,14 @@ public final class JDOMUtil { write(document, file, lineSeparator); } + /** + * Use {@link #write(Element, Path)} + */ + @Deprecated public static void write(@NotNull Element element, @NotNull File file) throws IOException { - write(element, file, "\n"); - } - - public static void write(@NotNull Element element, @NotNull File file, @Nullable String lineSeparator) throws IOException { FileUtil.createParentDirs(file); try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8))) { - writeElement(element, writer, createOutputter(lineSeparator)); + writeElement(element, writer, createOutputter("\n")); } } diff --git a/platform/util/src/com/intellij/openapi/util/LastComputedIconCache.java b/platform/util/src/com/intellij/openapi/util/LastComputedIconCache.java index dad1eda6aa95..8203d117fc02 100644 --- a/platform/util/src/com/intellij/openapi/util/LastComputedIconCache.java +++ b/platform/util/src/com/intellij/openapi/util/LastComputedIconCache.java @@ -1,4 +1,4 @@ -// Copyright 2000-2020 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-2021 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.util; import com.intellij.reference.SoftReference; @@ -7,6 +7,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; import javax.swing.*; import java.lang.ref.Reference; @@ -16,10 +17,7 @@ public final class LastComputedIconCache { public static @Nullable Icon get(@NotNull UserDataHolder holder, int flags) { Int2ObjectMap map = SoftReference.dereference(holder.getUserData(LAST_COMPUTED_ICON)); - if (map == null) { - return null; - } - return map.get(flags); + return map == null ? null : map.get(flags); } public static void put(@NotNull UserDataHolder holder, Icon icon, int flags) { @@ -48,4 +46,9 @@ public final class LastComputedIconCache { map.put(flags, icon); } } + + @TestOnly + public static void clear(@NotNull UserDataHolder holder) { + holder.putUserData(LAST_COMPUTED_ICON, null); + } } diff --git a/platform/util/src/com/intellij/openapi/util/registry/Registry.java b/platform/util/src/com/intellij/openapi/util/registry/Registry.java index 3d5bf21596cd..d1e16341295b 100644 --- a/platform/util/src/com/intellij/openapi/util/registry/Registry.java +++ b/platform/util/src/com/intellij/openapi/util/registry/Registry.java @@ -1,4 +1,4 @@ -// Copyright 2000-2020 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-2021 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.util.registry; import com.intellij.diagnostic.LoadingState; @@ -54,7 +54,7 @@ public final class Registry { } public static boolean is(@NonNls @NotNull String key, boolean defaultValue) { - if (!LoadingState.COMPONENTS_REGISTERED.isOccurred()) { + if (!LoadingState.CONFIGURATION_STORE_INITIALIZED.isOccurred()) { LoadingState.LAF_INITIALIZED.checkOccurred(); return defaultValue; } @@ -72,7 +72,7 @@ public final class Registry { } public static int intValue(@NonNls @NotNull String key, int defaultValue) { - if (!LoadingState.COMPONENTS_REGISTERED.isOccurred()) { + if (!LoadingState.CONFIGURATION_STORE_INITIALIZED.isOccurred()) { LoadingState.LAF_INITIALIZED.checkOccurred(); return defaultValue; } @@ -124,7 +124,7 @@ public final class Registry { } public static @NotNull Registry getInstance() { - LoadingState.COMPONENTS_REGISTERED.checkOccurred(); + LoadingState.CONFIGURATION_STORE_INITIALIZED.checkOccurred(); return ourInstance; } @@ -176,15 +176,18 @@ public final class Registry { List result = new ArrayList<>(); - Map contributedKeys = getInstance().myContributedKeys; + Registry instance = getInstance(); + Map contributedKeys = instance.myContributedKeys; while (keys.hasMoreElements()) { @NonNls final String each = keys.nextElement(); - if (each.endsWith(".description") || each.endsWith(".restartRequired") || contributedKeys.containsKey(each)) continue; - result.add(get(each)); + if (each.endsWith(".description") || each.endsWith(".restartRequired") || contributedKeys.containsKey(each)) { + continue; + } + result.add(instance.doGet(each)); } for (String key : contributedKeys.keySet()) { - result.add(get(key)); + result.add(instance.doGet(key)); } return result; @@ -192,9 +195,10 @@ public final class Registry { void restoreDefaults() { Map old = new HashMap<>(myUserProperties); + Registry instance = getInstance(); for (String each : old.keySet()) { try { - get(each).resetToDefault(); + instance.doGet(each).resetToDefault(); } catch (MissingResourceException e) { // outdated property that is not declared in registry.properties anymore @@ -212,17 +216,21 @@ public final class Registry { } private static boolean isRestartNeeded(@NotNull Map map) { + Registry instance = getInstance(); for (String s : map.keySet()) { - final RegistryValue eachValue = get(s); - if (eachValue.isRestartRequired() && eachValue.isChangedSinceAppStart()) return true; + RegistryValue eachValue = instance.doGet(s); + if (eachValue.isRestartRequired() && eachValue.isChangedSinceAppStart()) { + return true; + } } return false; } - public static synchronized void addKeys(@NotNull List descriptors) { + public static synchronized void addKeys(@NotNull Iterator descriptors) { // getInstance must be not used here - phase COMPONENT_REGISTERED is not yet completed - for (RegistryKeyDescriptor descriptor : descriptors) { + while (descriptors.hasNext()) { + RegistryKeyDescriptor descriptor = descriptors.next(); ourInstance.myContributedKeys.put(descriptor.getName(), descriptor); } } diff --git a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java index db2c268eca3d..02cf455f5302 100644 --- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java +++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java @@ -9,7 +9,6 @@ import com.intellij.openapi.util.NlsSafe; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; import com.intellij.util.*; -import com.intellij.util.containers.ContainerUtil; import com.intellij.util.text.CharArrayUtil; import com.intellij.util.text.CharSequenceSubSequence; import com.intellij.util.text.MergingCharSequence; @@ -106,9 +105,9 @@ public class StringUtil extends StringUtilRt { } } - public static final NotNullFunction QUOTER = s -> "\"" + s + "\""; + public static final java.util.function.Function QUOTER = s -> "\"" + s + "\""; - public static final NotNullFunction SINGLE_QUOTER = s -> "'" + s + "'"; + public static final java.util.function.Function SINGLE_QUOTER = s -> "'" + s + "'"; @Contract(pure = true) public static @NotNull List getWordsInStringLongestFirst(@NotNull String find) { @@ -133,7 +132,7 @@ public class StringUtil extends StringUtilRt { return Object::toString; } - public static final @NotNull Function TRIMMER = StringUtil::trim; + public static final @NotNull java.util.function.Function TRIMMER = StringUtil::trim; // Unlike String.replace(CharSequence,CharSequence) does not allocate intermediate objects on non-match // TODO revise when JDK9 arrives - its String.replace(CharSequence, CharSequence) is more optimized @@ -1211,7 +1210,7 @@ public class StringUtil extends StringUtilRt { } /** - * @return list containing all words in {@code text}, or {@link ContainerUtil#emptyList()} if there are none. + * @return list containing all words in {@code text}, or {@link Collections#emptyList()} if there are none. * The word here means the maximum sub-string consisting entirely of characters which are {@code Character.isJavaIdentifierPart(c)}. */ @Contract(pure = true) @@ -1239,7 +1238,7 @@ public class StringUtil extends StringUtilRt { } } if (result == null) { - return ContainerUtil.emptyList(); + return Collections.emptyList(); } return result; } @@ -1369,7 +1368,7 @@ public class StringUtil extends StringUtilRt { @Contract(pure = true) public static @NotNull String join(@NotNull Collection strings, @NotNull String separator) { if (strings.size() <= 1) { - return notNullize(ContainerUtil.getFirstItem(strings)); + return notNullize(strings.isEmpty() ? null : strings.iterator().next()); } StringBuilder result = new StringBuilder(); join(strings, separator, result); @@ -1468,7 +1467,7 @@ public class StringUtil extends StringUtilRt { return Formats.formatDuration(duration); } - /** + /** * Formats duration given in milliseconds as a sum of time units (example: {@code formatDuration(123456, "") = "2m 3s 456ms"}). * @deprecated use NlsMessages#formatDurationApproximateNarrow for localized output */ @@ -2749,6 +2748,7 @@ public class StringUtil extends StringUtilRt { @Contract(pure = true) public static @NotNull String formatLinks(@NotNull String message) { + @SuppressWarnings("HttpUrlsUsage") Pattern linkPattern = Pattern.compile("http://[a-zA-Z0-9./\\-+]+"); StringBuffer result = new StringBuffer(); Matcher m = linkPattern.matcher(message); diff --git a/platform/util/src/com/intellij/ui/IconManager.java b/platform/util/src/com/intellij/ui/IconManager.java index cc5543022ad8..22baeb07e090 100644 --- a/platform/util/src/com/intellij/ui/IconManager.java +++ b/platform/util/src/com/intellij/ui/IconManager.java @@ -1,4 +1,4 @@ -// Copyright 2000-2020 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-2021 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.openapi.util.Iconable; @@ -11,20 +11,20 @@ import org.jetbrains.annotations.TestOnly; import javax.swing.*; import java.awt.*; -import java.util.Iterator; -import java.util.ServiceLoader; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.Arrays; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Function; public interface IconManager { - @NotNull - static IconManager getInstance() { + static @NotNull IconManager getInstance() { return IconManagerHelper.instance; } // Icon Loader is quite heavy, better to not instantiate class unless required - static void activate() { - IconManagerHelper.activate(); + static void activate(@Nullable IconManager impl) throws Throwable { + IconManagerHelper.activate(impl); } @TestOnly @@ -52,39 +52,31 @@ public interface IconManager { return loadRasterizedIcon(path.startsWith("/") ? path.substring(1) : path, aClass.getClassLoader(), cacheKey, flags); } - @NotNull - default Icon createEmptyIcon(@NotNull Icon icon) { + default @NotNull Icon createEmptyIcon(@NotNull Icon icon) { return icon; } - @NotNull - default Icon createOffsetIcon(@NotNull Icon icon) { + default @NotNull Icon createOffsetIcon(@NotNull Icon icon) { return icon; } - @NotNull - Icon createLayered(Icon @NotNull ... icons); + @NotNull Icon createLayered(Icon @NotNull ... icons); - @NotNull - default Icon colorize(Graphics2D g, @NotNull Icon source, @NotNull Color color) { + default @NotNull Icon colorize(Graphics2D g, @NotNull Icon source, @NotNull Color color) { return source; } - @NotNull Icon createDeferredIcon(@Nullable Icon base, T param, @NotNull Function f); + @NotNull Icon createDeferredIcon(@Nullable Icon base, T param, @NotNull Function iconProducer); - @NotNull - RowIcon createLayeredIcon(@NotNull Iconable instance, Icon icon, int flags); + @NotNull RowIcon createLayeredIcon(@NotNull Iconable instance, Icon icon, int flags); - @NotNull - default RowIcon createRowIcon(int iconCount) { + default @NotNull RowIcon createRowIcon(int iconCount) { return createRowIcon(iconCount, RowIcon.Alignment.TOP); } - @NotNull - RowIcon createRowIcon(int iconCount, RowIcon.Alignment alignment); + @NotNull RowIcon createRowIcon(int iconCount, RowIcon.Alignment alignment); - @NotNull - RowIcon createRowIcon(Icon @NotNull ... icons); + @NotNull RowIcon createRowIcon(Icon @NotNull ... icons); void registerIconLayer(int flagMask, @NotNull Icon icon); @@ -95,14 +87,17 @@ final class IconManagerHelper { private static final AtomicBoolean isActivated = new AtomicBoolean(); static volatile IconManager instance = DummyIconManager.INSTANCE; - static void activate() { + static void activate(@Nullable IconManager impl) throws Throwable { if (!isActivated.compareAndSet(false, true)) { return; } - Iterator iterator = ServiceLoader.load(IconManager.class, IconManager.class.getClassLoader()).iterator(); - if (iterator.hasNext()) { - instance = iterator.next(); + if (impl == null) { + Class implClass = IconManagerHelper.class.getClassLoader().loadClass("com.intellij.ui.CoreIconManager"); + instance = (IconManager)MethodHandles.lookup().findConstructor(implClass, MethodType.methodType(void.class)).invoke(); + } + else { + instance = impl; } } @@ -124,21 +119,21 @@ final class DummyIconManager implements IconManager { return DummyIcon.INSTANCE; } - @NotNull @Override - public Icon getIcon(@NotNull String path, @NotNull Class aClass) { - return DummyIcon.INSTANCE; + public @NotNull Icon getIcon(@NotNull String path, @NotNull Class aClass) { + return new DummyIcon(path); } @Override public @NotNull Icon loadRasterizedIcon(@NotNull String path, @NotNull ClassLoader classLoader, long cacheKey, int flags) { - return DummyIcon.INSTANCE; + return new DummyIcon(path); } - @NotNull @Override - public RowIcon createLayeredIcon(@NotNull Iconable instance, Icon icon, int flags) { - return new DummyRowIcon(); + public @NotNull RowIcon createLayeredIcon(@NotNull Iconable instance, Icon icon, int flags) { + Icon[] icons = new Icon[2]; + icons[0] = icon; + return new DummyRowIcon(icons); } @Override @@ -147,34 +142,36 @@ final class DummyIconManager implements IconManager { @Override public @NotNull Icon tooltipOnlyIfComposite(@NotNull Icon icon) { - return new DummyIcon(); + return icon; } @Override - public @NotNull Icon createDeferredIcon(@Nullable Icon base, T param, @NotNull Function f) { + public @NotNull Icon createDeferredIcon(@Nullable Icon base, T param, @NotNull Function iconProducer) { return base; } - @NotNull @Override - public RowIcon createRowIcon(int iconCount, RowIcon.Alignment alignment) { + public @NotNull RowIcon createRowIcon(int iconCount, RowIcon.Alignment alignment) { return new DummyRowIcon(iconCount); } - @NotNull @Override - public Icon createLayered(Icon @NotNull ... icons) { + public @NotNull Icon createLayered(Icon @NotNull ... icons) { return new DummyRowIcon(icons); } - @NotNull @Override - public RowIcon createRowIcon(Icon @NotNull ... icons) { + public @NotNull RowIcon createRowIcon(Icon @NotNull ... icons) { return new DummyRowIcon(icons); } private static class DummyIcon implements Icon { - static final DummyIcon INSTANCE = new DummyIcon(); + static final DummyIcon INSTANCE = new DummyIcon(""); + private final String path; + + private DummyIcon(@NotNull String path) { + this.path = path; + } @Override public void paintIcon(Component c, Graphics g, int x, int y) { @@ -192,29 +189,33 @@ final class DummyIconManager implements IconManager { @Override public int hashCode() { - return 0; + return path.hashCode(); } @Override public boolean equals(Object obj) { - return obj instanceof DummyIcon; + return this == obj || (obj instanceof DummyIcon && ((DummyIcon)obj).path == path); + } + + @Override + public String toString() { + return path; } } - private static class DummyRowIcon extends DummyIcon implements RowIcon { + private static final class DummyRowIcon extends DummyIcon implements RowIcon { private Icon[] icons; DummyRowIcon(int iconCount) { + super(""); icons = new Icon[iconCount]; } DummyRowIcon(Icon[] icons) { + super(""); this.icons = icons; } - DummyRowIcon() { - } - @Override public int getIconCount() { return icons == null ? 0 : icons.length; @@ -233,9 +234,8 @@ final class DummyIconManager implements IconManager { icons[i] = icon; } - @NotNull @Override - public Icon getDarkIcon(boolean isDark) { + public @NotNull Icon getDarkIcon(boolean isDark) { return this; } @@ -243,5 +243,23 @@ final class DummyIconManager implements IconManager { public Icon @NotNull [] getAllIcons() { return icons == null ? new Icon[0] : ContainerUtil.packNullables(icons).toArray(new Icon[0]); } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + return o instanceof DummyRowIcon && Arrays.equals(icons, ((DummyRowIcon)o).icons); + } + + @Override + public int hashCode() { + return icons.length > 0 ? icons[0].hashCode() : 0; + } + + @Override + public String toString() { + return "Row icon. myIcons=" + Arrays.asList(icons); + } } } diff --git a/platform/util/src/com/intellij/util/containers/ContainerUtil.java b/platform/util/src/com/intellij/util/containers/ContainerUtil.java index 109e81f9f669..068a2bcc01d3 100644 --- a/platform/util/src/com/intellij/util/containers/ContainerUtil.java +++ b/platform/util/src/com/intellij/util/containers/ContainerUtil.java @@ -39,16 +39,6 @@ public final class ContainerUtil { return new HashMap<>(); } - /** - * @deprecated Use {@link HashMap#HashMap(Map)} - */ - @Contract(pure = true) - @ApiStatus.ScheduledForRemoval(inVersion = "2021.2") - @Deprecated - public static @NotNull HashMap newHashMap(@NotNull Map map) { - return new HashMap<>(map); - } - @SafeVarargs @Contract(pure = true) public static @NotNull Map newHashMap(@NotNull Pair first, Pair @NotNull ... entries) { @@ -93,16 +83,6 @@ public final class ContainerUtil { return map; } - /** - * @deprecated Use {@link THashMap#THashMap(Map)} - */ - @Deprecated - @ApiStatus.ScheduledForRemoval(inVersion = "2021.1") - @Contract(pure = true) - public static @NotNull THashMap newTroveMap() { - return new THashMap<>(); - } - @Deprecated @ApiStatus.ScheduledForRemoval(inVersion = "2021.1") public static @NotNull TObjectHashingStrategy canonicalStrategy() { @@ -117,15 +97,6 @@ public final class ContainerUtil { return TObjectHashingStrategy.IDENTITY; } - /** - * @deprecated Use {@link IdentityHashMap#IdentityHashMap()} - */ - @Deprecated - @ApiStatus.ScheduledForRemoval(inVersion = "2021.2") - public static @NotNull IdentityHashMap newIdentityHashMap() { - return new IdentityHashMap<>(); - } - /** * @deprecated Use {@link LinkedList#LinkedList()} */ @@ -2384,7 +2355,7 @@ public final class ContainerUtil { } return true; } - + @Contract(pure = true) public static boolean isSameElements(@NotNull Collection list1, @NotNull Collection list2) { return list1.size() == list2.size() && list1.containsAll(list2); diff --git a/platform/util/ui/src/com/intellij/openapi/util/IconLoader.java b/platform/util/ui/src/com/intellij/openapi/util/IconLoader.java index 3a0e6cbb1cf1..472ba09858b7 100644 --- a/platform/util/ui/src/com/intellij/openapi/util/IconLoader.java +++ b/platform/util/ui/src/com/intellij/openapi/util/IconLoader.java @@ -53,10 +53,10 @@ public final class IconLoader { private static final Logger LOG = Logger.getInstance(IconLoader.class); // the key: URL or Pair(path, classLoader) - private static final ConcurrentMap iconCache = new ConcurrentHashMap<>(100, 0.9f, 2); + private static final ConcurrentMap<@NotNull Object, @NotNull CachedImageIcon> iconCache = new ConcurrentHashMap<>(100, 0.9f, 2); // contains mapping between icons and disabled icons. - private static final Cache iconToDisabledIcon = Caffeine.newBuilder().weakKeys().build(); + private static final Cache<@NotNull Icon, @NotNull Icon> iconToDisabledIcon = Caffeine.newBuilder().weakKeys().build(); private static volatile boolean STRICT_GLOBAL; @@ -86,9 +86,9 @@ public final class IconLoader { } }; - private static boolean ourIsActivated; + private static boolean isActivated = !GraphicsEnvironment.isHeadless(); - private IconLoader() { } + private IconLoader() {} public static T performStrictly(@NotNull Supplier computable) { STRICT_LOCAL.set(true); @@ -116,8 +116,9 @@ public final class IconLoader { if (prev != next) { iconToDisabledIcon.invalidateAll(); - //clears svg cache + // clear svg cache ImageLoader.ImageCache.INSTANCE.clearCache(); + // iconCache is not cleared because it contain original icon (instance that will delegate to) } } @@ -147,10 +148,18 @@ public final class IconLoader { } public static void clearCache() { - // Copy the transform to trigger update of cached icons + // copy the transform to trigger update of cached icons updateTransform(IconTransform::copy); } + @TestOnly + public static void clearCacheInTests() { + iconCache.clear(); + iconToDisabledIcon.invalidateAll(); + ImageLoader.ImageCache.INSTANCE.clearCache(); + pathTransformGlobalModCount.incrementAndGet(); + } + /** * @deprecated Use {@link #getIcon(String, Class)} */ @@ -290,12 +299,12 @@ public final class IconLoader { } public static void activate() { - ourIsActivated = true; + isActivated = true; } @TestOnly public static void deactivate() { - ourIsActivated = false; + isActivated = false; } @Nullable @@ -518,7 +527,7 @@ public final class IconLoader { * Same as {@link #getDisabledIcon(Icon)} with an ancestor component for HiDPI-awareness. */ public static @NotNull Icon getDisabledIcon(@NotNull Icon icon, @Nullable Component ancestor) { - if (!ourIsActivated) { + if (!isActivated) { return icon; } @@ -778,7 +787,7 @@ public final class IconLoader { private @NotNull ImageIcon getRealIcon(@Nullable ScaleContext context) { ImageDataLoader resolver = this.resolver; - if (resolver == null || !ourIsActivated) { + if (resolver == null || !isActivated) { return EMPTY_ICON; } @@ -1389,7 +1398,7 @@ public final class IconLoader { return null; } - private static class LabelHolder { + private static final class LabelHolder { /** * To get disabled icon with paint it into the image. Some icons require * not null component to paint. diff --git a/plugins/stats-collector/resources/META-INF/plugin.xml b/plugins/stats-collector/resources/META-INF/plugin.xml index e357771cca29..f7f1ec7b6a06 100644 --- a/plugins/stats-collector/resources/META-INF/plugin.xml +++ b/plugins/stats-collector/resources/META-INF/plugin.xml @@ -43,9 +43,6 @@ - - diff --git a/plugins/stats-collector/src/com/intellij/stats/completion/sender/SenderPreloadingActivity.kt b/plugins/stats-collector/src/com/intellij/stats/completion/sender/SenderPreloadingActivity.kt index 2446a5decc6a..c02589e20d57 100644 --- a/plugins/stats-collector/src/com/intellij/stats/completion/sender/SenderPreloadingActivity.kt +++ b/plugins/stats-collector/src/com/intellij/stats/completion/sender/SenderPreloadingActivity.kt @@ -1,4 +1,4 @@ -// Copyright 2000-2020 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-2021 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.stats.completion.sender import com.intellij.internal.statistic.utils.StatisticsUploadAssistant @@ -9,7 +9,6 @@ import com.intellij.openapi.components.Service import com.intellij.openapi.components.service import com.intellij.openapi.diagnostic.logger import com.intellij.openapi.progress.ProgressIndicator -import com.intellij.openapi.util.registry.Registry import com.intellij.stats.completion.network.status.WebServiceStatusManager import com.intellij.util.Alarm import com.intellij.util.Time @@ -20,7 +19,7 @@ private fun isSendAllowed(): Boolean { } internal fun isCompletionLogsSendAllowed(): Boolean { - return ApplicationManager.getApplication().isEAP && Registry.`is`("completion.stats.send.logs") + return ApplicationManager.getApplication().isEAP && java.lang.Boolean.parseBoolean(System.getProperty("completion.stats.send.logs", "true")) } private val LOG = logger() diff --git a/python/testSrc/com/jetbrains/python/PyPackageIconTest.java b/python/testSrc/com/jetbrains/python/PyPackageIconTest.java index c62711eeabbd..a89712589263 100644 --- a/python/testSrc/com/jetbrains/python/PyPackageIconTest.java +++ b/python/testSrc/com/jetbrains/python/PyPackageIconTest.java @@ -1,11 +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. +// Copyright 2000-2021 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.jetbrains.python; import com.intellij.application.options.RegistryManager; +import com.intellij.icons.AllIcons; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiManager; -import com.intellij.util.PlatformIcons; +import com.intellij.ui.IconTestUtil; import com.intellij.util.PsiIconUtil; import com.jetbrains.python.fixtures.PyTestCase; import com.jetbrains.python.namespacePackages.PyNamespacePackagesService; @@ -16,7 +17,6 @@ import java.util.Collections; import java.util.List; public class PyPackageIconTest extends PyTestCase { - @Override public void setUp() throws Exception { super.setUp(); @@ -114,12 +114,12 @@ public class PyPackageIconTest extends PyTestCase { } private void checkPackageIcon(@NotNull String path, boolean has) { - final VirtualFile found = myFixture.findFileInTempDir(path); + VirtualFile found = myFixture.findFileInTempDir(path); assertNotNull(found); - final PsiDirectory dir = PsiManager.getInstance(myFixture.getProject()).findDirectory(found); + PsiDirectory dir = PsiManager.getInstance(myFixture.getProject()).findDirectory(found); assertNotNull(dir); - final Icon icon = PsiIconUtil.getProvidersIcon(dir, 0); - assertEquals(PlatformIcons.PACKAGE_ICON.equals(icon), has); + Icon icon = PsiIconUtil.getProvidersIcon(dir, 0); + assertEquals(AllIcons.Nodes.Package.equals(IconTestUtil.unwrapIcon(icon)), has); } private void toggleNamespacePackageDirectory(@NotNull String directory) { diff --git a/spellchecker/src/META-INF/SpellCheckerPlugin.xml b/spellchecker/src/META-INF/SpellCheckerPlugin.xml index 62ba9f0cda94..0c2b7f132ff6 100644 --- a/spellchecker/src/META-INF/SpellCheckerPlugin.xml +++ b/spellchecker/src/META-INF/SpellCheckerPlugin.xml @@ -13,9 +13,7 @@ serviceImplementation="com.intellij.spellchecker.ui.SpellCheckingEditorCustomizationProviderImpl" overrides="true"/> - - - + - + - diff --git a/spellchecker/src/com/intellij/spellchecker/SpellCheckerManager.java b/spellchecker/src/com/intellij/spellchecker/SpellCheckerManager.java index 46a43adea638..8276aac097f1 100644 --- a/spellchecker/src/com/intellij/spellchecker/SpellCheckerManager.java +++ b/spellchecker/src/com/intellij/spellchecker/SpellCheckerManager.java @@ -9,6 +9,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.WriteCommandAction; import com.intellij.openapi.command.undo.BasicUndoableAction; import com.intellij.openapi.command.undo.UndoManager; +import com.intellij.openapi.components.Service; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.project.Project; @@ -47,7 +48,8 @@ import static com.intellij.openapi.util.io.FileUtilRt.toSystemDependentName; import static com.intellij.openapi.vfs.VfsUtilCore.visitChildrenRecursively; import static com.intellij.project.ProjectKt.getProjectStoreDirectory; -public class SpellCheckerManager implements Disposable { +@Service(Service.Level.PROJECT) +public final class SpellCheckerManager implements Disposable { private static final Logger LOG = Logger.getInstance(SpellCheckerManager.class); private static final int MAX_METRICS = 1; @@ -70,7 +72,6 @@ public class SpellCheckerManager implements Disposable { private SpellCheckerEngine mySpellChecker; private SuggestionProvider mySuggestionProvider; - public static SpellCheckerManager getInstance(Project project) { return project.getService(SpellCheckerManager.class); } @@ -412,10 +413,12 @@ public class SpellCheckerManager implements Disposable { } } - private class CustomDictFileListener implements VirtualFileListener { + private final class CustomDictFileListener implements VirtualFileListener { private final SpellCheckerSettings mySettings; - CustomDictFileListener(@NotNull SpellCheckerSettings settings) {mySettings = settings;} + CustomDictFileListener(@NotNull SpellCheckerSettings settings) { + mySettings = settings; + } @Override public void fileDeleted(@NotNull VirtualFileEvent event) { diff --git a/spellchecker/src/com/intellij/spellchecker/settings/SettingsTransferActivity.java b/spellchecker/src/com/intellij/spellchecker/settings/SettingsTransferActivity.java index 2a71fe704fa4..7a95521cb97d 100644 --- a/spellchecker/src/com/intellij/spellchecker/settings/SettingsTransferActivity.java +++ b/spellchecker/src/com/intellij/spellchecker/settings/SettingsTransferActivity.java @@ -9,18 +9,19 @@ import org.jetbrains.annotations.NotNull; import static com.intellij.spellchecker.SpellCheckerManager.DictionaryLevel.APP; import static com.intellij.spellchecker.SpellCheckerManager.DictionaryLevel.PROJECT; -public class SettingsTransferActivity implements StartupActivity { - +final class SettingsTransferActivity implements StartupActivity.DumbAware { @Override public void runActivity(@NotNull Project project) { - final SpellCheckerSettings settings = SpellCheckerSettings.getInstance(project); - if (!settings.isSettingsTransferred()) { - if (settings.isUseSingleDictionaryToSave() && - PROJECT.getName().equals(settings.getDictionaryToSave()) && - project.getService(ProjectDictionaryState.class).getProjectDictionary().getWords().isEmpty()) { - settings.setDictionaryToSave(APP.getName()); - } - settings.setSettingsTransferred(true); + SpellCheckerSettings settings = SpellCheckerSettings.getInstance(project); + if (settings.isSettingsTransferred()) { + return; } + + if (settings.isUseSingleDictionaryToSave() && + PROJECT.getName().equals(settings.getDictionaryToSave()) && + project.getService(ProjectDictionaryState.class).getProjectDictionary().getWords().isEmpty()) { + settings.setDictionaryToSave(APP.getName()); + } + settings.setSettingsTransferred(true); } } diff --git a/spellchecker/src/com/intellij/spellchecker/settings/SpellCheckerSettings.java b/spellchecker/src/com/intellij/spellchecker/settings/SpellCheckerSettings.java index 8ee820594dec..6ecfd9d1fb37 100644 --- a/spellchecker/src/com/intellij/spellchecker/settings/SpellCheckerSettings.java +++ b/spellchecker/src/com/intellij/spellchecker/settings/SpellCheckerSettings.java @@ -1,10 +1,7 @@ // Copyright 2000-2021 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.settings; -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.components.*; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.NlsSafe; import com.intellij.spellchecker.SpellCheckerManager; @@ -20,7 +17,8 @@ import static com.intellij.openapi.util.text.StringUtil.notNullize; import static com.intellij.openapi.util.text.StringUtil.parseInt; @State(name = "SpellCheckerSettings", storages = @Storage(StoragePathMacros.WORKSPACE_FILE)) -public class SpellCheckerSettings implements PersistentStateComponent { +@Service(Service.Level.PROJECT) +public final class SpellCheckerSettings implements PersistentStateComponent { // For xml serialization private static final String SPELLCHECKER_MANAGER_SETTINGS_TAG = "SpellCheckerSettings"; @@ -46,7 +44,7 @@ public class SpellCheckerSettings implements PersistentStateComponent { private Set myRuntimeDisabledDictionariesNames = new HashSet<>(); private String myDictionaryToSave = DEFAULT_DICTIONARY_TO_SAVE; private boolean myUseSingleDictionaryToSave = DEFAULT_USE_SINGLE_DICT; - private boolean mySettingsTransferred = false; + private boolean mySettingsTransferred; @NlsSafe public String getDictionaryToSave() { diff --git a/spellchecker/src/com/intellij/spellchecker/state/CachedDictionaryState.java b/spellchecker/src/com/intellij/spellchecker/state/CachedDictionaryState.java index 2b7e14b3a8b8..0d967732c8e7 100644 --- a/spellchecker/src/com/intellij/spellchecker/state/CachedDictionaryState.java +++ b/spellchecker/src/com/intellij/spellchecker/state/CachedDictionaryState.java @@ -1,8 +1,7 @@ -// Copyright 2000-2020 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-2021 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.Disposable; -import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.*; import com.intellij.serviceContainer.NonInjectable; @@ -16,7 +15,8 @@ import org.jetbrains.annotations.NotNull; storages = @Storage(value = "cachedDictionary.xml", roamingType = RoamingType.DISABLED), reportStatistic = false ) -public class CachedDictionaryState extends DictionaryState implements PersistentStateComponent { +@Service(Service.Level.APP) +public final class CachedDictionaryState extends DictionaryState implements PersistentStateComponent { public static final String DEFAULT_NAME = "cached"; private final EventDispatcher myDictListenerEventDispatcher = EventDispatcher.create(DictionaryStateListener.class); diff --git a/xml/dom-openapi/src/com/intellij/util/xml/ui/BigStringComponent.java b/xml/dom-openapi/src/com/intellij/util/xml/ui/BigStringComponent.java index b71ed7846709..5b1d7e2b3c25 100644 --- a/xml/dom-openapi/src/com/intellij/util/xml/ui/BigStringComponent.java +++ b/xml/dom-openapi/src/com/intellij/util/xml/ui/BigStringComponent.java @@ -1,24 +1,10 @@ -/* - * 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-2021 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.xml.ui; +import com.intellij.icons.AllIcons; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.util.NlsContexts; -import com.intellij.util.PlatformIcons; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -36,7 +22,7 @@ public class BigStringComponent extends TextFieldWithBrowseButton { public BigStringComponent(boolean hasBorder, @NlsContexts.DialogTitle String windowTitle) { super(); myWindowTitle = windowTitle; - setButtonIcon(PlatformIcons.OPEN_EDIT_DIALOG_ICON); + setButtonIcon(AllIcons.Actions.ShowViewer); addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) {