diff --git a/platform/lang-impl/testSources/com/intellij/openapi/roots/ui/configuration/SdkTestCase.kt b/platform/lang-impl/testSources/com/intellij/openapi/roots/ui/configuration/SdkTestCase.kt index e791b8efaa6f..06b26b686a19 100644 --- a/platform/lang-impl/testSources/com/intellij/openapi/roots/ui/configuration/SdkTestCase.kt +++ b/platform/lang-impl/testSources/com/intellij/openapi/roots/ui/configuration/SdkTestCase.kt @@ -28,12 +28,9 @@ abstract class SdkTestCase : LightPlatformTestCase() { super.setUp() TestSdkGenerator.reset() - SdkType.EP_NAME.getPoint(null) - .registerExtension(TestSdkType, testRootDisposable) - SdkType.EP_NAME.getPoint(null) - .registerExtension(DependentTestSdkType, testRootDisposable) - SdkDownload.EP_NAME.getPoint(null) - .registerExtension(TestSdkDownloader, testRootDisposable) + SdkType.EP_NAME.point.registerExtension(TestSdkType, testRootDisposable) + SdkType.EP_NAME.point.registerExtension(DependentTestSdkType, testRootDisposable) + SdkDownload.EP_NAME.point.registerExtension(TestSdkDownloader, testRootDisposable) } fun createAndRegisterSdk(isProjectSdk: Boolean = false): TestSdk { @@ -82,7 +79,7 @@ abstract class SdkTestCase : LightPlatformTestCase() { sdks.forEach(::removeSdk) } - private fun setProjectSdk(sdk: TestSdk) { + private fun setProjectSdk(sdk: Sdk?) { invokeAndWaitIfNeeded { runWriteAction { val rootManager = ProjectRootManager.getInstance(project) @@ -91,6 +88,26 @@ abstract class SdkTestCase : LightPlatformTestCase() { } } + fun withProjectSdk(sdk: TestSdk, action: () -> Unit) { + val projectSdk = projectSdk + setProjectSdk(sdk) + try { + action() + } + finally { + setProjectSdk(projectSdk) + } + } + + fun withRegisteredSdk(sdk: TestSdk, isProjectSdk: Boolean, action: () -> Unit) { + withRegisteredSdks(sdk) { + when (isProjectSdk) { + true -> withProjectSdk(sdk, action) + else -> action() + } + } + } + fun withRegisteredSdks(vararg sdks: TestSdk, action: () -> Unit) { registerSdks(*sdks) try { diff --git a/plugins/gradle/java/src/service/project/wizard/AbstractGradleModuleBuilder.java b/plugins/gradle/java/src/service/project/wizard/AbstractGradleModuleBuilder.java index 6e29172c623a..622c57e0d05c 100644 --- a/plugins/gradle/java/src/service/project/wizard/AbstractGradleModuleBuilder.java +++ b/plugins/gradle/java/src/service/project/wizard/AbstractGradleModuleBuilder.java @@ -242,9 +242,8 @@ public abstract class AbstractGradleModuleBuilder extends AbstractExternalModule } private void setupAndLinkGradleProject(@NotNull Project project) { - Sdk projectSdk = ObjectUtils.chooseNotNull(getModuleJdk(), getNewProjectJdk(myWizardContext)); GradleProjectSettings projectSettings = getExternalProjectSettings(); - setupGradleSettings(projectSettings, rootProjectPath, project, projectSdk); + setupGradleSettings(projectSettings, rootProjectPath, project); getSystemSettings(project).linkProject(projectSettings); GradleJvmValidationUtil.validateJavaHome(project, rootProjectPath, projectSettings.resolveGradleVersion()); } diff --git a/plugins/gradle/java/testSources/importing/GradleCreateProjectTestCase.kt b/plugins/gradle/java/testSources/importing/GradleCreateProjectTestCase.kt index 28ee4f8d79ef..18fbc60274d4 100644 --- a/plugins/gradle/java/testSources/importing/GradleCreateProjectTestCase.kt +++ b/plugins/gradle/java/testSources/importing/GradleCreateProjectTestCase.kt @@ -241,16 +241,7 @@ abstract class GradleCreateProjectTestCase : GradleImportingTestCase() { } } - fun Project.use(save: Boolean = false, action: (Project) -> Unit) { - utilUse(save) { - try { - action(this) - } - finally { - GradleSetupProjectTest.removeGradleJvmSdk(this) - } - } - } + fun Project.use(save: Boolean = false, action: (Project) -> Unit) = utilUse(save, action) companion object { /** diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/open/GradleOpenProjectProvider.kt b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/open/GradleOpenProjectProvider.kt index 27cfaa62609d..b5229d18641e 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/open/GradleOpenProjectProvider.kt +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/open/GradleOpenProjectProvider.kt @@ -17,8 +17,6 @@ import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil import com.intellij.openapi.externalSystem.util.ExternalSystemUtil import com.intellij.openapi.project.Project -import com.intellij.openapi.projectRoots.Sdk -import com.intellij.openapi.roots.ProjectRootManager import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.vfs.VirtualFile @@ -38,9 +36,8 @@ internal class GradleOpenProjectProvider : AbstractOpenProjectProvider() { } override fun linkAndRefreshProject(projectDirectory: String, project: Project) { - val projectSdk = ProjectRootManager.getInstance(project).projectSdk val gradleProjectSettings = GradleProjectSettings() - setupGradleSettings(gradleProjectSettings, projectDirectory, project, projectSdk) + setupGradleSettings(gradleProjectSettings, projectDirectory, project) attachGradleProjectAndRefresh(gradleProjectSettings, project) validateJavaHome(project, projectDirectory, gradleProjectSettings.resolveGradleVersion()) } @@ -68,9 +65,10 @@ internal class GradleOpenProjectProvider : AbstractOpenProjectProvider() { .callback(createFinalImportCallback(project, externalProjectPath))) } - fun setupGradleSettings(settings: GradleProjectSettings, projectDirectory: String, project: Project, projectSdk: Sdk? = null) { + fun setupGradleSettings(settings: GradleProjectSettings, projectDirectory: String, project: Project) { GradleSettings.getInstance(project).setupGradleSettings() - settings.setupGradleProjectSettings(projectDirectory, project, projectSdk) + settings.setupGradleProjectSettings(projectDirectory) + setupGradleJvm(project, settings, projectDirectory) } private fun GradleSettings.setupGradleSettings() { @@ -80,13 +78,12 @@ internal class GradleOpenProjectProvider : AbstractOpenProjectProvider() { storeProjectFilesExternally = true } - private fun GradleProjectSettings.setupGradleProjectSettings(projectDirectory: String, project: Project, projectSdk: Sdk? = null) { + private fun GradleProjectSettings.setupGradleProjectSettings(projectDirectory: String) { externalProjectPath = projectDirectory isUseQualifiedModuleNames = true distributionType = GradleEnvironment.Headless.GRADLE_DISTRIBUTION_TYPE?.let(DistributionType::valueOf) ?: DistributionType.DEFAULT_WRAPPED gradleHome = GradleEnvironment.Headless.GRADLE_HOME ?: suggestGradleHome() - setupGradleJvm(project, projectSdk, this, projectDirectory, resolveGradleVersion()) } private fun suggestGradleHome(): String? { diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/open/GradleProjectImportUtil.kt b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/open/GradleProjectImportUtil.kt index 56d4a68cd154..cd85483b379e 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/open/GradleProjectImportUtil.kt +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/open/GradleProjectImportUtil.kt @@ -5,7 +5,6 @@ package org.jetbrains.plugins.gradle.service.project.open import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil import com.intellij.openapi.externalSystem.util.ExternalSystemBundle import com.intellij.openapi.project.Project -import com.intellij.openapi.projectRoots.Sdk import com.intellij.openapi.ui.Messages import com.intellij.openapi.ui.ValidationInfo import com.intellij.openapi.util.io.FileUtil @@ -45,8 +44,8 @@ fun linkAndRefreshGradleProject(projectFilePath: String, project: Project) { GradleOpenProjectProvider().linkToExistingProject(projectFile, project) } -fun setupGradleSettings(settings: GradleProjectSettings, projectDirectory: String, project: Project, projectSdk: Sdk? = null) = - GradleOpenProjectProvider().setupGradleSettings(settings, projectDirectory, project, projectSdk) +fun setupGradleSettings(settings: GradleProjectSettings, projectDirectory: String, project: Project) = + GradleOpenProjectProvider().setupGradleSettings(settings, projectDirectory, project) private fun validateGradleProject(projectFilePath: String, project: Project): ValidationInfo? { val systemSettings = ExternalSystemApiUtil.getSettings(project, GradleConstants.SYSTEM_ID) diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleJvmResolutionUtil.kt b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleJvmResolutionUtil.kt index ba65901ad8a3..626aba0009a9 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleJvmResolutionUtil.kt +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleJvmResolutionUtil.kt @@ -6,70 +6,65 @@ package org.jetbrains.plugins.gradle.util import com.intellij.openapi.application.runReadAction import com.intellij.openapi.externalSystem.service.execution.ExternalSystemJdkUtil -import com.intellij.openapi.externalSystem.service.execution.nonblockingResolveSdkBySdkName import com.intellij.openapi.project.Project import com.intellij.openapi.projectRoots.ProjectJdkTable import com.intellij.openapi.projectRoots.Sdk import com.intellij.openapi.roots.ProjectRootManager -import com.intellij.openapi.roots.ui.configuration.SdkLookupBuilderEx import com.intellij.openapi.roots.ui.configuration.SdkLookupProvider +import com.intellij.openapi.roots.ui.configuration.SdkLookupProvider.Id import org.gradle.util.GradleVersion import org.jetbrains.annotations.ApiStatus import org.jetbrains.plugins.gradle.settings.GradleProjectSettings import org.jetbrains.plugins.gradle.settings.GradleSettings import org.jetbrains.plugins.gradle.util.JavaHomeValidationStatus.Success -private data class GradleJvmProviderId(val projectSettings: GradleProjectSettings) : SdkLookupProvider.Id +private data class GradleJvmProviderId(val projectSettings: GradleProjectSettings) : Id fun getGradleJvmLookupProvider(project: Project, projectSettings: GradleProjectSettings) = SdkLookupProvider.getInstance(project, GradleJvmProviderId(projectSettings)) -fun setupGradleJvm( - project: Project, - projectSdk: Sdk?, - projectSettings: GradleProjectSettings, - externalProjectPath: String, - gradleVersion: GradleVersion -) { - with(GradleJvmResolutionContext(project, projectSdk, externalProjectPath, gradleVersion)) { - projectSettings.gradleJvm = null +fun setupGradleJvm(project: Project, projectSettings: GradleProjectSettings, externalProjectPath: String) { + setupGradleJvm(project, projectSettings, externalProjectPath, projectSettings.resolveGradleVersion()) +} + +fun setupGradleJvm(project: Project, projectSettings: GradleProjectSettings, externalProjectPath: String, gradleVersion: GradleVersion) { + with(GradleJvmResolutionContext(project, externalProjectPath, gradleVersion)) { + projectSettings.gradleJvm = findGradleJvm() + if (projectSettings.gradleJvm != null) return when { + canUseProjectSdk() -> projectSettings.gradleJvm = ExternalSystemJdkUtil.USE_PROJECT_JDK canUseGradleJavaHomeJdk() -> projectSettings.gradleJvm = USE_GRADLE_JAVA_HOME canUseJavaHomeJdk() -> projectSettings.gradleJvm = ExternalSystemJdkUtil.USE_JAVA_HOME - else -> SdkLookupBuilderEx { - getGradleJvmLookupProvider(project, projectSettings) - .newLookupBuilder() - .testSuggestedSdksFirst(getGradleJdks()) - .testSuggestedSdkFirst(ExternalSystemJdkUtil.USE_PROJECT_JDK) { getProjectJdk() } - .withVersionFilter { isSupported(gradleVersion, it) } - .withSdkType(ExternalSystemJdkUtil.getJavaSdkType()) - .withSdkHomeFilter { ExternalSystemJdkUtil.isValidJdk(it) } - .onSdkNameResolved { id, sdk -> - /* We have two types of sdk resolving: - * 1. Download sdk manually - * a. by download action from SdkComboBox - * b. by sdk downloader - * c. by action that detects incorrect project sdk - * 2. Lookup sdk (search in fs, download and etc) - * a. search in fs, search in sdk table and etc - * b. download - * - * All download actions generates fake (invalid) sdk and puts it to jdk table. - * This code allows to avoid some irregular conflicts - * For example: strange duplications in SdkComboBox or unexpected modifications of gradleJvm - */ - val fakeSdk = sdk?.let(::findRegisteredSdk) - if (fakeSdk != null && projectSettings.gradleJvm == null) { - projectSettings.gradleJvm = id ?: fakeSdk.name - } + else -> getGradleJvmLookupProvider(project, projectSettings) + .newLookupBuilder() + .withVersionFilter { isSupported(gradleVersion, it) } + .withSdkType(ExternalSystemJdkUtil.getJavaSdkType()) + .withSdkHomeFilter { ExternalSystemJdkUtil.isValidJdk(it) } + .onSdkNameResolved { sdk -> + /* We have two types of sdk resolving: + * 1. Download sdk manually + * a. by download action from SdkComboBox + * b. by sdk downloader + * c. by action that detects incorrect project sdk + * 2. Lookup sdk (search in fs, download and etc) + * a. search in fs, search in sdk table and etc + * b. download + * + * All download actions generates fake (invalid) sdk and puts it to jdk table. + * This code allows to avoid some irregular conflicts + * For example: strange duplications in SdkComboBox or unexpected modifications of gradleJvm + */ + val fakeSdk = sdk?.let(::findRegisteredSdk) + if (fakeSdk != null && projectSettings.gradleJvm == null) { + projectSettings.gradleJvm = fakeSdk.name } - .onSdkResolved { id, sdk -> - if (projectSettings.gradleJvm == null) { - projectSettings.gradleJvm = id ?: sdk?.name - } + } + .onSdkResolved { sdk -> + if (projectSettings.gradleJvm == null) { + projectSettings.gradleJvm = sdk?.name } - .executeLookup() - } + } + .executeLookup() } } } @@ -79,27 +74,19 @@ fun updateGradleJvm(project: Project, externalProjectPath: String) { val projectSettings = settings.getLinkedProjectSettings(externalProjectPath) ?: return val gradleJvm = projectSettings.gradleJvm ?: return val gradleVersion = projectSettings.resolveGradleVersion() - with(GradleJvmResolutionContext(project, null, externalProjectPath, gradleVersion)) { + with(GradleJvmResolutionContext(project, externalProjectPath, gradleVersion)) { val projectSdk = projectSdk ?: return if (projectSdk.name != gradleJvm) return - if (!isValidAndSupported(projectSdk)) return projectSettings.gradleJvm = ExternalSystemJdkUtil.USE_PROJECT_JDK } } private class GradleJvmResolutionContext( val project: Project, - projectSdk: Sdk?, val externalProjectPath: String, val gradleVersion: GradleVersion ) { - val projectSdk: Sdk? by lazy { projectSdk ?: ProjectRootManager.getInstance(project).projectSdk } -} - -private fun GradleJvmResolutionContext.isValidAndSupported(sdk: Sdk): Boolean { - if (!ExternalSystemJdkUtil.isValidJdk(sdk)) return false - val versionString = sdk.versionString ?: return false - return isSupported(gradleVersion, versionString) + val projectSdk: Sdk? by lazy { ProjectRootManager.getInstance(project).projectSdk } } private fun GradleJvmResolutionContext.canUseGradleJavaHomeJdk(): Boolean { @@ -115,20 +102,17 @@ private fun GradleJvmResolutionContext.canUseJavaHomeJdk(): Boolean { return validationStatus is Success } -private fun GradleJvmResolutionContext.getGradleJdks(): Sequence = sequence { +private fun GradleJvmResolutionContext.findGradleJvm(): String? { val settings = GradleSettings.getInstance(project) - for (projectSettings in settings.linkedProjectsSettings) { - val provider = getGradleJvmLookupProvider(project, projectSettings) - val gradleJvm = projectSettings.gradleJvm - yield(provider.nonblockingResolveSdkBySdkName(gradleJvm)) - } + return settings.linkedProjectsSettings.asSequence() + .mapNotNull { it.gradleJvm } + .firstOrNull() } -private fun GradleJvmResolutionContext.getProjectJdk(): Sdk? { - val projectSdk = projectSdk ?: return null +private fun GradleJvmResolutionContext.canUseProjectSdk(): Boolean { + val projectSdk = projectSdk ?: return false val resolvedProjectSdk = ExternalSystemJdkUtil.resolveDependentJdk(projectSdk) - if (!isValidAndSupported(resolvedProjectSdk)) return null - return resolvedProjectSdk + return ExternalSystemJdkUtil.isValidJdk(resolvedProjectSdk) } private fun findRegisteredSdk(sdk: Sdk): Sdk? = runReadAction { diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/util/GradleJdkResolutionTest.kt b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/util/GradleJdkResolutionTest.kt index b69828f728cc..bb676f19bcbc 100644 --- a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/util/GradleJdkResolutionTest.kt +++ b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/util/GradleJdkResolutionTest.kt @@ -17,7 +17,9 @@ class GradleJdkResolutionTest : GradleJdkResolutionTestCase() { assertGradleJvmSuggestion(expected = earliestSdk) } } - assertGradleJvmSuggestion(expected = USE_PROJECT_JDK, projectSdk = latestSdk) + withRegisteredSdk(latestSdk, isProjectSdk = true) { + assertGradleJvmSuggestion(expected = USE_PROJECT_JDK) + } environment.withVariables(JAVA_HOME to latestSdk.homePath) { assertGradleJvmSuggestion(expected = USE_JAVA_HOME) } @@ -45,15 +47,21 @@ class GradleJdkResolutionTest : GradleJdkResolutionTestCase() { assertGradleJvmSuggestion(expected = latestSdk) } withGradleLinkedProject(java = unsupportedSdk) { - assertGradleJvmSuggestion(expected = latestSdk) + assertGradleJvmSuggestion(expected = unsupportedSdk) } } @Test fun `test gradle jvm resolution (project sdk)`() { - assertGradleJvmSuggestion(expected = USE_PROJECT_JDK, projectSdk = earliestSdk) - assertGradleJvmSuggestion(expected = USE_PROJECT_JDK, projectSdk = latestSdk) - assertGradleJvmSuggestion(expected = latestSdk, projectSdk = unsupportedSdk, expectsSdkRegistration = true) + withRegisteredSdk(earliestSdk, isProjectSdk = true) { + assertGradleJvmSuggestion(expected = USE_PROJECT_JDK) + } + withRegisteredSdk(latestSdk, isProjectSdk = true) { + assertGradleJvmSuggestion(expected = USE_PROJECT_JDK) + } + withRegisteredSdk(unsupportedSdk, isProjectSdk = true) { + assertGradleJvmSuggestion(expected = USE_PROJECT_JDK) + } } @Test diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/util/GradleJdkResolutionTestCase.kt b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/util/GradleJdkResolutionTestCase.kt index 77fc55c03ab2..5d738bdc696d 100644 --- a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/util/GradleJdkResolutionTestCase.kt +++ b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/util/GradleJdkResolutionTestCase.kt @@ -46,29 +46,29 @@ abstract class GradleJdkResolutionTestCase : ExternalSystemJdkUtilTestCase() { environment.variables(GradleConstants.SYSTEM_DIRECTORY_PATH_KEY to null) } - fun assertGradleJvmSuggestion(expected: TestSdk, projectSdk: TestSdk? = null, expectsSdkRegistration: Boolean = false) { - assertGradleJvmSuggestion({ expected }, projectSdk, expectsSdkRegistration) + fun assertGradleJvmSuggestion(expected: TestSdk, expectsSdkRegistration: Boolean = false) { + assertGradleJvmSuggestion({ expected }, expectsSdkRegistration) } - fun assertGradleJvmSuggestion(expected: () -> TestSdk, projectSdk: TestSdk? = null, expectsSdkRegistration: Boolean = false) { + fun assertGradleJvmSuggestion(expected: () -> TestSdk, expectsSdkRegistration: Boolean = false) { assertNewlyRegisteredSdks({ if (expectsSdkRegistration) expected() else null }) { - val gradleJvm = suggestGradleJvm(project, projectSdk, externalProjectPath, gradleVersion) + val gradleJvm = suggestGradleJvm(project, externalProjectPath, gradleVersion) val gradleJdk = SdkLookupProviderImpl().nonblockingResolveSdkBySdkName(gradleJvm) requireNotNull(gradleJdk) { "expected: ${expected()}" } assertSdk(expected(), gradleJdk) } } - fun assertGradleJvmSuggestion(expected: String, projectSdk: TestSdk? = null) { + fun assertGradleJvmSuggestion(expected: String) { assertUnexpectedSdksRegistration { - val gradleJvm = suggestGradleJvm(project, projectSdk, externalProjectPath, gradleVersion) + val gradleJvm = suggestGradleJvm(project, externalProjectPath, gradleVersion) assertEquals(expected, gradleJvm) } } - private fun suggestGradleJvm(project: Project, projectSdk: Sdk?, externalProjectPath: String, gradleVersion: GradleVersion): String? { + private fun suggestGradleJvm(project: Project, externalProjectPath: String, gradleVersion: GradleVersion): String? { val projectSettings = GradleProjectSettings() - setupGradleJvm(project, projectSdk, projectSettings, externalProjectPath, gradleVersion) + setupGradleJvm(project, projectSettings, externalProjectPath, gradleVersion) val provider = getGradleJvmLookupProvider(project, projectSettings) provider.waitForLookup() return projectSettings.gradleJvm