cortinico / ktfmt-gradle

A Gradle plugin to apply ktfmt to your builds, and reformat you Kotlin source code like a glimpse ๐Ÿงน๐Ÿ˜
MIT License
147 stars 19 forks source link

ktfmt does not use custom source directories #292

Open christophsturm opened 2 months ago

christophsturm commented 2 months ago

๐Ÿ› Describe the bug

in my project I configure a flat directory layout by stetting srcDirs for the source sets:

sourceSets.main {
    java.srcDirs("src")
    resources.srcDirs("resources")
}
sourceSets.test {
    java.srcDirs("test")
    resources.srcDirs("testResources")
}

โš ๏ธ Current behavior

ktfmt does not format my sources, gradle says NO SOURCE

2024-05-21T22:04:42.174+0200 [LIFECYCLE] [class org.gradle.internal.buildevents.TaskExecutionLogger] > Task :failgood:ktfmtFormatMain NO-SOURCE

โœ… Expected behavior

Before I converted my project to the flat source directory structure I'm sure it worked.

๐Ÿ’ฃ Steps to reproduce

clone https://github.com/failgood/failgood run ./gradlew ktfmtFormat notice that sources are not reformatted, for example failgood/src/failgood/junit/ContextFinder.kt contains 2 unused imports.

cortinico commented 1 month ago

Yup this is a bug. I'm looking for someone to help me here, happy to review a PR. The problem is that ktfmt-gradle listens for kotlin.sourceSet and registers for changes there, while here you're manipulating the top level sourceSets (so ktfmt-gradle never receives the information on your source sets).

christophsturm commented 1 month ago

so the fix would be to listen to both? and the work around would be to set kotlin.sourceSet? why are there always so many different ways to do things in gradle....

christophsturm commented 1 month ago

I changed it to

kotlin {
    sourceSets.main {
        kotlin.srcDirs("src")
        resources.srcDirs("resources")
    }
    sourceSets.test {
        kotlin.srcDirs("test")
        resources.srcDirs("testResources")
    }

}

and it still does not format.

cortinico commented 1 month ago

why are there always so many different ways to do things in gradle....

Yeah man don't tell me about it :|

christophsturm commented 5 days ago

@cortinico I would be happy to help fix this, but it would be cool if we could come up with a workaround first. like i wrote above, it did not work for me when i set kotlin.sourceSets instead.

cortinico commented 5 days ago

Yeah I started to look into it but hit a road blocker. @simonhauck do you have a spare cycle to look at this one?

simonhauck commented 5 days ago

Yes I will finish my current PR an then have a look :)

simonhauck commented 5 days ago

@christophsturm For a fast workaround you could add the tasks manually. This is not so great, but at least you can format/check the code ;)

tasks.register<KtfmtFormatTask>("customFormat") {
    source = fileTree(layout.projectDirectory) { include("**/*.kt") }
}
simonhauck commented 5 days ago

I have an idea what could be the problem.

From the docs on the method SourceDirectorySet::getSourceDirectories() the docs say

    /**
     * Returns the source directories that make up this set, represented as a {@link FileCollection}. Does not filter source directories that do not exist.
     * Generally, it is preferable to use this method instead of {@link #getSrcDirs()}, as this method does not require the source directories to be calculated when it is called. Instead, the source directories are calculated when queried. The return value of this method also maintains dependency information.
     *
     * <p>The returned collection is live and reflects changes to this source directory set.
     */
    FileCollection getSourceDirectories();

My assumption is that the sourceSets are changed after the plugin is evaluated. That's why we do not detect the changes when we resolve it eagerly.

The solution is straightforward... expect one or two things... ;) We have to evaluate the sourceSet lazily. I was able to make the test green with the project.provider {} logic. But I am not sure how to handle the android sources with AGP < 7. I am not really an Android developer, so maybe @cortinico you could give me some feedback there.

Additionally, when selecting in IntelliJ settings > Build, Execution, Deployment > Build Tools > Gradle > Run tests using = IntelliJ IDEA, some tests are failing with really weird issues. This setting is super useful for debugging, and I am not sure if that behavior is new and happened due to my changes or was always there. I have to check this in the coming days.

And also, the build is still red :D