diff --git a/java/idea-ui/src/com/intellij/ide/impl/NewProjectUtil.kt b/java/idea-ui/src/com/intellij/ide/impl/NewProjectUtil.kt index 13b39227e070..2c1afda88648 100644 --- a/java/idea-ui/src/com/intellij/ide/impl/NewProjectUtil.kt +++ b/java/idea-ui/src/com/intellij/ide/impl/NewProjectUtil.kt @@ -268,7 +268,7 @@ suspend fun createProjectFromWizardImpl(wizard: AbstractProjectWizard, projectFi } serviceAsync().setProjectPathTrusted(projectDir, true) - (serviceAsync() as ProjectManagerEx).openProjectAsync(projectStoreBaseDir = projectDir, options = options) + (serviceAsync() as ProjectManagerEx).openProjectAsync(projectIdentityFile = projectDir, options = options) } if (!ApplicationManager.getApplication().isUnitTestMode) { serviceAsync().scheduleProjectSave(newProject) diff --git a/java/idea-ui/testSrc/com/intellij/ide/projectWizard/SaveProjectAsTemplateTest.kt b/java/idea-ui/testSrc/com/intellij/ide/projectWizard/SaveProjectAsTemplateTest.kt index 64c2a9166749..a9b766b7400b 100644 --- a/java/idea-ui/testSrc/com/intellij/ide/projectWizard/SaveProjectAsTemplateTest.kt +++ b/java/idea-ui/testSrc/com/intellij/ide/projectWizard/SaveProjectAsTemplateTest.kt @@ -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 {})!! } } diff --git a/platform/ide-core-impl/src/com/intellij/openapi/project/ex/ProjectManagerEx.kt b/platform/ide-core-impl/src/com/intellij/openapi/project/ex/ProjectManagerEx.kt index d5f6d0000798..d15a46921ec3 100644 --- a/platform/ide-core-impl/src/com/intellij/openapi/project/ex/ProjectManagerEx.kt +++ b/platform/ide-core-impl/src/com/intellij/openapi/project/ex/ProjectManagerEx.kt @@ -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 diff --git a/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.kt b/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.kt index 0bdc6468dd94..e5406a02d465 100644 --- a/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.kt +++ b/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.kt @@ -227,7 +227,7 @@ object ProjectUtil { val project: Project? if (processors.size == 1 && processors[0] is PlatformProjectOpenProcessor) { project = (serviceAsync() 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 }) diff --git a/platform/platform-impl/src/com/intellij/ide/lightEdit/project/LightEditProjectImpl.kt b/platform/platform-impl/src/com/intellij/ide/lightEdit/project/LightEditProjectImpl.kt index 66274eae8340..facd89866d22 100644 --- a/platform/platform-impl/src/com/intellij/ide/lightEdit/project/LightEditProjectImpl.kt +++ b/platform/platform-impl/src/com/intellij/ide/lightEdit/project/LightEditProjectImpl.kt @@ -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")) diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.kt b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.kt index a1b0b68a4291..9ab3554c95ba 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.kt +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.kt @@ -71,7 +71,7 @@ private val LOG = logger() private val DISPOSE_EARLY_DISPOSABLE_TRACE = Key.create("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 findConstructorAndInstantiateClass(lookup: MethodHandles.Lookup, aClass: Class): 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() } diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.kt b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.kt index 4a1b1f69f32c..89b200edb556 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.kt +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.kt @@ -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 + final override val allExcludedUrls: List 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 = synchronized(lock) { openProjects } + final override fun getOpenProjects(): Array = 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().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().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, diff --git a/platform/platform-impl/src/com/intellij/platform/PlatformProjectOpenProcessor.kt b/platform/platform-impl/src/com/intellij/platform/PlatformProjectOpenProcessor.kt index de2bd4c8b571..ef1606a664ff 100644 --- a/platform/platform-impl/src/com/intellij/platform/PlatformProjectOpenProcessor.kt +++ b/platform/platform-impl/src/com/intellij/platform/PlatformProjectOpenProcessor.kt @@ -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) { diff --git a/platform/projectModel-impl/src/com/intellij/configurationStore/ProjectStorePathManager.kt b/platform/projectModel-impl/src/com/intellij/configurationStore/ProjectStorePathManager.kt index 91a898518848..468615827bb9 100644 --- a/platform/projectModel-impl/src/com/intellij/configurationStore/ProjectStorePathManager.kt +++ b/platform/projectModel-impl/src/com/intellij/configurationStore/ProjectStorePathManager.kt @@ -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() } diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/performancePlugin/CreateMavenProjectCommand.kt b/plugins/maven/src/main/java/org/jetbrains/idea/maven/performancePlugin/CreateMavenProjectCommand.kt index b9e6bd18c85b..01299a872de5 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/performancePlugin/CreateMavenProjectCommand.kt +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/performancePlugin/CreateMavenProjectCommand.kt @@ -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) } } diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/MavenSetupProjectTestCase.kt b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/MavenSetupProjectTestCase.kt index f688f37397cf..cadce6b7aa39 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/MavenSetupProjectTestCase.kt +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/MavenSetupProjectTestCase.kt @@ -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