Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add toolchains support to Gradle plugin #5269

Merged
merged 3 commits into from Sep 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -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
)
Comment on lines +196 to +200
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs an update to the CLI page on the website as well

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On this page https://detekt.dev/docs/gettingstarted/cli? Isn't that auto generated now? Or have I misunderstood...

That said, it needs to be added to the Grade docs since they're manually maintained, will do that before merging.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't that auto generated now?

Yes you're right 👍 I forgot we autogenerate that 🚀

var jdkHome: Path? = null

@Parameter(
names = ["--version"],
description = "Prints the detekt CLI version."
Expand Down
Expand Up @@ -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
}
}
}
Expand Down
Expand Up @@ -33,7 +33,8 @@ internal class EnvironmentFacade(
projectSpec.inputPaths.toList(),
classpath,
compilerSpec.parseLanguageVersion(),
compilerSpec.parseJvmTarget()
compilerSpec.parseJvmTarget(),
compilerSpec.jdkHome,
)
createKotlinCoreEnvironment(compilerConfiguration, disposable)
}
Expand Down
2 changes: 2 additions & 0 deletions detekt-gradle-plugin/settings.gradle.kts
Expand Up @@ -2,6 +2,8 @@ pluginManagement {
includeBuild("../build-logic")
}

includeBuild("..")

dependencyResolutionManagement {
versionCatalogs {
create("libs") {
Expand Down
Expand Up @@ -19,13 +19,15 @@ 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
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
Expand All @@ -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
Expand Down Expand Up @@ -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<Boolean>
var debug: Boolean
Expand Down Expand Up @@ -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),
Expand Down
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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<List<String>> = project.provider {
listOf(
Expand Down
Expand Up @@ -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,
Expand Down Expand Up @@ -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 })
Expand All @@ -59,6 +77,20 @@ internal fun Project.registerCreateBaselineTask(
configuration: DetektCreateBaselineTask.() -> Unit
): TaskProvider<DetektCreateBaselineTask> =
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 })
Expand Down
@@ -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
Expand All @@ -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 {
Expand Down Expand Up @@ -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()
}
Expand Down
@@ -1,5 +1,5 @@
@file:JvmName("Main")
@file:Suppress("unused", "UNUSED_PARAMETER")
@file:Suppress("unused", "UNUSED_PARAMETER", "Filename")

package io.gitlab.arturbosch.detekt.cli

Expand Down
Expand Up @@ -67,7 +67,8 @@ fun createCompilerConfiguration(
pathsToAnalyze: List<Path>,
classpath: List<String>,
languageVersion: LanguageVersion?,
jvmTarget: JvmTarget
jvmTarget: JvmTarget,
jdkHome: Path?,
): CompilerConfiguration {
val javaFiles = pathsToAnalyze.flatMap { path ->
path.toFile().walk()
Expand Down Expand Up @@ -99,6 +100,8 @@ fun createCompilerConfiguration(
addJavaSourceRoots(javaFiles)
addKotlinSourceRoots(kotlinFiles)
addJvmClasspathRoots(classpathFiles)

jdkHome?.let { put(JVMConfigurationKeys.JDK_HOME, it.toFile()) }
configureJdkClasspathRoots()
}
}
Expand Down
3 changes: 3 additions & 0 deletions detekt-tooling/api/detekt-tooling.api
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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
}
Expand Down
@@ -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.
*/
Expand All @@ -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?
}
@@ -1,19 +1,22 @@
package io.github.detekt.tooling.dsl

import io.github.detekt.tooling.api.spec.CompilerSpec
import java.nio.file.Path

@ProcessingModelDsl
class CompilerSpecBuilder : Builder<CompilerSpec> {

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