diff --git a/core/src/main/java/org/kohsuke/stapler/jsr269/AbstractProcessorImpl.java b/core/src/main/java/org/kohsuke/stapler/jsr269/AbstractProcessorImpl.java index 017b9023ad..2671052b36 100644 --- a/core/src/main/java/org/kohsuke/stapler/jsr269/AbstractProcessorImpl.java +++ b/core/src/main/java/org/kohsuke/stapler/jsr269/AbstractProcessorImpl.java @@ -26,11 +26,14 @@ import javax.annotation.processing.AbstractProcessor; import javax.lang.model.element.Element; import javax.tools.FileObject; +import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; import java.io.StringWriter; +import java.io.Writer; import java.util.Properties; +import java.util.concurrent.atomic.AtomicInteger; import static javax.tools.Diagnostic.Kind.*; import static javax.tools.StandardLocation.*; @@ -66,8 +69,13 @@ protected void notice(String msg, Element location) { protected void writePropertyFile(Properties p, String name) throws IOException { FileObject f = createResource(name); - try (OutputStream os = f.openOutputStream()) { - p.store(os,null); + /* + * This is somewhat fragile, but it is the only practical option on Java 11 and 17. In Java 21, we could instead + * set the "java.properties.date" system property to a fixed string and avoid the need to work around internal + * Java Platform implementation details. + */ + try (Writer w = f.openWriter(); BufferedWriter bw = new CommentStrippingBufferedWriter(w)) { + p.store(bw,null); } } @@ -78,4 +86,19 @@ protected FileObject getResource(String name) throws IOException { protected FileObject createResource(String name) throws IOException { return processingEnv.getFiler().createResource(CLASS_OUTPUT, "", name); } + + private static class CommentStrippingBufferedWriter extends BufferedWriter { + private final AtomicInteger count = new AtomicInteger(0); + + public CommentStrippingBufferedWriter(Writer out) { + super(out); + } + + @Override + public void write(String str) throws IOException { + if (count.getAndIncrement() > 0 || !str.startsWith("#")) { + super.write(str); + } + } + } } diff --git a/core/src/test/java/org/kohsuke/stapler/jsr269/ConstructorProcessorTest.java b/core/src/test/java/org/kohsuke/stapler/jsr269/ConstructorProcessorTest.java index a8ac087682..e0a57a9403 100644 --- a/core/src/test/java/org/kohsuke/stapler/jsr269/ConstructorProcessorTest.java +++ b/core/src/test/java/org/kohsuke/stapler/jsr269/ConstructorProcessorTest.java @@ -1,5 +1,8 @@ package org.kohsuke.stapler.jsr269; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.not; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -8,6 +11,7 @@ import com.karuslabs.elementary.junit.annotations.Inline; import com.karuslabs.elementary.junit.annotations.Options; import com.karuslabs.elementary.junit.annotations.Processors; +import java.time.Year; import java.util.Collections; import java.util.List; import java.util.Locale; @@ -160,4 +164,22 @@ void duplicatedButNotAnnotatedConstructor(Results results) { assertEquals(0, diagnostics.size()); } // TODO nested classes use qualified rather than binary name + + //issue-526 + @Inline( + name = "some.pkg.Stuff", + source = { + "package some.pkg;", + "import org.kohsuke.stapler.DataBoundConstructor;", + "public class Stuff {", + " @DataBoundConstructor public Stuff(int count, String name) {}", + "}", + }) + @Test + void reproducibleBuild(Results results) { + assertEquals(Collections.emptyList(), results.diagnostics); + assertThat( + Utils.getGeneratedResource(results.sources, "some/pkg/Stuff.stapler"), + not(containsString(Integer.toString(Year.now().getValue())))); + } }