diff --git a/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/codegen/ApolloCodegenService.kt b/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/codegen/ApolloCodegenService.kt index 848f08acfe7..c481f946c74 100644 --- a/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/codegen/ApolloCodegenService.kt +++ b/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/codegen/ApolloCodegenService.kt @@ -4,6 +4,7 @@ import com.apollographql.ijplugin.gradle.CODEGEN_GRADLE_TASK_NAME import com.apollographql.ijplugin.gradle.GradleHasSyncedListener import com.apollographql.ijplugin.gradle.SimpleProgressListener import com.apollographql.ijplugin.gradle.getGradleRootPath +import com.apollographql.ijplugin.gradle.runGradleBuild import com.apollographql.ijplugin.project.ApolloProjectListener import com.apollographql.ijplugin.project.ApolloProjectService import com.apollographql.ijplugin.project.apolloProjectService @@ -24,7 +25,6 @@ import com.intellij.openapi.editor.Document import com.intellij.openapi.editor.EditorFactory import com.intellij.openapi.editor.event.DocumentEvent import com.intellij.openapi.editor.event.DocumentListener -import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil import com.intellij.openapi.fileEditor.FileDocumentManager import com.intellij.openapi.fileEditor.FileEditorManagerEvent import com.intellij.openapi.fileEditor.FileEditorManagerListener @@ -37,10 +37,6 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import org.gradle.tooling.CancellationTokenSource import org.gradle.tooling.GradleConnector -import org.jetbrains.plugins.gradle.service.execution.GradleExecutionHelper -import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings -import org.jetbrains.plugins.gradle.util.GradleConstants -import java.io.File @Service(Service.Level.PROJECT) class ApolloCodegenService( @@ -180,19 +176,18 @@ class ApolloCodegenService( } val modules = ModuleManager.getInstance(project).modules - val rootProjectPath = project.getGradleRootPath() ?: return coroutineScope.launch { - val executionSettings = - ExternalSystemApiUtil.getExecutionSettings(project, rootProjectPath, GradleConstants.SYSTEM_ID) - val gradleExecutionHelper = GradleExecutionHelper() - gradleExecutionHelper.execute(rootProjectPath, executionSettings) { connection -> - gradleCodegenCancellation = GradleConnector.newCancellationTokenSource() - logd("Start Gradle") - try { - val cancellationToken = gradleCodegenCancellation!!.token() - connection.newBuild() - .setJavaHome(executionSettings.javaHome?.let { File(it) }) - .forTasks(CODEGEN_GRADLE_TASK_NAME) + gradleCodegenCancellation = GradleConnector.newCancellationTokenSource() + logd("Start Gradle") + try { + val cancellationToken = gradleCodegenCancellation!!.token() + val gradleProjectPath = project.getGradleRootPath() + if (gradleProjectPath == null) { + logw("Could not get Gradle root project path") + return@launch + } + runGradleBuild(project, gradleProjectPath) { + it.forTasks(CODEGEN_GRADLE_TASK_NAME) .withCancellationToken(cancellationToken) .addArguments("--continuous") .let { @@ -211,13 +206,12 @@ class ApolloCodegenService( VfsUtil.markDirtyAndRefresh(true, true, true, *generatedSourceRoots.toTypedArray()) } }) - .run() - logd("Gradle execution finished") - } catch (t: Throwable) { - logd(t, "Gradle execution failed") - } finally { - gradleCodegenCancellation = null } + logd("Gradle execution finished") + } catch (t: Throwable) { + logd(t, "Gradle execution failed") + } finally { + gradleCodegenCancellation = null } } } diff --git a/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/gradle/DownloadSchemaAction.kt b/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/gradle/DownloadSchemaAction.kt index 7cb6705b5ea..e4fe6eb46e1 100644 --- a/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/gradle/DownloadSchemaAction.kt +++ b/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/gradle/DownloadSchemaAction.kt @@ -13,16 +13,11 @@ import com.intellij.notification.NotificationType import com.intellij.openapi.actionSystem.ActionUpdateThread import com.intellij.openapi.actionSystem.AnAction import com.intellij.openapi.actionSystem.AnActionEvent -import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil import com.intellij.openapi.progress.ProgressIndicator import com.intellij.openapi.progress.Task import com.intellij.openapi.project.Project import org.gradle.tooling.Failure import org.gradle.tooling.model.GradleProject -import org.jetbrains.plugins.gradle.service.execution.GradleExecutionHelper -import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings -import org.jetbrains.plugins.gradle.util.GradleConstants -import java.io.File class DownloadSchemaAction : AnAction() { override fun actionPerformed(e: AnActionEvent) { @@ -49,20 +44,13 @@ private class DownloadSchemaTask(project: Project) : Task.Backgroundable( false, ) { override fun run(indicator: ProgressIndicator) { - val rootProjectPath = project.getGradleRootPath() ?: return - val gradleExecutionHelper = GradleExecutionHelper() - val executionSettings = - ExternalSystemApiUtil.getExecutionSettings(project, rootProjectPath, GradleConstants.SYSTEM_ID) - val rootGradleProject = gradleExecutionHelper.execute(rootProjectPath, executionSettings) { connection -> - logd("Fetch Gradle project model") - return@execute try { - connection.model(GradleProject::class.java) - .setJavaHome(executionSettings.javaHome?.let { File(it) }) - .get() - } catch (t: Throwable) { - logw(t, "Couldn't fetch Gradle project model") - null - } + val gradleProjectPath = project.getGradleRootPath() ?: return + + val rootGradleProject: GradleProject = try { + getGradleModel(project, gradleProjectPath) { it } + } catch (t: Throwable) { + logw(t, "Couldn't fetch Gradle project model") + null } ?: return val allDownloadSchemaTasks: List = rootGradleProject.allChildrenRecursively() @@ -83,11 +71,9 @@ private class DownloadSchemaTask(project: Project) : Task.Backgroundable( return } - gradleExecutionHelper.execute(rootProjectPath, executionSettings) { connection -> - try { - connection.newBuild() - .setJavaHome(executionSettings.javaHome?.let { File(it) }) - .forTasks(*allDownloadSchemaTasks.toTypedArray()) + try { + runGradleBuild(project, gradleProjectPath) { + it.forTasks(*allDownloadSchemaTasks.toTypedArray()) .addProgressListener(object : SimpleProgressListener() { override fun onFailure(failures: List) { super.onFailure(failures) @@ -112,11 +98,10 @@ private class DownloadSchemaTask(project: Project) : Task.Backgroundable( ) } }) - .run() - logd("Gradle execution finished") - } catch (t: Throwable) { - logd(t, "Gradle execution failed") } + logd("Gradle execution finished") + } catch (t: Throwable) { + logd(t, "Gradle execution failed") } } } diff --git a/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/gradle/GradleToolingModelService.kt b/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/gradle/GradleToolingModelService.kt index f8e22e63c93..d525cf97522 100644 --- a/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/gradle/GradleToolingModelService.kt +++ b/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/gradle/GradleToolingModelService.kt @@ -16,7 +16,6 @@ import com.apollographql.ijplugin.util.newDisposable import com.intellij.openapi.Disposable import com.intellij.openapi.components.Service import com.intellij.openapi.components.service -import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil import com.intellij.openapi.progress.ProcessCanceledException import com.intellij.openapi.progress.ProgressManager import com.intellij.openapi.project.Project @@ -29,9 +28,6 @@ import kotlinx.coroutines.launch import org.gradle.tooling.CancellationTokenSource import org.gradle.tooling.GradleConnector import org.gradle.tooling.model.GradleProject -import org.jetbrains.plugins.gradle.service.execution.GradleExecutionHelper -import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings -import org.jetbrains.plugins.gradle.util.GradleConstants import java.io.File @Service(Service.Level.PROJECT) @@ -160,24 +156,22 @@ class GradleToolingModelService( private fun doRun() { logd() - val rootProjectPath = project.getGradleRootPath() ?: return - val gradleExecutionHelper = GradleExecutionHelper() - val executionSettings = - ExternalSystemApiUtil.getExecutionSettings(project, rootProjectPath, GradleConstants.SYSTEM_ID) - val rootGradleProject = gradleExecutionHelper.execute(rootProjectPath, executionSettings) { connection -> - gradleCancellation = GradleConnector.newCancellationTokenSource() - logd("Fetch Gradle project model") - return@execute try { - connection.model(GradleProject::class.java) - .setJavaHome(executionSettings.javaHome?.let { File(it) }) - .withCancellationToken(gradleCancellation!!.token()) - .get() - } catch (t: Throwable) { - logw(t, "Couldn't fetch Gradle project model") - null - } finally { - gradleCancellation = null + gradleCancellation = GradleConnector.newCancellationTokenSource() + logd("Fetch Gradle project model") + val gradleProjectPath = project.getGradleRootPath() + if (gradleProjectPath == null) { + logw("Could not get Gradle root project path") + return + } + val rootGradleProject: GradleProject = try { + getGradleModel(project, gradleProjectPath) { + it.withCancellationToken(gradleCancellation!!.token()) } + } catch (t: Throwable) { + logw(t, "Couldn't fetch Gradle project model") + null + } finally { + gradleCancellation = null } ?: return project.telemetryService.gradleModuleCount = rootGradleProject.children.size + 1 @@ -189,27 +183,25 @@ class GradleToolingModelService( val allToolingModels = allApolloGradleProjects.mapIndexedNotNull { index, gradleProject -> if (isAbortRequested()) return@doRun - gradleExecutionHelper.execute(gradleProject.projectDirectory.canonicalPath, executionSettings) { connection -> - gradleCancellation = GradleConnector.newCancellationTokenSource() - logd("Fetch tooling model for ${gradleProject.path}") - return@execute try { - connection.model(ApolloGradleToolingModel::class.java) - .setJavaHome(executionSettings.javaHome?.let { File(it) }) - .withCancellationToken(gradleCancellation!!.token()) - .get() - .takeIf { - val isCompatibleVersion = it.versionMajor == ApolloGradleToolingModel.VERSION_MAJOR - if (!isCompatibleVersion) { - logw("Incompatible version of Apollo Gradle plugin in module ${gradleProject.path}: ${it.versionMajor} != ${ApolloGradleToolingModel.VERSION_MAJOR}, ignoring") - } - isCompatibleVersion - } - } catch (t: Throwable) { - logw(t, "Couldn't fetch tooling model for ${gradleProject.path}") - null - } finally { - gradleCancellation = null + + gradleCancellation = GradleConnector.newCancellationTokenSource() + logd("Fetch tooling model for ${gradleProject.path}") + try { + getGradleModel(project, gradleProject.projectDirectory.canonicalPath ) { + it.withCancellationToken(gradleCancellation!!.token()) } + ?.takeIf { + val isCompatibleVersion = it.versionMajor == ApolloGradleToolingModel.VERSION_MAJOR + if (!isCompatibleVersion) { + logw("Incompatible version of Apollo Gradle plugin in module ${gradleProject.path}: ${it.versionMajor} != ${ApolloGradleToolingModel.VERSION_MAJOR}, ignoring") + } + isCompatibleVersion + } + } catch (t: Throwable) { + logw(t, "Couldn't fetch tooling model for ${gradleProject.path}") + null + } finally { + gradleCancellation = null } } @@ -226,7 +218,7 @@ class GradleToolingModelService( } try { ProgressManager.checkCanceled() - } catch (e: ProcessCanceledException) { + } catch (@Suppress("IncorrectCancellationExceptionHandling") _: ProcessCanceledException) { logd("Canceled by user") return true } diff --git a/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/gradle/GradleUtil.kt b/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/gradle/GradleUtil.kt index abbc8645d58..3438bb2e22e 100644 --- a/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/gradle/GradleUtil.kt +++ b/intellij-plugin/src/main/kotlin/com/apollographql/ijplugin/gradle/GradleUtil.kt @@ -4,7 +4,13 @@ import com.apollographql.ijplugin.util.logw import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil import com.intellij.openapi.module.ModuleManager import com.intellij.openapi.project.Project +import org.gradle.tooling.BuildLauncher +import org.gradle.tooling.GradleConnector +import org.gradle.tooling.ModelBuilder import org.gradle.tooling.model.GradleProject +import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings +import org.jetbrains.plugins.gradle.util.GradleConstants +import java.io.File const val CODEGEN_GRADLE_TASK_NAME = "generateApolloSources" @@ -19,3 +25,51 @@ fun Project.getGradleRootPath(): String? { fun GradleProject.allChildrenRecursively(): List { return listOf(this) + children.flatMap { it.allChildrenRecursively() } } + +fun runGradleBuild( + project: Project, + gradleProjectPath: String, + configureBuildLauncher: (BuildLauncher) -> BuildLauncher, +) { + val executionSettings = ExternalSystemApiUtil.getExecutionSettings( + project, + gradleProjectPath, + GradleConstants.SYSTEM_ID + ) + val connection = GradleConnector.newConnector() + .forProjectDirectory(File(gradleProjectPath)) + .connect() + val buildLauncher = configureBuildLauncher( + connection.newBuild() + .setJavaHome(executionSettings.javaHome?.let { File(it) }) + ) + try { + buildLauncher.run() + } finally { + connection.close() + } +} + +inline fun getGradleModel( + project: Project, + gradleProjectPath: String, + configureModelBuilder: (ModelBuilder) -> ModelBuilder, +): T? { + val executionSettings = ExternalSystemApiUtil.getExecutionSettings( + project, + gradleProjectPath, + GradleConstants.SYSTEM_ID + ) + val connection = GradleConnector.newConnector() + .forProjectDirectory(File(gradleProjectPath)) + .connect() + val modelBuilder = configureModelBuilder( + connection.model(T::class.java) + .setJavaHome(executionSettings.javaHome?.let { File(it) }) + ) + try { + return modelBuilder.get() + } finally { + connection.close() + } +}