Skip to content

Commit

Permalink
fix detection of android kotlin source directories in AGP >= 7
Browse files Browse the repository at this point in the history
increase maximum gradle version to 8.5
increase maximum ktlint version to 1.1.0
increase maximum kotlin version to 1.9.21
fix lint failures

fixes #702
based on work in #703

fix bashisms by manually specifying correct version of libdistro-info-perl
  • Loading branch information
wakingrufus authored and JLLeitschuh committed Jan 9, 2024
1 parent a826dcd commit 977af89
Show file tree
Hide file tree
Showing 24 changed files with 309 additions and 68 deletions.
1 change: 1 addition & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ indent_size = 4
ij_kotlin_packages_to_use_import_on_demand = unset
ij_kotlin_name_count_to_use_star_import = 999
ij_kotlin_name_count_to_use_star_import_for_members = 999
ktlint_code_style=intellij_idea

[*.{yml,yaml}]
indent_size = 2
4 changes: 4 additions & 0 deletions .github/workflows/build-and-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,12 @@ jobs:
with:
java-version: 11
distribution: 'zulu'
- name: update apt
run: sudo apt update
- name: Install lintian
run: sudo apt install -qq lintian=2.114.0ubuntu1.3
- name: Install libdistro
run: sudo apt install -qq libdistro-info-perl
- name: Install checkbashisms
run: sudo apt-get install -qq devscripts
- name: Restore Gradle caches
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/).

## [Unreleased]

