Use @Incremental with files being both input and output?

I have a custom task fixing whitespace issues in source files (code). The source files is both input and output to the task. I do not see how to combine the incremental input changes API together with input files also being the output files. Is there a way?

Currently the task works and is defined like this:

open class FixWhitespace : DefaultTask() {
  
  @OutputFiles
  lateinit var sourceFiles: FileTree

  @TaskAction
  fun fix() = ...
}

Only, when Gradle detects a change in one of the sourceFiles the task is re-run and doing its whitespace-thing. Great! The BIG drawback is however that the task is applied to all sourceFiles even if only one source file is modified.

I would like to take advantage of the incremental changes functionality in Gradle, only needing to apply the whitespace fixing to the source files actually changed, using something like this:

open class FixWhitespace : DefaultTask() {

  @Incremental
  @OutputFiles
  lateinit var sourceFiles: FileTree

  @TaskAction
  fun fix(changes: InputChanges) = changes.getFileChanges(sourceFiles).forEach { ... }
}

However, this seems to be hard to get working. Combining the annotation @Incremental and @OutputFiles throws exception in method InputChanges.getFileChanges:

> Cannot query incremental changes: No property found for value file tree. Incremental properties:

Instead, combining the annotation @Incremental and @InputFiles in sourceFiles, seems to have strange effects in my case. It deletes all sourceFiles before running the task, if the current build run happens to be non-incremental. As specified in API, when a full rebuild happens “output files of the work are removed prior to executing the work action”. Further, the task needs some specified outputs in order to ever get UP-TO-DATE, right?

So, is there a way to use InputChanges together with a FileTree being both the input and the output to the task?

FYI: I’m running Gradle version 5.6.4

Hi Joakim,

this is currently not possible. What you can do have your task create the fixed source files in a new location and then copy them back in a separate task. I know that this is far from idea :frowning:

Cheers,
Stefan

Hi Stefan, thanks for the quick and clear answer.