don't schedule post-start-up activities under modal progress

GitOrigin-RevId: 2ac572b66cf0ad8bc28a5713bc71967a8700f19d
This commit is contained in:
Vladimir Krivosheev
2022-07-20 14:06:46 +00:00
committed by intellij-monorepo-bot
parent aed14cb3c6
commit 57f7e14ea5
74 changed files with 888 additions and 1072 deletions
@@ -1,4 +1,4 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.compiler;
import com.intellij.CommonBundle;
@@ -114,7 +114,7 @@ public final class CompilerConfigurationImpl extends CompilerConfiguration imple
}
@Override
public void moduleAdded(@NotNull Project project, @NotNull Module module) {
public void modulesAdded(@NotNull Project project, @NotNull List<Module> modules) {
myProcessorsProfilesMap = null; // clear cache
}
@@ -1,96 +1,88 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.compiler;
package com.intellij.compiler
import com.intellij.compiler.impl.ModuleCompileScope;
import com.intellij.configurationStore.StoreUtilKt;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.roots.ModuleRootModificationUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import kotlin.Unit;
import org.jetbrains.annotations.NotNull;
import com.intellij.compiler.impl.ModuleCompileScope
import com.intellij.configurationStore.runInAllowSaveMode
import com.intellij.ide.impl.runUnderModalProgressIfIsEdt
import com.intellij.openapi.module.Module
import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.roots.ModuleRootModificationUtil
import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.util.io.TestFileSystemBuilder
import java.io.IOException
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import static com.intellij.util.io.TestFileSystemBuilder.fs;
public class UnloadedModulesCompilationTest extends BaseCompilerTestCase {
public void testDoNotCompileUnloadedModulesByDefault() {
VirtualFile a = createFile("unloaded/src/A.java", "class A{ error }");
Module unloaded = addModule("unloaded", a.getParent());
List<String> unloadedList = Collections.singletonList(unloaded.getName());
ModuleManager.getInstance(myProject).setUnloadedModules(unloadedList);
buildAllModules().assertUpToDate();
class UnloadedModulesCompilationTest : BaseCompilerTestCase() {
fun testDoNotCompileUnloadedModulesByDefault() {
val a = createFile("unloaded/src/A.java", "class A{ error }")
val unloaded = addModule("unloaded", a.parent)
val unloadedList = listOf(unloaded.name)
runUnderModalProgressIfIsEdt {
ModuleManager.getInstance(myProject).setUnloadedModules(unloadedList)
}
buildAllModules().assertUpToDate()
}
public void testCompileUnloadedModulesIfExplicitlySpecified() {
VirtualFile a = createFile("unloaded/src/A.java", "class A{}");
Module unloaded = addModule("unloaded", a.getParent());
File outputDir = getOutputDir(unloaded, false);
List<String> unloadedList = List.of(unloaded.getName());
StoreUtilKt.runInAllowSaveMode(true, () -> {
ModuleManager.getInstance(myProject).setUnloadedModules(unloadedList);
return Unit.INSTANCE;
});
make(createScopeWithUnloaded(Collections.emptyList(), unloadedList));
fs().file("A.class").build().assertDirectoryEqual(outputDir);
fun testCompileUnloadedModulesIfExplicitlySpecified() {
val a = createFile("unloaded/src/A.java", "class A{}")
val unloaded = addModule("unloaded", a.parent)
val outputDir = getOutputDir(unloaded, false)
val unloadedList = listOf(unloaded.name)
runInAllowSaveMode(true) {
runUnderModalProgressIfIsEdt {
ModuleManager.getInstance(myProject).setUnloadedModules(unloadedList)
}
}
make(createScopeWithUnloaded(emptyList(), unloadedList))
TestFileSystemBuilder.fs().file("A.class").build().assertDirectoryEqual(outputDir)
}
public void testCompileUsagesOfConstantInUnloadedModules() throws IOException {
VirtualFile utilFile = createFile("unloaded/src/Util.java", "class Util { public static final String FOO = \"foo\"; }");
VirtualFile a = createFile("unloaded/src/A.java", "class A{ { System.out.println(Util.FOO); } }");
Module unloaded = addModule("unloaded", a.getParent());
buildAllModules();
List<String> unloadedList = Collections.singletonList(unloaded.getName());
ModuleManager.getInstance(myProject).setUnloadedModules(unloadedList);
changeFile(utilFile, VfsUtilCore.loadText(utilFile).replace("foo", "foo2"));
make(createScopeWithUnloaded(Collections.emptyList(), unloadedList)).assertGenerated("A.class", "Util.class");
@Throws(IOException::class)
fun testCompileUsagesOfConstantInUnloadedModules() {
val utilFile = createFile("unloaded/src/Util.java", "class Util { public static final String FOO = \"foo\"; }")
val a = createFile("unloaded/src/A.java", "class A{ { System.out.println(Util.FOO); } }")
val unloaded = addModule("unloaded", a.parent)
buildAllModules()
val unloadedList = listOf(unloaded.name)
runUnderModalProgressIfIsEdt {
ModuleManager.getInstance(myProject).setUnloadedModules(unloadedList)
}
changeFile(utilFile, VfsUtilCore.loadText(utilFile).replace("foo", "foo2"))
make(createScopeWithUnloaded(emptyList(), unloadedList)).assertGenerated("A.class", "Util.class")
}
public void testCompileUsagesOfConstantFromNormalModuleInInUnloadedModules() throws IOException {
VirtualFile utilFile = createFile("util/src/Util.java", "class Util { public static final String FOO = \"foo\"; }");
Module util = addModule("util", utilFile.getParent());
VirtualFile a = createFile("unloaded/src/A.java", "class A{ { System.out.println(Util.FOO); } }");
Module unloaded = addModule("unloaded", a.getParent());
ModuleRootModificationUtil.addDependency(unloaded, util);
buildAllModules();
List<String> unloadedList = Collections.singletonList(unloaded.getName());
ModuleManager.getInstance(myProject).setUnloadedModules(unloadedList);
changeFile(utilFile, VfsUtilCore.loadText(utilFile).replace("foo", "foo2"));
make(createScopeWithUnloaded(Collections.singletonList(util), unloadedList)).assertGenerated("A.class", "Util.class");
@Throws(IOException::class)
fun testCompileUsagesOfConstantFromNormalModuleInInUnloadedModules() {
val utilFile = createFile("util/src/Util.java", "class Util { public static final String FOO = \"foo\"; }")
val util = addModule("util", utilFile.parent)
val a = createFile("unloaded/src/A.java", "class A{ { System.out.println(Util.FOO); } }")
val unloaded = addModule("unloaded", a.parent)
ModuleRootModificationUtil.addDependency(unloaded, util)
buildAllModules()
val unloadedList = listOf(unloaded.name)
runUnderModalProgressIfIsEdt {
ModuleManager.getInstance(myProject).setUnloadedModules(unloadedList)
}
changeFile(utilFile, VfsUtilCore.loadText(utilFile).replace("foo", "foo2"))
make(createScopeWithUnloaded(listOf(util), unloadedList)).assertGenerated("A.class", "Util.class")
}
public void testCompileUnloadedModuleAfterBuildingAllLoadedModules() {
VirtualFile utilFile = createFile("util/src/Util.java", "class Util { }");
Module util = addModule("util", utilFile.getParent());
VirtualFile a = createFile("unloaded/src/A.java", "class A { Util u = new Util(); }");
Module unloaded = addModule("unloaded", a.getParent());
ModuleRootModificationUtil.addDependency(unloaded, util);
buildAllModules();
List<String> unloadedList = Collections.singletonList(unloaded.getName());
ModuleManager.getInstance(myProject).setUnloadedModules(unloadedList);
changeFile(utilFile, "class Util { Util(int i) {} }");
buildAllModules().assertGenerated("Util.class");
compile(createScopeWithUnloaded(Collections.singletonList(util), unloadedList), false, true);
fun testCompileUnloadedModuleAfterBuildingAllLoadedModules() {
val utilFile = createFile("util/src/Util.java", "class Util { }")
val util = addModule("util", utilFile.parent)
val a = createFile("unloaded/src/A.java", "class A { Util u = new Util(); }")
val unloaded = addModule("unloaded", a.parent)
ModuleRootModificationUtil.addDependency(unloaded, util)
buildAllModules()
val unloadedList = listOf(unloaded.name)
runUnderModalProgressIfIsEdt {
ModuleManager.getInstance(myProject).setUnloadedModules(unloadedList)
}
changeFile(utilFile, "class Util { Util(int i) {} }")
buildAllModules().assertGenerated("Util.class")
compile(createScopeWithUnloaded(listOf(util), unloadedList), false, true)
}
@NotNull
private ModuleCompileScope createScopeWithUnloaded(List<Module> modules, List<String> unloaded) {
return new ModuleCompileScope(myProject, modules, unloaded, true, false);
private fun createScopeWithUnloaded(modules: List<Module>, unloaded: List<String>): ModuleCompileScope {
return ModuleCompileScope(myProject, modules, unloaded, true, false)
}
}
}
@@ -4,7 +4,6 @@ package com.intellij.compiler.progress
import com.intellij.build.BuildWorkspaceConfiguration
import com.intellij.compiler.BaseCompilerTestCase
import com.intellij.compiler.CompilerWorkspaceConfiguration
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.runWriteAction
import com.intellij.openapi.compiler.CompilationStatusListener
import com.intellij.openapi.compiler.CompileContext
@@ -19,17 +18,15 @@ import com.intellij.openapi.module.Module
import com.intellij.openapi.util.Disposer
import com.intellij.testFramework.PlatformTestUtil
import com.intellij.testFramework.PsiTestUtil.addSourceRoot
import com.intellij.testFramework.RunAll
import com.intellij.testFramework.common.runAll
import com.intellij.testFramework.fixtures.BuildViewTestFixture
import com.intellij.util.ThrowableRunnable
import org.assertj.core.api.Assertions.assertThat
import org.jetbrains.jps.model.java.JavaResourceRootType
class CompilerBuildViewTest : BaseCompilerTestCase() {
private lateinit var buildViewTestFixture: BuildViewTestFixture
private val testDisposable: Disposable = Disposer.newDisposable()
private val testDisposable = Disposer.newDisposable()
@Throws(Exception::class)
public override fun setUp() {
super.setUp()
buildViewTestFixture = BuildViewTestFixture(project)
@@ -37,11 +34,11 @@ class CompilerBuildViewTest : BaseCompilerTestCase() {
}
public override fun tearDown() {
RunAll(
ThrowableRunnable { if (::buildViewTestFixture.isInitialized) buildViewTestFixture.tearDown() },
ThrowableRunnable { Disposer.dispose(testDisposable) },
ThrowableRunnable { super.tearDown() }
).run()
runAll (
{ if (::buildViewTestFixture.isInitialized) buildViewTestFixture.tearDown() },
{ Disposer.dispose(testDisposable) },
{ super.tearDown() }
)
}
fun `test empty build`() {
@@ -70,7 +67,7 @@ class CompilerBuildViewTest : BaseCompilerTestCase() {
runWithProgressExIndicatorSupport { rebuildProject() }
buildViewTestFixture.assertBuildViewTreeEquals("-\n rebuild finished")
buildViewTestFixture.assertBuildViewSelectedNode("rebuild finished", false) { output: String? ->
buildViewTestFixture.assertBuildViewSelectedNode("rebuild finished", false) { output ->
assertThat(output).startsWith("Clearing build system data...\n" +
"Executing pre-compile tasks...\n" +
"Cleaning output directories…\n" +
@@ -91,7 +88,7 @@ class CompilerBuildViewTest : BaseCompilerTestCase() {
runWithProgressExIndicatorSupport { rebuild(module) }
buildViewTestFixture.assertBuildViewTreeEquals("-\n recompile finished")
buildViewTestFixture.assertBuildViewSelectedNode("recompile finished", false) { output: String? ->
buildViewTestFixture.assertBuildViewSelectedNode("recompile finished", false) { output ->
assertThat(output).startsWith("Executing pre-compile tasks...\n" +
"Cleaning output directories…\n" +
"Running 'before' tasks\n" +
@@ -122,7 +122,7 @@ public final class SnippetEditorDecorator implements EditorNotificationProvider
myBusConnection = project.getMessageBus().connect();
myBusConnection.subscribe(ProjectTopics.MODULES, new ModuleListener() {
@Override
public void moduleAdded(@NotNull Project project, @NotNull Module module) {
public void modulesAdded(@NotNull Project project, @NotNull List<Module> modules) {
reloadModules();
}
@@ -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-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.java.configurationStore
import com.intellij.ProjectTopics
@@ -78,7 +78,7 @@ class LoadProjectTest {
val fooModule = ModuleManager.getInstance(project).modules.single()
assertThat(fooModule.name).isEqualTo("foo")
runWriteActionAndWait {
val model = ModuleManager.getInstance(project).modifiableModel
val model = ModuleManager.getInstance(project).getModifiableModel()
model.loadModule("${project.basePath}/bar/bar.iml")
model.commit()
}
@@ -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-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.java.configurationStore
import com.intellij.openapi.application.runReadAction
@@ -43,7 +43,7 @@ class SaveProjectTest {
val module = projectModel.createModule("foo")
fun setGroupPath(path: Array<String>?) {
runWriteActionAndWait {
val model = projectModel.moduleManager.modifiableModel
val model = projectModel.moduleManager.getModifiableModel()
model.setModuleGroupPath(module, path)
model.commit()
}
@@ -84,7 +84,7 @@ class SaveProjectTest {
@Test
fun `save renamed module`() {
val model = runReadAction { projectModel.moduleManager.modifiableModel }
val model = runReadAction { projectModel.moduleManager.getModifiableModel() }
val module = projectModel.createModule("foo", model)
model.renameModule(module, "bar")
runWriteActionAndWait { model.commit() }
@@ -1,51 +1,53 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.openapi.roots.impl;
package com.intellij.openapi.roots.impl
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.roots.DependencyScope;
import com.intellij.openapi.roots.ModuleRootModificationUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ide.impl.runUnderModalProgressIfIsEdt
import com.intellij.openapi.module.ModuleManager.Companion.getInstance
import com.intellij.openapi.roots.DependencyScope
import com.intellij.openapi.roots.ModuleRootModificationUtil
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.testFramework.HeavyPlatformTestCase
import com.intellij.testFramework.UsefulTestCase
import java.io.IOException
import java.util.*
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
public class DirectoryIndexForUnloadedModuleTest extends DirectoryIndexTestCase {
public void testUnloadedModule() throws IOException {
Module unloadedModule = createModule("unloaded");
final File root = createTempDirectory();
VirtualFile contentRoot = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(root);
ModuleRootModificationUtil.addContentRoot(unloadedModule, contentRoot.getPath());
VirtualFile file = createChildData(contentRoot, "a.txt");
assertInProject(file);
ModuleManager.getInstance(myProject).setUnloadedModules(Arrays.asList("unloaded"));
assertFromUnloadedModule(file, "unloaded");
assertFromUnloadedModule(contentRoot, "unloaded");
class DirectoryIndexForUnloadedModuleTest : DirectoryIndexTestCase() {
@Throws(IOException::class)
fun testUnloadedModule() {
val unloadedModule = createModule("unloaded")
val root = createTempDirectory()
val contentRoot = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(root)
ModuleRootModificationUtil.addContentRoot(unloadedModule, contentRoot!!.path)
val file = HeavyPlatformTestCase.createChildData(contentRoot, "a.txt")
assertInProject(file)
runUnderModalProgressIfIsEdt {
getInstance(myProject).setUnloadedModules(Arrays.asList("unloaded"))
}
assertFromUnloadedModule(file, "unloaded")
assertFromUnloadedModule(contentRoot, "unloaded")
}
public void testDependentUnloadedModules() {
Module unloadedModule = createModule("unloaded");
Module main = createModule("main");
Module util = createModule("util");
Module common = createModule("common");
ModuleRootModificationUtil.addDependency(unloadedModule, main);
ModuleRootModificationUtil.addDependency(main, util);
ModuleRootModificationUtil.addDependency(main, common, DependencyScope.COMPILE, true);
ModuleManager.getInstance(myProject).setUnloadedModules(Arrays.asList("unloaded"));
assertSameElements(myIndex.getDependentUnloadedModules(main), "unloaded");
assertEmpty(myIndex.getDependentUnloadedModules(util));
assertSameElements(myIndex.getDependentUnloadedModules(common), "unloaded");
fun testDependentUnloadedModules() {
val unloadedModule = createModule("unloaded")
val main = createModule("main")
val util = createModule("util")
val common = createModule("common")
ModuleRootModificationUtil.addDependency(unloadedModule, main)
ModuleRootModificationUtil.addDependency(main, util)
ModuleRootModificationUtil.addDependency(main, common, DependencyScope.COMPILE, true)
runUnderModalProgressIfIsEdt {
getInstance(myProject).setUnloadedModules(Arrays.asList("unloaded"))
}
UsefulTestCase.assertSameElements(myIndex.getDependentUnloadedModules(main), "unloaded")
UsefulTestCase.assertEmpty(myIndex.getDependentUnloadedModules(util))
UsefulTestCase.assertSameElements(myIndex.getDependentUnloadedModules(common), "unloaded")
}
private void assertFromUnloadedModule(VirtualFile file, String moduleName) {
DirectoryInfo info = myIndex.getInfoForFile(file);
assertTrue(info.toString(), info.isExcluded(file));
assertNull(info.getModule());
assertEquals(moduleName, info.getUnloadedModuleName());
private fun assertFromUnloadedModule(file: VirtualFile?, moduleName: String) {
val info = myIndex.getInfoForFile(file!!)
assertTrue(info.toString(), info.isExcluded(file))
assertNull(info.module)
assertEquals(moduleName, info.unloadedModuleName)
}
}
}
@@ -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-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.openapi.roots.ui.configuration.actions;
import com.intellij.ide.projectView.ProjectView;
@@ -15,7 +15,6 @@ import com.intellij.testFramework.HeavyPlatformTestCase;
import com.intellij.testFramework.MapDataContext;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ModuleDeleteProviderTest extends HeavyPlatformTestCase {
@@ -56,7 +55,7 @@ public class ModuleDeleteProviderTest extends HeavyPlatformTestCase {
public void testUnloaded() {
createModule("a");
getModuleManager().setUnloadedModules(Arrays.asList("a"));
getModuleManager().setUnloadedModulesSync(List.of("a"));
assertNotNull(getModuleManager().getUnloadedModuleDescription("a"));
deleteModules("a");
assertNull(getModuleManager().getUnloadedModuleDescription("a"));
@@ -66,7 +65,7 @@ public class ModuleDeleteProviderTest extends HeavyPlatformTestCase {
Module a = createModule("a");
Module b = createModule("b");
ModuleRootModificationUtil.addDependency(a, b);
getModuleManager().setUnloadedModules(Arrays.asList("b"));
getModuleManager().setUnloadedModulesSync(List.of("b"));
assertSameElements(ModuleRootManager.getInstance(a).getDependencyModuleNames(), "b");
deleteModules("b");
assertEmpty(ModuleRootManager.getInstance(a).getDependencyModuleNames());
@@ -78,7 +77,7 @@ public class ModuleDeleteProviderTest extends HeavyPlatformTestCase {
ModuleRootModificationUtil.addDependency(a, b);
ModuleRootModificationUtil.addDependency(myModule, a);
ModuleRootModificationUtil.addDependency(myModule, b);
getModuleManager().setUnloadedModules(Arrays.asList("a"));
getModuleManager().setUnloadedModulesSync(List.of("a"));
assertSameElements(ModuleRootManager.getInstance(myModule).getDependencyModuleNames(), "a", "b");
deleteModules("a", "b");
assertNull(getModuleManager().findModuleByName("a"));
@@ -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-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.projectView
import com.intellij.ide.highlighter.ModuleFileType
import com.intellij.ide.impl.runUnderModalProgressIfIsEdt
import com.intellij.openapi.application.WriteAction
import com.intellij.openapi.module.Module
import com.intellij.openapi.module.ModuleManager
@@ -55,18 +56,20 @@ class ModulesInProjectViewTest : BaseProjectViewTestCase() {
""".trimIndent()
assertStructureEqual(expected)
ModuleManager.getInstance(myProject).setUnloadedModules(listOf("unloaded", "unloaded-inner"))
runUnderModalProgressIfIsEdt {
ModuleManager.getInstance(myProject).setUnloadedModules(listOf("unloaded", "unloaded-inner"))
}
assertStructureEqual("""
Project
loaded
unloaded-inner
subdir
y.txt
unloaded
loaded-inner
subdir
z.txt
""".trimIndent())
Project
loaded
unloaded-inner
subdir
y.txt
unloaded
loaded-inner
subdir
z.txt
""".trimIndent())
}
fun `test unloaded module with qualified name`() {
@@ -93,7 +96,9 @@ class ModulesInProjectViewTest : BaseProjectViewTestCase() {
""".trimIndent()
assertStructureEqual(expected)
ModuleManager.getInstance(myProject).setUnloadedModules(listOf("unloaded"))
runUnderModalProgressIfIsEdt {
ModuleManager.getInstance(myProject).setUnloadedModules(listOf("unloaded"))
}
assertStructureEqual(expected)
}
@@ -1,16 +1,15 @@
// 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-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.roots
import com.intellij.facet.FacetManager
import com.intellij.facet.mock.MockFacetType
import com.intellij.facet.mock.registerFacetType
import com.intellij.ide.impl.runUnderModalProgressIfIsEdt
import com.intellij.idea.TestFor
import com.intellij.openapi.application.ex.PathManagerEx
import com.intellij.openapi.application.runWriteAction
import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.module.StdModuleTypes
import com.intellij.openapi.project.ex.ProjectManagerEx
import com.intellij.openapi.project.impl.ProjectManagerImpl
import com.intellij.openapi.roots.ModuleRootManager
import com.intellij.openapi.roots.ModuleRootModificationUtil
import com.intellij.openapi.util.io.FileUtil
@@ -46,12 +45,16 @@ class UnloadedModulesConfigurationTest : JavaModuleTestCase() {
ModuleRootModificationUtil.addContentRoot(a, contentRootPath)
ModuleRootModificationUtil.addDependency(a, b)
val moduleManager = ModuleManager.getInstance(project)
moduleManager.setUnloadedModules(listOf("a"))
runUnderModalProgressIfIsEdt {
moduleManager.setUnloadedModules(listOf("a"))
}
assertEquals("a", assertOneElement(moduleManager.unloadedModuleDescriptions).name)
assertNull(moduleManager.findModuleByName("a"))
assertNotNull(moduleManager.findModuleByName("b"))
moduleManager.setUnloadedModules(listOf("b"))
runUnderModalProgressIfIsEdt {
moduleManager.setUnloadedModules(listOf("b"))
}
assertEquals("b", assertOneElement(moduleManager.unloadedModuleDescriptions).name)
val newA = moduleManager.findModuleByName("a")
assertNotNull(newA)
@@ -73,12 +76,16 @@ class UnloadedModulesConfigurationTest : JavaModuleTestCase() {
}
val moduleManager = ModuleManager.getInstance(project)
moduleManager.setUnloadedModules(listOf("a"))
runUnderModalProgressIfIsEdt {
moduleManager.setUnloadedModules(listOf("a"))
}
assertEquals("a", assertOneElement(moduleManager.unloadedModuleDescriptions).name)
assertNull(moduleManager.findModuleByName("a"))
assertNotNull(moduleManager.findModuleByName("b"))
moduleManager.setUnloadedModules(listOf())
runUnderModalProgressIfIsEdt {
moduleManager.setUnloadedModules(listOf())
}
val moduleA = ModuleManager.getInstance(project).findModuleByName("a")!!
val allFacets = FacetManager.getInstance(moduleA).allFacets
@@ -92,7 +99,9 @@ class UnloadedModulesConfigurationTest : JavaModuleTestCase() {
val a = createModule("a")
val aImlPath = a.moduleFilePath
val moduleManager = ModuleManager.getInstance(project)
moduleManager.setUnloadedModules(listOf("a"))
runUnderModalProgressIfIsEdt {
moduleManager.setUnloadedModules(listOf("a"))
}
assertEquals("a", assertOneElement(moduleManager.unloadedModuleDescriptions).name)
runWriteAction {
@@ -105,16 +114,16 @@ class UnloadedModulesConfigurationTest : JavaModuleTestCase() {
createModule("a")
val b = createModule("b")
val moduleManager = ModuleManager.getInstance(project)
moduleManager.setUnloadedModules(listOf("a"))
runUnderModalProgressIfIsEdt {
moduleManager.setUnloadedModules(listOf("a"))
}
assertEquals("a", assertOneElement(moduleManager.unloadedModuleDescriptions).name)
runWriteAction {
val model = moduleManager.modifiableModel
val model = moduleManager.getModifiableModel()
model.renameModule(b, "a")
model.commit()
}
assertEmpty(moduleManager.unloadedModuleDescriptions)
}
private fun getProjectManager() = ProjectManagerEx.getInstanceEx() as ProjectManagerImpl
}
@@ -1,5 +1,5 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
@file:Suppress("ReplaceGetOrSet")
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
@file:Suppress("ReplaceGetOrSet", "ReplacePutWithAssignment")
package com.intellij.serviceContainer
import com.intellij.ide.plugins.IdeaPluginDescriptor
@@ -153,12 +153,14 @@ class SourceFolderManagerImpl(private val project: Project) : SourceFolderManage
})
project.messageBus.connect().subscribe(ProjectTopics.MODULES, object : ModuleListener {
override fun moduleAdded(project: Project, module: Module) {
override fun modulesAdded(project: Project, modules: List<Module>) {
synchronized(mutex) {
moduleNamesToSourceFolderState[module.name].forEach {
loadSourceFolderState(it, module)
for (module in modules) {
moduleNamesToSourceFolderState[module.name].forEach {
loadSourceFolderState(it, module)
}
moduleNamesToSourceFolderState.remove(module.name)
}
moduleNamesToSourceFolderState.remove(module.name)
}
}
})
@@ -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-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.openapi.externalSystem.service.project.manage
import com.intellij.openapi.application.runWriteAction
@@ -103,7 +103,7 @@ class SourceFolderManagerTest: HeavyPlatformTestCase() {
private fun createModuleWithContentRoot(dir: File, moduleName: String = "topModule"): Module {
val moduleManager = ModuleManager.getInstance(project)
val modifiableModel = moduleManager.modifiableModel
val modifiableModel = moduleManager.getModifiableModel()
val newModule: Module =
try {
modifiableModel.newModule(dir.toPath().resolve(moduleName).toAbsolutePath(), ModuleTypeId.JAVA_MODULE)
@@ -2,7 +2,6 @@ project.configuration.save.file.not.found={0} not found
project.load.undefined.path.variables.message=There are undefined path variables in project configuration files.
project.load.default.error=Error Loading Default Project
project.loading.components=Loading components...
project.preparing.workspace=Preparing workspace...
project.configure.path.variables.title=Configure Path Variables
project.open.select.from.multiple.processors.dialog.title=Open or Import Project
project.open.select.from.multiple.processors.dialog.description.line1=Found {0} project configurations in ''{1}''.
@@ -105,7 +105,7 @@ val Project.modules: Array<Module>
get() = ModuleManager.getInstance(this).modules
inline fun <T> Project.modifyModules(crossinline task: ModifiableModuleModel.() -> T): T {
val model = ModuleManager.getInstance(this).modifiableModel
val model = ModuleManager.getInstance(this).getModifiableModel()
val result = model.task()
runWriteAction {
model.commit()
@@ -1,4 +1,4 @@
// 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.
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.facet.impl
import com.intellij.ProjectTopics
@@ -13,7 +13,6 @@ import com.intellij.openapi.project.ModuleListener
import com.intellij.openapi.project.Project
import com.intellij.util.containers.ContainerUtil
import java.util.*
import kotlin.collections.HashMap
@Service
internal class FacetEventsPublisher(private val project: Project) {
@@ -23,8 +22,10 @@ internal class FacetEventsPublisher(private val project: Project) {
init {
val connection = project.messageBus.connect()
connection.subscribe(ProjectTopics.MODULES, object : ModuleListener {
override fun moduleAdded(project: Project, module: Module) {
onModuleAdded(module)
override fun modulesAdded(project: Project, modules: MutableList<Module>) {
for (module in modules) {
onModuleAdded(module)
}
}
override fun moduleRemoved(project: Project, module: Module) {
@@ -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-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.facet.impl;
import com.intellij.ProjectTopics;
@@ -46,7 +46,7 @@ public final class ProjectFacetManagerImpl extends ProjectFacetManagerEx impleme
}, project);
project.getMessageBus().connect().subscribe(ProjectTopics.MODULES, new ModuleListener() {
@Override
public void moduleAdded(@NotNull Project project, @NotNull Module module) {
public void modulesAdded(@NotNull Project project, @NotNull List<Module> modules) {
myIndex = null;
}
@@ -1,4 +1,4 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.facet.impl.pointers;
import com.intellij.facet.pointers.FacetPointersManager;
@@ -10,18 +10,18 @@ import org.jetbrains.annotations.NotNull;
import java.util.List;
public class FacetPointerModuleListener implements ModuleListener {
final class FacetPointerModuleListener implements ModuleListener {
private final Project myProject;
public FacetPointerModuleListener(Project project) { myProject = project; }
FacetPointerModuleListener(Project project) {
myProject = project;
}
@Override
public void moduleAdded(@NotNull Project project, @NotNull Module module) {
public void modulesAdded(@NotNull Project project, @NotNull List<Module> modules) {
FacetPointersManager manager = FacetPointersManager.getInstance(myProject);
if (manager instanceof FacetPointersManagerImpl) {
FacetPointersManagerImpl managerImpl = (FacetPointersManagerImpl)manager;
managerImpl.refreshPointers();
((FacetPointersManagerImpl)manager).refreshPointers();
}
}
@@ -18,6 +18,7 @@ import com.intellij.workspaceModel.storage.EntityStorage
import com.intellij.workspaceModel.storage.bridgeEntities.api.ModuleDependencyItem
import com.intellij.workspaceModel.storage.bridgeEntities.api.ModuleId
import com.intellij.xml.util.XmlStringUtil
import kotlinx.coroutines.launch
/**
* If some modules were unloaded and new modules appears after loading project configuration, automatically unloads those which
@@ -119,7 +120,9 @@ internal class AutomaticModuleUnloaderImpl(private val project: Project) : Simpl
val moduleManager = ModuleManager.getInstance(project)
moduleManager.unloadedModuleDescriptions.mapTo(unloaded) { it.name }
action(unloaded)
moduleManager.setUnloadedModules(unloaded)
project.coroutineScope.launch {
moduleManager.setUnloadedModules(unloaded)
}
notification.expire()
}
}
@@ -11,7 +11,6 @@ import com.intellij.openapi.components.impl.stores.IComponentStore;
import com.intellij.openapi.components.impl.stores.ModuleStore;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleComponent;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.impl.scopes.ModuleScopeProviderImpl;
import com.intellij.openapi.progress.ProgressIndicator;
@@ -197,10 +196,10 @@ public class ModuleImpl extends ComponentManagerImpl implements ModuleEx {
@Override
public void projectOpened() {
//noinspection deprecation
processInitializedComponents(ModuleComponent.class, (component, __) -> {
//noinspection removal,UnnecessaryFullyQualifiedName
processInitializedComponents(com.intellij.openapi.module.ModuleComponent.class, (component, __) -> {
try {
//noinspection deprecation
//noinspection removal
component.projectOpened();
}
catch (Exception e) {
@@ -212,17 +211,17 @@ public class ModuleImpl extends ComponentManagerImpl implements ModuleEx {
@Override
public void projectClosed() {
//noinspection deprecation
List<ModuleComponent> components = new ArrayList<>();
//noinspection deprecation
processInitializedComponents(ModuleComponent.class, (component, __) -> {
@SuppressWarnings({"removal", "UnnecessaryFullyQualifiedName"})
List<com.intellij.openapi.module.ModuleComponent> components = new ArrayList<>();
//noinspection removal,UnnecessaryFullyQualifiedName
processInitializedComponents(com.intellij.openapi.module.ModuleComponent.class, (component, __) -> {
components.add(component);
return Unit.INSTANCE;
});
for (int i = components.size() - 1; i >= 0; i--) {
try {
//noinspection deprecation
//noinspection removal
components.get(i).projectClosed();
}
catch (Throwable e) {
@@ -251,9 +250,9 @@ public class ModuleImpl extends ComponentManagerImpl implements ModuleEx {
@Override
public void moduleAdded() {
isModuleAdded = true;
//noinspection deprecation
processInitializedComponents(ModuleComponent.class, (component, __) -> {
//noinspection deprecation
//noinspection removal,UnnecessaryFullyQualifiedName
processInitializedComponents(com.intellij.openapi.module.ModuleComponent.class, (component, __) -> {
//noinspection removal
component.moduleAdded();
return Unit.INSTANCE;
});
@@ -67,6 +67,8 @@ public class ProjectRootManagerComponent extends ProjectRootManagerImpl implemen
private final static ExtensionPointName<WatchedRootsProvider> WATCHED_ROOTS_PROVIDER_EP_NAME = new ExtensionPointName<>("com.intellij.roots.watchedRootsProvider");
private boolean isStartupActivityPerformed;
private final ExecutorService myExecutor = ApplicationManager.getApplication().isUnitTestMode()
? ConcurrencyUtil.newSameThreadExecutorService()
: AppExecutorUtil.createBoundedApplicationPoolExecutor("Project Root Manager", 1);
@@ -119,7 +121,7 @@ public class ProjectRootManagerComponent extends ProjectRootManagerImpl implemen
}
});
StartupManager.getInstance(myProject).registerStartupActivity(() -> myStartupActivityPerformed = true);
StartupManager.getInstance(myProject).registerStartupActivity(() -> isStartupActivityPerformed = true);
connection.subscribe(BatchUpdateListener.TOPIC, new BatchUpdateListener() {
@Override
@@ -209,7 +211,9 @@ public class ProjectRootManagerComponent extends ProjectRootManagerImpl implemen
isFiringEvent = false;
}
synchronizeRoots(indexingInfos);
if (isStartupActivityPerformed) {
EntityIndexingService.getInstance().indexChanges(myProject, indexingInfos);
}
addRootsToWatch();
}
@@ -294,11 +298,6 @@ public class ProjectRootManagerComponent extends ProjectRootManagerImpl implemen
}
}
private void synchronizeRoots(@NotNull List<? extends RootsChangeRescanningInfo> indexingInfos) {
if (!myStartupActivityPerformed) return;
EntityIndexingService.getInstance().indexChanges(myProject, indexingInfos);
}
@Override
protected void clearScopesCaches() {
super.clearScopesCaches();
@@ -30,6 +30,7 @@ import com.intellij.util.graph.*
import com.intellij.util.ui.GridBag
import com.intellij.util.ui.tree.TreeUtil
import com.intellij.xml.util.XmlStringUtil
import kotlinx.coroutines.launch
import java.awt.BorderLayout
import java.awt.Dimension
import java.awt.GridBagConstraints
@@ -198,7 +199,10 @@ class ConfigureUnloadedModulesDialog(private val project: Project, selectedModul
}
override fun doOKAction() {
ModuleManager.getInstance(project).setUnloadedModules(unloadedModulesTree.getAllModules().map { it.name })
val unloadedModuleNames = unloadedModulesTree.getAllModules().map { it.name }
project.coroutineScope.launch {
ModuleManager.getInstance(project).setUnloadedModules(unloadedModuleNames)
}
super.doOKAction()
}
}
@@ -1,7 +1,8 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.workspaceModel.ide.impl.legacyBridge.module
import com.intellij.configurationStore.RenameableStateStorageManager
import com.intellij.facet.Facet
import com.intellij.facet.FacetManager
import com.intellij.ide.plugins.IdeaPluginDescriptor
import com.intellij.ide.plugins.IdeaPluginDescriptorImpl
@@ -23,16 +24,17 @@ import com.intellij.workspaceModel.ide.impl.legacyBridge.module.ModuleManagerBri
import com.intellij.workspaceModel.ide.legacyBridge.ModuleBridge
import com.intellij.workspaceModel.ide.toPath
import com.intellij.workspaceModel.storage.EntityChange
import com.intellij.workspaceModel.storage.MutableEntityStorage
import com.intellij.workspaceModel.storage.VersionedEntityStorage
import com.intellij.workspaceModel.storage.VersionedStorageChange
import com.intellij.workspaceModel.storage.MutableEntityStorage
import com.intellij.workspaceModel.storage.bridgeEntities.addModuleCustomImlDataEntity
import com.intellij.workspaceModel.storage.bridgeEntities.api.ModuleEntity
import com.intellij.workspaceModel.storage.bridgeEntities.api.ModuleId
import com.intellij.workspaceModel.storage.bridgeEntities.api.modifyEntity
import com.intellij.workspaceModel.storage.impl.VersionedEntityStorageOnStorage
import com.intellij.workspaceModel.storage.url.VirtualFileUrl
import com.intellij.workspaceModel.storage.bridgeEntities.api.modifyEntity
@Suppress("OVERRIDE_DEPRECATION")
internal class ModuleBridgeImpl(
override var moduleEntityId: ModuleId,
name: String,
@@ -97,7 +99,7 @@ internal class ModuleBridgeImpl(
}
override fun initFacets() {
FacetManager.getInstance(this).allFacets.forEach { it.initFacet() }
FacetManager.getInstance(this).allFacets.forEach(Facet<*>::initFacet)
}
override fun registerComponents(corePlugin: IdeaPluginDescriptor?,
@@ -163,6 +165,7 @@ internal class ModuleBridgeImpl(
}
}
else {
@Suppress("DEPRECATION")
if (getOptionValue(key) != value) {
WriteAction.runAndWait<RuntimeException> {
WorkspaceModel.getInstance(project).updateProjectModel { builder ->
@@ -177,6 +180,4 @@ internal class ModuleBridgeImpl(
return
}
override fun getOptionsModificationCount(): Long = 0
}
@@ -24,37 +24,52 @@ import com.intellij.workspaceModel.ide.impl.legacyBridge.project.ProjectRootMana
import com.intellij.workspaceModel.storage.EntitySource
import com.intellij.workspaceModel.storage.EntityStorage
import com.intellij.workspaceModel.storage.bridgeEntities.api.ModuleEntity
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.coroutines.*
internal class ModuleBridgeLoaderService(private val project: Project) {
companion object {
private val LOG = logger<ModuleBridgeLoaderService>()
}
private var storeToEntitySources: Pair<EntityStorage, List<EntitySource>>? = null
private var activity: Activity? = null
private val loadModuleJob: Job
init {
if (!project.isDefault) {
val workspaceModel = WorkspaceModel.getInstance(project) as WorkspaceModelImpl
if (project.isDefault) {
loadModuleJob = CompletableDeferred(value = null)
}
else {
val projectModelSynchronizer = JpsProjectModelSynchronizer.getInstance(project)
if (projectModelSynchronizer != null) {
if (workspaceModel.loadedFromCache && projectModelSynchronizer.hasNoSerializedJpsModules()) {
LOG.warn("Loaded from cache, but no serialized modules found. Workspace model cache will be ignored, project structure will be recreated.")
workspaceModel.ignoreCache() // sets `WorkspaceModelImpl#loadedFromCache` to `false`
project.putUserData(PROJECT_LOADED_FROM_CACHE_BUT_HAS_NO_MODULES, true)
if (projectModelSynchronizer == null) {
loadModuleJob = CompletableDeferred(value = null)
}
else {
val workspaceModel = WorkspaceModel.getInstance(project) as WorkspaceModelImpl
if (workspaceModel.loadedFromCache) {
if (projectModelSynchronizer.hasNoSerializedJpsModules()) {
LOG.warn("Loaded from cache, but no serialized modules found. Workspace model cache will be ignored, project structure will be recreated.")
workspaceModel.ignoreCache() // sets `WorkspaceModelImpl#loadedFromCache` to `false`
project.putUserData(PROJECT_LOADED_FROM_CACHE_BUT_HAS_NO_MODULES, true)
}
activity = StartUpMeasurer.startActivity("modules loading with cache", ActivityCategory.DEFAULT)
loadModuleJob = project.coroutineScope.async {
loadModules()
}
}
if (!workspaceModel.loadedFromCache) {
else {
LOG.info("Workspace model loaded without cache. Loading real project state into workspace model. ${Thread.currentThread()}")
activity = StartUpMeasurer.startActivity("modules loading without cache", ActivityCategory.DEFAULT)
storeToEntitySources = projectModelSynchronizer.loadProjectToEmptyStorage(project)
}
else {
activity = StartUpMeasurer.startActivity("modules loading with cache", ActivityCategory.DEFAULT)
loadModules()
loadModuleJob = CompletableDeferred(value = null)
}
}
}
}
private fun loadModules() {
private suspend fun loadModules() {
val childActivity = activity?.startChild("modules instantiation")
val moduleManager = ModuleManager.getInstance(project) as ModuleManagerComponentBridge
val entities = moduleManager.entityStore.current.entities(ModuleEntity::class.java)
@@ -72,8 +87,11 @@ internal class ModuleBridgeLoaderService(private val project: Project) {
override suspend fun serviceCreated(project: Project) {
LOG.debug { "Project component initialized" }
val workspaceModel = WorkspaceModel.getInstance(project) as WorkspaceModelImpl
val moduleLoaderService = project.getService(ModuleBridgeLoaderService::class.java)
moduleLoaderService.loadModuleJob.join()
if (!workspaceModel.loadedFromCache) {
val moduleLoaderService = project.getService(ModuleBridgeLoaderService::class.java)
val projectModelSynchronizer = JpsProjectModelSynchronizer.getInstance(project) ?: return
projectModelSynchronizer.applyLoadedStorage(moduleLoaderService.storeToEntitySources)
project.messageBus.syncPublisher(JpsProjectLoadedListener.LOADED).loaded()
@@ -88,13 +106,5 @@ internal class ModuleBridgeLoaderService(private val project: Project) {
}
WorkspaceModelTopics.getInstance(project).notifyModulesAreLoaded()
}
companion object {
private val LOG = logger<ModuleBridgeProjectServiceInitializedListener>()
}
}
companion object {
private val LOG = logger<ModuleBridgeLoaderService>()
}
}
@@ -1,22 +1,25 @@
// 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.
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.workspaceModel.ide.impl.legacyBridge.module
import com.intellij.ProjectTopics
import com.intellij.diagnostic.ActivityCategory
import com.intellij.diagnostic.StartUpMeasurer
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.EDT
import com.intellij.openapi.components.ServiceDescriptor
import com.intellij.openapi.components.impl.stores.IComponentStore
import com.intellij.openapi.diagnostic.debug
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.module.AutomaticModuleUnloader
import com.intellij.openapi.module.Module
import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.module.impl.ModuleEx
import com.intellij.openapi.module.impl.NonPersistentModuleStore
import com.intellij.openapi.module.impl.UnloadedModulesListStorage
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.ProjectManager
import com.intellij.openapi.project.ProjectManagerListener
import com.intellij.openapi.startup.InitProjectActivity
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.serviceContainer.ComponentManagerImpl
@@ -32,32 +35,50 @@ import com.intellij.workspaceModel.ide.impl.legacyBridge.module.roots.ModuleRoot
import com.intellij.workspaceModel.ide.impl.legacyBridge.project.ProjectRootsChangeListener
import com.intellij.workspaceModel.ide.impl.legacyBridge.watcher.VirtualFileUrlWatcher
import com.intellij.workspaceModel.ide.legacyBridge.ModuleBridge
import com.intellij.workspaceModel.storage.*
import com.intellij.workspaceModel.storage.EntityChange
import com.intellij.workspaceModel.storage.MutableEntityStorage
import com.intellij.workspaceModel.storage.VersionedEntityStorage
import com.intellij.workspaceModel.storage.VersionedStorageChange
import com.intellij.workspaceModel.storage.bridgeEntities.api.*
import com.intellij.workspaceModel.storage.url.VirtualFileUrl
import com.intellij.workspaceModel.storage.url.VirtualFileUrlManager
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.IOException
import java.nio.file.Paths
class ModuleManagerComponentBridge(private val project: Project) : ModuleManagerBridgeImpl(project) {
private val virtualFileManager: VirtualFileUrlManager = VirtualFileUrlManager.getInstance(project)
internal class ModuleManagerInitProjectActivity : InitProjectActivity {
override suspend fun run(project: Project) {
val activity = StartUpMeasurer.startActivity("firing modules_added event", ActivityCategory.DEFAULT)
val moduleManager = ModuleManager.getInstance(project) as ModuleManagerComponentBridge
val modules = moduleManager.modules().toList()
withContext(Dispatchers.EDT) {
ApplicationManager.getApplication().runWriteAction {
for (module in modules) {
if (!module.isLoaded) {
module.moduleAdded()
}
}
}
moduleManager.fireModulesAdded(modules)
for (module in modules) {
module.projectOpened()
}
}
activity.end()
}
}
init {
// default project doesn't have modules
if (!project.isDefault) {
val busConnection = project.messageBus.connect(this)
busConnection.subscribe(ProjectManager.TOPIC, object : ProjectManagerListener {
override fun projectOpened(eventProject: Project) {
val activity = StartUpMeasurer.startActivity("firing modules_added event", ActivityCategory.DEFAULT)
if (project == eventProject) {
fireModulesAdded()
for (module in modules()) {
module.projectOpened()
}
}
activity.end()
}
override fun projectClosed(eventProject: Project) {
if (project == eventProject) {
for (module in modules()) {
@@ -172,7 +193,7 @@ class ModuleManagerComponentBridge(private val project: Project) : ModuleManager
oldModuleNames: MutableMap<Module, String>, event: VersionedStorageChange) {
when (change) {
is EntityChange.Removed -> {
// It's possible case then idToModule doesn't contain element e.g if unloaded module was removed
// It's possible case then idToModule doesn't contain element e.g. if unloaded module was removed
val module = event.storageBefore.findModuleByEntity(change.entity)
if (module != null) {
fireEventAndDisposeModule(module)
@@ -271,23 +292,17 @@ class ModuleManagerComponentBridge(private val project: Project) : ModuleManager
private fun List<EntityChange<LibraryEntity>>.filterModuleLibraryChanges() = filter { it.isModuleLibrary() }
private fun fireModulesAdded() {
for (module in modules()) {
fireModuleAddedInWriteAction(module)
}
}
private fun fireModuleAddedInWriteAction(module: ModuleEx) {
ApplicationManager.getApplication().runWriteAction {
if (!module.isLoaded) {
module.moduleAdded()
fireModuleAdded(module)
fireModulesAdded(listOf(module))
}
}
}
private fun fireModuleAdded(module: Module) {
project.messageBus.syncPublisher(ProjectTopics.MODULES).moduleAdded(project, module)
private fun fireModulesAdded(modules: List<Module>) {
project.messageBus.syncPublisher(ProjectTopics.MODULES).modulesAdded(project, modules)
}
override fun registerNonPersistentModuleStore(module: ModuleBridge) {
@@ -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-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.openapi.roots
import com.intellij.openapi.application.runReadAction
@@ -260,7 +260,7 @@ class ModuleDependencyInRootModelTest {
val a = projectModel.createModule("a")
val model = createModifiableModel(mainModule)
model.addModuleOrderEntry(a)
val moduleModel = runReadAction { projectModel.moduleManager.modifiableModel }
val moduleModel = runReadAction { projectModel.moduleManager.getModifiableModel() }
moduleModel.renameModule(a, "b")
val entry = dropModuleSourceEntry(model, 1).single() as ModuleOrderEntry
assertThat(entry.module).isEqualTo(a)
@@ -300,7 +300,7 @@ class ModuleDependencyInRootModelTest {
@Test
fun `add not yet committed module`() {
val moduleModel = runReadAction { projectModel.moduleManager.modifiableModel }
val moduleModel = runReadAction { projectModel.moduleManager.getModifiableModel() }
val a = projectModel.createModule("a", moduleModel)
run {
val model = createModifiableModel(mainModule)
@@ -319,7 +319,7 @@ class ModuleDependencyInRootModelTest {
@Test
fun `add not yet committed module and do not commit it`() {
val moduleModel = runReadAction { projectModel.moduleManager.modifiableModel }
val moduleModel = runReadAction { projectModel.moduleManager.getModifiableModel() }
val a = projectModel.createModule("a", moduleModel)
run {
val model = createModifiableModel(mainModule)
@@ -339,7 +339,7 @@ class ModuleDependencyInRootModelTest {
@Test
fun `add not yet committed module with configuration accessor`() {
val moduleModel = runReadAction { projectModel.moduleManager.modifiableModel }
val moduleModel = runReadAction { projectModel.moduleManager.getModifiableModel() }
val a = projectModel.createModule("a", moduleModel)
run {
val model = createModifiableModel(mainModule, object : RootConfigurationAccessor() {
@@ -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-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.openapi.roots
import com.intellij.openapi.application.runReadAction
@@ -306,7 +306,7 @@ class ModuleModelTest {
assertThat(modules[0].name).isEqualTo(antModuleName)
runWriteActionAndWait {
moduleManager.modifiableModel.let { model ->
moduleManager.getModifiableModel().let { model ->
model.renameModule(antModule, mavenModuleName)
model.renameModule(antModule, gradleModuleName)
model.commit()
@@ -373,7 +373,7 @@ class ModuleModelTest {
private fun createModifiableModuleModel(): @NotNull ModifiableModuleModel {
//we need to get module manager outside of read action because it may lazily initialize the project requiring write action
val moduleManager = projectModel.moduleManager
return runReadAction { moduleManager.modifiableModel }
return runReadAction { moduleManager.getModifiableModel() }
}
private fun getSortedModules() = runReadAction { projectModel.moduleManager.sortedModules }
@@ -1849,7 +1849,6 @@ notification.group.system.messages=System messages
action.text.install.keymap=Install {0} Keymap
action.text.search.for.keymap=Search for {0} Keymap plugin
action.separator.file.templates=File templates
startup.indicator.text.running.startup.activities=Running startup activities\u2026
notification.configurable.display.name.notifications=Notifications
dumb.balloon.this.action=This action
dumb.balloon.none.of.the.following.actions=None of the following actions
@@ -1,4 +1,6 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
@file:Suppress("ReplaceGetOrSet")
package com.intellij.ide
import com.intellij.openapi.components.BaseState
@@ -60,7 +62,7 @@ class RecentProjectManagerState : BaseState() {
fun validateRecentProjects(modCounter: AtomicLong) {
val limit = AdvancedSettings.getInt("ide.max.recent.projects")
if (additionalInfo.size <= limit) {
if (additionalInfo.size <= limit || limit < 1) {
return
}
@@ -68,7 +70,7 @@ class RecentProjectManagerState : BaseState() {
val iterator = additionalInfo.keys.iterator()
while (iterator.hasNext()) {
val path = iterator.next()
if (!additionalInfo[path]!!.opened) {
if (!additionalInfo.get(path)!!.opened) {
iterator.remove()
break
}
@@ -21,10 +21,12 @@ import com.intellij.openapi.application.ex.ApplicationManagerEx
import com.intellij.openapi.components.*
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.diagnostic.runAndLogException
import com.intellij.openapi.extensions.ExtensionNotApplicableException
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.ProjectManagerListener
import com.intellij.openapi.project.ex.ProjectManagerEx
import com.intellij.openapi.project.impl.*
import com.intellij.openapi.startup.ProjectPostStartupActivity
import com.intellij.openapi.util.ModificationTracker
import com.intellij.openapi.util.SystemInfo
import com.intellij.openapi.util.io.FileUtil
@@ -317,10 +319,6 @@ open class RecentProjectsManagerBase : RecentProjectsManager, PersistentStateCom
}
}
fun setLastOpenedProject(path: String) {
state.lastOpenedProject = path
}
fun getLastOpenedProject() = state.lastOpenedProject
init {
@@ -336,28 +334,42 @@ open class RecentProjectsManagerBase : RecentProjectsManager, PersistentStateCom
}, AWTEvent.WINDOW_EVENT_MASK)
}
@VisibleForTesting
suspend fun runProjectPostStartupActivity(project: Project) {
if (disableUpdatingRecentInfo.get() || LightEdit.owns(project)) {
return
}
val projectPath = getProjectPath(project) ?: return
synchronized(stateLock) {
findAndRemoveNewlyClonedProject(projectPath)
markPathRecent(projectPath, project)
state.lastOpenedProject = projectPath
updateProjectOpenedState(project, updateTime = true)
state.validateRecentProjects(modCounter)
}
withContext(Dispatchers.EDT) {
updateSystemDockMenu()
}
}
internal class MyProjectPostStartupActivity : ProjectPostStartupActivity {
init {
if (ApplicationManager.getApplication().isUnitTestMode) {
throw ExtensionNotApplicableException.create()
}
}
override suspend fun execute(project: Project) {
getInstanceEx().runProjectPostStartupActivity(project)
}
}
@Internal
@VisibleForTesting
class MyProjectListener : ProjectManagerListener {
override fun projectOpened(project: Project) {
val manager = getInstanceEx()
if (manager.disableUpdatingRecentInfo.get() || LightEdit.owns(project)) {
return
}
manager.getProjectPath(project)?.let { path ->
synchronized(manager.stateLock) {
manager.findAndRemoveNewlyClonedProject(path)
manager.markPathRecent(path, project)
manager.setLastOpenedProject(path)
manager.updateProjectOpenedState(project, updateTime = true)
manager.state.validateRecentProjects(manager.modCounter)
}
}
updateSystemDockMenu()
}
override fun projectClosing(project: Project) {
val app = ApplicationManagerEx.getApplicationEx()
if (app.isExitInProgress) {
@@ -385,7 +397,7 @@ open class RecentProjectsManagerBase : RecentProjectsManager, PersistentStateCom
fun getRecentPaths(): List<String> {
synchronized(stateLock) {
state.validateRecentProjects(modCounter)
return state.additionalInfo.keys.toList().asReversed()
return state.additionalInfo.keys.reversed()
}
}
@@ -1,173 +0,0 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.ide;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.project.ProjectManagerListener;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.openapi.wm.StatusBar;
import com.intellij.openapi.wm.impl.ProjectFrameHelper;
import com.intellij.util.Alarm;
import com.intellij.util.BitUtil;
import com.intellij.util.ReflectionUtil;
import org.jetbrains.annotations.NotNull;
import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
import javax.swing.*;
import javax.swing.event.CaretListener;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentListener;
import javax.swing.text.AbstractDocument;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
import java.awt.*;
import java.awt.event.HierarchyEvent;
import java.lang.reflect.Field;
import java.util.EventListener;
/**
* This class listens event from ProjectManager and cleanup some
* internal Swing references.
*
* @author Vladimir Kondratyev
*/
public final class SwingCleanuper {
private final Alarm myAlarm;
public SwingCleanuper(@NotNull Application application) {
myAlarm = new Alarm(application);
application.getMessageBus().connect().subscribe(ProjectManager.TOPIC, new ProjectManagerListener() {
@Override
public void projectOpened(@NotNull final Project project) {
myAlarm.cancelAllRequests();
}
// Swing keeps references to the last focused component inside DefaultKeyboardFocusManager.realOppositeComponent
// which is used to compose next focus event. Actually this component could be an editors or a tool window. To fix this
// memory leak we (if the project was closed and a new one was not opened yet) request focus to the status bar and after
// the focus events have passed the queue, we put 'null' to the DefaultKeyboardFocusManager.realOppositeComponent field.
@Override
public void projectClosed(@NotNull final Project project){
myAlarm.cancelAllRequests();
myAlarm.addRequest(
() -> {
// request focus into some focusable component inside IdeFrame
ProjectFrameHelper frame = ProjectFrameHelper.getFrameHelper(KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusedWindow());
if (frame != null) {
final Application app = ApplicationManager.getApplication();
if (app != null && app.isActive()) {
StatusBar statusBar = frame.getStatusBar();
if (statusBar != null) {
IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown(() -> IdeFocusManager.getGlobalInstance().requestFocus((JComponent)statusBar, true));
}
}
}
},
2500
);
}
}
);
if (SystemInfo.isMac) {
Toolkit.getDefaultToolkit().addAWTEventListener(event -> {
if (!Registry.is("ide.mac.fix.accessibleLeak")) return;
HierarchyEvent he = (HierarchyEvent)event;
if (BitUtil.isSet(he.getChangeFlags(), HierarchyEvent.SHOWING_CHANGED)) {
if (he.getComponent() != null && !he.getComponent().isShowing()) {
Component c = he.getComponent();
if (c instanceof JTextComponent) {
JTextComponent textComponent = (JTextComponent)c;
CaretListener[] carets = textComponent.getListeners(CaretListener.class);
for (CaretListener each : carets) {
if (isCAccessibleListener(each)) {
textComponent.removeCaretListener(each);
}
}
Document document = textComponent.getDocument();
if (document instanceof AbstractDocument) {
DocumentListener[] documentListeners = ((AbstractDocument)document).getDocumentListeners();
for (DocumentListener each : documentListeners) {
if (isCAccessibleListener(each)) {
document.removeDocumentListener(each);
}
}
}
}
else if (c instanceof JProgressBar) {
JProgressBar bar = (JProgressBar)c;
ChangeListener[] changeListeners = bar.getChangeListeners();
for (ChangeListener each : changeListeners) {
if (isCAccessibleListener(each)) {
bar.removeChangeListener(each);
}
}
}
else if (c instanceof JSlider) {
JSlider slider = (JSlider)c;
ChangeListener[] changeListeners = slider.getChangeListeners();
for (ChangeListener each : changeListeners) {
if (isCAccessibleListener(each)) {
slider.removeChangeListener(each);
}
}
}
Field nativeAXResource_Field = null;
Field accessibleContext_Field = null;
try {
nativeAXResource_Field = ReflectionUtil.findField(AccessibleContext.class, Object.class, "nativeAXResource");
accessibleContext_Field = ReflectionUtil.findField(Component.class, AccessibleContext.class, "accessibleContext");
}
catch (NoSuchFieldException ignored) {
}
if (accessibleContext_Field != null) {
try {
// Component's AccessibleContext is not necessarily initialized. In this case we don't want to force its creation.
// So, first we check the Component.accessibleContext field. The field has a protected access and it's a common
// Swing pattern to set it in the Component.getAccessibleContext() method when it's overriden by a subclass
// (and we're to follow it).
AccessibleContext ac = (AccessibleContext)accessibleContext_Field.get(c);
if (ac != null) {
// The getter may have a side effect, so call it to get the up-to-date context.
ac = c.getAccessibleContext();
if (ac != null) {
Object resource = nativeAXResource_Field.get(ac);
if (resource != null && isCAccessible(resource)) {
Field accessible = ReflectionUtil.findField(resource.getClass(), Accessible.class, "accessible");
accessible.set(resource, null);
}
}
}
}
catch (Exception ignored) {
}
}
}
}
}, AWTEvent.HIERARCHY_EVENT_MASK);
}
}
private static boolean isCAccessible(Object resource) {
final String name = resource.getClass().getName();
return isCAccessible(name);
}
static boolean isCAccessible(String name) {
return name.equals("apple.awt.CAccessible") || name.equals("sun.lwawt.macosx.CAccessible");
}
private static boolean isCAccessibleListener(EventListener listener) {
return listener != null && listener.toString().contains("AXTextChangeNotifier");
}
}
@@ -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-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.ide.actions.project
import com.intellij.CommonBundle
@@ -174,7 +174,7 @@ internal class ConvertModuleGroupsToQualifiedNamesDialog(val project: Project) :
val renamingScheme = getRenamingScheme()
if (renamingScheme.isNotEmpty()) {
val model = ModuleManager.getInstance(project).modifiableModel
val model = ModuleManager.getInstance(project).getModifiableModel()
val byName = modules.associateBy { it.name }
for (entry in renamingScheme) {
model.renameModule(byName[entry.key]!!, entry.value)
@@ -1,88 +1,79 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.ide.lightEdit.project;
package com.intellij.ide.lightEdit.project
import com.intellij.ide.startup.impl.StartupManagerImpl;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.project.ProjectManagerListener;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.util.TimeoutUtil;
import kotlin.coroutines.EmptyCoroutineContext;
import kotlinx.coroutines.BuildersKt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.intellij.ide.impl.runUnderModalProgressIfIsEdt
import com.intellij.ide.startup.impl.StartupManagerImpl
import com.intellij.openapi.actionSystem.ActionManager
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.ProjectManager
import com.intellij.openapi.project.ProjectManagerListener
import com.intellij.openapi.startup.StartupManager
import com.intellij.util.TimeoutUtil
public final class LightEditProjectManager {
private static final Logger LOG = Logger.getInstance(LightEditProjectManager.class);
private static final Object LOCK = new Object();
class LightEditProjectManager {
companion object {
private val LOG = logger<LightEditProjectManager>()
private val LOCK = Any()
private volatile LightEditProjectImpl myProject;
private fun fireProjectOpened(project: Project) {
val app = ApplicationManager.getApplication()
val fireRunnable = Runnable {
// similar to com.intellij.openapi.project.impl.ProjectManagerExImplKt.openProject
app.messageBus.syncPublisher(ProjectManager.TOPIC).projectOpened(project)
runUnderModalProgressIfIsEdt {
val startupManager = StartupManager.getInstance(project) as StartupManagerImpl
startupManager.initProject(null)
startupManager.runStartupActivities()
}
}
if (app.isDispatchThread || app.isUnitTestMode) {
fireRunnable.run()
}
else {
// Initialize ActionManager out of EDT to pass "assert !app.isDispatchThread()" in ActionManagerImpl
ActionManager.getInstance()
app.invokeLater(fireRunnable)
}
}
public @Nullable Project getProject() {
return myProject;
private fun createProject(): LightEditProjectImpl {
val start = System.nanoTime()
val project = LightEditProjectImpl()
LOG.info(LightEditProjectImpl::class.java.simpleName + " loaded in " + TimeoutUtil.getDurationMillis(start) + " ms")
return project
}
}
public @NotNull Project getOrCreateProject() {
LightEditProjectImpl project = myProject;
@Volatile
private var projectImpl: LightEditProjectImpl? = null
val project: Project?
get() = projectImpl
fun getOrCreateProject(): Project {
var project = projectImpl
if (project == null) {
boolean created = false;
synchronized (LOCK) {
if (myProject == null) {
myProject = createProject();
created = true;
var created = false
synchronized(LOCK) {
if (projectImpl == null) {
projectImpl = createProject()
created = true
}
project = myProject;
project = projectImpl
}
if (created) {
fireProjectOpened(project);
ApplicationManager.getApplication().getMessageBus().connect().subscribe(ProjectManager.TOPIC, new ProjectManagerListener() {
@Override
public void projectClosed(@NotNull Project project) {
if (project == myProject) {
synchronized (LOCK) {
myProject = null;
}
fireProjectOpened(project!!)
ApplicationManager.getApplication().messageBus.connect().subscribe(ProjectManager.TOPIC, object : ProjectManagerListener {
override fun projectClosed(project: Project) {
if (project === projectImpl) {
synchronized(LOCK) { projectImpl = null }
}
}
});
})
}
}
return project;
return project!!
}
private static void fireProjectOpened(@NotNull Project project) {
Application app = ApplicationManager.getApplication();
Runnable fireRunnable = () -> {
// similar to com.intellij.openapi.project.impl.ProjectManagerExImplKt.openProject
app.getMessageBus().syncPublisher(ProjectManager.TOPIC).projectOpened(project);
try {
BuildersKt.runBlocking(EmptyCoroutineContext.INSTANCE, (scope, continuation) -> {
((StartupManagerImpl)StartupManager.getInstance(project)).projectOpened(null, continuation);
return null;
});
}
catch (InterruptedException e) {
throw new RuntimeException(e);
}
};
if (app.isDispatchThread() || app.isUnitTestMode()) {
fireRunnable.run();
}
else {
// Initialize ActionManager out of EDT to pass "assert !app.isDispatchThread()" in ActionManagerImpl
ActionManager.getInstance();
app.invokeLater(fireRunnable);
}
}
private static @NotNull LightEditProjectImpl createProject() {
long start = System.nanoTime();
LightEditProjectImpl project = new LightEditProjectImpl();
LOG.info(LightEditProjectImpl.class.getSimpleName() + " loaded in " + TimeoutUtil.getDurationMillis(start) + " ms");
return project;
}
}
}
@@ -75,9 +75,7 @@ open class StartupManagerImpl(private val project: Project) : StartupManagerEx()
if (activity is DumbAware) {
project.coroutineScope.launch {
if (activity is ProjectPostStartupActivity) {
DumbService.getInstance(project).runWithWaitForSmartModeDisabled().use {
startupManager.runActivityAndMeasureDuration(activity, descriptor.pluginId, project !is LightEditCompatible)
}
startupManager.runActivityAndMeasureDuration(activity, descriptor.pluginId, project !is LightEditCompatible)
}
else {
startupManager.runActivityAndMeasureDuration(activity, pluginId)
@@ -95,7 +93,7 @@ open class StartupManagerImpl(private val project: Project) : StartupManagerEx()
}
private val lock = Any()
private val startupActivities = ArrayDeque<Runnable>()
private val initProjectStartupActivities = ArrayDeque<Runnable>()
private val postStartupActivities = ArrayDeque<Runnable>()
@MagicConstant(intValues = [0, DUMB_AWARE_PASSED.toLong(), ALL_PASSED.toLong()])
@@ -104,7 +102,7 @@ open class StartupManagerImpl(private val project: Project) : StartupManagerEx()
private val allActivitiesPassed = CompletableDeferred<Any?>()
@Volatile
private var isStartupActivitiesPassed = false
private var isInitProjectActivitiesPassed = false
private fun checkNonDefaultProject() {
LOG.assertTrue(!project.isDefault, "Please don't register startup activities for the default project: they won't ever be run")
@@ -112,9 +110,9 @@ open class StartupManagerImpl(private val project: Project) : StartupManagerEx()
override fun registerStartupActivity(runnable: Runnable) {
checkNonDefaultProject()
LOG.assertTrue(!isStartupActivitiesPassed, "Registering startup activity that will never be run")
LOG.assertTrue(!isInitProjectActivitiesPassed, "Registering startup activity that will never be run")
synchronized(lock) {
startupActivities.add(runnable)
initProjectStartupActivities.add(runnable)
}
}
@@ -135,12 +133,12 @@ open class StartupManagerImpl(private val project: Project) : StartupManagerEx()
LOG.error("Registering post-startup activity that will never be run (" +
" disposed=${project.isDisposed}" +
", open=${project.isOpen}" +
", passed=$isStartupActivitiesPassed"
", passed=$isInitProjectActivitiesPassed"
+ ")")
}
}
override fun startupActivityPassed() = isStartupActivitiesPassed
override fun startupActivityPassed() = isInitProjectActivitiesPassed
override fun postStartupActivityPassed(): Boolean {
return when (postStartupActivitiesPassed) {
@@ -152,17 +150,18 @@ open class StartupManagerImpl(private val project: Project) : StartupManagerEx()
override fun getAllActivitiesPassedFuture() = allActivitiesPassed
suspend fun projectOpened(indicator: ProgressIndicator?) {
val app = ApplicationManager.getApplication()
suspend fun initProject(indicator: ProgressIndicator?) {
// see https://github.com/JetBrains/intellij-community/blob/master/platform/service-container/overview.md#startup-activity
LOG.assertTrue(!isStartupActivitiesPassed)
LOG.assertTrue(!isInitProjectActivitiesPassed)
runActivity("project startup") {
tracer.spanBuilder("run startup activities").useWithScope {
runStartUpActivities(indicator, app)
isStartupActivitiesPassed = true
tracer.spanBuilder("run init project activities").useWithScope {
runInitProjectActivities(indicator)
isInitProjectActivitiesPassed = true
}
}
}
suspend fun runStartupActivities() {
// opened on startup
StartUpMeasurer.compareAndSetCurrentState(LoadingState.COMPONENTS_LOADED, LoadingState.PROJECT_OPENED)
// opened from the welcome screen
@@ -170,6 +169,7 @@ open class StartupManagerImpl(private val project: Project) : StartupManagerEx()
coroutineContext.ensureActive()
val app = ApplicationManager.getApplication()
if (app.isUnitTestMode && !app.isDispatchThread) {
runPostStartupActivities()
}
@@ -180,14 +180,14 @@ open class StartupManagerImpl(private val project: Project) : StartupManagerEx()
}
if (app.isUnitTestMode) {
LOG.assertTrue(app.isDispatchThread)
@Suppress("TestOnlyProblems")
waitAndProcessInvocationEventsInIdeEventQueue(this)
}
}
}
private suspend fun runStartUpActivities(indicator: ProgressIndicator?, app: Application) {
runActivities(startupActivities)
private suspend fun runInitProjectActivities(indicator: ProgressIndicator?) {
runActivities(initProjectStartupActivities)
val app = ApplicationManager.getApplication()
val extensionPoint = (app.extensionArea as ExtensionsAreaImpl).getExtensionPoint<StartupActivity>("com.intellij.startupActivity")
// do not create extension if not allow-listed
@@ -224,7 +224,7 @@ open class StartupManagerImpl(private val project: Project) : StartupManagerEx()
// Must be executed in a pooled thread outside of project loading modal task. The only exclusion - test mode.
private suspend fun runPostStartupActivities() {
try {
LOG.assertTrue(isStartupActivitiesPassed)
LOG.assertTrue(isInitProjectActivitiesPassed)
val snapshot = PerformanceWatcher.takeSnapshot()
// strictly speaking, the activity is not sequential, because sub-activities are performed in different threads
// (depending on dumb-awareness), but because there is no other concurrent phase, we measure it as a sequential activity
@@ -237,36 +237,33 @@ open class StartupManagerImpl(private val project: Project) : StartupManagerEx()
val isProjectLightEditCompatible = project is LightEditCompatible
StartupActivity.POST_STARTUP_ACTIVITY.processExtensions { activity, pluginDescriptor ->
if (activity is ProjectPostStartupActivity) {
runActivityAndMeasureDuration(activity, pluginDescriptor.pluginId, isProjectLightEditCompatible)
return@processExtensions
}
@Suppress("SSBasedInspection")
if (activity is DumbAware) {
dumbService.runWithWaitForSmartModeDisabled().use {
runActivityAndMeasureDuration(activity, pluginDescriptor.pluginId, isProjectLightEditCompatible)
runActivityAndMeasureDuration(activity, pluginDescriptor.pluginId)
}
return@processExtensions
}
else {
@Suppress("SSBasedInspection")
if (activity is DumbAware) {
dumbService.runWithWaitForSmartModeDisabled().use {
runActivityAndMeasureDuration(activity, pluginDescriptor.pluginId)
}
return@processExtensions
if (edtActivity.get() == null) {
edtActivity.set(StartUpMeasurer.startActivity("project post-startup edt activities"))
}
else {
if (edtActivity.get() == null) {
edtActivity.set(StartUpMeasurer.startActivity("project post-startup edt activities"))
}
// DumbService.unsafeRunWhenSmart throws an assertion in LightEdit mode, see LightEditDumbService.unsafeRunWhenSmart
if (!isProjectLightEditCompatible) {
counter.incrementAndGet()
val traceContext = Context.current()
dumbService.unsafeRunWhenSmart {
traceContext.makeCurrent()
val duration = runActivityAndMeasureDuration(activity, pluginDescriptor.pluginId)
if (duration > EDT_WARN_THRESHOLD_IN_NANO) {
reportUiFreeze(uiFreezeWarned)
}
dumbUnawarePostActivitiesPassed(edtActivity, counter.decrementAndGet())
// DumbService.unsafeRunWhenSmart throws an assertion in LightEdit mode, see LightEditDumbService.unsafeRunWhenSmart
if (!isProjectLightEditCompatible) {
counter.incrementAndGet()
val traceContext = Context.current()
dumbService.unsafeRunWhenSmart {
traceContext.makeCurrent()
val duration = runActivityAndMeasureDuration(activity, pluginDescriptor.pluginId)
if (duration > EDT_WARN_THRESHOLD_IN_NANO) {
reportUiFreeze(uiFreezeWarned)
}
dumbUnawarePostActivitiesPassed(edtActivity, counter.decrementAndGet())
}
}
}
@@ -324,7 +321,7 @@ open class StartupManagerImpl(private val project: Project) : StartupManagerEx()
activity: ProjectPostStartupActivity,
pluginId: PluginId,
isProjectLightEditCompatible: Boolean
): Long {
) {
val startTime = StartUpMeasurer.getCurrentTime()
tracer.spanBuilder("run activity")
.setAttribute(AttributeKey.stringKey("class"), activity.javaClass.name)
@@ -334,7 +331,7 @@ open class StartupManagerImpl(private val project: Project) : StartupManagerEx()
activity.execute(project)
}
}
return addCompletedActivity(startTime = startTime, runnableClass = activity.javaClass, pluginId = pluginId)
addCompletedActivity(startTime = startTime, runnableClass = activity.javaClass, pluginId = pluginId)
}
private suspend fun runPostStartupActivitiesRegisteredDynamically() {
@@ -464,7 +461,7 @@ open class StartupManagerImpl(private val project: Project) : StartupManagerEx()
@Synchronized
fun prepareForNextTest() {
synchronized(lock) {
startupActivities.clear()
initProjectStartupActivities.clear()
postStartupActivities.clear()
}
}
@@ -474,7 +471,7 @@ open class StartupManagerImpl(private val project: Project) : StartupManagerEx()
fun checkCleared() {
try {
synchronized(lock) {
assert(startupActivities.isEmpty()) { "Activities: $startupActivities" }
assert(initProjectStartupActivities.isEmpty()) { "Activities: $initProjectStartupActivities" }
assert(postStartupActivities.isEmpty()) { "DumbAware Post Activities: $postStartupActivities" }
}
}
@@ -209,7 +209,6 @@ fun initApplication(rawArgs: List<String>, prepareUiFuture: Deferred<Any>) {
}
}
@OptIn(ExperimentalCoroutinesApi::class)
private suspend fun prepareStart(app: ApplicationImpl, initAppActivity: Activity, pluginSet: PluginSet, mainScope: CoroutineScope) {
coroutineScope {
app.preloadServices(
@@ -243,10 +242,9 @@ private suspend fun prepareStart(app: ApplicationImpl, initAppActivity: Activity
createAppLocatorFile()
}
if (!app.isUnitTestMode && !app.isHeadlessEnvironment &&
java.lang.Boolean.parseBoolean(System.getProperty("enable.activity.preloading", "true"))) {
if (!app.isUnitTestMode && !app.isHeadlessEnvironment && System.getProperty("enable.activity.preloading", "true").toBoolean()) {
// do not execute as a single long task, make sure that other more important tasks may slip in between
launchAndMeasure("preloading activity executing", Dispatchers.Default.limitedParallelism(1)) {
launchAndMeasure("preloading activity executing") {
executePreloadActivities(app)
}
}
@@ -197,17 +197,10 @@ public abstract class FileEditorManagerImpl extends FileEditorManagerEx implemen
}
});
connection.subscribe(ProjectManager.TOPIC, new ProjectManagerListener() {
@Override
public void projectOpened(@NotNull Project project) {
if (project == myProject) {
FileEditorManagerImpl.this.projectOpened(connection);
}
}
@Override
public void projectClosing(@NotNull Project project) {
if (project == myProject) {
// Dispose created editors. We do not use use closeEditor method because
// Dispose created editors. We do not use closeEditor method because
// it fires event and changes history.
closeAllFiles();
}
@@ -545,6 +538,7 @@ public abstract class FileEditorManagerImpl extends FileEditorManagerEx implemen
getActiveSplittersAsync().onSuccess(splitters -> splitters.updateFileName(null));
}
@SuppressWarnings("removal")
@Override
public VirtualFile getFile(@NotNull FileEditor editor) {
EditorComposite editorComposite = getComposite(editor);
@@ -940,7 +934,7 @@ public abstract class FileEditorManagerImpl extends FileEditorManagerEx implemen
/**
* @param file to be opened. Unlike openFile method, file can be
* invalid. For example, all file were invalidate and they are being
* invalid. For example, all file where invalidate, and they are being
* removed one by one. If we have removed one invalid file, then another
* invalid file become selected. That's why we do not require that
* passed file is valid.
@@ -1202,7 +1196,7 @@ public abstract class FileEditorManagerImpl extends FileEditorManagerEx implemen
}
if (state == null && newEditor) {
// We have to try to get state from the history only in case
// if editor is not opened. Otherwise history entry might have a state
// if editor is not opened. Otherwise, history entry might have a state
// out of sync with the current editor state.
state = EditorHistoryManager.getInstance(myProject).getState(file, provider);
}
@@ -1415,7 +1409,7 @@ public abstract class FileEditorManagerImpl extends FileEditorManagerEx implemen
return getSelectedTextEditor(false);
}
public Editor getSelectedTextEditor(boolean lockfree) {
public Editor getSelectedTextEditor(boolean isLockFree) {
if (!ClientId.isCurrentlyUnderLocalId()) {
ClientFileEditorManager clientManager = getClientFileEditorManager();
if (clientManager == null) {
@@ -1425,11 +1419,11 @@ public abstract class FileEditorManagerImpl extends FileEditorManagerEx implemen
return selectedEditor instanceof TextEditor ? ((TextEditor)selectedEditor).getEditor() : null;
}
if (!lockfree) {
if (!isLockFree) {
assertDispatchThread();
}
EditorWindow currentWindow = lockfree ? getMainSplitters().getCurrentWindow() : getSplitters().getCurrentWindow();
EditorWindow currentWindow = isLockFree ? getMainSplitters().getCurrentWindow() : getSplitters().getCurrentWindow();
if (currentWindow != null) {
EditorComposite selectedEditor = currentWindow.getSelectedComposite();
if (selectedEditor != null && selectedEditor.getSelectedEditor() instanceof TextEditor) {
@@ -1686,7 +1680,8 @@ public abstract class FileEditorManagerImpl extends FileEditorManagerEx implemen
myListenerList.remove(listener);
}
protected void projectOpened(@NotNull MessageBusConnection connection) {
@ApiStatus.Internal
public final void init() {
//myFocusWatcher.install(myWindows.getComponent ());
getMainSplitters().startListeningFocus();
@@ -1695,6 +1690,8 @@ public abstract class FileEditorManagerImpl extends FileEditorManagerEx implemen
// updates tabs colors
fileStatusManager.addFileStatusListener(new MyFileStatusListener(), myProject);
}
MessageBusConnection connection = myProject.getMessageBus().connect(this);
connection.subscribe(FileTypeManager.TOPIC, new MyFileTypeListener());
connection.subscribe(ProjectTopics.PROJECT_ROOTS, new MyRootsListener());
connection.subscribe(AdditionalLibraryRootsListener.TOPIC, new MyRootsListener());
@@ -2127,7 +2124,7 @@ public abstract class FileEditorManagerImpl extends FileEditorManagerEx implemen
/**
* Gets notifications from UISetting component to track changes of RECENT_FILES_LIMIT
* and EDITOR_TAB_LIMIT, etc values.
* and EDITOR_TAB_LIMIT, etc. values.
*/
private final class MyUISettingsListener implements UISettingsListener {
@Override
@@ -18,12 +18,17 @@ import com.intellij.openapi.project.isNotificationSilentMode
import com.intellij.openapi.startup.InitProjectActivity
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
internal class OpenFilesActivity : InitProjectActivity {
override suspend fun run(project: Project) {
ProgressManager.getInstance().progressIndicator?.text = IdeBundle.message("progress.text.reopening.files")
val fileEditorManager = FileEditorManager.getInstance(project) as? FileEditorManagerImpl ?: return
withContext(Dispatchers.EDT) {
fileEditorManager.init()
}
val editorSplitters = fileEditorManager.mainSplitters
val panel = editorSplitters.restoreEditors()
(project as ProjectEx).coroutineScope.launch(Dispatchers.EDT + ModalityState.NON_MODAL.asContextElement()) {
@@ -4,6 +4,7 @@ package com.intellij.openapi.project.impl
import com.intellij.configurationStore.runInAutoSaveDisabledMode
import com.intellij.configurationStore.saveSettings
import com.intellij.diagnostic.ActivityCategory
import com.intellij.diagnostic.LoadingState
import com.intellij.diagnostic.PluginException
import com.intellij.diagnostic.StartUpMeasurer
import com.intellij.ide.impl.runUnderModalProgressIfIsEdt
@@ -358,7 +359,7 @@ open class ProjectImpl(filePath: Path, projectName: String?)
override fun getContainerDescriptor(pluginDescriptor: IdeaPluginDescriptorImpl) = pluginDescriptor.projectContainerDescriptor
override fun setProgressDuringInit(indicator: ProgressIndicator) {
indicator.fraction = getPercentageOfComponentsLoaded() / if (ourClassesAreLoaded) 10 else 2
indicator.fraction = getPercentageOfComponentsLoaded() / if (LoadingState.PROJECT_OPENED.isOccurred) 10 else 2
}
override fun save() {
@@ -97,10 +97,11 @@ open class ProjectManagerImpl : ProjectManagerEx(), Disposable {
init {
val connection = ApplicationManager.getApplication().messageBus.connect()
connection.subscribe(TOPIC, object : ProjectManagerListener {
@Suppress("removal")
override fun projectOpened(project: Project) {
for (listener in getAllListeners(project)) {
try {
@Suppress("DEPRECATION")
@Suppress("DEPRECATION", "removal")
listener.projectOpened(project)
}
catch (e: Exception) {
@@ -292,6 +293,7 @@ open class ProjectManagerImpl : ProjectManagerEx(), Disposable {
}
app.assertIsWriteThread()
@Suppress("TestOnlyProblems")
if (isLight(project)) {
// if we close project at the end of the test, just mark it closed;
// if we are shutting down the entire test framework, proceed to full dispose
@@ -562,18 +564,10 @@ open class ProjectManagerImpl : ProjectManagerEx(), Disposable {
throw CancellationException("not trusted")
}
val waitEdtActivity = StartUpMeasurer.startActivity("placing calling projectOpened on event queue")
val indicator = ProgressManager.getInstance().progressIndicator
if (indicator != null) {
indicator.text = if (ApplicationManager.getApplication().isInternal) "Waiting on event queue..." // NON-NLS (internal mode)
else ProjectBundle.message("project.preparing.workspace")
indicator.isIndeterminate = true
}
tracer.spanBuilder("open project")
.setAttribute(AttributeKey.stringKey("project"), project.name)
.useWithScope {
runStartupActivities(project, indicator, isRunStartUpActivitiesEnabled(project), waitEdtActivity)
runInitProjectActivities(project)
}
}
@@ -613,6 +607,11 @@ open class ProjectManagerImpl : ProjectManagerEx(), Disposable {
disableAutoSaveToken.finish()
}
if (isRunStartUpActivitiesEnabled(project)) {
(StartupManager.getInstance(project) as StartupManagerImpl).runStartupActivities()
}
LifecycleUsageTriggerCollector.onProjectOpened(project)
options.callback?.projectOpened(project, module ?: ModuleManager.getInstance(project).modules[0])
return project
}
@@ -848,69 +847,51 @@ private fun message(e: Throwable): String {
@Internal
@VisibleForTesting
suspend fun runStartupActivities(project: Project,
indicator: ProgressIndicator?,
runStartUpActivities: Boolean,
waitEdtActivity: Activity?) {
suspend fun runInitProjectActivities(project: Project) {
val traceContext = Context.current()
withContext(Dispatchers.EDT) {
waitEdtActivity?.end()
if (indicator != null && ApplicationManager.getApplication().isInternal) {
indicator.text = "Running project opened tasks..." // NON-NLS (internal mode)
coroutineScope {
launch {
(StartupManager.getInstance(project) as StartupManagerImpl).initProject(null)
}
LOG.debug("projectOpened")
val waitEdtActivity = StartUpMeasurer.startActivity("placing calling projectOpened on event queue")
launch(Dispatchers.EDT) {
waitEdtActivity.end()
val activity = StartUpMeasurer.startActivity("project opened callbacks")
runActivity("projectOpened event executing") {
tracer.spanBuilder("execute projectOpened handlers").setParent(traceContext).useWithScope {
@Suppress("DEPRECATION")
ApplicationManager.getApplication().messageBus.syncPublisher(ProjectManager.TOPIC).projectOpened(project)
}
}
coroutineContext.ensureActive()
@Suppress("DEPRECATION")
(project as ComponentManagerImpl)
.processInitializedComponents(com.intellij.openapi.components.ProjectComponent::class.java) { component, pluginDescriptor ->
coroutineContext.ensureActive()
try {
val componentActivity = StartUpMeasurer.startActivity(component.javaClass.name, ActivityCategory.PROJECT_OPEN_HANDLER,
pluginDescriptor.pluginId.idString)
component.projectOpened()
componentActivity.end()
}
catch (e: CancellationException) {
throw e
}
catch (e: ProcessCanceledException) {
throw e
}
catch (e: Throwable) {
LOG.error(e)
val activity = StartUpMeasurer.startActivity("project opened callbacks")
runActivity("projectOpened event executing") {
tracer.spanBuilder("execute projectOpened handlers").setParent(traceContext).useWithScope {
@Suppress("DEPRECATION", "removal")
ApplicationManager.getApplication().messageBus.syncPublisher(ProjectManager.TOPIC).projectOpened(project)
}
}
activity.end()
}
coroutineContext.ensureActive()
ProjectImpl.ourClassesAreLoaded = true
@Suppress("DEPRECATION")
(project as ComponentManagerImpl)
.processInitializedComponents(com.intellij.openapi.components.ProjectComponent::class.java) { component, pluginDescriptor ->
coroutineContext.ensureActive()
try {
val componentActivity = StartUpMeasurer.startActivity(component.javaClass.name, ActivityCategory.PROJECT_OPEN_HANDLER,
pluginDescriptor.pluginId.idString)
component.projectOpened()
componentActivity.end()
}
catch (e: CancellationException) {
throw e
}
catch (e: ProcessCanceledException) {
throw e
}
catch (e: Throwable) {
LOG.error(e)
}
}
if (runStartUpActivities) {
val app = ApplicationManager.getApplication()
if (indicator != null && app.isInternal) {
indicator.text = IdeBundle.message("startup.indicator.text.running.startup.activities")
}
tracer.spanBuilder("StartupManager.projectOpened").useWithScope {
(StartupManager.getInstance(project) as StartupManagerImpl).projectOpened(indicator)
activity.end()
}
}
LifecycleUsageTriggerCollector.onProjectOpened(project)
}
private val LOG = logger<ProjectManagerImpl>()
@@ -992,6 +973,7 @@ private fun ensureCouldCloseIfUnableToSave(project: Project): Boolean {
}
}
@Suppress("HardCodedStringLiteral")
return Messages.showYesNoDialog(project, message.toString(),
IdeUICustomization.getInstance().projectMessage("dialog.title.unsaved.project"),
Messages.getWarningIcon()) == Messages.YES
@@ -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-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.ui.mac;
import com.intellij.ide.DataManager;
import com.intellij.ide.RecentProjectListActionProvider;
import com.intellij.ide.RecentProjectsManager;
import com.intellij.ide.ReopenProjectAction;
import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.actionSystem.AnAction;
@@ -15,7 +14,6 @@ import com.intellij.openapi.wm.impl.SystemDock;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
/**
* @author Denis Fokin
@@ -57,14 +55,9 @@ public final class MacDockDelegate implements SystemDock.Delegate {
@Override
public void updateRecentProjectsMenu () {
RecentProjectsManager projectsManager = RecentProjectsManager.getInstance();
if (projectsManager == null) {
return;
}
List<AnAction> recentProjectActions = RecentProjectListActionProvider.getInstance().getActions(false);
recentProjectsMenu.removeAll();
for (AnAction action : recentProjectActions) {
for (AnAction action : RecentProjectListActionProvider.getInstance().getActions(false)) {
MenuItem menuItem = new MenuItem(((ReopenProjectAction)action).getProjectNameToDisplay());
menuItem.addActionListener(new ActionListener() {
@Override
@@ -3,6 +3,11 @@
<applicationService serviceInterface="com.intellij.openapi.project.impl.ProjectStoreFactory"
serviceImplementation="com.intellij.configurationStore.PlatformLangProjectStoreFactory"
overrides="true"/>
<projectService serviceImplementation="com.intellij.workspaceModel.ide.impl.legacyBridge.module.ModuleBridgeLoaderService" preload="true"/>
<projectServiceContainerInitializedListener implementation="com.intellij.workspaceModel.ide.impl.legacyBridge.module.ModuleBridgeLoaderService$ModuleBridgeProjectServiceInitializedListener"/>
<projectService serviceInterface="com.intellij.openapi.module.AutomaticModuleUnloader"
serviceImplementation="com.intellij.openapi.module.impl.AutomaticModuleUnloaderImpl" overrides="true"/>
<projectService serviceInterface="com.intellij.openapi.roots.ProjectRootManager"
serviceImplementation="com.intellij.workspaceModel.ide.impl.legacyBridge.project.ProjectRootManagerBridge" preload="await"/>
@@ -106,11 +111,6 @@
<applicationService serviceInterface="com.intellij.ui.ExperimentalUI"
serviceImplementation="com.intellij.ui.ExperimentalUIImpl"/>
<projectService serviceImplementation="com.intellij.workspaceModel.ide.impl.legacyBridge.module.ModuleBridgeLoaderService" preload="await"/>
<projectServiceContainerInitializedListener implementation="com.intellij.workspaceModel.ide.impl.legacyBridge.module.ModuleBridgeLoaderService$ModuleBridgeProjectServiceInitializedListener"/>
<projectService serviceInterface="com.intellij.openapi.module.AutomaticModuleUnloader"
serviceImplementation="com.intellij.openapi.module.impl.AutomaticModuleUnloaderImpl" overrides="true"/>
<actionConfigurationCustomizer implementation="com.intellij.tools.ToolManager$MyActionTuner"/>
<projectService serviceInterface="com.intellij.pom.PomModel"
@@ -47,6 +47,10 @@
</extensionPoints>
<extensions defaultExtensionNs="com.intellij">
<startupActivity
implementation="com.intellij.workspaceModel.ide.impl.legacyBridge.module.ModuleManagerComponentBridge$ModuleManagerInitProjectActivity"
order="first"/>
<applicationService serviceInterface="com.intellij.openapi.command.undo.UndoManager"
serviceImplementation="com.intellij.openapi.command.impl.UndoManagerImpl" preload="await"/>
@@ -125,6 +129,8 @@
<applicationService serviceImplementation="com.intellij.ide.IdeTooltipManager" preload="notHeadless"/>
<applicationService serviceInterface="com.intellij.refactoring.RefactoringUiService" serviceImplementation="com.intellij.refactoring.RefactoringUiServiceImpl"/>
<postStartupActivity implementation="com.intellij.ide.RecentProjectsManagerBase$MyProjectPostStartupActivity"/>
</extensions>
<!--suppress PluginXmlDynamicPlugin -->
@@ -1,19 +1,5 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.module
import com.intellij.ide.projectView.impl.ModuleGroup
@@ -68,7 +54,7 @@ class ExplicitModuleGroupTest : HeavyPlatformTestCase() {
private fun createModuleInGroup(name: String, vararg path: String): Module {
val module = createModule(name)
val model = ModuleManager.getInstance(myProject).modifiableModel
val model = ModuleManager.getInstance(myProject).getModifiableModel()
model.setModuleGroupPath(module, path)
runWriteAction { model.commit() }
return module
@@ -6,6 +6,7 @@ package com.intellij.openapi.project.impl
import com.intellij.ide.*
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.project.ProjectManager
import com.intellij.openapi.project.ex.ProjectManagerEx
import com.intellij.project.stateStore
import com.intellij.testFramework.*
import com.intellij.testFramework.assertions.Assertions.assertThat
@@ -13,12 +14,13 @@ import com.intellij.ui.DeferredIconImpl
import com.intellij.util.PathUtil
import com.intellij.util.messages.SimpleMessageBusConnection
import com.intellij.util.ui.EmptyIcon
import kotlinx.coroutines.runBlocking
import org.junit.ClassRule
import org.junit.Rule
import org.junit.Test
import org.junit.rules.ExternalResource
import java.nio.file.Path
import java.nio.file.Paths
import java.util.*
class RecentProjectsTest {
companion object {
@@ -44,7 +46,7 @@ class RecentProjectsTest {
val tempDir = TemporaryDirectory()
@Test
fun testMostRecentOnTop() {
fun testMostRecentOnTop() = runBlocking {
val p1 = createAndOpenProject("p1")
val p2 = createAndOpenProject("p2")
val p3 = createAndOpenProject("p3")
@@ -57,7 +59,7 @@ class RecentProjectsTest {
}
@Test
fun testGroupsOrder() {
fun testGroupsOrder() = runBlocking {
val p1 = createAndOpenProject("p1")
val p2 = createAndOpenProject("p2")
val p3 = createAndOpenProject("p3")
@@ -81,19 +83,24 @@ class RecentProjectsTest {
}
@Test
fun timestampForOpenProjectUpdatesWhenGetStateCalled() {
fun timestampForOpenProjectUpdatesWhenGetStateCalled(): Unit = runBlocking {
val z1 = tempDir.newPath("z1")
var project = PlatformTestUtil.loadAndOpenProject(z1, disposableRule.disposable)
val projectManager = ProjectManagerEx.getInstanceEx()
var project = projectManager.openProjectAsync(z1, createTestOpenProjectOptions(runPostStartUpActivities = false))!!
try {
val recentProjectManager = RecentProjectsManagerBase.getInstanceEx()
recentProjectManager.runProjectPostStartupActivity(project)
val timestamp = getProjectOpenTimestamp("z1")
PlatformTestUtil.forceCloseProjectWithoutSaving(project)
project = PlatformTestUtil.loadAndOpenProject(z1, disposableRule.disposable)
RecentProjectsManagerBase.getInstanceEx().updateLastProjectPath()
projectManager.forceCloseProjectAsync(project)
project = projectManager.openProjectAsync(z1, createTestOpenProjectOptions(runPostStartUpActivities = false))!!
recentProjectManager.runProjectPostStartupActivity(project)
recentProjectManager.updateLastProjectPath()
// "Timestamp for opened project has not been updated"
assertThat(getProjectOpenTimestamp("z1")).isGreaterThan(timestamp)
}
finally {
PlatformTestUtil.forceCloseProjectWithoutSaving(project)
projectManager.forceCloseProjectAsync(project)
}
}
@@ -102,7 +109,7 @@ class RecentProjectsTest {
// For Rider
val rpm = (RecentProjectsManager.getInstance() as RecentProjectsManagerBase)
val projectDir = Paths.get("${PlatformTestUtil.getPlatformTestDataPath()}/recentProjects/dotNetSampleRecent/Povysh")
val projectDir = Path.of("${PlatformTestUtil.getPlatformTestDataPath()}/recentProjects/dotNetSampleRecent/Povysh")
val slnFile = projectDir.resolve("Povysh.sln")
val icon = (rpm.getProjectIcon(slnFile.toString(), false) as DeferredIconImpl<*>).evaluate()
@@ -120,15 +127,24 @@ class RecentProjectsTest {
return -1
}
private fun doReopenCloseAndCheck(projectPath: Path, vararg results: String) {
val project = PlatformTestUtil.loadAndOpenProject(projectPath, disposableRule.disposable)
PlatformTestUtil.forceCloseProjectWithoutSaving(project)
private suspend fun doReopenCloseAndCheck(projectPath: Path, vararg results: String) {
openProjectAndClose(projectPath)
checkRecents(*results)
}
private fun doReopenCloseAndCheckGroups(projectPath: Path, results: List<String>) {
val project = PlatformTestUtil.loadAndOpenProject(projectPath, disposableRule.disposable)
PlatformTestUtil.forceCloseProjectWithoutSaving(project)
private suspend fun openProjectAndClose(projectPath: Path) {
val projectManager = ProjectManagerEx.getInstanceEx()
val project = projectManager.openProjectAsync(projectPath, createTestOpenProjectOptions(runPostStartUpActivities = false))!!
try {
RecentProjectsManagerBase.getInstanceEx().runProjectPostStartupActivity(project)
}
finally {
projectManager.forceCloseProjectAsync(project)
}
}
private suspend fun doReopenCloseAndCheckGroups(projectPath: Path, results: List<String>) {
openProjectAndClose(projectPath)
checkGroups(results)
}
@@ -150,17 +166,21 @@ class RecentProjectsTest {
assertThat(recentGroups).isEqualTo(groups)
}
private fun createAndOpenProject(name: String): Path {
private suspend fun createAndOpenProject(name: String): Path {
val path = tempDir.newPath(name)
var project = PlatformTestUtil.loadAndOpenProject(path, disposableRule.disposable)
val projectManager = ProjectManagerEx.getInstanceEx()
var project = projectManager.openProjectAsync(path, createTestOpenProjectOptions(runPostStartUpActivities = false))!!
try {
val recentProjectManager = RecentProjectsManagerBase.getInstanceEx()
recentProjectManager.runProjectPostStartupActivity(project)
project.stateStore.saveComponent(RecentProjectsManager.getInstance() as RecentProjectsManagerBase)
PlatformTestUtil.forceCloseProjectWithoutSaving(project)
project = PlatformTestUtil.loadAndOpenProject(path, disposableRule.disposable)
projectManager.forceCloseProjectAsync(project)
project = projectManager.openProjectAsync(path, createTestOpenProjectOptions(runPostStartUpActivities = false))!!
recentProjectManager.runProjectPostStartupActivity(project)
return path
}
finally {
PlatformTestUtil.forceCloseProjectWithoutSaving(project)
projectManager.forceCloseProjectAsync(project)
}
}
}
@@ -3,6 +3,7 @@
package com.intellij.openapi.project.impl.navigation
import com.intellij.ide.RecentProjectsManagerBase
import com.intellij.navigation.areOriginsEqual
import com.intellij.openapi.application.EDT
import com.intellij.openapi.application.JBProtocolCommand
@@ -61,18 +62,17 @@ class JBNavigateCommandTest : NavigationTestBase() {
@Test
fun pathOpenProject(): Unit = runBlocking {
val projectManager = ProjectManagerEx.getInstanceEx()
val prevProjects = projectManager.openProjects.toHashSet()
createOrLoadProject(tempDir, useDefaultProjectSettings = false) { project ->
setUpProject(project)
RecentProjectsManagerBase.getInstanceEx().runProjectPostStartupActivity(project)
}
val prevProjects = projectManager.openProjects.toHashSet()
try {
ProjectManagerEx.getInstanceEx().forceCloseProjectAsync(project)
val result = withContext(Dispatchers.EDT) {
navigate(mapOf("path" to "A.java"))
}
assertThat(result).isNull()
yield()
withContext(Dispatchers.EDT) {
yield()
}
@@ -1,4 +1,4 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.openapi.roots.impl.indexing
import com.intellij.openapi.application.runWriteAction
@@ -21,7 +21,6 @@ import com.intellij.util.indexing.FileBasedIndexEx
import com.intellij.util.indexing.FileBasedIndexImpl
import com.intellij.util.indexing.IndexableSetContributor
import org.junit.Test
import java.util.*
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
@@ -347,9 +346,9 @@ class IndexableFilesRegularTest : IndexableFilesBaseTest() {
}
}
assertIndexableFiles(contentFileToUnload.file, contentFileToRetain.file)
ModuleManager.getInstance(project).setUnloadedModules(Arrays.asList("moduleToUnload"))
ModuleManager.getInstance(project).setUnloadedModulesSync(listOf("moduleToUnload"))
assertIndexableFiles(contentFileToRetain.file)
ModuleManager.getInstance(project).setUnloadedModules(Collections.emptyList())
ModuleManager.getInstance(project).setUnloadedModulesSync(emptyList())
assertIndexableFiles(contentFileToUnload.file, contentFileToRetain.file)
}
@@ -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-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.openapi.roots.impl.indexing
import com.intellij.openapi.application.runWriteAction
@@ -287,7 +287,7 @@ private fun createJavaModule(project: Project, moduleName: String, moduleRootDir
val type = ModuleTypeManager.getInstance().findByID(ModuleTypeId.JAVA_MODULE)
return WriteCommandAction.writeCommandAction(project).compute(
ThrowableComputable<Module, RuntimeException> {
val moduleModel = ModuleManager.getInstance(project).modifiableModel
val moduleModel = ModuleManager.getInstance(project).getModifiableModel()
val module = moduleModel.newModule(moduleRootDirectory.resolve("$moduleName.iml"), type.id)
moduleModel.commit()
module
@@ -11,16 +11,14 @@ import com.intellij.openapi.project.Project;
* {@link #initComponent()}, {@link #moduleAdded()} methods will be called for each module even if user doesn't use
* any feature of your plugin. Also, plugins declaring module components do not support dynamic loading.
*/
@Deprecated
@Deprecated(forRemoval = true)
public interface ModuleComponent extends BaseComponent {
/**
* Invoked when the project corresponding to this component instance is opened.<p>
* Note that components may be created for even unopened projects and this method can be never
* invoked for a particular component instance (for example for default project).
*
* @deprecated Please use {@link com.intellij.openapi.project.ProjectManager#TOPIC} ({@link com.intellij.openapi.project.ProjectManagerListener#projectOpened(Project)} (Project, Module)})
* @deprecated Do not use.
* <a href=" https://plugins.jetbrains.com/docs/intellij/plugin-components.html#comintellijpoststartupactivity">Post start-up activity</a>
* maybe an alternative.
*/
@Deprecated
@Deprecated(forRemoval = true)
default void projectOpened() {
}
@@ -31,7 +29,7 @@ public interface ModuleComponent extends BaseComponent {
*
* @deprecated Please use {@link com.intellij.openapi.project.ProjectManager#TOPIC} ({@link com.intellij.openapi.project.ProjectManagerListener#projectClosed(Project)} (Project, Module)})
*/
@Deprecated
@Deprecated(forRemoval = true)
default void projectClosed() {
}
@@ -41,7 +39,7 @@ public interface ModuleComponent extends BaseComponent {
*
* @deprecated Consider to use {@link com.intellij.ProjectTopics#MODULES} ({@link com.intellij.openapi.project.ModuleListener#moduleAdded(Project, Module)})
*/
@Deprecated
@Deprecated(forRemoval = true)
default void moduleAdded() {
}
}
@@ -1,36 +1,33 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.openapi.module;
package com.intellij.openapi.module
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.NlsSafe;
import com.intellij.openapi.util.SimpleModificationTracker;
import com.intellij.util.graph.Graph;
import org.jdom.JDOMException;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.SimpleModificationTracker
import com.intellij.util.graph.Graph
import org.jdom.JDOMException
import org.jetbrains.annotations.ApiStatus
import org.jetbrains.annotations.NonNls
import org.jetbrains.annotations.TestOnly
import java.io.File
import java.io.IOException
import java.nio.file.Path
/**
* Provides services for working with the modules of a project.
*/
@ApiStatus.NonExtendable
public abstract class ModuleManager extends SimpleModificationTracker {
/**
* Returns the module manager instance for the current project.
*
* @param project the project for which the module manager is requested.
* @return the module manager instance.
*/
public static ModuleManager getInstance(@NotNull Project project) {
return project.getComponent(ModuleManager.class);
abstract class ModuleManager : SimpleModificationTracker() {
companion object {
/**
* Returns the module manager instance for the current project.
*
* @param project the project for which the module manager is requested.
* @return the module manager instance.
*/
@JvmStatic
fun getInstance(project: Project): ModuleManager = project.getComponent(ModuleManager::class.java)
fun getInstanceIfDefined(project: Project): ModuleManager? = project.getComponent(ModuleManager::class.java)
}
/**
@@ -41,32 +38,29 @@ public abstract class ModuleManager extends SimpleModificationTracker {
* @param moduleTypeId the ID of the module type to create.
* @return the module instance.
*/
public abstract @NotNull Module newModule(@NotNull @NonNls String filePath, @NotNull String moduleTypeId);
abstract fun newModule(filePath: @NonNls String, moduleTypeId: String): Module
public @NotNull Module newModule(@NotNull Path file, @NotNull String moduleTypeId) {
return newModule(file.toString().replace(File.separatorChar, '/'), moduleTypeId);
fun newModule(file: Path, moduleTypeId: String): Module {
return newModule(file.toString().replace(File.separatorChar, '/'), moduleTypeId)
}
/**
* Creates a non-persistent module of the specified type and adds it to the project
* to which the module manager is related. {@link #commit()} must be called to
* to which the module manager is related. [.commit] must be called to
* bring the changes in effect.
*
* In contrast with modules created by {@link #newModule(String, String)},
* In contrast with modules created by [.newModule],
* non-persistent modules aren't stored on a filesystem and aren't being written
* in a project XML file. When IDE closes, all non-persistent modules vanishes out.
*/
@ApiStatus.Experimental
@NotNull
public Module newNonPersistentModule(@NotNull String moduleName, @NotNull String id) {
throw new UnsupportedOperationException();
open fun newNonPersistentModule(moduleName: String, id: String): Module {
throw UnsupportedOperationException()
}
/**
* @deprecated Use {@link #loadModule(Path)}
*/
@Deprecated
public abstract @NotNull Module loadModule(@NotNull String filePath) throws IOException, JDOMException, ModuleWithNameAlreadyExists;
@Deprecated("Use {@link #loadModule(Path)}")
@Throws(IOException::class, JDOMException::class, ModuleWithNameAlreadyExists::class)
abstract fun loadModule(filePath: String): Module
/**
* Loads a module from an .iml file with the specified path and adds it to the project.
@@ -76,21 +70,22 @@ public abstract class ModuleManager extends SimpleModificationTracker {
* @throws IOException if an I/O error occurred when loading the module file.
* @throws ModuleWithNameAlreadyExists if a module with such a name already exists in the project.
*/
public abstract @NotNull Module loadModule(@NotNull Path file) throws IOException, ModuleWithNameAlreadyExists;
@Throws(IOException::class, ModuleWithNameAlreadyExists::class)
abstract fun loadModule(file: Path): Module
/**
* Disposes of the specified module and removes it from the project.
*
* @param module the module to remove.
*/
public abstract void disposeModule(@NotNull Module module);
abstract fun disposeModule(module: Module)
/**
* Returns the list of all modules in the project.
*
* @return the array of modules.
*/
public abstract Module @NotNull [] getModules();
abstract val modules: Array<Module>
/**
* Returns the project module with the specified name.
@@ -98,8 +93,7 @@ public abstract class ModuleManager extends SimpleModificationTracker {
* @param name the name of the module to find.
* @return the module instance, or null if no module with such name exists.
*/
@Nullable
public abstract Module findModuleByName(@NonNls @NotNull String name);
abstract fun findModuleByName(name: @NonNls String): Module?
/**
* Returns the list of modules sorted by dependency (the modules which do not depend
@@ -108,7 +102,7 @@ public abstract class ModuleManager extends SimpleModificationTracker {
*
* @return the sorted array of modules.
*/
public abstract Module @NotNull [] getSortedModules();
abstract val sortedModules: Array<Module>
/**
* Returns the module comparator which can be used for sorting modules by dependency
@@ -117,35 +111,32 @@ public abstract class ModuleManager extends SimpleModificationTracker {
*
* @return the module comparator instance.
*/
@NotNull
public abstract Comparator<Module> moduleDependencyComparator();
abstract fun moduleDependencyComparator(): Comparator<Module>
/**
* Returns the list of modules which directly depend on the specified module.
*
* @param module the module for which the list of dependent modules is requested.
* @return list of <i>modules that depend on</i> given module.
* @see ModuleUtilCore#getAllDependentModules(Module)
* @return list of *modules that depend on* given module.
* @see ModuleUtilCore.getAllDependentModules
*/
@NotNull
public abstract List<Module> getModuleDependentModules(@NotNull Module module);
abstract fun getModuleDependentModules(module: Module): List<Module>
/**
* Checks if one of the specified modules directly depends on the other module.
*
* @param module the module to check the dependency for.
* @param onModule the module on which {@code module} may depend.
* @return true if {@code module} directly depends on {@code onModule}, false otherwise.
* @param onModule the module on which `module` may depend.
* @return true if `module` directly depends on `onModule`, false otherwise.
*/
public abstract boolean isModuleDependent(@NotNull Module module, @NotNull Module onModule);
abstract fun isModuleDependent(module: Module, onModule: Module): Boolean
/**
* Returns the graph of dependencies between modules in the project.
*
* @return the module dependency graph.
*/
@NotNull
public abstract Graph<Module> moduleGraph();
abstract fun moduleGraph(): Graph<Module>
/**
* Returns the graph of dependencies between modules in the project.
@@ -153,8 +144,7 @@ public abstract class ModuleManager extends SimpleModificationTracker {
* @param includeTests whether test-only dependencies should be included
* @return the module dependency graph.
*/
@NotNull
public abstract Graph<Module> moduleGraph(boolean includeTests);
abstract fun moduleGraph(includeTests: Boolean): Graph<Module>
/**
* Returns the model for the list of modules in the project, which can be used to add,
@@ -162,49 +152,48 @@ public abstract class ModuleManager extends SimpleModificationTracker {
*
* @return the modifiable model instance.
*/
@NotNull
public abstract ModifiableModuleModel getModifiableModel();
abstract fun getModifiableModel(): ModifiableModuleModel
/**
* Returns the path to the group to which the specified module belongs, as an array of group names starting from the project root.
* <p>
* <strong>Use {@link ModuleGrouper#getGroupPath(Module)} instead.</strong> Explicit module groups will be replaced
* by automatic module grouping accordingly to qualified names of modules, see <a href="https://youtrack.jetbrains.com/issue/IDEA-166061">IDEA-166061</a> for details.
* </p>
*
*
* **Use [ModuleGrouper.getGroupPath] instead.** Explicit module groups will be replaced
* by automatic module grouping accordingly to qualified names of modules, see [IDEA-166061](https://youtrack.jetbrains.com/issue/IDEA-166061) for details.
*
* @param module the module for which the path is requested.
* @return the path to the group for the module, or null if the module does not belong to any group.
*/
public abstract @NlsSafe String @Nullable [] getModuleGroupPath(@NotNull Module module);
abstract fun getModuleGroupPath(module: Module): Array<String>?
public abstract boolean hasModuleGroups();
abstract fun hasModuleGroups(): Boolean
/**
* @return description of all modules in the project including unloaded
*/
@ApiStatus.Experimental
@NotNull
public abstract Collection<ModuleDescription> getAllModuleDescriptions();
@get:ApiStatus.Experimental
abstract val allModuleDescriptions: Collection<ModuleDescription>
@get:ApiStatus.Experimental
abstract val unloadedModuleDescriptions: Collection<UnloadedModuleDescription>
@ApiStatus.Experimental
@NotNull
public abstract Collection<UnloadedModuleDescription> getUnloadedModuleDescriptions();
abstract fun getUnloadedModuleDescription(moduleName: String): UnloadedModuleDescription?
@ApiStatus.Experimental
@Nullable
public abstract UnloadedModuleDescription getUnloadedModuleDescription(@NotNull String moduleName);
@NotNull
public abstract ModuleGrouper getModuleGrouper(@Nullable ModifiableModuleModel model);
abstract fun getModuleGrouper(model: ModifiableModuleModel?): ModuleGrouper
/**
* Specify list of modules which will be unloaded from the project.
* @see UnloadedModuleDescription
*/
@ApiStatus.Experimental
public abstract void setUnloadedModules(@NotNull List<String> unloadedModuleNames);
abstract suspend fun setUnloadedModules(unloadedModuleNames: List<String>)
@Deprecated("Use setUnloadedModules")
@TestOnly
abstract fun setUnloadedModulesSync(unloadedModuleNames: List<String>)
@ApiStatus.Experimental
public void removeUnloadedModules(@NotNull Collection<? extends UnloadedModuleDescription> unloadedModules) {
open fun removeUnloadedModules(unloadedModules: Collection<UnloadedModuleDescription>) {
}
}
}
@@ -1,4 +1,4 @@
// 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.
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.openapi.project;
import com.intellij.ProjectTopics;
@@ -21,6 +21,12 @@ public interface ModuleListener extends EventListener {
default void moduleAdded(@NotNull Project project, @NotNull Module module) {
}
default void modulesAdded(@NotNull Project project, @NotNull List<Module> modules) {
for (Module module : modules) {
moduleAdded(project, module);
}
}
default void beforeModuleRemoved(@NotNull Project project, @NotNull Module module) {
}
@@ -17,6 +17,7 @@ public interface ProjectManagerListener extends EventListener {
* <a href=" https://plugins.jetbrains.com/docs/intellij/plugin-components.html#comintellijpoststartupactivity">Post start-up activity</a>
* maybe an alternative.
*/
@Deprecated(forRemoval = true)
default void projectOpened(@NotNull Project project) {
}
@@ -28,6 +28,8 @@ public abstract class ProjectRootManagerEx extends ProjectRootManager {
public abstract void makeRootsChange(@NotNull Runnable runnable, @NotNull RootsChangeRescanningInfo changes);
public abstract @NotNull AutoCloseable withRootsChange(@NotNull RootsChangeRescanningInfo changes);
public abstract void markRootsForRefresh();
public abstract void mergeRootsChangesDuring(@NotNull Runnable runnable);
@@ -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-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.openapi.module
import com.intellij.openapi.module.impl.createGrouper
@@ -18,11 +18,13 @@ class EmptyModuleManager(private val project: Project) : ModuleManager() {
override fun disposeModule(module: Module) {
}
override fun getModules(): Array<Module> = emptyArray<Module>()
override val modules: Array<Module>
get() = emptyArray()
override fun findModuleByName(name: String): Nothing? = null
override fun getSortedModules(): Array<Module> = emptyArray<Module>()
override val sortedModules: Array<Module>
get() = emptyArray()
override fun moduleDependencyComparator(): Nothing = throw UnsupportedOperationException()
@@ -36,21 +38,27 @@ class EmptyModuleManager(private val project: Project) : ModuleManager() {
override fun getModifiableModel(): Nothing = throw UnsupportedOperationException()
override fun getModuleGroupPath(module: Module): Array<String> = emptyArray<String>()
override fun getModuleGroupPath(module: Module): Array<String> = emptyArray()
override fun setUnloadedModules(unloadedModuleNames: MutableList<String>) {
override suspend fun setUnloadedModules(unloadedModuleNames: List<String>) {
}
override fun setUnloadedModulesSync(unloadedModuleNames: List<String>) {
}
override fun getModuleGrouper(model: ModifiableModuleModel?): ModuleGrouper {
return createGrouper(project, model)
}
override fun getAllModuleDescriptions(): List<ModuleDescription> = emptyList<ModuleDescription>()
override val allModuleDescriptions: List<ModuleDescription>
get() = emptyList()
override fun getUnloadedModuleDescriptions(): List<UnloadedModuleDescription> = emptyList<UnloadedModuleDescription>()
override val unloadedModuleDescriptions: List<UnloadedModuleDescription>
get() = emptyList()
override fun getUnloadedModuleDescription(moduleName: String): Nothing? = null
override fun removeUnloadedModules(unloadedModules: MutableCollection<out UnloadedModuleDescription>) {
override fun removeUnloadedModules(unloadedModules: Collection<UnloadedModuleDescription>) {
}
}
@@ -33,14 +33,12 @@ class ModulePointerManagerImpl(private val project: Project) : ModulePointerMana
unregisterPointer(module)
}
override fun moduleAdded(project: Project, module: Module) {
moduleAppears(module)
override fun modulesAdded(project: Project, modules: List<Module>) {
modulesAppears(modules)
}
override fun modulesRenamed(project: Project, modules: List<Module>, oldNameProvider: Function<in Module, String>) {
for (module in modules) {
moduleAppears(module)
}
modulesAppears(modules)
val renamedOldToNew = modules.associateBy({ oldNameProvider.`fun`(it) }, { it.name })
for (entry in oldToNewName.entries) {
val newValue = renamedOldToNew.get(entry.value)
@@ -95,11 +93,13 @@ class ModulePointerManagerImpl(private val project: Project) : ModulePointerMana
}
}
private fun moduleAppears(module: Module) {
private fun modulesAppears(modules: List<Module>) {
lock.write {
unresolved.remove(module.name)?.forEach {
it.moduleAdded(module)
registerPointer(module, it)
for (module in modules) {
unresolved.remove(module.name)?.forEach {
it.moduleAdded(module)
registerPointer(module, it)
}
}
}
}
@@ -1,26 +1,8 @@
/*
* 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-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.openapi.module.impl
import com.intellij.ide.highlighter.ModuleFileType
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.util.PathUtil
import com.intellij.util.io.URLUtil
import org.jdom.Element
import org.jetbrains.jps.model.serialization.JpsProjectLoader
import com.intellij.util.PathUtilRt
/**
* Path here must be system-independent.
@@ -33,41 +15,5 @@ data class ModulePath(val path: String, val group: String?) {
}
fun getModuleNameByFilePath(path: String): String {
return PathUtil.getFileName(path).removeSuffix(ModuleFileType.DOT_DEFAULT_EXTENSION)
}
internal abstract class SaveItem {
protected abstract val moduleName: String
protected abstract val moduleFilePath: String
protected abstract val groupPathString: String?
fun writeExternal(parentElement: Element) {
val moduleFilePath = moduleFilePath
// moduleFilePath is empty for non-persistent modules. Such modules should disappear when IDE exits,
// hence they should not be mentioned in `modules.xml`.
if (moduleFilePath.isNotEmpty()) {
val moduleElement = Element(JpsProjectLoader.MODULE_TAG)
val url = VirtualFileManager.constructUrl(URLUtil.FILE_PROTOCOL, moduleFilePath)
moduleElement.setAttribute(JpsProjectLoader.FILE_URL_ATTRIBUTE, url)
// support for older builds
moduleElement.setAttribute(JpsProjectLoader.FILE_PATH_ATTRIBUTE, moduleFilePath)
groupPathString?.let {
moduleElement.setAttribute(JpsProjectLoader.GROUP_ATTRIBUTE, it)
}
parentElement.addContent(moduleElement)
}
}
}
internal class ModulePathSaveItem(private val modulePath: ModulePath) : SaveItem() {
override val groupPathString: String?
get() = modulePath.group
override val moduleFilePath: String
get() = modulePath.path
override val moduleName: String
get() = modulePath.moduleName
return PathUtilRt.getFileName(path).removeSuffix(ModuleFileType.DOT_DEFAULT_EXTENSION)
}
@@ -49,7 +49,6 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Pers
private final OrderRootsCache myRootsCache;
protected boolean myStartupActivityPerformed;
private boolean myStateLoaded;
@ApiStatus.Internal
@@ -450,6 +449,12 @@ public class ProjectRootManagerImpl extends ProjectRootManagerEx implements Pers
}
}
@Override
public @NotNull AutoCloseable withRootsChange(@NotNull RootsChangeRescanningInfo changes) {
myRootsChanged.beforeRootsChanged();
return () -> myRootsChanged.rootsChanged(changes);
}
protected boolean isFiringEvent;
private void fireBeforeRootsChanged(boolean fileTypes) {
@@ -5,8 +5,9 @@ import com.intellij.ProjectTopics
import com.intellij.ide.plugins.PluginManagerCore
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.EDT
import com.intellij.openapi.application.WriteAction
import com.intellij.openapi.application.runWriteAction
import com.intellij.openapi.application.asContextElement
import com.intellij.openapi.components.impl.stores.IComponentStore
import com.intellij.openapi.components.impl.stores.ModuleStore
import com.intellij.openapi.diagnostic.debug
@@ -14,6 +15,8 @@ import com.intellij.openapi.diagnostic.getOrLogException
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.module.*
import com.intellij.openapi.module.impl.*
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.progress.impl.CoreProgressManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.RootsChangeRescanningInfo
import com.intellij.openapi.roots.ModuleRootManager
@@ -25,7 +28,6 @@ import com.intellij.openapi.vfs.pointers.VirtualFilePointerManager
import com.intellij.serviceContainer.PrecomputedExtensionModel
import com.intellij.serviceContainer.precomputeExtensionModel
import com.intellij.util.graph.*
import com.intellij.util.io.systemIndependentPath
import com.intellij.workspaceModel.ide.*
import com.intellij.workspaceModel.ide.impl.legacyBridge.module.roots.ModuleLibraryTableBridgeImpl
import com.intellij.workspaceModel.ide.impl.legacyBridge.module.roots.ModuleRootComponentBridge
@@ -33,22 +35,20 @@ import com.intellij.workspaceModel.ide.legacyBridge.ModuleBridge
import com.intellij.workspaceModel.storage.*
import com.intellij.workspaceModel.storage.bridgeEntities.api.*
import com.intellij.workspaceModel.storage.url.VirtualFileUrl
import kotlinx.coroutines.*
import org.jdom.Element
import org.jetbrains.annotations.ApiStatus
import org.jetbrains.jps.model.serialization.JpsProjectLoader
import java.nio.file.Path
import java.util.*
import java.util.concurrent.Callable
import java.util.concurrent.ForkJoinTask
@Suppress("OVERRIDE_DEPRECATION")
@ApiStatus.Internal
abstract class ModuleManagerBridgeImpl(private val project: Project) : ModuleManagerEx(), Disposable {
protected val unloadedModules: MutableMap<String, UnloadedModuleDescription> = LinkedHashMap()
override fun dispose() {
modules().forEach {
Disposer.dispose(it)
}
modules().forEach(Disposer::dispose)
}
protected fun modules(): Sequence<ModuleBridge> {
@@ -80,7 +80,7 @@ abstract class ModuleManagerBridgeImpl(private val project: Project) : ModuleMan
val entityStore = WorkspaceModel.getInstance(project).entityStorage
fun loadModules(entities: Sequence<ModuleEntity>) {
suspend fun loadModules(entities: Sequence<ModuleEntity>) {
val unloadedModuleNames = UnloadedModulesListStorage.getInstance(project).unloadedModuleNames
val (unloadedEntities, loadedEntities) = entities.partition { it.name in unloadedModuleNames }
LOG.debug { "Loading modules for ${loadedEntities.size} entities" }
@@ -88,26 +88,27 @@ abstract class ModuleManagerBridgeImpl(private val project: Project) : ModuleMan
val precomputedExtensionModel = precomputeExtensionModel()
val tasks = loadedEntities.map { moduleEntity ->
ForkJoinTask.adapt(Callable {
project.coroutineScope.async {
runCatching {
val module = createModuleInstance(moduleEntity, entityStore, null, false, precomputedExtensionModel)
moduleEntity to module
}.getOrLogException(LOG)
})
}
}
ForkJoinTask.invokeAll(tasks)
val result = tasks.awaitAll()
UnloadedModuleDescriptionBridge.createDescriptions(unloadedEntities).associateByTo(unloadedModules) { it.name }
val modules = HashSet<ModuleBridge>()
val modules = LinkedHashSet<ModuleBridge>(result.size)
WorkspaceModel.getInstance(project).updateProjectModelSilent { builder ->
val moduleMap = builder.mutableModuleMap
for (task in tasks) {
val (entity, module) = task.rawResult ?: continue
modules += module
for (item in result) {
val (entity, module) = item ?: continue
modules.add(module)
moduleMap.addMapping(entity, module)
(ModuleRootComponentBridge.getInstance(
module).getModuleLibraryTable() as ModuleLibraryTableBridgeImpl).registerModuleLibraryInstances(builder)
(ModuleRootComponentBridge.getInstance(module).getModuleLibraryTable() as ModuleLibraryTableBridgeImpl)
.registerModuleLibraryInstances(builder)
}
}
// Facets that are loaded from the cache do not generate "EntityAdded" event and aren't initialized
@@ -115,7 +116,7 @@ abstract class ModuleManagerBridgeImpl(private val project: Project) : ModuleMan
//
// Possible issue - if we'll initialize facets here and after that we'll get "EntityAdded" event, the facet will be initialized twice
// But 1. That seems impossible as we don't create facets before the modules are loaded 2. I hope that facets initialization is idempotent
modules.forEach { module -> module.initFacets() }
modules.forEach(ModuleBridge::initFacets)
}
override fun unloadNewlyAddedModulesIfPossible(storage: EntityStorage) {
@@ -133,7 +134,7 @@ abstract class ModuleManagerBridgeImpl(private val project: Project) : ModuleMan
override fun newModule(filePath: String, moduleTypeId: String): Module {
incModificationCount()
val modifiableModel = modifiableModel
val modifiableModel = getModifiableModel()
val module = modifiableModel.newModule(filePath, moduleTypeId)
modifiableModel.commit()
return module
@@ -141,7 +142,7 @@ abstract class ModuleManagerBridgeImpl(private val project: Project) : ModuleMan
override fun newNonPersistentModule(moduleName: String, id: String): Module {
incModificationCount()
val modifiableModel = modifiableModel
val modifiableModel = getModifiableModel()
val module = modifiableModel.newNonPersistentModule(moduleName, id)
modifiableModel.commit()
return module
@@ -149,7 +150,8 @@ abstract class ModuleManagerBridgeImpl(private val project: Project) : ModuleMan
override fun getModuleDependentModules(module: Module): List<Module> = modules.filter { isModuleDependent(it, module) }
override fun getUnloadedModuleDescriptions(): Collection<UnloadedModuleDescription> = unloadedModules.values
override val unloadedModuleDescriptions: Collection<UnloadedModuleDescription>
get() = unloadedModules.values
override fun getFailedModulePaths(): Collection<ModulePath> = emptyList()
@@ -157,20 +159,22 @@ abstract class ModuleManagerBridgeImpl(private val project: Project) : ModuleMan
override fun isModuleDependent(module: Module, onModule: Module): Boolean = ModuleRootManager.getInstance(module).isDependsOn(onModule)
override fun getAllModuleDescriptions(): Collection<ModuleDescription> {
return (modules().map { LoadedModuleDescriptionImpl(it) } + unloadedModuleDescriptions).toList()
}
override val allModuleDescriptions: Collection<ModuleDescription>
get() = (modules().map { LoadedModuleDescriptionImpl(it) } + unloadedModuleDescriptions).toList()
override fun getModuleGroupPath(module: Module): Array<String>? = getModuleGroupPath(module, entityStore)
override fun getModuleGrouper(model: ModifiableModuleModel?): ModuleGrouper = createGrouper(project, model)
override fun loadModule(file: Path): Module {
return loadModule(file.systemIndependentPath)
val model = getModifiableModel()
val module = model.loadModule(file)
model.commit()
return module
}
override fun loadModule(filePath: String): Module {
val model = modifiableModel
val model = getModifiableModel()
val module = model.loadModule(filePath)
model.commit()
return module
@@ -182,7 +186,8 @@ abstract class ModuleManagerBridgeImpl(private val project: Project) : ModuleMan
modules(storage).toList().toTypedArray()
}
override fun getModules(): Array<Module> = entityStore.cachedValue(modulesArrayValue)
override val modules: Array<Module>
get() = entityStore.cachedValue(modulesArrayValue)
private val sortedModulesValue = CachedValue { storage ->
val allModules = modules(storage).toList().toTypedArray<Module>()
@@ -190,7 +195,8 @@ abstract class ModuleManagerBridgeImpl(private val project: Project) : ModuleMan
allModules
}
override fun getSortedModules(): Array<Module> = entityStore.cachedValue(sortedModulesValue)
override val sortedModules: Array<Module>
get() = entityStore.cachedValue(sortedModulesValue)
override fun findModuleByName(name: String): Module? {
val entity = entityStore.current.resolve(ModuleId(name)) ?: return null
@@ -198,13 +204,14 @@ abstract class ModuleManagerBridgeImpl(private val project: Project) : ModuleMan
}
override fun disposeModule(module: Module) = ApplicationManager.getApplication().runWriteAction {
val modifiableModel = modifiableModel
val modifiableModel = getModifiableModel()
modifiableModel.disposeModule(module)
modifiableModel.commit()
}
override fun setUnloadedModules(unloadedModuleNames: List<String>) {
if (unloadedModules.keys == unloadedModuleNames) { // optimization
override suspend fun setUnloadedModules(unloadedModuleNames: List<String>) {
// optimization
if (unloadedModules.keys == unloadedModuleNames) {
return
}
@@ -238,38 +245,60 @@ abstract class ModuleManagerBridgeImpl(private val project: Project) : ModuleMan
project.save()
}
runWriteAction {
ProjectRootManagerEx.getInstanceEx(project).makeRootsChange({
for ((moduleEntity, module) in modulesToUnload) {
fireBeforeModuleRemoved(module)
withContext(Dispatchers.EDT) {
ApplicationManager.getApplication().runWriteAction {
ProjectRootManagerEx.getInstanceEx(project).withRootsChange(RootsChangeRescanningInfo.NO_RESCAN_NEEDED).use {
for ((moduleEntity, module) in modulesToUnload) {
fireBeforeModuleRemoved(module)
val description = LoadedModuleDescriptionImpl(module)
val modulePath = getModulePath(module, entityStore)
val pointerManager = VirtualFilePointerManager.getInstance()
val contentRoots = ModuleRootManager.getInstance(module).contentRootUrls.map { url ->
pointerManager.create(url, this, null)
val description = LoadedModuleDescriptionImpl(module)
val modulePath = getModulePath(module, entityStore)
val pointerManager = VirtualFilePointerManager.getInstance()
val contentRoots = ModuleRootManager.getInstance(
module).contentRootUrls.map { url ->
pointerManager.create(url, this@ModuleManagerBridgeImpl, null)
}
val unloadedModuleDescription = UnloadedModuleDescriptionImpl(
modulePath, description.dependencyModuleNames, contentRoots)
unloadedModules[module.name] = unloadedModuleDescription
WorkspaceModel.getInstance(project).updateProjectModelSilent {
it.mutableModuleMap.removeMapping(moduleEntity)
}
fireEventAndDisposeModule(module)
}
val unloadedModuleDescription = UnloadedModuleDescriptionImpl(modulePath, description.dependencyModuleNames, contentRoots)
unloadedModules[module.name] = unloadedModuleDescription
WorkspaceModel.getInstance(project).updateProjectModelSilent {
it.mutableModuleMap.removeMapping(moduleEntity)
}
fireEventAndDisposeModule(module)
}
// Remove Facet bridges to recreate them. String constant is taken from
// com.intellij.workspaceModel.ide.impl.legacyBridge.facet.FacetModelBridge.FACET_BRIDGE_MAPPING_ID
WorkspaceModel.getInstance(project).updateProjectModelSilent { builder ->
moduleEntitiesToLoad.flatMap { it.facets }.forEach {
builder.getMutableExternalMapping<Any>("intellij.facets.bridge").removeMapping(it)
// Remove Facet bridges to recreate them. String constant is taken from
// com.intellij.workspaceModel.ide.impl.legacyBridge.facet.FacetModelBridge.FACET_BRIDGE_MAPPING_ID
WorkspaceModel.getInstance(
project).updateProjectModelSilent { builder ->
moduleEntitiesToLoad.flatMap { it.facets }.forEach {
builder.getMutableExternalMapping<Any>(
"intellij.facets.bridge").removeMapping(it)
}
}
// todo why we load modules in a write action
runBlocking {
loadModules(moduleEntitiesToLoad.asSequence())
}
}
loadModules(moduleEntitiesToLoad.asSequence())
}, RootsChangeRescanningInfo.NO_RESCAN_NEEDED)
}
}
}
override fun removeUnloadedModules(unloadedModules: MutableCollection<out UnloadedModuleDescription>) {
override fun setUnloadedModulesSync(unloadedModuleNames: List<String>) {
if (!ApplicationManager.getApplication().isDispatchThread) {
return runBlocking(CoreProgressManager.getCurrentThreadProgressModality().asContextElement()) { setUnloadedModules(unloadedModuleNames) }
}
ProgressManager.getInstance().runProcessWithProgressSynchronously(Runnable {
val modalityState = CoreProgressManager.getCurrentThreadProgressModality()
runBlocking(modalityState.asContextElement()) {
setUnloadedModules(unloadedModuleNames)
}
}, "", true, project)
}
override fun removeUnloadedModules(unloadedModules: Collection<UnloadedModuleDescription>) {
ApplicationManager.getApplication().assertWriteAccessAllowed()
unloadedModules.forEach { this.unloadedModules.remove(it.name) }
@@ -437,8 +466,8 @@ abstract class ModuleManagerBridgeImpl(private val project: Project) : ModuleMan
else {
VirtualFileManager.extractPath(fileUrlValue)
}
paths.add(ModulePath(FileUtilRt.toSystemIndependentName(Objects.requireNonNull(filepath)),
moduleElement.getAttributeValue(JpsProjectLoader.GROUP_ATTRIBUTE)))
paths.add(ModulePath(path = FileUtilRt.toSystemIndependentName(filepath!!),
group = moduleElement.getAttributeValue(JpsProjectLoader.GROUP_ATTRIBUTE)))
}
return paths
}
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.module
import com.intellij.openapi.application.runWriteAction
@@ -39,7 +25,7 @@ fun <T> runWithQualifiedModuleNamesEnabled(action: () -> T): T {
}
fun renameModule(module: Module, newName: String) {
val model = ModuleManager.getInstance(module.project).modifiableModel
val model = ModuleManager.getInstance(module.project).getModifiableModel()
model.renameModule(module, newName)
runWriteAction { model.commit() }
}
@@ -8,6 +8,7 @@ import com.intellij.ide.impl.OpenProjectTask
import com.intellij.ide.impl.ProjectUtil
import com.intellij.ide.impl.runUnderModalProgressIfIsEdt
import com.intellij.ide.startup.StartupManagerEx
import com.intellij.ide.startup.impl.StartupManagerImpl
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.AccessToken
import com.intellij.openapi.application.ApplicationManager
@@ -17,12 +18,12 @@ import com.intellij.openapi.command.impl.UndoManagerImpl
import com.intellij.openapi.command.undo.UndoManager
import com.intellij.openapi.components.StorageScheme
import com.intellij.openapi.progress.ProcessCanceledException
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.project.Project
import com.intellij.openapi.project.ex.ProjectEx
import com.intellij.openapi.project.impl.ProjectImpl
import com.intellij.openapi.project.impl.ProjectManagerImpl
import com.intellij.openapi.project.impl.runStartupActivities
import com.intellij.openapi.project.impl.runInitProjectActivities
import com.intellij.openapi.startup.StartupManager
import com.intellij.openapi.util.Disposer
import com.intellij.testFramework.LeakHunter
import com.intellij.testFramework.TestApplicationManager.Companion.publishHeapDump
@@ -31,7 +32,6 @@ import com.intellij.util.containers.UnsafeWeakList
import com.intellij.util.ref.GCUtil
import kotlinx.coroutines.runBlocking
import org.jetbrains.annotations.ApiStatus
import org.jetbrains.annotations.NotNull
import java.nio.file.Path
import java.util.*
import java.util.concurrent.TimeUnit
@@ -118,13 +118,12 @@ open class TestProjectManager : ProjectManagerImpl() {
}
val app = ApplicationManager.getApplication()
try {
runUnderModalProgressIfIsEdt {
runStartupActivities(project = project,
indicator = ProgressManager.getInstance().progressIndicator,
runStartUpActivities = isRunStartUpActivitiesEnabled(project),
waitEdtActivity = null)
runInitProjectActivities(project = project)
if (isRunStartUpActivitiesEnabled(project)) {
(StartupManager.getInstance(project) as StartupManagerImpl).runStartupActivities()
}
}
}
catch (e: ProcessCanceledException) {
@@ -142,7 +141,7 @@ open class TestProjectManager : ProjectManagerImpl() {
return project
}
private fun trackProject(project: @NotNull Project) {
private fun trackProject(project: Project) {
if (isTracking) {
synchronized(this) {
if (isTracking) {
@@ -1,4 +1,4 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.testFramework.rules
import com.intellij.facet.Facet
@@ -173,7 +173,7 @@ open class ProjectModelRule(private val forceEnableWorkspaceModel: Boolean = fal
}
fun renameModule(module: Module, newName: String) {
val model = runReadAction { moduleManager.modifiableModel }
val model = runReadAction { moduleManager.getModifiableModel() }
model.renameModule(module, newName)
runWriteActionAndWait { model.commit() }
}
@@ -1,5 +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-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.openapi.vcs.impl;
import com.intellij.ProjectTopics;
@@ -22,10 +21,11 @@ import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class ModuleDefaultVcsRootPolicy extends DefaultVcsRootPolicy {
public ModuleDefaultVcsRootPolicy(@NotNull Project project) {
final class ModuleDefaultVcsRootPolicy extends DefaultVcsRootPolicy {
ModuleDefaultVcsRootPolicy(@NotNull Project project) {
super(project);
MyModulesListener listener = new MyModulesListener();
@@ -66,14 +66,14 @@ public class ModuleDefaultVcsRootPolicy extends DefaultVcsRootPolicy {
return result;
}
private class MyModulesListener implements ModuleRootListener, ModuleListener, AdditionalLibraryRootsListener {
private final class MyModulesListener implements ModuleRootListener, ModuleListener, AdditionalLibraryRootsListener {
@Override
public void rootsChanged(@NotNull ModuleRootEvent event) {
scheduleMappedRootsUpdate();
}
@Override
public void moduleAdded(@NotNull Project project, @NotNull Module module) {
public void modulesAdded(@NotNull Project project, @NotNull List<Module> modules) {
scheduleMappedRootsUpdate();
}
@@ -82,7 +82,7 @@ class LibraryPropertiesTest {
val elementAsString = "<properties data=\"$propertyData\" />"
val moduleFile = File(project.basePath, "$moduleName.iml")
val module = ModuleManager.getInstance(project).modifiableModel.let { moduleModel ->
val module = ModuleManager.getInstance(project).getModifiableModel().let { moduleModel ->
val module = moduleModel.newModule(moduleFile.path, EmptyModuleType.getInstance().id) as ModuleBridge
moduleModel.commit()
module
@@ -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-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.workspaceModel.ide
import com.intellij.openapi.application.runWriteActionAndWait
@@ -50,7 +50,7 @@ class ModifiableRootModelBridgeTest {
@Test(expected = Test.None::class)
fun `getting module root model from modifiable module`() {
runWriteActionAndWait {
val moduleModifiableModel = ModuleManager.getInstance(projectModel.project).modifiableModel
val moduleModifiableModel = ModuleManager.getInstance(projectModel.project).getModifiableModel()
val newModule = moduleModifiableModel.newModule(projectModel.projectRootDir.resolve("myModule/myModule.iml"),
EmptyModuleType.EMPTY_MODULE) as ModuleBridge
@@ -68,7 +68,7 @@ class ModifiableRootModelBridgeTest {
@Test(expected = Test.None::class)
fun `get modifiable models of renamed module`() {
runWriteActionAndWait {
val moduleModifiableModel = ModuleManager.getInstance(projectModel.project).modifiableModel
val moduleModifiableModel = ModuleManager.getInstance(projectModel.project).getModifiableModel()
val newModule = moduleModifiableModel.newModule(projectModel.projectRootDir.resolve("myModule/myModule.iml"),
EmptyModuleType.EMPTY_MODULE) as ModuleBridge
moduleModifiableModel.commit()
@@ -82,7 +82,7 @@ class ModuleBridgesTest {
WriteCommandAction.runWriteCommandAction(project) {
val moduleManager = ModuleManager.getInstance(project)
val module = moduleManager.modifiableModel.let {
val module = moduleManager.getModifiableModel().let {
val m = it.newModule(File(project.basePath, "xxx.iml").path, EmptyModuleType.getInstance().id) as ModuleBridge
it.commit()
m
@@ -103,7 +103,7 @@ class ModuleBridgesTest {
arrayOf(contentRootUrl.url)
)
moduleManager.modifiableModel.let {
moduleManager.getModifiableModel().let {
it.disposeModule(module)
it.commit()
}
@@ -115,7 +115,7 @@ class ModuleBridgesTest {
WriteCommandAction.runWriteCommandAction(project) {
val moduleManager = ModuleManager.getInstance(project)
val modulesModifiableModel = moduleManager.modifiableModel
val modulesModifiableModel = moduleManager.getModifiableModel()
try {
val m = modulesModifiableModel.newModule(File(project.basePath, "xxx.iml").path, ModuleType.EMPTY.id) as ModuleBridge
val rootModel = m.rootManager.modifiableModel
@@ -143,7 +143,7 @@ class ModuleBridgesTest {
runBlocking {
val module = withContext(Dispatchers.EDT) {
runWriteAction {
val model = moduleManager.modifiableModel
val model = moduleManager.getModifiableModel()
val module = model.newModule(oldNameFile.path, ModuleType.EMPTY.id)
model.commit()
module
@@ -159,7 +159,7 @@ class ModuleBridgesTest {
withContext(Dispatchers.EDT) {
ApplicationManager.getApplication().runWriteAction {
val model = moduleManager.modifiableModel
val model = moduleManager.getModifiableModel()
assertSame(module, model.findModuleByName(oldModuleName))
assertNull(model.getModuleToBeRenamed(oldModuleName))
@@ -212,7 +212,7 @@ class ModuleBridgesTest {
val (antModule, mavenModule) = withContext(Dispatchers.EDT) {
runWriteAction {
val model = moduleManager.modifiableModel
val model = moduleManager.getModifiableModel()
val antModule = model.newModule(antModuleFile.path, ModuleType.EMPTY.id)
val mavenModule = model.newModule(mavenModuleFile.path, ModuleType.EMPTY.id)
model.commit()
@@ -232,7 +232,7 @@ class ModuleBridgesTest {
withContext(Dispatchers.EDT) {
ApplicationManager.getApplication().runWriteAction {
val model = moduleManager.modifiableModel
val model = moduleManager.getModifiableModel()
model.renameModule(antModule, gradleModuleName)
model.commit()
}
@@ -287,7 +287,7 @@ class ModuleBridgesTest {
WriteCommandAction.runWriteCommandAction(project) {
val moduleManager = ModuleManager.getInstance(project)
val module = moduleManager.modifiableModel.let {
val module = moduleManager.getModifiableModel().let {
val m = it.newModule(File(project.basePath, "xxx.iml").path, EmptyModuleType.getInstance().id) as ModuleBridge
it.commit()
m
@@ -314,7 +314,7 @@ class ModuleBridgesTest {
WriteCommandAction.runWriteCommandAction(project) {
val moduleManager = ModuleManager.getInstance(project)
val module = moduleManager.modifiableModel.let {
val module = moduleManager.getModifiableModel().let {
val m = it.newModule(File(project.basePath, "xxx.iml").path, EmptyModuleType.getInstance().id) as ModuleBridge
it.commit()
m
@@ -631,7 +631,7 @@ class ModuleBridgesTest {
val module = withContext(Dispatchers.EDT) {
runWriteAction {
val module = ModuleManager.getInstance(project).modifiableModel.let { moduleModel ->
val module = ModuleManager.getInstance(project).getModifiableModel().let { moduleModel ->
val module = moduleModel.newModule(moduleFile.path, EmptyModuleType.getInstance().id) as ModuleBridge
moduleModel.commit()
module
@@ -674,7 +674,7 @@ class ModuleBridgesTest {
val antLibraryFolder = "ant-lib"
val moduleFile = File(project.basePath, "$moduleName.iml")
val module = ModuleManager.getInstance(project).modifiableModel.let { moduleModel ->
val module = ModuleManager.getInstance(project).getModifiableModel().let { moduleModel ->
val module = moduleModel.newModule(moduleFile.path, EmptyModuleType.getInstance().id) as ModuleBridge
moduleModel.commit()
module
@@ -705,7 +705,7 @@ class ModuleBridgesTest {
fun `test disposed module doesn't appear in rootsChanged`() = WriteCommandAction.runWriteCommandAction(project) {
val moduleName = "build"
val moduleFile = File(project.basePath, "$moduleName.iml")
val module = ModuleManager.getInstance(project).modifiableModel.let { moduleModel ->
val module = ModuleManager.getInstance(project).getModifiableModel().let { moduleModel ->
val module = moduleModel.newModule(moduleFile.path, EmptyModuleType.getInstance().id) as ModuleBridge
moduleModel.commit()
module
@@ -726,7 +726,7 @@ class ModuleBridgesTest {
WriteCommandAction.runWriteCommandAction(project) {
val moduleManager = ModuleManager.getInstance(project) as ModuleManagerBridgeImpl
moduleManager.modifiableModel.let { modifiableModel ->
moduleManager.getModifiableModel().let { modifiableModel ->
modifiableModel.newModule(File(project.basePath, "xxx.iml").path, EmptyModuleType.getInstance().id) as ModuleBridge
modifiableModel.commit()
}
@@ -754,7 +754,7 @@ class ModuleBridgesTest {
fun `remove module without removing module library`() = WriteCommandAction.runWriteCommandAction(project) {
val moduleManager = ModuleManager.getInstance(project) as ModuleManagerBridgeImpl
val module = moduleManager.modifiableModel.let { modifiableModel ->
val module = moduleManager.getModifiableModel().let { modifiableModel ->
val module = modifiableModel.newModule(File(project.basePath, "xxx.iml").path, EmptyModuleType.getInstance().id)
modifiableModel.commit()
module as ModuleBridge
@@ -785,13 +785,13 @@ class ModuleBridgesTest {
fun `readd module`() = WriteCommandAction.runWriteCommandAction(project) {
val moduleManager = ModuleManager.getInstance(project)
val module = moduleManager.modifiableModel.let { modifiableModel ->
val module = moduleManager.getModifiableModel().let { modifiableModel ->
val module = modifiableModel.newModule(File(project.basePath, "xxx.iml").path, EmptyModuleType.getInstance().id)
modifiableModel.commit()
module as ModuleBridge
}
val newModule = moduleManager.modifiableModel.let { modifiableModel ->
val newModule = moduleManager.getModifiableModel().let { modifiableModel ->
modifiableModel.disposeModule(module)
val newModule = modifiableModel.newModule(File(project.basePath, "xxx.iml").path, EmptyModuleType.getInstance().id)
modifiableModel.commit()
@@ -56,7 +56,7 @@ class ModuleLibraryBridgeTest {
val moduleFile = File(project.basePath, "$moduleName.iml")
val module = WriteCommandAction.writeCommandAction(project).compute<ModuleBridge, RuntimeException> {
val module = ModuleManager.getInstance(project).modifiableModel.let { moduleModel ->
val module = ModuleManager.getInstance(project).getModifiableModel().let { moduleModel ->
val module = moduleModel.newModule(moduleFile.path, EmptyModuleType.getInstance().id) as ModuleBridge
moduleModel.commit()
module
@@ -102,7 +102,7 @@ class ModuleLibraryBridgeTest {
val moduleFile = File(project.basePath, "$moduleName.iml")
val module = WriteCommandAction.writeCommandAction(project).compute<ModuleBridge, RuntimeException> {
val module = ModuleManager.getInstance(project).modifiableModel.let { moduleModel ->
val module = ModuleManager.getInstance(project).getModifiableModel().let { moduleModel ->
val module = moduleModel.newModule(moduleFile.path, EmptyModuleType.getInstance().id) as ModuleBridge
moduleModel.commit()
module
@@ -166,7 +166,7 @@ class ModuleLibraryBridgeTest {
val moduleFile = File(project.basePath, "$moduleName.iml")
val rootModel = WriteCommandAction.writeCommandAction(project).compute<ModifiableRootModel, RuntimeException> {
val module = ModuleManager.getInstance(project).modifiableModel.let { moduleModel ->
val module = ModuleManager.getInstance(project).getModifiableModel().let { moduleModel ->
val module = moduleModel.newModule(moduleFile.path, EmptyModuleType.getInstance().id) as ModuleBridge
moduleModel.commit()
module
@@ -257,7 +257,7 @@ class ModuleLibraryBridgeTest {
val moduleFile = File(project.basePath, "$moduleName.iml")
val module = WriteCommandAction.writeCommandAction(project).compute<ModuleBridge, RuntimeException> {
val module = ModuleManager.getInstance(project).modifiableModel.let { moduleModel ->
val module = ModuleManager.getInstance(project).getModifiableModel().let { moduleModel ->
val module = moduleModel.newModule(moduleFile.path, EmptyModuleType.getInstance().id) as ModuleBridge
moduleModel.commit()
module
@@ -329,7 +329,7 @@ class ModuleLibraryBridgeTest {
val moduleFile = File(project.basePath, "$moduleName.iml")
val moduleRootManager = WriteCommandAction.writeCommandAction(project).compute<ModuleRootManager, RuntimeException> {
val module = ModuleManager.getInstance(project).modifiableModel.let { moduleModel ->
val module = ModuleManager.getInstance(project).getModifiableModel().let { moduleModel ->
val module = moduleModel.newModule(moduleFile.path, EmptyModuleType.getInstance().id) as ModuleBridge
moduleModel.commit()
module
@@ -366,7 +366,7 @@ class ModuleLibraryBridgeTest {
val gradleLibraryName = "gradle-lib"
val moduleFile = File(project.basePath, "$moduleName.iml")
val module = ModuleManager.getInstance(project).modifiableModel.let { moduleModel ->
val module = ModuleManager.getInstance(project).getModifiableModel().let { moduleModel ->
val module = moduleModel.newModule(moduleFile.path, EmptyModuleType.getInstance().id) as ModuleBridge
moduleModel.commit()
module
@@ -412,7 +412,7 @@ class ModuleLibraryBridgeTest {
val moduleFile = File(project.basePath, "$moduleName.iml")
val module = WriteCommandAction.writeCommandAction(project).compute<ModuleBridge, RuntimeException> {
val module = ModuleManager.getInstance(project).modifiableModel.let { moduleModel ->
val module = ModuleManager.getInstance(project).getModifiableModel().let { moduleModel ->
val module = moduleModel.newModule(moduleFile.path, EmptyModuleType.getInstance().id) as ModuleBridge
moduleModel.commit()
module
@@ -453,7 +453,7 @@ class ModuleLibraryBridgeTest {
val moduleFile = File(project.basePath, "$moduleName.iml")
val module = WriteCommandAction.writeCommandAction(project).compute<ModuleBridge, RuntimeException> {
val module = ModuleManager.getInstance(project).modifiableModel.let { moduleModel ->
val module = ModuleManager.getInstance(project).getModifiableModel().let { moduleModel ->
val module = moduleModel.newModule(moduleFile.path, EmptyModuleType.getInstance().id) as ModuleBridge
moduleModel.commit()
module
@@ -335,7 +335,7 @@ class ProjectLibraryBridgeTest {
assertTrue(iprFile.readText().contains(antLibraryName))
WriteCommandAction.runWriteCommandAction(project) {
val module = ModuleManager.getInstance(project).modifiableModel.let {
val module = ModuleManager.getInstance(project).getModifiableModel().let {
val module = it.newModule(moduleFile.path, EmptyModuleType.getInstance().id) as ModuleBridge
it.commit()
module
@@ -386,7 +386,7 @@ class ProjectLibraryBridgeTest {
val moduleFile = File(project.basePath, "$moduleName.iml")
val library = runBlocking { createProjectLibrary(antLibraryName, withRoots = false) }
WriteCommandAction.runWriteCommandAction(project) {
val module = ModuleManager.getInstance(project).modifiableModel.let { moduleModel ->
val module = ModuleManager.getInstance(project).getModifiableModel().let { moduleModel ->
val module = moduleModel.newModule(moduleFile.path, EmptyModuleType.getInstance().id) as ModuleBridge
moduleModel.commit()
module
@@ -1,4 +1,4 @@
// 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.
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.workspaceModel.ide
import com.intellij.openapi.application.ex.ApplicationManagerEx
@@ -127,7 +127,7 @@ class WorkspaceModelPerformanceTest(private val modulesCount: Int) {
private fun hundredModulesRemove(modules: MutableList<Module>,
moduleManager: ModuleManager) {
modules.forEach {
val modifiableModel = moduleManager.modifiableModel
val modifiableModel = moduleManager.getModifiableModel()
modifiableModel.disposeModule(it)
modifiableModel.commit()
}
@@ -178,7 +178,7 @@ class WorkspaceModelPerformanceTest(private val modulesCount: Int) {
private fun hundredModulesCreation(moduleManager: ModuleManager,
modules: MutableList<Module>) {
(1..100).forEach {
val modifiableModel = moduleManager.modifiableModel
val modifiableModel = moduleManager.getModifiableModel()
modules.add(modifiableModel.newModule(File(project.basePath, "$TEST_MODULE_PREFIX$it.iml").path, EmptyModuleType.getInstance().id))
modifiableModel.commit()
}
@@ -1,4 +1,4 @@
// 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.
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.plugins.gradle.importing;
import com.intellij.ide.highlighter.ModuleFileType;
@@ -173,7 +173,7 @@ public class GradleMiscImportingTest extends GradleJavaImportingTestCase {
);
assertModules("project", "project.main", "project.test");
edt(() -> ModuleManager.getInstance(myProject).setUnloadedModules(Collections.singletonList("project.main")));
edt(() -> ModuleManager.getInstance(myProject).setUnloadedModulesSync(Collections.singletonList("project.main")));
assertModules("project", "project.test");
importProject();
@@ -1,4 +1,4 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.testFramework
@@ -262,7 +262,7 @@ class ModuleDescription(val moduleName: String) {
val moduleVirtualFile = LocalFileSystem.getInstance().refreshAndFindFileByNioFile(modulePath) ?: error("unable to find ${modulePath}")
runWriteAction {
val moduleManager = ModuleManager.getInstance(project)
val module = with(moduleManager.modifiableModel) {
val module = with(moduleManager.getModifiableModel()) {
val imlPath = modulePath.resolve("$moduleName${ModuleFileType.DOT_DEFAULT_EXTENSION}")
val module = newModule(imlPath, ModuleTypeId.JAVA_MODULE)
PsiTestUtil.addSourceRoot(module, moduleVirtualFile.findFileByRelativePath(src) ?: error("no '$src' in $this"))
@@ -1,4 +1,4 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.tools.projectWizard.wizard
import com.intellij.ide.RecentProjectsManager
@@ -107,7 +107,7 @@ class NewProjectWizardModuleBuilder : EmptyModuleBuilder() {
runWriteAction {
wizard.jdk?.let { jdk -> JavaSdkUtil.applyJdkToProject(project, jdk) }
}
val modulesModel = model ?: ModuleManager.getInstance(project).modifiableModel
val modulesModel = model ?: ModuleManager.getInstance(project).getModifiableModel()
val success = wizard.apply(
services = buildList {
+IdeaServices.createScopeDependent(project)
@@ -1,4 +1,4 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.test
@@ -63,7 +63,7 @@ abstract class KotlinMultiFileTestCase : MultiFileTestCase() {
override fun prepareProject(rootDir: VirtualFile) {
if (isMultiModule) {
val model = ModuleManager.getInstance(project).modifiableModel
val model = ModuleManager.getInstance(project).getModifiableModel()
VfsUtilCore.visitChildrenRecursively(
rootDir,
@@ -583,9 +583,13 @@ public class MavenProjectsManager extends MavenSimpleProjectComponent
private void projectClosed() {
initLock.lock();
try {
if (!isInitialized.getAndSet(false)) return;
if (!isInitialized.getAndSet(false)) {
return;
}
Disposer.dispose(myImportingQueue);
if (myImportingQueue != null) {
Disposer.dispose(myImportingQueue);
}
myWatcher.stop();
@@ -92,7 +92,7 @@ internal val Project.trustedProjectFlow: Flow<Boolean>
internal val Project.nativeModulesFlow: Flow<List<Module>>
get() = messageBusFlow(ProjectTopics.MODULES, { getNativeModules() }) {
object : ModuleListener {
override fun moduleAdded(project: Project, module: Module) {
override fun modulesAdded(project: Project, modules: List<Module>) {
trySend(getNativeModules())
}
@@ -81,8 +81,7 @@ public final class PythonLanguageLevelPusher implements FilePropertyPusher<Strin
}
@Override
@NotNull
public Key<String> getFileDataKey() {
public @NotNull Key<String> getFileDataKey() {
return KEY;
}
@@ -92,19 +91,16 @@ public final class PythonLanguageLevelPusher implements FilePropertyPusher<Strin
}
@Override
@NotNull
public String getDefaultValue() {
public @NotNull String getDefaultValue() {
return LanguageLevel.getDefault().toPythonVersion();
}
@Override
@Nullable
public String getImmediateValue(@NotNull Project project, @Nullable VirtualFile file) {
public @Nullable String getImmediateValue(@NotNull Project project, @Nullable VirtualFile file) {
return null;
}
@Nullable
private static Sdk getFileSdk(@NotNull Project project, @NotNull VirtualFile file) {
private static @Nullable Sdk getFileSdk(@NotNull Project project, @NotNull VirtualFile file) {
final Module module = ModuleUtilCore.findModuleForFile(file, project);
if (module != null) {
return PythonSdkUtil.findPythonSdk(module);
@@ -114,8 +110,7 @@ public final class PythonLanguageLevelPusher implements FilePropertyPusher<Strin
}
}
@Nullable
private static Sdk findSdkForFileOutsideTheProject(Project project, VirtualFile file) {
private static @Nullable Sdk findSdkForFileOutsideTheProject(Project project, VirtualFile file) {
if (file != null) {
final List<OrderEntry> orderEntries = ProjectRootManager.getInstance(project).getFileIndex().getOrderEntriesForFile(file);
for (OrderEntry orderEntry : orderEntries) {
@@ -128,8 +123,7 @@ public final class PythonLanguageLevelPusher implements FilePropertyPusher<Strin
}
@Override
@NotNull
public String getImmediateValue(@NotNull Module module) {
public @NotNull String getImmediateValue(@NotNull Module module) {
if (ApplicationManager.getApplication().isUnitTestMode() && LanguageLevel.FORCE_LANGUAGE_LEVEL != null) {
return LanguageLevel.FORCE_LANGUAGE_LEVEL.toPythonVersion();
}
@@ -189,7 +183,7 @@ public final class PythonLanguageLevelPusher implements FilePropertyPusher<Strin
return PythonFileType.INSTANCE.equals(FileTypeRegistry.getInstance().getFileTypeByFileName(child.getNameSequence()));
}
private static void clearSdkPathCache(@NotNull final VirtualFile child) {
private static void clearSdkPathCache(final @NotNull VirtualFile child) {
final Project[] projects = ProjectManager.getInstance().getOpenProjects();
for (Project project : projects) {
final Sdk sdk = getFileSdk(project, child);
@@ -201,7 +195,7 @@ public final class PythonLanguageLevelPusher implements FilePropertyPusher<Strin
}
@Override
public void afterRootsChanged(@NotNull final Project project) {
public void afterRootsChanged(final @NotNull Project project) {
final Map<Module, Sdk> moduleSdks = getPythonModuleSdks(project);
final boolean needToReparseOpenFiles = ContainerUtil.exists(moduleSdks.entrySet(), entry -> {
final Module module = entry.getKey();
@@ -224,10 +218,11 @@ public final class PythonLanguageLevelPusher implements FilePropertyPusher<Strin
}
}
@NotNull
private static Map<@NotNull Module, @NotNull Sdk> getPythonModuleSdks(@NotNull Project project) {
final ModuleManager moduleManager = ModuleManager.getInstance(project);
if (moduleManager == null) return Collections.emptyMap();
private static @NotNull Map<@NotNull Module, @NotNull Sdk> getPythonModuleSdks(@NotNull Project project) {
ModuleManager moduleManager = ModuleManager.Companion.getInstanceIfDefined(project);
if (moduleManager == null) {
return Collections.emptyMap();
}
final Map<Module, Sdk> result = new LinkedHashMap<>();
for (Module module : moduleManager.getModules()) {
@@ -284,8 +279,7 @@ public final class PythonLanguageLevelPusher implements FilePropertyPusher<Strin
results.add(new UpdateRootTask(project, root, languageLevel, shouldSuppressSizeLimit));
}
@NotNull
private static LanguageLevel guessLanguageLevelWithCaching(@NotNull Project project, @NotNull Collection<? extends @NotNull Sdk> pythonModuleSdks) {
private static @NotNull LanguageLevel guessLanguageLevelWithCaching(@NotNull Project project, @NotNull Collection<? extends @NotNull Sdk> pythonModuleSdks) {
LanguageLevel languageLevel = LanguageLevel.fromPythonVersion(project.getUserData(KEY));
if (languageLevel == null) {
languageLevel = guessLanguageLevel(pythonModuleSdks);
@@ -299,8 +293,7 @@ public final class PythonLanguageLevelPusher implements FilePropertyPusher<Strin
project.putUserData(KEY, null);
}
@NotNull
private static LanguageLevel guessLanguageLevel(@NotNull Collection<? extends @NotNull Sdk> pythonModuleSdks) {
private static @NotNull LanguageLevel guessLanguageLevel(@NotNull Collection<? extends @NotNull Sdk> pythonModuleSdks) {
LanguageLevel maxLevel = null;
for (Sdk sdk : pythonModuleSdks) {
final LanguageLevel level = PythonRuntimeService.getInstance().getLanguageLevelForSdk(sdk);
@@ -319,8 +312,7 @@ public final class PythonLanguageLevelPusher implements FilePropertyPusher<Strin
*
* @see LanguageLevel#forElement
*/
@NotNull
public static LanguageLevel getLanguageLevelForVirtualFile(@NotNull Project project, @NotNull VirtualFile virtualFile) {
public static @NotNull LanguageLevel getLanguageLevelForVirtualFile(@NotNull Project project, @NotNull VirtualFile virtualFile) {
if (virtualFile instanceof VirtualFileWindow) {
virtualFile = ((VirtualFileWindow)virtualFile).getDelegate();
}
@@ -339,9 +331,9 @@ public final class PythonLanguageLevelPusher implements FilePropertyPusher<Strin
}
private final class UpdateRootTask implements Runnable {
@NotNull private final Project myProject;
@NotNull private final VirtualFile myRoot;
@NotNull private final LanguageLevel myLanguageLevel;
private final @NotNull Project myProject;
private final @NotNull VirtualFile myRoot;
private final @NotNull LanguageLevel myLanguageLevel;
private final boolean myShouldSuppressSizeLimit;
UpdateRootTask(@NotNull Project project, @NotNull VirtualFile root, @NotNull LanguageLevel languageLevel,
@@ -401,8 +393,7 @@ public final class PythonLanguageLevelPusher implements FilePropertyPusher<Strin
file.putUserData(KEY, languageLevel == null ? null : languageLevel.toPythonVersion());
}
@Nullable
private static LanguageLevel specifiedFileLanguageLevel(@Nullable VirtualFile file) {
private static @Nullable LanguageLevel specifiedFileLanguageLevel(@Nullable VirtualFile file) {
if (file == null) return null;
final LanguageLevel specified = LanguageLevel.fromPythonVersion(file.getUserData(KEY));
@@ -421,7 +412,7 @@ public final class PythonLanguageLevelPusher implements FilePropertyPusher<Strin
}
private final class MyDumbModeTask extends DumbModeTask {
private @NotNull final Project project;
private final @NotNull Project project;
private final @NotNull Map<Module, Sdk> moduleSdks;
private final SimpleMessageBusConnection connection;