- fix detection of android kotlin source directories in AGP >= 7 [#733](https://github.com/JLLeitschuh/ktlint-gradle/pull/733)

## [12.0.3] - 2023-12-11

- fix: apply configuration for source sets and targets that are added after the plugin is
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ Minimal supported [Kotlin](https://kotlinlang.org) version: `1.4`

Minimal supported [ktlint](https://github.com/pinterest/ktlint) version: `0.47.1`

Minimal supported [Android Gradle plugin](https://developer.android.com/build) version: `4.1.0`

### Ktlint plugin

#### Simple setup
Expand Down
18 changes: 18 additions & 0 deletions plugin/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
root = true

[*]
charset = utf-8
insert_final_newline = true
trim_trailing_whitespace = true

[*.{kt,kts}]
indent_size = 4
ij_kotlin_packages_to_use_import_on_demand = unset
ij_kotlin_name_count_to_use_star_import = 999
ij_kotlin_name_count_to_use_star_import_for_members = 999
ij_kotlin_allow_trailing_comma = false
ij_kotlin_allow_trailing_comma_on_call_site = false
ktlint_code_style=intellij_idea

[*.{yml,yaml}]
indent_size = 2
2 changes: 1 addition & 1 deletion plugin/VERSION_LATEST_RELEASE.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
11.6.1
12.0.3
29 changes: 17 additions & 12 deletions plugin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ java {
}
}

ktlint {
version = "1.1.0"
}

tasks.withType<KotlinCompile> {
kotlinOptions {
// target 1.4 as ktlint 0.49 requires it for inline classes
Expand All @@ -56,6 +60,7 @@ configurations {
}
configurations["compileOnly"].extendsFrom(shadowImplementation)
configurations["testImplementation"].extendsFrom(shadowImplementation)

sourceSets {
val adapter by creating {
}
Expand Down Expand Up @@ -88,13 +93,15 @@ sourceSets {
runtimeClasspath = adapters.map { it.output }.fold(runtimeClasspath) { a, b -> a + b }
}
}

val test by getting {
kotlin {
compileClasspath = adapters.map { it.output }.fold(compileClasspath) { a, b -> a + b }
runtimeClasspath = adapters.map { it.output }.fold(runtimeClasspath) { a, b -> a + b }
}
}
}

val adapterSources = listOf(
sourceSets.named("adapter"),
sourceSets.named("adapter47"),
Expand Down Expand Up @@ -140,12 +147,6 @@ dependencies {
// Explicitly added for shadow plugin to relocate implementation as well
shadowImplementation(libs.slf4j.nop)

/*
* Do not depend upon the gradle script kotlin plugin API. IE: gradleScriptKotlinApi()
* It's currently in flux and has binary breaking changes in gradle 4.0
* https://github.com/JLLeitschuh/ktlint-gradle/issues/9
*/

testImplementation(libs.junit.jupiter)
testImplementation(libs.assertj.core)
testImplementation(libs.kotlin.reflect)
Expand All @@ -165,12 +166,8 @@ kotlin {
}
}

// Test tasks loods plugin from local maven repository
tasks.named<Test>("test") {
dependsOn("publishToMavenLocal")
}

tasks.withType<Test> {
dependsOn("publishToMavenLocal")
useJUnitPlatform()
maxParallelForks = (Runtime.getRuntime().availableProcessors() / 2).takeIf { it > 0 } ?: 1
doFirst {
Expand All @@ -195,6 +192,12 @@ tasks.withType<Test> {
maxFailures.set(10)
}
}

javaLauncher.set(
javaToolchains.launcherFor {
languageVersion = JavaLanguageVersion.of(JavaVersion.current().majorVersion)
}
)
}

val relocateShadowJar = tasks.register<ConfigureShadowRelocation>("relocateShadowJar")
Expand Down Expand Up @@ -273,7 +276,9 @@ fun setupPublishingEnvironment() {

if (System.getProperty(keyProperty) == null || System.getProperty(secretProperty) == null) {
logger
.info("`$keyProperty` or `$secretProperty` were not set. Attempting to configure from environment variables")
.info(
"`$keyProperty` or `$secretProperty` were not set. Attempting to configure from environment variables"
)

val key: String? = System.getenv(keyEnvironmentVariable)
val secret: String? = System.getenv(secretEnvironmentVariable)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ interface ReportersLoaderAdapter<
R,
RP : Serializable,
GR : GenericReporter<R>,
GRP : GenericReporterProvider<GR>> {
GRP : GenericReporterProvider<GR>
> {
fun loadAllReporterProviders(): List<ReporterProviderWrapper<RP>>
fun filterEnabledBuiltInProviders(
enabledReporters: Set<ReporterType>,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@file:Suppress("ConstPropertyName")

package org.jlleitschuh.gradle.ktlint

import org.eclipse.jgit.lib.RepositoryBuilder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ open class KtlintPlugin : Plugin<Project> {
private fun PluginHolder.addKtLintTasksToKotlinPlugin() {
target.plugins.withId("kotlin", applyKtLint())
target.plugins.withId("org.jetbrains.kotlin.js", applyKtLint())
target.plugins.withId("kotlin-android", applyKtLintToAndroid())
target.plugins.withId("org.jetbrains.kotlin.android", applyKtLintToAndroid())
target.plugins.withId(
"org.jetbrains.kotlin.multiplatform",
applyKtlintMultiplatform()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
package org.jlleitschuh.gradle.ktlint.android

import com.android.build.api.dsl.AndroidSourceDirectorySet
import com.android.build.api.dsl.AndroidSourceSet
import com.android.build.api.dsl.BuildFeatures
import com.android.build.api.dsl.BuildType
import com.android.build.api.dsl.CommonExtension
import com.android.build.api.dsl.DefaultConfig
import com.android.build.api.dsl.ProductFlavor
import com.android.build.api.dsl.SigningConfig
import com.android.build.api.variant.Variant
import com.android.build.api.variant.VariantProperties
import com.android.build.gradle.internal.api.DefaultAndroidSourceDirectorySet
import org.gradle.api.Plugin
import org.gradle.api.file.FileCollection
Expand All @@ -21,6 +15,7 @@ import org.jlleitschuh.gradle.ktlint.createGenerateReportsTask
import org.jlleitschuh.gradle.ktlint.setCheckTaskDependsOnGenerateReportsTask
import org.jlleitschuh.gradle.ktlint.tasks.GenerateReportsTask
import java.util.concurrent.Callable
import kotlin.reflect.full.memberProperties

internal fun KtlintPlugin.PluginHolder.applyKtLintToAndroid(): (Plugin<in Any>) -> Unit {
return {
Expand All @@ -43,33 +38,32 @@ internal fun KtlintPlugin.PluginHolder.applyKtLintToAndroid(): (Plugin<in Any>)
}
}

@Suppress("UnstableApiUsage")
private typealias AndroidCommonExtension = CommonExtension<
AndroidSourceSet,
BuildFeatures,
BuildType,
DefaultConfig,
ProductFlavor,
SigningConfig,
Variant<VariantProperties>,
VariantProperties
>

/*
* Variant manager returns all sources for variant,
* so most probably main source set maybe checked several times.
* This approach creates one check tasks per one source set.
*/
@Suppress("UNCHECKED_CAST", "UnstableApiUsage")
@Suppress("UnstableApiUsage")
private fun androidPluginConfigureAction(
pluginHolder: KtlintPlugin.PluginHolder
): (Plugin<Any>) -> Unit = {
pluginHolder.target.extensions.configure(CommonExtension::class.java) {
val androidCommonExtension = this as AndroidCommonExtension

androidCommonExtension.sourceSets.all {
// https://issuetracker.google.com/u/1/issues/170650362
val androidSourceSet = java as DefaultAndroidSourceDirectorySet
// kotlin property exists in AGP >= 7
val kotlinProperty = AndroidSourceSet::class.memberProperties.firstOrNull { it.name == "kotlin" }
if (kotlinProperty == null) {
pluginHolder.target.logger.warn(
buildString {
append("In AGP <7 kotlin source directories are not auto-detected. ")
append("In order to lint kotlin sources, manually add the directory to the source set. ")
append("""For example: sourceSets.getByName("main").java.srcDirs("src/main/kotlin/")""")
}
)
}
val sourceMember: AndroidSourceSet.() -> AndroidSourceDirectorySet = {
kotlinProperty?.get(this) as AndroidSourceDirectorySet? ?: this.java
}
sourceSets.all {
val androidSourceSet = sourceMember(this) as DefaultAndroidSourceDirectorySet
// Passing Callable, so returned FileCollection, will lazy evaluate it
// only when task will need it.
// Solves the problem of having additional source dirs in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,8 @@ abstract class GenerateReportsTask @Inject constructor(
internal enum class LintType(
val suffix: String
) {
CHECK("Check"), FORMAT("Format")
CHECK("Check"),
FORMAT("Format")
}

internal companion object {
Expand Down
9 changes: 9 additions & 0 deletions plugin/src/test/kotlin/org/assertj/core/api/Assertions.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.assertj.core.api

import org.gradle.testkit.runner.BuildTask
import org.gradle.testkit.runner.TaskOutcome

fun ObjectAssert<BuildTask?>.hasOutcome(outcome: TaskOutcome) {
this.objects.assertNotNull(this.info, this.actual)
this.objects.assertEqual(this.info, this.actual!!.outcome, outcome)
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ abstract class AbstractPluginTest {
GenerateReportsTask.LintType.CHECK
)

protected
fun File.withCleanSources() = createSourceFile(
protected fun File.withCleanSources() = createSourceFile(
"src/main/kotlin/CleanSource.kt",
"""
val foo = "bar"
Expand All @@ -53,12 +52,10 @@ abstract class AbstractPluginTest {
""".trimIndent()
)

protected
fun File.withAlternativeFailingSources(baseDir: String) =
protected fun File.withAlternativeFailingSources(baseDir: String) =
createSourceFile("$baseDir/FailSource.kt", """val foo = "bar"""")

protected
fun File.createSourceFile(sourceFilePath: String, contents: String) {
protected fun File.createSourceFile(sourceFilePath: String, contents: String) {
val sourceFile = resolve(sourceFilePath)
sourceFile.parentFile.mkdirs()
sourceFile.writeText(contents)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses
@AnalyzeClasses(
packages = ["org.jlleitschuh.gradle.ktlint.."]
)
@Suppress("PropertyName")
internal class KtLintClassesUsageScopeTest {
@ArchTest
val `Non-worker plugin classes should not use ktlint classes` = noClasses()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,8 @@ class KtLintSupportedVersionsTest : AbstractPluginTest() {
"0.49.1",
"0.50.0",
"1.0.0",
"1.0.1"
"1.0.1",
"1.1.0"
)

override fun provideArguments(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,8 @@ class KtlintPluginTest : AbstractPluginTest() {

removeSourceFile(fileOne)
val fileThree = "src/main/kotlin/FileThree.kt"
createSourceFile( // Need to add or modify a source to repro file not found error.
// Need to add or modify a source to repro file not found error.
createSourceFile(
fileThree,
"""
val bar = "foo"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package org.jlleitschuh.gradle.ktlint
import org.assertj.core.api.Assertions.assertThat
import org.gradle.util.GradleVersion
import org.jlleitschuh.gradle.ktlint.testdsl.buildAndFail
import org.jlleitschuh.gradle.ktlint.testdsl.getMajorJavaVersion
import org.jlleitschuh.gradle.ktlint.testdsl.project
import org.junit.jupiter.api.Assumptions
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.condition.DisabledOnOs
Expand All @@ -14,7 +16,15 @@ class UnsupportedGradleTest : AbstractPluginTest() {
@Test
@DisabledOnOs(OS.WINDOWS)
internal fun errorOnOldGradleVersion() {
project(GradleVersion.version("6.9.2")) {
/**
* This test ensures the proper error message is printed when an unsupported version of gradle is used.
* However, our minimum version of gradle is still 7.x, which will not run at all on Java 21.
* Gradle 8.5 is needed for Java 21.
* So if java 21 is currently being used, skip this test
*/
Assumptions.assumeFalse(getMajorJavaVersion() >= 21)

project(GradleVersion.version("7.4.1")) {
buildAndFail(CHECK_PARENT_TASK_NAME) {
assertThat(output).contains(
"Current version of plugin supports minimal Gradle version: " +
Expand Down
Loading

0 comments on commit 977af89

Please sign in to comment.