From aa0d28eefe6343e9a6238ba41392127ecba48b5c Mon Sep 17 00:00:00 2001
From: Lars Grefer <github@larsgrefer.de>
Date: Wed, 2 Mar 2022 02:42:13 +0100
Subject: [PATCH] Fix Gradles up-to-date checks by correctly declaing the task
 inputs and outputs

---
 .../gradle/SpringJavaFormatPlugin.java        |  4 +++
 .../javaformat/gradle/tasks/Format.java       | 16 ++++++++++
 .../gradle/tasks/FormatterTask.java           | 31 ++++++++++++++++++-
 .../javaformat/gradle/FormatTaskTests.java    | 19 ++++++++++++
 4 files changed, 69 insertions(+), 1 deletion(-)

diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/SpringJavaFormatPlugin.java b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/SpringJavaFormatPlugin.java
index 9c14a75f..ed2c516d 100644
--- a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/SpringJavaFormatPlugin.java
+++ b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/SpringJavaFormatPlugin.java
@@ -27,6 +27,7 @@
 import org.gradle.api.tasks.TaskContainer;
 import org.gradle.api.tasks.TaskProvider;
 
+import io.spring.javaformat.config.JavaFormatConfig;
 import io.spring.javaformat.gradle.tasks.CheckFormat;
 import io.spring.javaformat.gradle.tasks.Format;
 import io.spring.javaformat.gradle.tasks.FormatterTask;
@@ -78,6 +79,9 @@ private <T extends FormatterTask> TaskProvider<T> addFormatterTask(SourceSet sou
 		provider.configure((task) -> {
 			task.setDescription(desc + " for " + sourceSet.getName());
 			task.setSource(sourceSet.getAllJava());
+			JavaFormatConfig javaFormatConfig = JavaFormatConfig.findFrom(this.project.getProjectDir());
+			task.getJavaBaseline().convention(javaFormatConfig.getJavaBaseline());
+			task.getIndentationStyle().convention(javaFormatConfig.getIndentationStyle());
 		});
 		return provider;
 	}
diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/tasks/Format.java b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/tasks/Format.java
index 591377c5..0c9b8b85 100644
--- a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/tasks/Format.java
+++ b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/tasks/Format.java
@@ -19,6 +19,11 @@
 import java.io.IOException;
 
 import org.gradle.api.GradleException;
+import org.gradle.api.file.FileTree;
+import org.gradle.api.tasks.InputFiles;
+import org.gradle.api.tasks.OutputFiles;
+import org.gradle.api.tasks.PathSensitive;
+import org.gradle.api.tasks.PathSensitivity;
 import org.gradle.api.tasks.TaskAction;
 
 import io.spring.javaformat.formatter.FileEdit;
@@ -51,4 +56,15 @@ public void format() throws IOException, InterruptedException {
 		}
 	}
 
+	@Override
+	@InputFiles
+	@PathSensitive(PathSensitivity.RELATIVE)
+	public FileTree getSource() {
+		return super.getSource();
+	}
+
+	@OutputFiles
+	public FileTree getOutputFiles() {
+		return super.getSource();
+	}
 }
diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/tasks/FormatterTask.java b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/tasks/FormatterTask.java
index 64486ee2..b839d429 100644
--- a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/tasks/FormatterTask.java
+++ b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/main/java/io/spring/javaformat/gradle/tasks/FormatterTask.java
@@ -19,10 +19,13 @@
 import java.nio.charset.Charset;
 import java.util.stream.Stream;
 
+import org.gradle.api.provider.Property;
 import org.gradle.api.tasks.Input;
 import org.gradle.api.tasks.Optional;
 import org.gradle.api.tasks.SourceTask;
 
+import io.spring.javaformat.config.IndentationStyle;
+import io.spring.javaformat.config.JavaBaseline;
 import io.spring.javaformat.config.JavaFormatConfig;
 import io.spring.javaformat.formatter.FileEdit;
 import io.spring.javaformat.formatter.FileFormatter;
