Skip to content

Commit

Permalink
[Gradle|NPW|Daemon|JVM] new: configure Daemon JVM criteria when creat…
Browse files Browse the repository at this point in the history
…ing project via NPW

closes #2883

Issues: IDEA-358562

GitOrigin-RevId: 6ce214c3a1f108d253a2c0f92ac6ca87fcbd8c0d
  • Loading branch information
vmadalin authored and intellij-monorepo-bot committed Jan 22, 2025
1 parent 88fd647 commit 38270c0
Show file tree
Hide file tree
Showing 20 changed files with 226 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@
import com.intellij.openapi.projectRoots.JavaSdkType;
import com.intellij.openapi.projectRoots.SdkTypeId;
import com.intellij.openapi.projectRoots.impl.DependentSdkType;
import com.intellij.openapi.projectRoots.impl.jdkDownloader.JdkDownloadTask;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
import com.intellij.openapi.roots.ui.configuration.projectRoot.SdkDownloadTask;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.io.FileUtil;
Expand All @@ -53,16 +55,20 @@
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.java.JdkVersionDetector;
import org.jetbrains.plugins.gradle.codeInspection.GradleInspectionBundle;
import org.jetbrains.plugins.gradle.frameworkSupport.BuildScriptDataBuilder;
import org.jetbrains.plugins.gradle.frameworkSupport.buildscript.GradleBuildScriptBuilder;
import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData;
import org.jetbrains.plugins.gradle.service.execution.GradleDaemonJvmCriteria;
import org.jetbrains.plugins.gradle.service.execution.GradleDaemonJvmHelper;
import org.jetbrains.plugins.gradle.service.project.wizard.util.GradleWrapperUtil;
import org.jetbrains.plugins.gradle.settings.DistributionType;
import org.jetbrains.plugins.gradle.settings.GradleDefaultProjectSettings;
import org.jetbrains.plugins.gradle.settings.GradleProjectSettings;
import org.jetbrains.plugins.gradle.settings.GradleSettings;
import org.jetbrains.plugins.gradle.util.GradleConstants;
import org.jetbrains.plugins.gradle.util.GradleJvmCriteriaUtil;
import org.jetbrains.plugins.gradle.util.GradleJvmResolutionUtil;
import org.jetbrains.plugins.gradle.util.GradleJvmValidationUtil;

Expand Down Expand Up @@ -105,6 +111,7 @@ public abstract class AbstractGradleModuleBuilder extends AbstractExternalModule
private Path rootProjectPath;
private boolean myUseKotlinDSL;
private boolean isCreatingNewProject;
private boolean isCreatingDaemonToolchain = false;
private boolean isCreatingEmptyContentRoots = true;
private GradleVersion gradleVersion;
private DistributionType gradleDistributionType;
Expand All @@ -116,6 +123,8 @@ public abstract class AbstractGradleModuleBuilder extends AbstractExternalModule
private VirtualFile buildScriptFile;
private GradleBuildScriptBuilder<?> buildScriptBuilder;

private @Nullable SdkDownloadTask mySdkDownloadTask;

public AbstractGradleModuleBuilder() {
super(GradleConstants.SYSTEM_ID, GradleDefaultProjectSettings.createProjectSettings(""));
}
Expand Down Expand Up @@ -237,18 +246,60 @@ private void finishModuleSetup(@Nullable VirtualFile buildScriptFile, @NotNull P
if (isCreatingWrapper && isCreatingNewLinkedProject() && gradleDistributionType.isWrapped()) {
generateGradleWrapper(project);
}
reloadProject(project);
ExternalProjectsManagerImpl.getInstance(project).runWhenInitialized(() -> {
setUpProjectDaemonJvmCriteria(project, () -> {
reloadProject(project);
});
});
}

