Skip to content

Commit

Permalink
Implement different build issues for Daemon toolchain related exceptions
Browse files Browse the repository at this point in the history
  • Loading branch information
vmadalin committed Dec 5, 2024
1 parent 9ac0461 commit e2bfcdf
Show file tree
Hide file tree
Showing 9 changed files with 340 additions and 0 deletions.
6 changes: 6 additions & 0 deletions plugins/gradle/plugin-resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@
<issueChecker implementation="org.jetbrains.plugins.gradle.issue.GradleDaemonStartupIssueChecker"/>
<issueChecker implementation="org.jetbrains.plugins.gradle.issue.GradleBuildCancelledIssueChecker"/>
<issueChecker implementation="org.jetbrains.plugins.gradle.issue.GradleOutOfMemoryIssueChecker"/>
<issueChecker implementation="org.jetbrains.kotlin.idea.gradleJava.issues.checkers.GradleInvalidDaemonJvmCriteriaIssueChecker"/>
<issueChecker implementation="org.jetbrains.kotlin.idea.gradleJava.issues.checkers.GradleToolchainDownloadedMismatchCriteriaIssueChecker"/>
<issueChecker implementation="org.jetbrains.kotlin.idea.gradleJava.issues.checkers.GradleToolchainDownloadingErrorIssueChecker"/>
<issueChecker implementation="org.jetbrains.kotlin.idea.gradleJava.issues.checkers.GradleToolchainInstalledNotFoundMatchingCriteriaIssueChecker"/>
<issueChecker implementation="org.jetbrains.kotlin.idea.gradleJava.issues.checkers.GradleUndefinedDaemonJvmCriteriaIssueChecker"/>
<issueChecker implementation="org.jetbrains.kotlin.idea.gradleJava.issues.checkers.GradleUndefinedToolchainRepositoriesIssueChecker"/>
<executionHelperExtension implementation="org.jetbrains.plugins.gradle.service.execution.GradleTaskExecutionMeasuringExtension"/>
<executionHelperExtension
implementation="org.jetbrains.plugins.gradle.service.execution.telemetry.GradleTelemetryAgentProvidingExecutionHelperExtension"/>
Expand Down
7 changes: 7 additions & 0 deletions plugins/gradle/resources/messages/GradleBundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,13 @@ gradle.build.issue.gradle.supported.description=The minimum supported Gradle ver
gradle.build.issue.gradle.deprecated.title=Deprecated Gradle Version
gradle.build.issue.gradle.deprecated.description=Gradle {0} support is deprecated and scheduled for removal.

gradle.build.issue.daemon.toolchain.not.found.title=Not Found Toolchain Matching Gradle Daemon JVM Criteria
gradle.build.issue.daemon.toolchain.invalid.criteria.title=Invalid Gradle Daemon JVM Criteria
gradle.build.issue.daemon.toolchain.undefined.criteria.title=Undefined Gradle Daemon JVM Criteria
gradle.build.issue.daemon.toolchain.download.error.title=Unable to Install Toolchain Matching Criteria
gradle.build.issue.daemon.toolchain.downloaded.mismatch.criteria.title=Unexpected Downloaded Toolchain Specs
gradle.build.issue.daemon.toolchain.repositories.undefined.title=Undefined Toolchain Download Repositories

gradle.toolchain.download.error.title=Unable to Download Toolchain
gradle.toolchain.download.error.message.without.vendor=Failed to locate and download a matching toolchain with version: ''{0}''. \
Consider installing it manually or modify Daemon JVM criteria.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.plugins.gradle.issue

import com.intellij.build.issue.BuildIssueQuickFix
import com.intellij.build.issue.ConfigurableBuildIssue
import com.intellij.util.PlatformUtils
import com.intellij.util.lang.JavaVersion
Expand Down Expand Up @@ -29,4 +30,11 @@ abstract class ConfigurableGradleBuildIssue : ConfigurableBuildIssue() {
val hyperlinkReference = addQuickFix(quickFix)
addQuickFixPrompt(GradleBundle.message("gradle.build.quick.fix.gradle.jvm", hyperlinkReference, javaVersion))
}

