mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IJPL-217691 avoid extra launch - use ProjectActivity scope
GitOrigin-RevId: a47b513216df15561c56102e87195a806b657cf9
This commit is contained in:
committed by
intellij-monorepo-bot
parent
a7b9240cad
commit
47cea42589
+23
-21
@@ -692,7 +692,7 @@ open class ProjectManagerImpl : ProjectManagerEx(), Disposable {
|
||||
|
||||
if (Registry.`is`("ide.create.project.root.entity") && options.projectRootDir != null) {
|
||||
val root = options.projectRootDir!!.toVirtualFileUrl(project.workspaceModel.getVirtualFileUrlManager())
|
||||
project.serviceAsync<ProjectRootPersistentStateComponent>().projectRootUrls += root.url
|
||||
project.serviceAsync<ProjectRootPersistentStateComponent>().addProjectRoot(root.url)
|
||||
|
||||
// We also register the project root here, so project view will have "files" node immediately.
|
||||
// Otherwise, it might appear too late causing issues like AMPER-4695
|
||||
@@ -741,7 +741,7 @@ open class ProjectManagerImpl : ProjectManagerEx(), Disposable {
|
||||
result?.let { project ->
|
||||
try {
|
||||
withContext(Dispatchers.EDT) {
|
||||
closeProject(project, saveProject = false, checkCanClose = false)
|
||||
closeProject(project = project, saveProject = false, checkCanClose = false)
|
||||
}
|
||||
}
|
||||
catch (secondException: Throwable) {
|
||||
@@ -784,16 +784,18 @@ open class ProjectManagerImpl : ProjectManagerEx(), Disposable {
|
||||
|
||||
protected open fun createFrameAllocator(projectStoreBaseDir: Path, options: OpenProjectTask): ProjectFrameAllocator {
|
||||
val app = ApplicationManager.getApplication()
|
||||
return if (app.isHeadlessEnvironment || app.isUnitTestMode) {
|
||||
HeadlessProjectFrameAllocator()
|
||||
if (app.isHeadlessEnvironment || app.isUnitTestMode) {
|
||||
return HeadlessProjectFrameAllocator()
|
||||
}
|
||||
else {
|
||||
IdeProjectFrameAllocator(options, projectStoreBaseDir)
|
||||
return IdeProjectFrameAllocator(options, projectStoreBaseDir)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun cancelProjectOpening(project: Project?, e: CancellationException? = null) {
|
||||
if (project == null) return
|
||||
if (project == null) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
try {
|
||||
@@ -806,7 +808,7 @@ open class ProjectManagerImpl : ProjectManagerEx(), Disposable {
|
||||
|
||||
withContext(Dispatchers.EDT) {
|
||||
writeIntentReadAction {
|
||||
closeProject(project, saveProject = false, checkCanClose = false)
|
||||
closeProject(project = project, saveProject = false, checkCanClose = false)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -847,30 +849,30 @@ open class ProjectManagerImpl : ProjectManagerEx(), Disposable {
|
||||
}
|
||||
|
||||
override fun newProject(file: Path, options: OpenProjectTask): Project? {
|
||||
return try {
|
||||
try {
|
||||
@Suppress("DEPRECATION")
|
||||
runUnderModalProgressIfIsEdt {
|
||||
return runUnderModalProgressIfIsEdt {
|
||||
newProjectAsync(file, options)
|
||||
}
|
||||
}
|
||||
catch (t: Throwable) {
|
||||
handleErrorOnNewProject(t)
|
||||
null
|
||||
catch (e: Throwable) {
|
||||
handleErrorOnNewProject(e)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
final override suspend fun newProjectAsync(file: Path, options: OpenProjectTask): Project {
|
||||
TrustedProjects.setProjectTrusted(file, true)
|
||||
TrustedProjects.setProjectTrusted(path = file, isTrusted = true)
|
||||
return prepareNewProject(
|
||||
file,
|
||||
options.projectName,
|
||||
options.beforeInit,
|
||||
options.useDefaultProjectAsTemplate,
|
||||
options.preloadServices,
|
||||
options.isProjectCreatedWithWizard,
|
||||
markAsNew = false
|
||||
identityFle = file,
|
||||
projectName = options.projectName,
|
||||
beforeInit = options.beforeInit,
|
||||
useDefaultProjectAsTemplate = options.useDefaultProjectAsTemplate,
|
||||
preloadServices = options.preloadServices,
|
||||
markAsNewlyCreated = options.isProjectCreatedWithWizard,
|
||||
markAsNew = false,
|
||||
).also { project ->
|
||||
TrustedProjects.setProjectTrusted(project, true)
|
||||
TrustedProjects.setProjectTrusted(project = project, isTrusted = true)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-2
@@ -10,8 +10,12 @@ import org.jetbrains.annotations.ApiStatus
|
||||
@Service(Service.Level.PROJECT)
|
||||
@State(name = "ProjectRoots", storages = [Storage(StoragePathMacros.PRODUCT_WORKSPACE_FILE)])
|
||||
@ApiStatus.Internal
|
||||
class ProjectRootPersistentStateComponent(val scope: CoroutineScope) :
|
||||
SerializablePersistentStateComponent<ProjectRootPersistentStateComponent.State>(State()) {
|
||||
class ProjectRootPersistentStateComponent : SerializablePersistentStateComponent<ProjectRootPersistentStateComponent.State>(State()) {
|
||||
fun addProjectRoot(projectRootUrl: String) {
|
||||
updateState {
|
||||
it.copy(projectRootUrls = it.projectRootUrls + projectRootUrl)
|
||||
}
|
||||
}
|
||||
|
||||
var projectRootUrls: List<String>
|
||||
get() = state.projectRootUrls
|
||||
|
||||
+31
-25
@@ -1,7 +1,9 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.openapi.project.impl
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.components.serviceAsync
|
||||
import com.intellij.openapi.extensions.ExtensionNotApplicableException
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.startup.ProjectActivity
|
||||
import com.intellij.openapi.util.registry.Registry
|
||||
@@ -9,44 +11,48 @@ import com.intellij.platform.backend.workspace.WorkspaceModel
|
||||
import com.intellij.platform.workspace.storage.entities
|
||||
import com.intellij.workspaceModel.ide.ProjectRootEntity
|
||||
import com.intellij.workspaceModel.ide.registerProjectRoot
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.launch
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
import org.jetbrains.annotations.ApiStatus.Internal
|
||||
import org.jetbrains.annotations.VisibleForTesting
|
||||
|
||||
@ApiStatus.Internal
|
||||
@Internal
|
||||
class ProjectRootsSynchronizer : ProjectActivity {
|
||||
override suspend fun execute(project: Project) {
|
||||
if (!Registry.`is`("ide.create.project.root.entity")) return
|
||||
companion object {
|
||||
@VisibleForTesting
|
||||
suspend fun doRegister(project: Project) {
|
||||
if (!Registry.`is`("ide.create.project.root.entity")) {
|
||||
return
|
||||
}
|
||||
|
||||
val projectRootsComponent = project.serviceAsync<ProjectRootPersistentStateComponent>()
|
||||
val roots = projectRootsComponent.projectRootUrls
|
||||
val virtualFileUrlManager = project.serviceAsync<WorkspaceModel>().getVirtualFileUrlManager()
|
||||
for (root in roots) {
|
||||
registerProjectRoot(project, virtualFileUrlManager.getOrCreateFromUrl(root))
|
||||
val projectRootsComponent = project.serviceAsync<ProjectRootPersistentStateComponent>()
|
||||
val roots = projectRootsComponent.projectRootUrls
|
||||
val virtualFileUrlManager = project.serviceAsync<WorkspaceModel>().getVirtualFileUrlManager()
|
||||
for (root in roots) {
|
||||
registerProjectRoot(project, virtualFileUrlManager.getOrCreateFromUrl(root))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
launchListener(project, projectRootsComponent.scope)
|
||||
override suspend fun execute(project: Project) {
|
||||
doRegister(project)
|
||||
return
|
||||
|
||||
launchListener(project)
|
||||
}
|
||||
|
||||
/**
|
||||
* Keeps [ProjectRootPersistentStateComponent] in sync with the actual ProjectRootEntities in the workspace model.
|
||||
*/
|
||||
private fun launchListener(project: Project, scope: CoroutineScope) {
|
||||
private suspend fun launchListener(project: Project) {
|
||||
val workspaceModel = project.serviceAsync<WorkspaceModel>()
|
||||
val flow = workspaceModel.eventLog
|
||||
.filter { change -> change.getChanges(ProjectRootEntity::class.java).isNotEmpty() }
|
||||
|
||||
scope.launch {
|
||||
val workspaceModel = project.serviceAsync<WorkspaceModel>()
|
||||
val flow = workspaceModel.eventLog
|
||||
.filter { change -> change.getChanges(ProjectRootEntity::class.java).isNotEmpty() }
|
||||
|
||||
val component = project.serviceAsync<ProjectRootPersistentStateComponent>()
|
||||
component.projectRootUrls = workspaceModel.currentSnapshot.entities<ProjectRootEntity>().map { it.root.url }.toList()
|
||||
|
||||
flow.collect { change ->
|
||||
val newRoots = change.storageAfter.entities<ProjectRootEntity>().map { it.root.url }.toList()
|
||||
val component = project.serviceAsync<ProjectRootPersistentStateComponent>()
|
||||
component.projectRootUrls = newRoots.toList()
|
||||
}
|
||||
val component = project.serviceAsync<ProjectRootPersistentStateComponent>()
|
||||
component.projectRootUrls = workspaceModel.currentSnapshot.entities<ProjectRootEntity>().map { it.root.url }.toList()
|
||||
flow.collect { change ->
|
||||
component.projectRootUrls = change.storageAfter.entities<ProjectRootEntity>().map { it.root.url }.toList()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ class ProjectRootEntityTest {
|
||||
projectFile.createDirectories()
|
||||
val options = createTestOpenProjectOptions().copy(projectName = name, projectRootDir = projectFile)
|
||||
ProjectUtil.openOrImportAsync(projectFile, options)!!.useProjectAsync { project ->
|
||||
ProjectRootsSynchronizer().execute(project) // background startup activities are not executed in unit tests on project open
|
||||
ProjectRootsSynchronizer.doRegister(project) // background startup activities are not executed in unit tests on project open
|
||||
val roots = project.workspaceModel.currentSnapshot.entities(ProjectRootEntity::class.java).toList()
|
||||
assertThat(roots.map { it.root }).isEqualTo(listOf(projectFile.toVirtualFileUrl(project.workspaceModel.getVirtualFileUrlManager())))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user