]> dgit.raspbian.org Git - openjdk-25.git/commitdiff
[PATCH] 8385738: Javadoc does not produce reproducible output due to the snippet...
authorVladimir Petko <vpetko@openjdk.org>
Wed, 3 Jun 2026 06:35:57 +0000 (06:35 +0000)
committerVladimir Petko <vladimir.petko@canonical.com>
Wed, 22 Jul 2026 00:23:02 +0000 (12:23 +1200)
Bug: https://bugs.openjdk.org/browse/JDK-8385738
Reviewed-by: nbenalla
Gbp-Pq: Name jdk-8385738.diff

src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/SnippetTaglet.java
test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetTag.java

index 32bcab0eef586b7d5b6c50976fd79e136a3ccab5..b5bf9f2519723e100ffce95a7ae619350f753fc4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2026, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -49,6 +49,7 @@ import com.sun.source.util.DocTreePath;
 
 import jdk.javadoc.doclet.Taglet;
 import jdk.javadoc.internal.doclets.formats.html.HtmlConfiguration;
+import jdk.javadoc.internal.doclets.formats.html.HtmlDocletWriter;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyles;
 import jdk.javadoc.internal.doclets.formats.html.taglets.snippet.Action;
 import jdk.javadoc.internal.doclets.formats.html.taglets.snippet.ParseException;
@@ -124,7 +125,8 @@ public class SnippetTaglet extends BaseTaglet {
         if (id != null && !id.isBlank()) {
             pre.put(HtmlAttr.ID, id);
         } else {
-            pre.put(HtmlAttr.ID, config.htmlIds.forSnippet(element, ids).name());
+            var set = ids.computeIfAbsent(tagletWriter.htmlWriter, _ -> new HashSet<>());
+            pre.put(HtmlAttr.ID, config.htmlIds.forSnippet(element, set).name());
         }
         var code = HtmlTree.CODE()
                 .addUnchecked(Text.EMPTY); // Make sure the element is always rendered
@@ -205,7 +207,7 @@ public class SnippetTaglet extends BaseTaglet {
         return snippetContainer.add(pre.add(code));
     }
 
-    private final Set<String> ids = new HashSet<>();
+    private final HashMap<HtmlDocletWriter, Set<String>> ids = new HashMap<>();
 
     private static final class BadSnippetException extends Exception {
 
index 413de03d23bb7978804fe1b9a4a67eec45a8c80d..02001fe8a0519bf9c6f844ea1aa68274f08ce93b 100644 (file)
@@ -39,6 +39,7 @@ import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.nio.file.StandardOpenOption;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Optional;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -2675,4 +2676,94 @@ public class TestSnippetTag extends SnippetTester {
                         """);
         checkNoCrashes();
     }
+
+    @Test
+    public void testSnippetIdCounterResetsPerPage(Path base) throws IOException {
+        Path src = base.resolve("src");
+
+        tb.writeJavaFiles(src,
+                """
+                package p;
+                import java.lang.annotation.Target;
+                import java.lang.annotation.ElementType;
+                @Target({ElementType.TYPE, ElementType.METHOD})
+                public @interface ACustomAnnotation {
+                }
+                """,
+                """
+                package p;
+                import java.lang.annotation.Target;
+                import java.lang.annotation.ElementType;
+                @Target({ElementType.TYPE, ElementType.METHOD})
+                public @interface ZCustomAnnotation {
+                }
+                """,
+                """
+                package p;
+                /** Class A. */
+                public class A {
+                    /**
+                     * First snippet on A.foo:
+                     * {@snippet :
+                     *     int x = 1; // first
+                     * }
+                     * Second snippet on A.foo:
+                     * {@snippet :
+                     *     int y = 2; // second
+                     * }
+                     */
+                    @ACustomAnnotation
+                    @ZCustomAnnotation
+                    public void foo() {}
+                }
+                """,
+                """
+                package p;
+                /** Class B. */
+                public class B {
+                    /**
+                     * First snippet on B.foo:
+                     * {@snippet :
+                     *     int x = 1; // first
+                     * }
+                     * Second snippet on B.foo:
+                     * {@snippet :
+                     *     int y = 2; // second
+                     * }
+                     */
+                    @ACustomAnnotation
+                    @ZCustomAnnotation
+                    public void foo() {}
+                }
+                """);
+
+        javadoc("-d", base.resolve("out").toString(),
+                "-use",
+                "-sourcepath", src.toString(),
+                "p");
+        checkExit(Exit.OK);
+        for (String cls : new String[] {
+                "A.html",
+                "B.html",
+                "class-use/ACustomAnnotation.html",
+                "class-use/ZCustomAnnotation.html"}) {
+            var file = base
+                .resolve("out")
+                .resolve("p")
+                .resolve(cls);
+            String content = Files.readString(file);
+            for (var snippetId : new String[] {"snippet-foo()1", "snippet-foo()2"}) {
+                checking("id \"" + snippetId + "\" present in " + cls);
+                if (content.contains("id=\"" + snippetId + "\"")) {
+                    passed("found");
+                } else {
+                    failed("" + snippetId + " not found in " +
+                        String.join("\n", Arrays.asList(content.split("\n"))
+                            .stream()
+                            .filter(l -> l.contains("pre class=\"snippet\""))
+                            .toList()));
+                }
+            }
+        }
+    }
 }