From 7d46d2e96798808a6c4f75a6d7aba262b1dee8c6 Mon Sep 17 00:00:00 2001 From: Matthew Haughton <3flex@users.noreply.github.com> Date: Wed, 31 Aug 2022 12:50:29 +1000 Subject: [PATCH 1/3] Add jdkHome parameter to CLI --- .../kotlin/io/gitlab/arturbosch/detekt/cli/CliArgs.kt | 7 +++++++ .../main/kotlin/io/gitlab/arturbosch/detekt/cli/Spec.kt | 1 + .../arturbosch/detekt/core/settings/EnvironmentAware.kt | 3 ++- .../io/github/detekt/parser/KotlinEnvironmentUtils.kt | 5 ++++- detekt-tooling/api/detekt-tooling.api | 3 +++ .../io/github/detekt/tooling/api/spec/CompilerSpec.kt | 8 ++++++++ .../io/github/detekt/tooling/dsl/CompilerSpecBuilder.kt | 7 +++++-- 7 files changed, 30 insertions(+), 4 deletions(-) diff --git a/detekt-cli/src/main/kotlin/io/gitlab/arturbosch/detekt/cli/CliArgs.kt b/detekt-cli/src/main/kotlin/io/gitlab/arturbosch/detekt/cli/CliArgs.kt index b223993bf1c..851f0a2ee8e 100644 --- a/detekt-cli/src/main/kotlin/io/gitlab/arturbosch/detekt/cli/CliArgs.kt +++ b/detekt-cli/src/main/kotlin/io/gitlab/arturbosch/detekt/cli/CliArgs.kt @@ -193,6 +193,13 @@ class CliArgs { ) var jvmTarget: String = JvmTarget.DEFAULT.description + @Parameter( + names = ["--jdk-home"], + description = "EXPERIMENTAL: Use a custom JDK home directory to include into the classpath", + converter = PathConverter::class + ) + var jdkHome: Path? = null + @Parameter( names = ["--version"], description = "Prints the detekt CLI version." diff --git a/detekt-cli/src/main/kotlin/io/gitlab/arturbosch/detekt/cli/Spec.kt b/detekt-cli/src/main/kotlin/io/gitlab/arturbosch/detekt/cli/Spec.kt index cc920fdd848..4d5eaa55cef 100644 --- a/detekt-cli/src/main/kotlin/io/gitlab/arturbosch/detekt/cli/Spec.kt +++ b/detekt-cli/src/main/kotlin/io/gitlab/arturbosch/detekt/cli/Spec.kt @@ -68,6 +68,7 @@ internal fun CliArgs.createSpec(output: Appendable, error: Appendable): Processi jvmTarget = args.jvmTarget languageVersion = args.languageVersion?.versionString classpath = args.classpath?.trim() + jdkHome = args.jdkHome } } } diff --git a/detekt-core/src/main/kotlin/io/gitlab/arturbosch/detekt/core/settings/EnvironmentAware.kt b/detekt-core/src/main/kotlin/io/gitlab/arturbosch/detekt/core/settings/EnvironmentAware.kt index 89fa882894c..7f671a9741f 100644 --- a/detekt-core/src/main/kotlin/io/gitlab/arturbosch/detekt/core/settings/EnvironmentAware.kt +++ b/detekt-core/src/main/kotlin/io/gitlab/arturbosch/detekt/core/settings/EnvironmentAware.kt @@ -33,7 +33,8 @@ internal class EnvironmentFacade( projectSpec.inputPaths.toList(), classpath, compilerSpec.parseLanguageVersion(), - compilerSpec.parseJvmTarget() + compilerSpec.parseJvmTarget(), + compilerSpec.jdkHome, ) createKotlinCoreEnvironment(compilerConfiguration, disposable) } diff --git a/detekt-parser/src/main/kotlin/io/github/detekt/parser/KotlinEnvironmentUtils.kt b/detekt-parser/src/main/kotlin/io/github/detekt/parser/KotlinEnvironmentUtils.kt index cbc3d4c94f7..19370df9ae6 100644 --- a/detekt-parser/src/main/kotlin/io/github/detekt/parser/KotlinEnvironmentUtils.kt +++ b/detekt-parser/src/main/kotlin/io/github/detekt/parser/KotlinEnvironmentUtils.kt @@ -67,7 +67,8 @@ fun createCompilerConfiguration( pathsToAnalyze: List, classpath: List, languageVersion: LanguageVersion?, - jvmTarget: JvmTarget + jvmTarget: JvmTarget, + jdkHome: Path?, ): CompilerConfiguration { val javaFiles = pathsToAnalyze.flatMap { path -> path.toFile().walk() @@ -99,6 +100,8 @@ fun createCompilerConfiguration( addJavaSourceRoots(javaFiles) addKotlinSourceRoots(kotlinFiles) addJvmClasspathRoots(classpathFiles) + + jdkHome?.let { put(JVMConfigurationKeys.JDK_HOME, it.toFile()) } configureJdkClasspathRoots() } } diff --git a/detekt-tooling/api/detekt-tooling.api b/detekt-tooling/api/detekt-tooling.api index 4155a325ada..7d89ba6422e 100644 --- a/detekt-tooling/api/detekt-tooling.api +++ b/detekt-tooling/api/detekt-tooling.api @@ -116,6 +116,7 @@ public abstract interface class io/github/detekt/tooling/api/spec/BaselineSpec { public abstract interface class io/github/detekt/tooling/api/spec/CompilerSpec { public abstract fun getClasspath ()Ljava/lang/String; + public abstract fun getJdkHome ()Ljava/nio/file/Path; public abstract fun getJvmTarget ()Ljava/lang/String; public abstract fun getLanguageVersion ()Ljava/lang/String; } @@ -243,9 +244,11 @@ public final class io/github/detekt/tooling/dsl/CompilerSpecBuilder : io/github/ public fun build ()Lio/github/detekt/tooling/api/spec/CompilerSpec; public synthetic fun build ()Ljava/lang/Object; public final fun getClasspath ()Ljava/lang/String; + public final fun getJdkHome ()Ljava/nio/file/Path; public final fun getJvmTarget ()Ljava/lang/String; public final fun getLanguageVersion ()Ljava/lang/String; public final fun setClasspath (Ljava/lang/String;)V + public final fun setJdkHome (Ljava/nio/file/Path;)V public final fun setJvmTarget (Ljava/lang/String;)V public final fun setLanguageVersion (Ljava/lang/String;)V } diff --git a/detekt-tooling/src/main/kotlin/io/github/detekt/tooling/api/spec/CompilerSpec.kt b/detekt-tooling/src/main/kotlin/io/github/detekt/tooling/api/spec/CompilerSpec.kt index e924157ca7b..79c5ad9f343 100644 --- a/detekt-tooling/src/main/kotlin/io/github/detekt/tooling/api/spec/CompilerSpec.kt +++ b/detekt-tooling/src/main/kotlin/io/github/detekt/tooling/api/spec/CompilerSpec.kt @@ -1,5 +1,7 @@ package io.github.detekt.tooling.api.spec +import java.nio.file.Path + /** * All these properties are based down to the Kotlin compiler for type- and symbol resolution. */ @@ -19,4 +21,10 @@ interface CompilerSpec { * Paths to class files and jars separated by a path separator. */ val classpath: String? + + /** + * Path to custom JDK home. Includes the custom JDK from the specified location into the classpath instead of using + * the JRE from the runtime environment. + */ + val jdkHome: Path? } diff --git a/detekt-tooling/src/main/kotlin/io/github/detekt/tooling/dsl/CompilerSpecBuilder.kt b/detekt-tooling/src/main/kotlin/io/github/detekt/tooling/dsl/CompilerSpecBuilder.kt index f2cf162820a..3806b0f5c11 100644 --- a/detekt-tooling/src/main/kotlin/io/github/detekt/tooling/dsl/CompilerSpecBuilder.kt +++ b/detekt-tooling/src/main/kotlin/io/github/detekt/tooling/dsl/CompilerSpecBuilder.kt @@ -1,6 +1,7 @@ package io.github.detekt.tooling.dsl import io.github.detekt.tooling.api.spec.CompilerSpec +import java.nio.file.Path @ProcessingModelDsl class CompilerSpecBuilder : Builder { @@ -8,12 +9,14 @@ class CompilerSpecBuilder : Builder { var jvmTarget: String = "1.8" var languageVersion: String? = null var classpath: String? = null + var jdkHome: Path? = null - override fun build(): CompilerSpec = CompilerModel(jvmTarget, languageVersion, classpath) + override fun build(): CompilerSpec = CompilerModel(jvmTarget, languageVersion, classpath, jdkHome) } private data class CompilerModel( override val jvmTarget: String, override val languageVersion: String?, - override val classpath: String? + override val classpath: String?, + override val jdkHome: Path?, ) : CompilerSpec From 413f446668787bfeb9768dbc42621208eae1c5f9 Mon Sep 17 00:00:00 2001 From: Matthew Haughton <3flex@users.noreply.github.com> Date: Thu, 1 Sep 2022 13:17:39 +1000 Subject: [PATCH 2/3] Add toolchain support to Gradle plugin This aligns to the behaviour of toolchains in the Kotlin Gradle Plugin. KGP will set jvmTarget and jdkHome based on the enabled toolchain, assuming it hasn't been set elsewhere in the build script. --- detekt-gradle-plugin/settings.gradle.kts | 2 ++ .../io/gitlab/arturbosch/detekt/Detekt.kt | 9 ++++++ .../detekt/DetektCreateBaselineTask.kt | 7 ++++ .../arturbosch/detekt/internal/SharedTasks.kt | 32 +++++++++++++++++++ .../arturbosch/detekt/invoke/CliArgument.kt | 6 ++++ 5 files changed, 56 insertions(+) diff --git a/detekt-gradle-plugin/settings.gradle.kts b/detekt-gradle-plugin/settings.gradle.kts index feb401417fd..730717cc790 100644 --- a/detekt-gradle-plugin/settings.gradle.kts +++ b/detekt-gradle-plugin/settings.gradle.kts @@ -2,6 +2,8 @@ pluginManagement { includeBuild("../build-logic") } +includeBuild("..") + dependencyResolutionManagement { versionCatalogs { create("libs") { diff --git a/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/Detekt.kt b/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/Detekt.kt index ff1876a7f01..7a7d29cb0a1 100644 --- a/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/Detekt.kt +++ b/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/Detekt.kt @@ -19,6 +19,7 @@ import io.gitlab.arturbosch.detekt.invoke.DetektInvoker import io.gitlab.arturbosch.detekt.invoke.DisableDefaultRuleSetArgument import io.gitlab.arturbosch.detekt.invoke.FailFastArgument import io.gitlab.arturbosch.detekt.invoke.InputArgument +import io.gitlab.arturbosch.detekt.invoke.JdkHomeArgument import io.gitlab.arturbosch.detekt.invoke.JvmTargetArgument import io.gitlab.arturbosch.detekt.invoke.LanguageVersionArgument import io.gitlab.arturbosch.detekt.invoke.ParallelArgument @@ -26,6 +27,7 @@ import io.gitlab.arturbosch.detekt.invoke.isDryRunEnabled import org.gradle.api.Action import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.Directory +import org.gradle.api.file.DirectoryProperty import org.gradle.api.file.FileTree import org.gradle.api.file.RegularFile import org.gradle.api.file.RegularFileProperty @@ -38,6 +40,7 @@ import org.gradle.api.tasks.Classpath import org.gradle.api.tasks.Console import org.gradle.api.tasks.IgnoreEmptyDirectories import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputDirectory import org.gradle.api.tasks.InputFile import org.gradle.api.tasks.InputFiles import org.gradle.api.tasks.Internal @@ -96,6 +99,11 @@ abstract class Detekt @Inject constructor( get() = jvmTargetProp.get() set(value) = jvmTargetProp.set(value) + @get:InputDirectory + @get:PathSensitive(PathSensitivity.ABSOLUTE) + @get:Optional + abstract val jdkHome: DirectoryProperty + @get:Internal internal abstract val debugProp: Property var debug: Boolean @@ -216,6 +224,7 @@ abstract class Detekt @Inject constructor( ClasspathArgument(classpath), LanguageVersionArgument(languageVersionProp.orNull), JvmTargetArgument(jvmTargetProp.orNull), + JdkHomeArgument(jdkHome), ConfigArgument(config), BaselineArgument(baseline.orNull), DefaultReportArgument(DetektReportType.XML, xmlReportFile.orNull), diff --git a/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/DetektCreateBaselineTask.kt b/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/DetektCreateBaselineTask.kt index 37452d8e0e4..add1f5143c1 100644 --- a/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/DetektCreateBaselineTask.kt +++ b/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/DetektCreateBaselineTask.kt @@ -17,6 +17,7 @@ import io.gitlab.arturbosch.detekt.invoke.InputArgument import io.gitlab.arturbosch.detekt.invoke.JvmTargetArgument import io.gitlab.arturbosch.detekt.invoke.ParallelArgument import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.file.DirectoryProperty import org.gradle.api.file.FileTree import org.gradle.api.file.RegularFileProperty import org.gradle.api.provider.Property @@ -26,6 +27,7 @@ import org.gradle.api.tasks.Classpath import org.gradle.api.tasks.Console import org.gradle.api.tasks.IgnoreEmptyDirectories import org.gradle.api.tasks.Input +import org.gradle.api.tasks.InputDirectory import org.gradle.api.tasks.InputFiles import org.gradle.api.tasks.Internal import org.gradle.api.tasks.Optional @@ -113,6 +115,11 @@ abstract class DetektCreateBaselineTask : SourceTask() { get() = jvmTargetProp.get() set(value) = jvmTargetProp.set(value) + @get:InputDirectory + @get:PathSensitive(PathSensitivity.ABSOLUTE) + @get:Optional + abstract val jdkHome: DirectoryProperty + @get:Internal internal val arguments: Provider> = project.provider { listOf( diff --git a/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/internal/SharedTasks.kt b/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/internal/SharedTasks.kt index c663e448360..5997a817dc9 100644 --- a/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/internal/SharedTasks.kt +++ b/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/internal/SharedTasks.kt @@ -3,8 +3,12 @@ package io.gitlab.arturbosch.detekt.internal import io.gitlab.arturbosch.detekt.Detekt import io.gitlab.arturbosch.detekt.DetektCreateBaselineTask import io.gitlab.arturbosch.detekt.extensions.DetektExtension +import org.gradle.api.JavaVersion import org.gradle.api.Project +import org.gradle.api.plugins.JavaBasePlugin +import org.gradle.api.plugins.JavaPluginExtension import org.gradle.api.tasks.TaskProvider +import org.gradle.jvm.toolchain.JavaToolchainService internal fun Project.registerDetektTask( name: String, @@ -40,6 +44,20 @@ internal fun Project.registerDetektTask( } } + project.plugins.withType(JavaBasePlugin::class.java) { _ -> + val toolchain = project.extensions.getByType(JavaPluginExtension::class.java).toolchain + + // acquire a provider that returns the launcher for the toolchain + val service = project.extensions.getByType(JavaToolchainService::class.java) + val defaultLauncher = service.launcherFor(toolchain) + it.jdkHome.convention(defaultLauncher.map { launcher -> launcher.metadata.installationPath }) + it.jvmTargetProp.convention( + defaultLauncher.map { launcher -> + JavaVersion.toVersion(launcher.metadata.languageVersion.asInt()).toString() + } + ) + } + it.debugProp.convention(provider { extension.debug }) it.parallelProp.convention(provider { extension.parallel }) it.disableDefaultRuleSetsProp.convention(provider { extension.disableDefaultRuleSets }) @@ -59,6 +77,20 @@ internal fun Project.registerCreateBaselineTask( configuration: DetektCreateBaselineTask.() -> Unit ): TaskProvider = tasks.register(name, DetektCreateBaselineTask::class.java) { + project.plugins.withType(JavaBasePlugin::class.java) { _ -> + val toolchain = project.extensions.getByType(JavaPluginExtension::class.java).toolchain + + // acquire a provider that returns the launcher for the toolchain + val service = project.extensions.getByType(JavaToolchainService::class.java) + val defaultLauncher = service.launcherFor(toolchain) + it.jdkHome.convention(defaultLauncher.map { launcher -> launcher.metadata.installationPath }) + it.jvmTargetProp.convention( + defaultLauncher.map { launcher -> + JavaVersion.toVersion(launcher.metadata.languageVersion.asInt()).toString() + } + ) + } + it.config.setFrom(project.provider { extension.config }) it.debug.convention(project.provider { extension.debug }) it.parallel.convention(project.provider { extension.parallel }) diff --git a/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/invoke/CliArgument.kt b/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/invoke/CliArgument.kt index f44401694ae..01768b6f108 100644 --- a/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/invoke/CliArgument.kt +++ b/detekt-gradle-plugin/src/main/kotlin/io/gitlab/arturbosch/detekt/invoke/CliArgument.kt @@ -1,6 +1,7 @@ package io.gitlab.arturbosch.detekt.invoke import io.gitlab.arturbosch.detekt.extensions.DetektReportType +import org.gradle.api.file.DirectoryProperty import org.gradle.api.file.FileCollection import org.gradle.api.file.RegularFile import java.io.File @@ -21,6 +22,7 @@ private const val CREATE_BASELINE_PARAMETER = "--create-baseline" private const val CLASSPATH_PARAMETER = "--classpath" private const val LANGUAGE_VERSION_PARAMETER = "--language-version" private const val JVM_TARGET_PARAMETER = "--jvm-target" +private const val JDK_HOME_PARAMETER = "--jdk-home" private const val BASE_PATH_PARAMETER = "--base-path" internal sealed class CliArgument { @@ -58,6 +60,10 @@ internal data class JvmTargetArgument(val jvmTarget: String?) : CliArgument() { override fun toArgument() = jvmTarget?.let { listOf(JVM_TARGET_PARAMETER, it) }.orEmpty() } +internal data class JdkHomeArgument(val jdkHome: DirectoryProperty) : CliArgument() { + override fun toArgument() = jdkHome.orNull?.let { listOf(JDK_HOME_PARAMETER, it.toString()) }.orEmpty() +} + internal data class BaselineArgument(val baseline: RegularFile?) : CliArgument() { override fun toArgument() = baseline?.let { listOf(BASELINE_PARAMETER, it.asFile.absolutePath) }.orEmpty() } From 83ca75519405508627f7a324dc6133c9796f8134 Mon Sep 17 00:00:00 2001 From: Matthew Haughton <3flex@users.noreply.github.com> Date: Fri, 2 Sep 2022 14:45:44 +1000 Subject: [PATCH 3/3] Fix lint error in test sources --- .../src/test/kotlin/io/gitlab/arturbosch/detekt/cli/Main.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/cli/Main.kt b/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/cli/Main.kt index a1929b88fdb..82315f0b619 100644 --- a/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/cli/Main.kt +++ b/detekt-gradle-plugin/src/test/kotlin/io/gitlab/arturbosch/detekt/cli/Main.kt @@ -1,5 +1,5 @@ @file:JvmName("Main") -@file:Suppress("unused", "UNUSED_PARAMETER") +@file:Suppress("unused", "UNUSED_PARAMETER", "Filename") package io.gitlab.arturbosch.detekt.cli