fun addQuickFixes(quickFixesMap: Map<BuildIssueQuickFix, String>) {
quickFixesMap.forEach { (quickFix, quickFixText) ->
val hyperlinkReference = addQuickFix(quickFix)
addQuickFixPrompt("<a href=\"${hyperlinkReference}\">$quickFixText</a>")
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.gradleJava.issues.checkers

import com.intellij.build.FilePosition
import com.intellij.build.events.BuildEvent
import com.intellij.build.issue.BuildIssue
import org.gradle.internal.buildconfiguration.DaemonJvmPropertiesConfigurator
import org.jetbrains.kotlin.idea.gradleJava.issues.quickfix.GradleOpenDaemonJvmSettingsQuickFix
import org.jetbrains.plugins.gradle.issue.ConfigurableGradleBuildIssue
import org.jetbrains.plugins.gradle.issue.GradleIssueChecker
import org.jetbrains.plugins.gradle.issue.GradleIssueData
import org.jetbrains.plugins.gradle.service.execution.GradleExecutionErrorHandler.getRootCauseAndLocation
import org.jetbrains.plugins.gradle.util.GradleBundle
import java.util.function.Consumer

/**
* An [GradleIssueChecker] handling Daemon JVM criteria exceptions like:
* "Value 'invalid version' given for toolchainVersion is an invalid Java version"
*/
class GradleInvalidDaemonJvmCriteriaIssueChecker : GradleIssueChecker {

override fun check(issueData: GradleIssueData): BuildIssue? {
val rootCause = getRootCauseAndLocation(issueData.error).first
if (rootCause?.toString()?.endsWith("toolchainVersion is an invalid Java version") == true) {
return GradleInvalidDaemonJvmCriteriaBuildIssue(rootCause)
}
return null
}

override fun consumeBuildOutputFailureMessage(
message: String,
failureCause: String,
stacktrace: String?,
location: FilePosition?,
parentEventId: Any,
messageConsumer: Consumer<in BuildEvent>
): Boolean {
return parentEventId == ":${DaemonJvmPropertiesConfigurator.TASK_NAME}"
}
}

private class GradleInvalidDaemonJvmCriteriaBuildIssue(
cause: Throwable
) : ConfigurableGradleBuildIssue() {
init {
setTitle(GradleBundle.message("gradle.build.issue.daemon.toolchain.invalid.criteria.title"))
addDescription(cause.message ?: title)
addQuickFixes(
mapOf(GradleOpenDaemonJvmSettingsQuickFix to GradleBundle.message("gradle.build.quick.fix.modify.gradle.jvm.criteria"))
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.gradleJava.issues.checkers

import com.intellij.build.FilePosition
import com.intellij.build.events.BuildEvent
import com.intellij.build.issue.BuildIssue
import org.gradle.internal.buildconfiguration.DaemonJvmPropertiesConfigurator
import org.jetbrains.kotlin.idea.gradleJava.issues.quickfix.GradleOpenDaemonJvmSettingsQuickFix
import org.jetbrains.kotlin.idea.gradleJava.issues.quickfix.GradleRecreateToolchainDownloadUrlsQuickFix
import org.jetbrains.plugins.gradle.issue.ConfigurableGradleBuildIssue
import org.jetbrains.plugins.gradle.issue.GradleIssueChecker
import org.jetbrains.plugins.gradle.issue.GradleIssueData
import org.jetbrains.plugins.gradle.service.execution.GradleExecutionErrorHandler.getRootCauseAndLocation
import org.jetbrains.plugins.gradle.util.GradleBundle
import java.util.function.Consumer

/**
* An [GradleIssueChecker] handling Daemon JVM criteria exceptions like:
* "Toolchain provisioned from '<URL>' doesn't satisfy the specification: {languageVersion=11, vendor=any, implementation=vendor-specific}"
*/
class GradleToolchainDownloadedMismatchCriteriaIssueChecker : GradleIssueChecker {

override fun check(issueData: GradleIssueData): BuildIssue? {
val rootCause = getRootCauseAndLocation(issueData.error).first
if (rootCause.message?.startsWith("Toolchain provisioned from") == true) {
return GradleToolchainDownloadedMismatchCriteriaBuildIssue(rootCause, issueData.projectPath)
}
return null
}

override fun consumeBuildOutputFailureMessage(
message: String,
failureCause: String,
stacktrace: String?,
location: FilePosition?,
parentEventId: Any,
messageConsumer: Consumer<in BuildEvent>
): Boolean {
return parentEventId == ":${DaemonJvmPropertiesConfigurator.TASK_NAME}"
}
}

private class GradleToolchainDownloadedMismatchCriteriaBuildIssue(
cause: Throwable,
externalProjectPath: String
) : ConfigurableGradleBuildIssue() {
init {
setTitle(GradleBundle.message("gradle.build.issue.daemon.toolchain.downloaded.mismatch.criteria.title"))
addDescription(cause.message ?: title)
addQuickFixes(
mapOf(
GradleRecreateToolchainDownloadUrlsQuickFix(externalProjectPath) to GradleBundle.message("gradle.build.quick.fix.recreate.download.urls"),
GradleOpenDaemonJvmSettingsQuickFix to GradleBundle.message("gradle.build.quick.fix.modify.gradle.jvm.criteria")
)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.gradleJava.issues.checkers

import com.intellij.build.FilePosition
import com.intellij.build.events.BuildEvent
import com.intellij.build.issue.BuildIssue
import org.gradle.internal.buildconfiguration.DaemonJvmPropertiesConfigurator
import org.jetbrains.kotlin.idea.gradleJava.issues.quickfix.GradleDownloadToolchainQuickFix
import org.jetbrains.kotlin.idea.gradleJava.issues.quickfix.GradleOpenDaemonJvmSettingsQuickFix
import org.jetbrains.plugins.gradle.issue.ConfigurableGradleBuildIssue
import org.jetbrains.plugins.gradle.issue.GradleIssueChecker
import org.jetbrains.plugins.gradle.issue.GradleIssueData
import org.jetbrains.plugins.gradle.service.execution.GradleExecutionErrorHandler.getRootCauseAndLocation
import org.jetbrains.plugins.gradle.util.GradleBundle
import java.util.function.Consumer

/**
* An [GradleIssueChecker] handling Daemon JVM criteria exceptions like:
* "Unable to download toolchain matching the requirements ({languageVersion=1.1, vendor=any vendor, implementation=vendor-specific})
* from '<URL>', due to: No defined toolchain download url for MAC_OS on aarch64 architecture."
*/
class GradleToolchainDownloadingErrorIssueChecker : GradleIssueChecker {

override fun check(issueData: GradleIssueData): BuildIssue? {
val rootCause = getRootCauseAndLocation(issueData.error).first
if (rootCause.message?.startsWith("Unable to download toolchain matching the requirements") == true) {
return GradleToolchainDownloadingErrorBuildIssue(rootCause, issueData.projectPath)
}
return null
}

override fun consumeBuildOutputFailureMessage(
message: String,
failureCause: String,
stacktrace: String?,
location: FilePosition?,
parentEventId: Any,
messageConsumer: Consumer<in BuildEvent>
): Boolean {
return parentEventId == ":${DaemonJvmPropertiesConfigurator.TASK_NAME}"
}
}

private class GradleToolchainDownloadingErrorBuildIssue(
cause: Throwable,
externalProjectPath: String
) : ConfigurableGradleBuildIssue() {
init {
setTitle(GradleBundle.message("gradle.build.issue.daemon.toolchain.download.error.title"))
addDescription(cause.message ?: title)
addQuickFixes(
mapOf(
GradleDownloadToolchainQuickFix(externalProjectPath) to GradleBundle.message("gradle.build.quick.fix.install.missing.toolchain"),
GradleOpenDaemonJvmSettingsQuickFix to GradleBundle.message("gradle.build.quick.fix.modify.gradle.jvm.criteria")
)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.gradleJava.issues.checkers

import com.intellij.build.FilePosition
import com.intellij.build.events.BuildEvent
import com.intellij.build.issue.BuildIssue
import org.gradle.internal.buildconfiguration.DaemonJvmPropertiesConfigurator
import org.jetbrains.kotlin.idea.gradleJava.issues.quickfix.GradleDownloadToolchainQuickFix
import org.jetbrains.kotlin.idea.gradleJava.issues.quickfix.GradleOpenDaemonJvmSettingsQuickFix
import org.jetbrains.plugins.gradle.issue.ConfigurableGradleBuildIssue
import org.jetbrains.plugins.gradle.issue.GradleIssueChecker
import org.jetbrains.plugins.gradle.issue.GradleIssueData
import org.jetbrains.plugins.gradle.service.execution.GradleExecutionErrorHandler.getRootCauseAndLocation
import org.jetbrains.plugins.gradle.util.GradleBundle
import java.util.function.Consumer

/**
* An [GradleIssueChecker] handling Daemon JVM criteria exceptions like:
* "Cannot find a Java installation on your machine (Mac OS X 14.7.1 aarch64) matching: Compatible with Java 20,
* vendor matching('dasdsada') (from gradle/gradle-daemon-jvm.properties)."
*/
class GradleToolchainInstalledNotFoundMatchingCriteriaIssueChecker : GradleIssueChecker {

override fun check(issueData: GradleIssueData): BuildIssue? {
val rootCause = getRootCauseAndLocation(issueData.error).first
if (rootCause.message?.startsWith("Cannot find a Java installation on your machine") == true) {
return GradleToolchainInstalledNotFoundMatchingCriteriaBuildIssue(rootCause, issueData.projectPath)
}
return null
}

override fun consumeBuildOutputFailureMessage(
message: String,
failureCause: String,
stacktrace: String?,
location: FilePosition?,
parentEventId: Any,
messageConsumer: Consumer<in BuildEvent>
): Boolean {
return parentEventId == ":${DaemonJvmPropertiesConfigurator.TASK_NAME}"
}
}

private class GradleToolchainInstalledNotFoundMatchingCriteriaBuildIssue(
cause: Throwable,
externalProjectPath: String
) : ConfigurableGradleBuildIssue() {
init {
setTitle(GradleBundle.message("gradle.build.issue.daemon.toolchain.not.found.title"))
addDescription(cause.message ?: title)
addQuickFixes(
mapOf(
GradleDownloadToolchainQuickFix(externalProjectPath) to GradleBundle.message("gradle.build.quick.fix.install.missing.toolchain"),
GradleOpenDaemonJvmSettingsQuickFix to GradleBundle.message("gradle.build.quick.fix.modify.gradle.jvm.criteria")
)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.gradleJava.issues.checkers

import com.intellij.build.issue.BuildIssue
import org.jetbrains.kotlin.idea.gradleJava.issues.quickfix.GradleAddDaemonToolchainCriteriaQuickFix
import org.jetbrains.plugins.gradle.issue.ConfigurableGradleBuildIssue
import org.jetbrains.plugins.gradle.issue.GradleIssueChecker
import org.jetbrains.plugins.gradle.issue.GradleIssueData
import org.jetbrains.plugins.gradle.service.execution.GradleExecutionErrorHandler.getRootCauseAndLocation
import org.jetbrains.plugins.gradle.util.GradleBundle

/**
* An [GradleIssueChecker] handling Daemon JVM criteria exception when isn't defined for the project
*/
class GradleUndefinedDaemonJvmCriteriaIssueChecker : GradleIssueChecker {

override fun check(issueData: GradleIssueData): BuildIssue? {
val rootCause = getRootCauseAndLocation(issueData.error).first
if (false) { // TODO: No known exception since right now is an opt-in feature
return GradleUndefinedDaemonJvmCriteriaBuildIssue(rootCause, issueData.projectPath)
}
return null
}
}

private class GradleUndefinedDaemonJvmCriteriaBuildIssue(
cause: Throwable,
externalProjectPath: String
) : ConfigurableGradleBuildIssue() {
init {
setTitle(GradleBundle.message("gradle.build.issue.daemon.toolchain.undefined.criteria.title"))
addDescription(cause.message ?: title)
addQuickFixes(
mapOf(
GradleAddDaemonToolchainCriteriaQuickFix(externalProjectPath) to GradleBundle.message("gradle.build.quick.fix.add.toolchain.criteria")
)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package org.jetbrains.kotlin.idea.gradleJava.issues.checkers

import com.intellij.build.FilePosition
import com.intellij.build.events.BuildEvent
import com.intellij.build.issue.BuildIssue
import org.gradle.internal.buildconfiguration.DaemonJvmPropertiesConfigurator
import org.jetbrains.kotlin.idea.gradleJava.issues.quickfix.GradleAddDownloadToolchainRepositoryQuickFix
import org.jetbrains.plugins.gradle.issue.ConfigurableGradleBuildIssue
import org.jetbrains.plugins.gradle.issue.GradleIssueChecker
import org.jetbrains.plugins.gradle.issue.GradleIssueData
import org.jetbrains.plugins.gradle.service.execution.GradleExecutionErrorHandler.getRootCauseAndLocation
import org.jetbrains.plugins.gradle.util.GradleBundle
import java.util.function.Consumer

/**
* An [GradleIssueChecker] handling Daemon JVM criteria exceptions like:
* "Cannot find a Java installation on your machine (Mac OS X 14.7.1 aarch64) matching: {languageVersion=99, vendor=any vendor,
* implementation=vendor-specific}. Toolchain download repositories have not been configured."
*/
class GradleUndefinedToolchainRepositoriesIssueChecker : GradleIssueChecker {

override fun check(issueData: GradleIssueData): BuildIssue? {
val rootCause = getRootCauseAndLocation(issueData.error).first
if (rootCause.message?.contains("Toolchain download repositories have not been configured.") == true) {
return GradleUndefinedToolchainRepositoriesBuildIssue(rootCause)
}
return null
}

override fun consumeBuildOutputFailureMessage(
message: String,
failureCause: String,
stacktrace: String?,
location: FilePosition?,
parentEventId: Any,
messageConsumer: Consumer<in BuildEvent>
): Boolean {
return parentEventId == ":${DaemonJvmPropertiesConfigurator.TASK_NAME}"
}
}

private class GradleUndefinedToolchainRepositoriesBuildIssue(
cause: Throwable,
) : ConfigurableGradleBuildIssue() {
init {
setTitle(GradleBundle.message("gradle.build.issue.daemon.toolchain.repositories.undefined.title"))
addDescription(cause.message ?: title)
addQuickFixes(
mapOf(
GradleAddDownloadToolchainRepositoryQuickFix to GradleBundle.message("gradle.build.quick.fix.add.toolchain.repository")
)
)
}
}

0 comments on commit e2bfcdf

Please sign in to comment.