@@ -36,7 +39,13 @@ public abstract class FormatterTask extends SourceTask {
 
 	private String encoding;
 
+	private final Property<JavaBaseline> javaBaseline;
+
+	private final Property<IndentationStyle> indentationStyle;
+
 	FormatterTask() {
+		this.javaBaseline = getProject().getObjects().property(JavaBaseline.class);
+		this.indentationStyle = getProject().getObjects().property(IndentationStyle.class);
 	}
 
 	/**
@@ -57,12 +66,32 @@ public void setEncoding(String encoding) {
 		this.encoding = encoding;
 	}
 
+	/**
+	 * The java baseline used for the internal {@link JavaFormatConfig}.
+	 * @return the java baseline property
+	 * @see JavaFormatConfig#getJavaBaseline()
+	 */
+	@Input
+	public Property<JavaBaseline> getJavaBaseline() {
+		return this.javaBaseline;
+	}
+
+	/**
+	 * The java indentation style for the internal {@link JavaFormatConfig}.
+	 * @return the indentation style property
+	 * @see JavaFormatConfig#getIndentationStyle()
+	 */
+	@Input
+	public Property<IndentationStyle> getIndentationStyle() {
+		return this.indentationStyle;
+	}
+
 	/**
 	 * Format the source files and provide a {@link Stream} of {@link FileEdit} instances.
 	 * @return the file edits
 	 */
 	protected final Stream<FileEdit> formatFiles() {
-		JavaFormatConfig javaFormatConfig = JavaFormatConfig.findFrom(getProject().getProjectDir());
+		JavaFormatConfig javaFormatConfig = JavaFormatConfig.of(this.javaBaseline.get(), this.indentationStyle.get());
 		FileFormatter formatter = new FileFormatter(javaFormatConfig);
 		Charset encoding = (getEncoding() != null ? Charset.forName(getEncoding()) : Charset.defaultCharset());
 		return formatter.formatFiles(getSource().getFiles(), encoding);
diff --git a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/java/io/spring/javaformat/gradle/FormatTaskTests.java b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/java/io/spring/javaformat/gradle/FormatTaskTests.java
index 071cf75c..b8cb2197 100644
--- a/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/java/io/spring/javaformat/gradle/FormatTaskTests.java
+++ b/spring-javaformat-gradle/spring-javaformat-gradle-plugin/src/test/java/io/spring/javaformat/gradle/FormatTaskTests.java
@@ -21,6 +21,7 @@
 import java.nio.file.Files;
 
 import org.gradle.testkit.runner.BuildResult;
+import org.gradle.testkit.runner.GradleRunner;
 import org.gradle.testkit.runner.TaskOutcome;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
@@ -50,6 +51,24 @@ public void checkOk() throws IOException {
 		assertThat(formattedContent).contains("class Simple {").contains("	public static void main");
 	}
 
+	@Test
+	public void checkUpTpDate() throws IOException {
+		GradleRunner runner = this.gradleBuild.source("src/test/resources/format").prepareRunner("format");
+
+		// 1) Actually format the sources.
+		BuildResult result1 = runner.build();
+		assertThat(result1.task(":formatMain").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
+
+		// 2) No-op reformat the sources
+		// Not up-to-date yet because 1) changed the sources.
+		BuildResult result2 = runner.build();
+		assertThat(result2.task(":formatMain").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
+
+		// 3) Now we should be up-to-date since 2) was effectively a no-op
+		BuildResult result3 = runner.build();
+		assertThat(result3.task(":formatMain").getOutcome()).isEqualTo(TaskOutcome.UP_TO_DATE);
+	}
+
 	@Test
 	public void checkSpacesOk() throws IOException {
 		BuildResult result = this.gradleBuild.source("src/test/resources/format-spaces").build("format");