private void reloadProject(@NotNull Project project) {
ExternalProjectsManagerImpl.getInstance(project).runWhenInitialized(() -> {
ImportSpecBuilder importSpec = new ImportSpecBuilder(project, GradleConstants.SYSTEM_ID);
if (isCreatingEmptyContentRoots) {
importSpec.createDirectoriesForEmptyContentRoots();
private void setUpProjectDaemonJvmCriteria(@NotNull Project project, @NotNull Runnable callback) {
if (!isCreatingDaemonToolchain) {
LOG.debug("The Gradle Daemon JVM criteria's setting up is skipped");
callback.run();
return;
}
var daemonJvmCriteria = resolveDaemonJvmCriteria();
if (daemonJvmCriteria == null) {
LOG.warn("Unable to obtain current Gradle JDK configuration to set up Daemon JVM criteria");
callback.run();
return;
}
var externalProjectPath = getExternalProjectSettings().getExternalProjectPath();
GradleDaemonJvmHelper.updateProjectDaemonJvmCriteria(project, externalProjectPath, daemonJvmCriteria)
.whenComplete((isSuccess, exception) -> {
if (exception != null || !isSuccess) {
LOG.warn("Unable to update to set up Daemon JVM criteria");
}
callback.run();
});
}

private @Nullable GradleDaemonJvmCriteria resolveDaemonJvmCriteria() {
var jdk = myJdk;
if (jdk != null) {
var homePath = jdk.getHomePath();
if (homePath != null) {
var jdkInfo = JdkVersionDetector.getInstance().detectJdkVersionInfo(homePath);
if (jdkInfo != null) {
return GradleJvmCriteriaUtil.toJvmCriteria(jdkInfo);
}
}
importSpec.callback(new ConfigureGradleModuleCallback(importSpec));
ExternalSystemUtil.refreshProject(PathKt.getSystemIndependentPath(rootProjectPath), importSpec);
});
}
var sdkDownloadTask = mySdkDownloadTask;
if (sdkDownloadTask instanceof JdkDownloadTask jdkDownloadTask) {
return GradleJvmCriteriaUtil.toJvmCriteria(jdkDownloadTask.jdkItem);
}
return null;
}

private void reloadProject(@NotNull Project project) {
ImportSpecBuilder importSpec = new ImportSpecBuilder(project, GradleConstants.SYSTEM_ID);
if (isCreatingEmptyContentRoots) {
importSpec.createDirectoriesForEmptyContentRoots();
}
importSpec.callback(new ConfigureGradleModuleCallback(importSpec));
ExternalSystemUtil.refreshProject(PathKt.getSystemIndependentPath(rootProjectPath), importSpec);
}

private void generateGradleWrapper(@NotNull Project project) {
Expand Down Expand Up @@ -496,6 +547,14 @@ public void setCreatingNewProject(boolean creatingNewProject) {
isCreatingNewProject = creatingNewProject;
}

public boolean isCreatingDaemonToolchain() {
return isCreatingDaemonToolchain;
}

public void setCreatingDaemonToolchain(boolean usingDaemonToolchain) {
isCreatingDaemonToolchain = usingDaemonToolchain;
}

public boolean isCreatingEmptyContentRoots() {
return isCreatingEmptyContentRoots;
}
Expand Down Expand Up @@ -540,6 +599,14 @@ public boolean isCreatingBuildScriptFile() {
return isCreatingBuildScriptFile;
}

public @Nullable SdkDownloadTask getSdkDownloadTask() {
return mySdkDownloadTask;
}

public void setSdkDownloadTask(@Nullable SdkDownloadTask sdkDownloadTask) {
mySdkDownloadTask = sdkDownloadTask;
}

@Override
public void cleanup() {
myJdk = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,11 @@ internal class GradleJavaNewProjectWizard : BuildSystemJavaNewProjectWizard {
withJavaSampleCodeAsset("src/main/java", parent.groupId, parent.generateOnboardingTips)
}

addOrConfigureSettingsScript()
addOrConfigureSettingsScript {
if (parent.isCreatingDaemonToolchain) {
withFoojayPlugin()
}
}
addBuildScript {

addGroup(parent.groupId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import com.intellij.openapi.ui.validation.CHECK_DIRECTORY
import com.intellij.openapi.ui.validation.CHECK_NON_EMPTY
import com.intellij.openapi.ui.validation.WHEN_GRAPH_PROPAGATION_FINISHED
import com.intellij.openapi.util.NlsContexts
import com.intellij.openapi.util.registry.Registry
import com.intellij.ui.dsl.builder.*
import com.intellij.ui.dsl.listCellRenderer.textListCellRenderer
import com.intellij.ui.layout.ValidationInfoBuilder
Expand All @@ -53,6 +54,7 @@ import org.jetbrains.plugins.gradle.frameworkSupport.GradleDsl
import org.jetbrains.plugins.gradle.frameworkSupport.settingsScript.isFoojayPluginSupported
import org.jetbrains.plugins.gradle.jvmcompat.GradleJvmSupportMatrix
import org.jetbrains.plugins.gradle.service.GradleInstallationManager
import org.jetbrains.plugins.gradle.service.execution.GradleDaemonJvmHelper
import org.jetbrains.plugins.gradle.service.project.open.suggestGradleHome
import org.jetbrains.plugins.gradle.service.project.wizard.GradleNewProjectWizardStep.DistributionTypeItem.LOCAL
import org.jetbrains.plugins.gradle.service.project.wizard.GradleNewProjectWizardStep.DistributionTypeItem.WRAPPER
Expand Down Expand Up @@ -483,18 +485,27 @@ abstract class GradleNewProjectWizardStep<ParentStep>(parent: ParentStep) :
return isFoojayPluginSupported(gradleVersionToUse)
}

val isCreatingDaemonToolchain: Boolean by lazy {
Registry.`is`("gradle.daemon.jvm.criteria.new.project") &&
isCreatingNewLinkedProject && isFoojayPluginSupported &&
GradleDaemonJvmHelper.isDaemonJvmCriteriaSupported(gradleVersionToUse)
}

@ApiStatus.Internal
fun setupProjectFromBuilder(project: Project) {
val builder = object : AbstractGradleModuleBuilder() {}

builder.moduleJdk = sdk
builder.sdkDownloadTask = sdkDownloadTask

builder.name = parentStep.name
builder.contentEntryPath = parentStep.path + "/" + parentStep.name

builder.isCreatingWrapper = false
builder.isCreatingBuildScriptFile = false
builder.isCreatingSettingsScriptFile = false
builder.isCreatingEmptyContentRoots = false
builder.isCreatingDaemonToolchain = isCreatingDaemonToolchain
builder.isCreatingNewProject = context.isCreatingNewProject

builder.parentProject = parentData
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,11 @@ class GradleGroovyNewProjectWizard : BuildSystemGroovyNewProjectWizard {
addFilesToOpen(sourcePath)
}

addOrConfigureSettingsScript()
addOrConfigureSettingsScript {
if (parent.isCreatingDaemonToolchain) {
withFoojayPlugin()
}
}
addBuildScript {

addGroup(parent.groupId)
Expand Down
25 changes: 24 additions & 1 deletion plugins/gradle/java/testSources/setup/GradleCreateProjectTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import com.intellij.ide.wizard.NewProjectWizardBaseData.Companion.baseData
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.use
import com.intellij.testFramework.useProjectAsync
import com.intellij.platform.testFramework.assertion.moduleAssertion.ModuleAssertions.assertModules
import com.intellij.testFramework.junit5.RegistryKey
import com.intellij.testFramework.useProjectAsync
import com.intellij.testFramework.withProjectAsync
import com.intellij.workspaceModel.ide.impl.WorkspaceModelCacheImpl
import kotlinx.coroutines.runBlocking
Expand Down Expand Up @@ -143,6 +144,28 @@ class GradleCreateProjectTest : GradleCreateProjectTestCase() {
}
}

@Test
@RegistryKey("gradle.daemon.jvm.criteria.new.project", "true")
fun `test project generation with Gradle daemon JVM criteria`() = runBlocking {
val projectInfo = projectInfo("project") {
withJavaBuildFile()
withSettingsFile {
withFoojayPlugin()
setProjectName("project")
include("module")
}
moduleInfo("project.module", "module") {
withJavaBuildFile()
}
}
createProjectByWizard(projectInfo)
.useProjectAsync { project ->
assertProjectState(project, projectInfo)
assertBuildFiles(projectInfo)
assertDaemonJvmProperties(project)
}
}

@Test
fun `test NPW properties suggestion`() {
runBlocking {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,14 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.jetbrains.plugins.gradle.frameworkSupport.GradleDsl
import org.jetbrains.plugins.gradle.frameworkSupport.buildscript.GradleBuildScriptBuilder
import org.jetbrains.plugins.gradle.properties.GradleDaemonJvmPropertiesFile
import org.jetbrains.plugins.gradle.service.project.wizard.GradleJavaNewProjectWizardData.Companion.javaGradleData
import org.jetbrains.plugins.gradle.testFramework.GradleTestCase
import org.jetbrains.plugins.gradle.testFramework.util.ModuleInfo
import org.jetbrains.plugins.gradle.testFramework.util.ProjectInfo
import org.jetbrains.plugins.gradle.testFramework.util.withBuildFile
import org.jetbrains.plugins.gradle.util.GradleConstants
import org.jetbrains.plugins.gradle.util.toJvmCriteria
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.BeforeEach
import java.nio.file.Path
Expand Down Expand Up @@ -191,6 +193,13 @@ abstract class GradleCreateProjectTestCase : GradleTestCase() {
}
}

fun assertDaemonJvmProperties(project: Project) {
val externalProjectPath = Path.of(project.basePath!!)
val properties = GradleDaemonJvmPropertiesFile.getProperties(externalProjectPath)
Assertions.assertNotNull(properties)
Assertions.assertEquals(gradleJvmInfo.toJvmCriteria(), properties!!.criteria)
}

companion object {

val NEW_EMPTY_PROJECT = UIBundle.message("label.project.wizard.empty.project.generator.name")
Expand Down
2 changes: 2 additions & 0 deletions plugins/gradle/plugin-resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@

<registryKey key="gradle.daemon.jvm.criteria" defaultValue="true"
description="Enable the Gradle Daemon JVM criteria allowing to detect provisioning required toolchain for the build"/>
<registryKey key="gradle.daemon.jvm.criteria.new.project" defaultValue="false"
description="Enable to allow new projects to be created with the Gradle Daemon JVM criteria"/>
<registryKey key="gradle.phased.sync.enabled" defaultValue="true"
description="Enable the phased Gradle sync execution"/>
<registryKey defaultValue="https://download.jetbrains.com/resources/intellij/plugins/gradle/v1/compatibility.json"
Expand Down
1 change: 1 addition & 0 deletions plugins/gradle/resources/messages/GradleBundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ column.name.daemon.timestamp=Timestamp
column.name.daemon.info=Info
gradle.execution.name.build.project.=Build {0}
grable.execution.name.upgrade.wrapper=Upgrade Gradle wrapper
gradle.execution.name.config.daemon.jvm.criteria=Configure Daemon JVM Criteria
gradle.target.configure.label=Gradle configuration
gradle.target.run.label=Run Gradle task
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ package org.jetbrains.plugins.gradle.service.execution
import com.intellij.execution.executors.DefaultRunExecutor
import com.intellij.openapi.externalSystem.model.execution.ExternalSystemTaskExecutionSettings
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId
import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode
import com.intellij.openapi.externalSystem.task.TaskCallback
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil
import com.intellij.openapi.externalSystem.util.task.TaskExecutionSpec
Expand All @@ -20,6 +19,7 @@ import org.jetbrains.annotations.ApiStatus
import org.jetbrains.plugins.gradle.properties.GradleDaemonJvmPropertiesFile
import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings
import org.jetbrains.plugins.gradle.settings.GradleProjectSettings
import org.jetbrains.plugins.gradle.util.GradleBundle
import org.jetbrains.plugins.gradle.util.GradleConstants
import java.nio.file.Path
import java.util.concurrent.CompletableFuture
Expand Down Expand Up @@ -83,11 +83,12 @@ object GradleDaemonJvmHelper {
fun updateProjectDaemonJvmCriteria(
project: Project,
externalProjectPath: String,
daemonJvmCriteria: GradleDaemonJvmCriteria,
daemonJvmCriteria: GradleDaemonJvmCriteria
): CompletableFuture<Boolean> {
val taskSettings = ExternalSystemTaskExecutionSettings().apply {
this.externalProjectPath = externalProjectPath
externalSystemIdString = GradleConstants.SYSTEM_ID.id
executionName = GradleBundle.message("gradle.execution.name.config.daemon.jvm.criteria")
taskNames = buildList {
add(DaemonJvmPropertiesConfigurator.TASK_NAME)
val version = daemonJvmCriteria.version
Expand Down Expand Up @@ -120,8 +121,6 @@ object GradleDaemonJvmHelper {
}

val executionSpec = TaskExecutionSpec.create(project, GradleConstants.SYSTEM_ID, DefaultRunExecutor.EXECUTOR_ID, taskSettings)
.withProgressExecutionMode(ProgressExecutionMode.START_IN_FOREGROUND_ASYNC)
.withActivateToolWindowBeforeRun(true)
.withUserData(taskUserData)
.withCallback(taskCallback)
.build()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import com.intellij.openapi.util.Disposer
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.testFramework.common.runAll
import org.gradle.util.GradleVersion
import org.jetbrains.jps.model.java.JdkVersionDetector.JdkVersionInfo
import org.jetbrains.plugins.gradle.testFramework.fixtures.GradleTestFixture
import org.jetbrains.plugins.gradle.testFramework.fixtures.application.GradleTestApplication
import org.jetbrains.plugins.gradle.testFramework.fixtures.impl.GradleTestFixtureImpl
Expand All @@ -26,6 +27,7 @@ abstract class GradleBaseTestCase {

val testRoot: VirtualFile get() = gradleTestFixture.testRoot
val gradleJvm: String get() = gradleTestFixture.gradleJvm
val gradleJvmInfo: JdkVersionInfo get() = gradleTestFixture.gradleJvmInfo
val gradleVersion: GradleVersion get() = gradleTestFixture.gradleVersion

@BeforeEach
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.testFramework.fixtures.IdeaTestFixture
import org.gradle.util.GradleVersion
import org.jetbrains.jps.model.java.JdkVersionDetector.JdkVersionInfo

interface GradleTestFixture : IdeaTestFixture {

val testRoot: VirtualFile

val gradleJvm: String

val gradleJvmInfo: JdkVersionInfo

val gradleVersion: GradleVersion

suspend fun openProject(relativePath: String, numProjectSyncs: Int = 1): Project
Expand Down
Loading

0 comments on commit 38270c0

Please sign in to comment.