BAZEL-2160 make clear that ProjectImpl doesn't require project identity file

GitOrigin-RevId: 3c9f972ff0cbe903dc16ad0b6df67ad5c0814383
This commit is contained in:
Vladimir Krivosheev
2025-09-18 15:14:18 +00:00
committed by intellij-monorepo-bot
parent e3abde3310
commit 13a6f05618
11 changed files with 58 additions and 57 deletions
@@ -268,7 +268,7 @@ suspend fun createProjectFromWizardImpl(wizard: AbstractProjectWizard, projectFi
}
serviceAsync<TrustedPaths>().setProjectPathTrusted(projectDir, true)
(serviceAsync<ProjectManager>() as ProjectManagerEx).openProjectAsync(projectStoreBaseDir = projectDir, options = options)
(serviceAsync<ProjectManager>() as ProjectManagerEx).openProjectAsync(projectIdentityFile = projectDir, options = options)
}
if (!ApplicationManager.getApplication().isUnitTestMode) {
serviceAsync<SaveAndSyncHandler>().scheduleProjectSave(newProject)
@@ -161,7 +161,7 @@ public class Bar {
val projectFile = getProjectDirOrFile(true)
Files.createDirectories(projectFile.parent.resolve(Project.DIRECTORY_STORE_FOLDER))
return runBlocking {
ProjectManagerEx.getInstanceEx().openProjectAsync(projectStoreBaseDir = projectFile.parent, options = OpenProjectTask {})!!
ProjectManagerEx.getInstanceEx().openProjectAsync(projectIdentityFile = projectFile.parent, options = OpenProjectTask {})!!
}
}
@@ -74,7 +74,7 @@ abstract class ProjectManagerEx : ProjectManager() {
abstract fun openProject(projectStoreBaseDir: Path, options: OpenProjectTask): Project?
abstract suspend fun openProjectAsync(projectStoreBaseDir: Path, options: OpenProjectTask = OpenProjectTask()): Project?
abstract suspend fun openProjectAsync(projectIdentityFile: Path, options: OpenProjectTask = OpenProjectTask()): Project?
@Internal
abstract fun loadProject(path: Path): Project
@@ -90,9 +90,10 @@ abstract class ProjectManagerEx : ProjectManager() {
* The project and the app settings will be not saved.
*/
@Internal
fun forceCloseProject(project: Project): Boolean =
fun forceCloseProject(project: Project): Boolean {
@Suppress("TestOnlyProblems")
forceCloseProject(project, save = false)
return forceCloseProject(project = project, save = false)
}
@TestOnly
abstract fun forceCloseProject(project: Project, save: Boolean): Boolean
@@ -101,9 +102,10 @@ abstract class ProjectManagerEx : ProjectManager() {
abstract suspend fun forceCloseProjectAsync(project: Project, save: Boolean = false): Boolean
@Internal
fun saveAndForceCloseProject(project: Project): Boolean =
fun saveAndForceCloseProject(project: Project): Boolean {
@Suppress("TestOnlyProblems")
forceCloseProject(project, save = true)
return forceCloseProject(project = project, save = true)
}
// return true if successful
abstract fun closeAndDisposeAllProjects(checkCanClose: Boolean): Boolean
@@ -227,7 +227,7 @@ object ProjectUtil {
val project: Project?
if (processors.size == 1 && processors[0] is PlatformProjectOpenProcessor) {
project = (serviceAsync<ProjectManager>() as ProjectManagerEx).openProjectAsync(
projectStoreBaseDir = file,
projectIdentityFile = file,
options = options.copy(
isNewProject = true,
useDefaultProjectAsTemplate = true,
@@ -675,7 +675,7 @@ object ProjectUtil {
return null
}
return projectManager.openProjectAsync(projectStoreBaseDir = projectFile, options = OpenProjectTask {
return projectManager.openProjectAsync(projectIdentityFile = projectFile, options = OpenProjectTask {
runConfigurators = true
isProjectCreatedWithWizard = true
})
@@ -25,7 +25,7 @@ import java.nio.file.Path
internal class LightEditProjectImpl private constructor(identityFle: Path) :
ProjectImpl(
parent = ApplicationManager.getApplication().getComponentManagerImpl(),
identityFle = identityFle,
isLightTestProject = false,
projectName = PROJECT_NAME,
), LightEditCompatible {
constructor() : this(PathManager.getConfigDir().resolve("light-edit"))
@@ -71,7 +71,7 @@ private val LOG = logger<ProjectImpl>()
private val DISPOSE_EARLY_DISPOSABLE_TRACE = Key.create<String>("ProjectImpl.DISPOSE_EARLY_DISPOSABLE_TRACE")
@Internal
open class ProjectImpl(parent: ComponentManagerImpl, identityFle: Path, projectName: String?)
open class ProjectImpl(parent: ComponentManagerImpl, private val isLightTestProject: Boolean, projectName: String?)
: ClientAwareComponentManager(parent), ProjectEx, ProjectStoreOwner {
companion object {
@Internal
@@ -116,8 +116,6 @@ open class ProjectImpl(parent: ComponentManagerImpl, identityFle: Path, projectN
var isTemporarilyDisposed: Boolean = false
private set
private val isLight: Boolean
private var cachedName: String?
private val componentStoreValue = SynchronizedClearableLazy {
@@ -136,9 +134,6 @@ open class ProjectImpl(parent: ComponentManagerImpl, identityFle: Path, projectN
registerServiceInstance(Project::class.java, this, fakeCorePluginDescriptor)
cachedName = projectName
// a light project may be changed later during test, so we need to remember its initial state
@Suppress("TestOnlyProblems")
isLight = ApplicationManager.getApplication().isUnitTestMode && identityFle.toString().contains(LIGHT_PROJECT_NAME)
}
final override fun <T : Any> findConstructorAndInstantiateClass(lookup: MethodHandles.Lookup, aClass: Class<T>): T {
@@ -264,7 +259,7 @@ open class ProjectImpl(parent: ComponentManagerImpl, identityFle: Path, projectN
return cachedVirtualFile.resolvedVirtualFile
}
final override fun isLight(): Boolean = isLight
final override fun isLight(): Boolean = isLightTestProject
@Internal
final override fun activityNamePrefix(): String = "project "
@@ -357,7 +352,7 @@ open class ProjectImpl(parent: ComponentManagerImpl, identityFle: Path, projectN
@TestOnly
fun setLightProjectName(name: String) {
assert(isLight)
assert(isLightTestProject)
setProjectName(name)
storeCreationTrace()
}
@@ -55,6 +55,7 @@ import com.intellij.openapi.progress.runBlockingCancellable
import com.intellij.openapi.project.*
import com.intellij.openapi.project.ex.ProjectEx
import com.intellij.openapi.project.ex.ProjectManagerEx
import com.intellij.openapi.project.impl.ProjectImpl.Companion.LIGHT_PROJECT_NAME
import com.intellij.openapi.project.impl.ProjectImpl.Companion.PROJECT_PATH
import com.intellij.openapi.startup.InitProjectActivity
import com.intellij.openapi.startup.StartupManager
@@ -62,7 +63,7 @@ import com.intellij.openapi.ui.MessageDialogBuilder
import com.intellij.openapi.ui.Messages
import com.intellij.openapi.util.*
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.io.NioFiles.deleteRecursively
import com.intellij.openapi.util.io.NioFiles
import com.intellij.openapi.util.registry.Registry
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.impl.ZipHandler
@@ -197,13 +198,13 @@ open class ProjectManagerImpl : ProjectManagerEx(), Disposable {
Disposer.register(parentDisposable) { getAllExcludedUrlsCallback = null }
}
override val allExcludedUrls: List<String>
final override val allExcludedUrls: List<String>
get() {
getAllExcludedUrlsCallback?.run()
return excludeRootsCache.excludedUrls
}
override fun dispose() {
final override fun dispose() {
ThreadingAssertions.assertWriteAccess()
// dispose manually, because TimedReference.dispose() can already be called (in Timed.disposeTimed()) and then default project resurrected
Disposer.dispose(defaultProject)
@@ -217,7 +218,7 @@ open class ProjectManagerImpl : ProjectManagerEx(), Disposable {
val modalityState = CoreProgressManager.getCurrentThreadProgressModality()
return runBlockingCancellable {
withContext(modalityState.asContextElement()) {
prepareProject(projectStoreBaseDir = path,
prepareProject(projectIdentityFile = path,
projectName = null,
beforeInit = null,
projectInitHelper = null,
@@ -227,10 +228,10 @@ open class ProjectManagerImpl : ProjectManagerEx(), Disposable {
}
}
override val isDefaultProjectInitialized: Boolean
final override val isDefaultProjectInitialized: Boolean
get() = defaultProject.isCached
override fun getDefaultProject(): Project {
final override fun getDefaultProject(): Project {
@Suppress("GrazieInspection")
LOG.assertTrue(!ApplicationManager.getApplication().isDisposed, "Application has already been disposed!")
defaultProject.markRequested()
@@ -243,9 +244,9 @@ open class ProjectManagerImpl : ProjectManagerEx(), Disposable {
defaultProject.disposeDefaultProjectAndCleanupComponentsForDynamicPluginTests()
}
override fun getOpenProjects(): Array<Project> = synchronized(lock) { openProjects }
final override fun getOpenProjects(): Array<Project> = synchronized(lock) { openProjects }
override fun isProjectOpened(project: Project): Boolean = synchronized(lock) { openProjects.contains(project) }
final override fun isProjectOpened(project: Project): Boolean = synchronized(lock) { openProjects.contains(project) }
protected fun addToOpened(project: Project): Boolean {
assert(!project.isDisposed) { "Must not open already disposed project" }
@@ -283,22 +284,22 @@ open class ProjectManagerImpl : ProjectManagerEx(), Disposable {
}
}
override fun findOpenProjectByHash(locationHash: String?): Project? = openProjectByHash[locationHash]
final override fun findOpenProjectByHash(locationHash: String?): Project? = openProjectByHash[locationHash]
override fun reloadProject(project: Project) {
final override fun reloadProject(project: Project) {
StoreReloadManager.getInstance(project).reloadProject()
}
@Suppress("OVERRIDE_DEPRECATION")
override fun closeProject(project: Project): Boolean {
final override fun closeProject(project: Project): Boolean {
return closeProject(project = project, saveProject = true, dispose = false, checkCanClose = true)
}
override fun forceCloseProject(project: Project, save: Boolean): Boolean {
final override fun forceCloseProject(project: Project, save: Boolean): Boolean {
return closeProject(project = project, saveProject = save, checkCanClose = false)
}
override suspend fun forceCloseProjectAsync(project: Project, save: Boolean): Boolean {
final override suspend fun forceCloseProjectAsync(project: Project, save: Boolean): Boolean {
if (save) {
// HeadlessSaveAndSyncHandler doesn't save, but if `save` is requested,
// it means that we must save it in any case (for example, see GradleSourceSetsTest)
@@ -317,7 +318,7 @@ open class ProjectManagerImpl : ProjectManagerEx(), Disposable {
}
// return true if successful
override fun closeAndDisposeAllProjects(checkCanClose: Boolean): Boolean {
final override fun closeAndDisposeAllProjects(checkCanClose: Boolean): Boolean {
var projects = openProjects
LightEditUtil.getProjectIfCreated()?.let {
projects += it
@@ -550,10 +551,10 @@ open class ProjectManagerImpl : ProjectManagerEx(), Disposable {
return runUnderModalProgressIfIsEdt { openProjectAsync(projectStoreBaseDir, options) }
}
final override suspend fun openProjectAsync(projectStoreBaseDir: Path, options: OpenProjectTask): Project? {
if (projectStoreBaseDir.fileSystem.javaClass.name == MultiRoutingFileSystem::javaClass.name) {
final override suspend fun openProjectAsync(projectIdentityFile: Path, options: OpenProjectTask): Project? {
if (projectIdentityFile.fileSystem.javaClass.name == MultiRoutingFileSystem::javaClass.name) {
span("EelInitialization.runEelInitialization") {
EelInitialization.runEelInitialization(projectStoreBaseDir.toString())
EelInitialization.runEelInitialization(projectIdentityFile.toString())
}
}
@@ -569,7 +570,7 @@ open class ProjectManagerImpl : ProjectManagerEx(), Disposable {
}
val continueOpen = span("checkChildProcess") {
!checkChildProcess(projectStoreBaseDir, options)
!checkChildProcess(projectIdentityFile, options)
}
if (!continueOpen) {
withContext(NonCancellable) {
@@ -591,7 +592,7 @@ open class ProjectManagerImpl : ProjectManagerEx(), Disposable {
}
}
if (checkExistingProjectOnOpen(projectToClose, options, projectStoreBaseDir)) {
if (checkExistingProjectOnOpen(projectToClose, options, projectIdentityFile)) {
LOG.info("Project check is not succeeded -> return null")
withContext(NonCancellable) {
cancelProjectOpening(options.project)
@@ -602,7 +603,7 @@ open class ProjectManagerImpl : ProjectManagerEx(), Disposable {
}
span("checkTrustedState") {
if (!checkTrustedState(projectStoreBaseDir)) {
if (!checkTrustedState(projectIdentityFile)) {
LOG.info("Project is not trusted, aborting")
if (options.showWelcomeScreen) {
WelcomeFrame.showIfNoProjectOpened()
@@ -620,12 +621,12 @@ open class ProjectManagerImpl : ProjectManagerEx(), Disposable {
}
return span("ProjectManager.openAsync") {
doOpenAsync(options, projectStoreBaseDir)
doOpenAsync(options, projectIdentityFile)
}
}
private suspend fun doOpenAsync(options: OpenProjectTask, projectStoreBaseDir: Path): Project? {
val frameAllocator = createFrameAllocator(projectStoreBaseDir, options)
private suspend fun doOpenAsync(options: OpenProjectTask, projectIdentityFile: Path): Project? {
val frameAllocator = createFrameAllocator(projectIdentityFile, options)
val unitTestMode = ApplicationManager.getApplication().isUnitTestMode
val disableAutoSaveToken = serviceAsync<SaveAndSyncHandler>().disableAutoSave()
val module: Module? = null
@@ -652,14 +653,14 @@ open class ProjectManagerImpl : ProjectManagerEx(), Disposable {
val project = when {
options.project != null -> options.project!!
options.isNewProject -> prepareNewProject(
identityFle = projectStoreBaseDir,
identityFle = projectIdentityFile,
projectName = options.projectName,
beforeInit = options.beforeInit,
useDefaultProjectAsTemplate = options.useDefaultProjectAsTemplate,
preloadServices = options.preloadServices
)
else -> prepareProject(
projectStoreBaseDir = projectStoreBaseDir,
projectIdentityFile = projectIdentityFile,
projectName = options.projectName,
beforeInit = options.beforeInit,
projectInitHelper = initHelper.takeIf { initFrameEarly },
@@ -675,7 +676,7 @@ open class ProjectManagerImpl : ProjectManagerEx(), Disposable {
throw CancellationException("beforeOpen callback returned false")
}
configureWorkspace(project, projectStoreBaseDir, options)
configureWorkspace(project, projectIdentityFile, options)
}
if (Registry.`is`("ide.create.project.root.entity") && options.projectRootDir != null) {
@@ -825,7 +826,7 @@ open class ProjectManagerImpl : ProjectManagerEx(), Disposable {
}
}
override suspend fun newProjectAsync(file: Path, options: OpenProjectTask): Project {
final override suspend fun newProjectAsync(file: Path, options: OpenProjectTask): Project {
TrustedProjects.setProjectTrusted(file, true)
return prepareNewProject(
file,
@@ -858,9 +859,10 @@ open class ProjectManagerImpl : ProjectManagerEx(), Disposable {
projectName: String?,
beforeInit: ((Project) -> Unit)?,
): ProjectImpl {
@Suppress("TestOnlyProblems")
val project = span("project instantiation") {
ProjectImpl(
identityFle = identityFle,
isLightTestProject = ApplicationManager.getApplication().isUnitTestMode && identityFle.toString().contains(LIGHT_PROJECT_NAME),
projectName = projectName,
parent = ApplicationManager.getApplication().getComponentManagerImpl(),
)
@@ -893,14 +895,14 @@ open class ProjectManagerImpl : ProjectManagerEx(), Disposable {
withContext(Dispatchers.IO) {
launch {
try {
ProjectStorePathManager.getInstance().getStoreDescriptor(identityFle).removeProjectConfigurationAndCaches()
serviceAsync<ProjectStorePathManager>().getStoreDescriptor(identityFle).removeProjectConfigurationAndCaches()
}
catch (_: IOException) {
}
}
launch {
try {
deleteRecursively(getProjectDataPathRoot(identityFle))
NioFiles.deleteRecursively(getProjectDataPathRoot(identityFle))
}
catch (_: IOException) {
}
@@ -924,7 +926,7 @@ open class ProjectManagerImpl : ProjectManagerEx(), Disposable {
}
private suspend fun prepareProject(
projectStoreBaseDir: Path,
projectIdentityFile: Path,
projectName: String?,
beforeInit: ((Project) -> Unit)?,
projectInitHelper: ProjectInitHelper?,
@@ -932,17 +934,17 @@ open class ProjectManagerImpl : ProjectManagerEx(), Disposable {
preloadServices: Boolean,
): Project {
val conversionResult: ConversionResult? = if (runConversionBeforeOpen) {
runConversion(projectStoreBaseDir)
runConversion(projectIdentityFile)
}
else {
null
}
val project = instantiateProject(projectStoreBaseDir, projectName, beforeInit)
val project = instantiateProject(projectIdentityFile, projectName, beforeInit)
// template as null here because it is not a new project
initProject(
file = projectStoreBaseDir,
file = projectIdentityFile,
project = project,
preloadServices = preloadServices,
template = null,
@@ -176,7 +176,7 @@ class PlatformProjectOpenProcessor : ProjectOpenProcessor(), CommandLineProjectO
}
)
TrustedPaths.getInstance().setProjectPathTrusted(path = baseDir, value = true)
val project = ProjectManagerEx.getInstanceEx().openProjectAsync(projectStoreBaseDir = baseDir, options = copy) ?: return null
val project = ProjectManagerEx.getInstanceEx().openProjectAsync(projectIdentityFile = baseDir, options = copy) ?: return null
openFileFromCommandLine(project = project, file = file, line = copy.line, column = copy.column)
return project
}
@@ -245,7 +245,7 @@ class PlatformProjectOpenProcessor : ProjectOpenProcessor(), CommandLineProjectO
if (Files.isDirectory(file)) {
return ProjectManagerEx.getInstanceEx().openProjectAsync(
projectStoreBaseDir = file,
projectIdentityFile = file,
options = createOptionsToOpenDotIdeaOrCreateNewIfNotExists(file, projectToClose = null),
)
}
@@ -291,7 +291,7 @@ class PlatformProjectOpenProcessor : ProjectOpenProcessor(), CommandLineProjectO
}
val project = ProjectManagerEx.getInstanceEx().openProjectAsync(
projectStoreBaseDir = baseDir,
projectIdentityFile = baseDir,
options = if (baseDir == file) options else options.copy(projectName = file.fileName.toString())
)
if (project != null && file != baseDir) {
@@ -4,6 +4,7 @@ package com.intellij.configurationStore
import com.intellij.openapi.components.service
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread
import com.intellij.util.concurrency.annotations.RequiresBlockingContext
import org.jetbrains.annotations.ApiStatus
import java.nio.file.Path
@@ -14,6 +15,7 @@ import java.nio.file.Path
@ApiStatus.Internal
interface ProjectStorePathManager {
companion object {
@RequiresBlockingContext
fun getInstance(): ProjectStorePathManager = service()
}
@@ -79,7 +79,7 @@ class CreateMavenProjectCommand(text: String, line: Int) : PerformanceCommandCor
TrustedPaths.getInstance().setProjectPathTrusted(projectPath, true)
GeneralSettings.getInstance().confirmOpenNewProject = GeneralSettings.OPEN_PROJECT_SAME_WINDOW
ProjectManagerEx.getInstanceEx().openProjectAsync(projectStoreBaseDir = projectPath, options = options)
ProjectManagerEx.getInstanceEx().openProjectAsync(projectIdentityFile = projectPath, options = options)
context.setProject(newProject)
}
}
@@ -45,7 +45,7 @@ abstract class MavenSetupProjectTestCase : MavenMultiVersionImportingTestCase()
suspend fun openPlatformProjectAsync(projectDirectory: VirtualFile): Project {
return closeOpenedProjectsIfFailAsync {
ProjectManagerEx.getInstanceEx().openProjectAsync(
projectStoreBaseDir = projectDirectory.toNioPath(),
projectIdentityFile = projectDirectory.toNioPath(),
options = OpenProjectTask {
forceOpenInNewFrame = true
useDefaultProjectAsTemplate = false