detekt / detekt

Static code analysis for Kotlin
https://detekt.dev
Apache License 2.0
6.14k stars 757 forks source link

Custom Detekt task doesn't respect `include()` function #7023

Open oheyadam opened 4 months ago

oheyadam commented 4 months ago

Expected Behavior

I have this custom detekt task to which I pass only the files that were changed because I don't want to run full detekt. I'm passing the files via include(). I expect it to run against this subset of files only

Observed Behavior

Running the task with `--info says it has NO-SOURCE, even though I am passing a list of files.

Steps to Reproduce

Create the task as such:

    val changedFilesProvider = providers.of(GitChangedFilesValueSource::class) {
        parameters.rootDir.set(rootProject.layout.projectDirectory.asFile.name)
    }
    tasks.register<Detekt>("fastDetekt") {
        changedFilesProvider.get()
            .forEach { file -> include(file) }
    }

GitChangedFilesValueSource is defined as such:

abstract class GitChangedFilesValueSource : ValueSource<List<String>, Parameters> {

    @get:Inject
    abstract val execOperations: ExecOperations

    interface Parameters : ValueSourceParameters {
        val rootDir: Property<String>
    }

    override fun obtain(): List<String> {
        val output = ByteArrayOutputStream()
        execOperations.exec {
            commandLine("git", "diff", "--name-only", "--diff-filter=ACM")
            standardOutput = output
        }
        val result = String(output.toByteArray(), Charset.defaultCharset())
            .trim()
            .split("\n")
            .map { line -> "${parameters.rootDir.get()}/$line" }
        println("Changed files: $result") // this is here for debugging. it prints the correct list of files
        return result
    }
}

Run ./gradlew fastDetekt, it always succeeds even if you intentionally break some detekt rules in any of your files

Context

Your Environment

3flex commented 4 months ago

Includes/excludes applies filters to the paths passed to source - you should pass the files you wish to scan to that parameter.

oheyadam commented 4 months ago

Includes/excludes applies filters to the paths passed to source - you should pass the files you wish to scan to that parameter.

Sorry I failed to mention that I have a global Detekt config block that passes the source. Also doesn't detekt have a default value for this anyway?

I already have the following:

tasks.withType<Detekt>.configureEach {
    setSource(project.layout.projectDirectory)
}

Typing down this code on my phone, so it might be wrong, but you get the idea. I even copied this over to my custom task and it still doesn't work.

3flex commented 4 months ago

Can you please put a self contained reproducer together? That will make it much easier to have a look at what's going on.

oheyadam commented 4 months ago

Hi @3flex, sorry for the delay. Here's a reproducer. An easy way to trigger this behavior is to add this line back to MainActivity and run ./gradlew detekt. This fails as expected, but running ./gradlew fastDetekt doesn't. Thanks

oheyadam commented 2 months ago

Hey @3flex, just wanted to add another thing I noticed. In the same project structure that I linked, the detektBaseline function doesn't seem to work. Every time you invoke it, it just generates an empty file, even if you have new issues in your project.

What's wrong here? Does Detekt just not play nice when used in included builds?