/* * Copyright (c) 2024, 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 * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * @test * @bug 8297879 * @library /tools/lib ../../lib * @modules jdk.javadoc/jdk.javadoc.internal.tool * @build toolbox.ToolBox javadoc.tester.* * @run main TestErasure */ import java.io.IOException; import java.nio.file.Path; import javadoc.tester.JavadocTester; import toolbox.ToolBox; public class TestErasure extends JavadocTester { private final ToolBox tb = new ToolBox(); public static void main(String... args) throws Exception { new TestErasure().runTests(); } /* * Create confusion between: * - a constructor/method type parameter and a like-named class * - similarly named but differently bounded constructor type parameters * - similarly named but differently bounded type parameter in methods */ @Test public void test1(Path base) throws IOException { Path src = base.resolve("src"); // - put public class first so that writeJavaFiles is not confused // on the name of the file it should create // // - an _abstract_ class is used only for convenience: like an interface, // it allows to keep the test minimal, but unlike an interface, it // allows to test constructors tb.writeJavaFiles(src, """ public abstract class Foo { public Foo(T arg) { } public Foo(T arg) { } public Foo(T arg) { } public abstract T m(T arg); public abstract T m(T arg); public abstract T m(T arg); } class T { } class X { } class Y { } """); javadoc("-d", base.resolve("out").toString(), src.resolve("Foo.java").toString()); checkExit(Exit.OK); // constructors checkOutput("Foo.html", true, """

Constructor Summary

Constructors
Constructor
Description
\ Foo(T arg)
 
\ Foo(T arg)
 
\ Foo(T arg)
 
"""); checkOutput("Foo.html", true, """
  • Constructor Details
    1. Foo(T)
    2. Foo(T)
    3. Foo(T)
  • """); checkOutput("index-all.html", true, """
    Foo(T)\ - Constructor for class Foo
     
    Foo(T)\ - Constructor for class Foo
     
    Foo(T)\ - Constructor for class Foo
     
    """); checkOutput("member-search-index.js", true, """ {"p":"","c":"Foo","l":"Foo(T)","u":"%3Cinit%3E(T)"},\ {"p":"","c":"Foo","l":"Foo(T)","u":"%3Cinit%3E(X)"},\ {"p":"","c":"Foo","l":"Foo(T)","u":"%3Cinit%3E(Y)"}"""); // methods checkOutput("Foo.html", true, """
    abstract T
    m(T arg)
     
    abstract <T extends X>
    T
    m(T arg)
     
    abstract <T extends Y>
    T
    m(T arg)
     
    """); checkOutput("Foo.html", true, """
  • Method Details
    1. m(T)
    2. m(T)
    3. m(T)
  • """); checkOutput("index-all.html", true, """
    m(T)\ - Method in class Foo
     
    m(T)\ - Method in class Foo
     
    m(T)\ - Method in class Foo
     
    """); checkOutput("member-search-index.js", true, """ {"p":"","c":"Foo","l":"m(T)"},\ {"p":"","c":"Foo","l":"m(T)","u":"m(X)"},\ {"p":"","c":"Foo","l":"m(T)","u":"m(Y)"}"""); } /* * Create confusion between the class type parameter * and a like-named constructor/method type parameter. */ @Test public void test2(Path base) throws IOException { Path src = base.resolve("src"); tb.writeJavaFiles(src, """ public abstract class Foo { public Foo(T arg) { } public Foo(T arg) { } public abstract T m(T arg); public abstract T m(T arg); } class X { } """); javadoc("-d", base.resolve("out").toString(), src.resolve("Foo.java").toString()); checkExit(Exit.OK); // constructors checkOutput("Foo.html", true, """

    Constructor Summary

    Constructors
    Constructor
    Description
    \ Foo\ (T arg)
     
    \ Foo(T arg)
     
    """); checkOutput("Foo.html", true, """
  • Constructor Details
    1. Foo(T)
    2. Foo(T)
  • """); checkOutput("index-all.html", true, """
    Foo(T)\ - Constructor for class Foo
     
    Foo(T)\ - Constructor for class Foo
     
    """); checkOutput("member-search-index.js", true, """ {"p":"","c":"Foo","l":"Foo(T)","u":"%3Cinit%3E(T)"},\ {"p":"","c":"Foo","l":"Foo(T)","u":"%3Cinit%3E(X)"}"""); // methods checkOutput("Foo.html", true, """
    abstract T
    m\ (T arg)
     
    abstract <T extends X>
    T
    m(T arg)
     
    """); checkOutput("Foo.html", true, """
  • Method Details
    1. m(T)
    2. m(T)
  • """); checkOutput("index-all.html", true, """
    m(T)\ - Method in class Foo
     
    m(T)\ - Method in class Foo
     
    """); checkOutput("member-search-index.js", true, """ {"p":"","c":"Foo","l":"m(T)"},\ {"p":"","c":"Foo","l":"m(T)","u":"m(X)"}"""); } @Test public void testNewAndDeprecated(Path base) throws IOException { Path src = base.resolve("src"); tb.writeJavaFiles(src, """ public abstract class Foo { /** @since today */ @Deprecated(since="tomorrow") public Foo(T arg) { } /** @since today */ @Deprecated(since="tomorrow") public Foo(T arg) { } /** @since today */ @Deprecated(since="tomorrow") public Foo(T arg) { } /** @since today */ @Deprecated(since="tomorrow") public abstract T m(T arg); /** @since today */ @Deprecated(since="tomorrow") public abstract T m(T arg); /** @since today */ @Deprecated(since="tomorrow") public abstract T m(T arg); } class T { } class X { } class Y { } """); javadoc("-d", base.resolve("out").toString(), "--since", "today", src.resolve("Foo.java").toString()); checkExit(Exit.OK); checkOutput("new-list.html", true, """
    today
     
    today
     
    today
     
    """); checkOutput("new-list.html", true, """
    today
     
    today
     
    today
     
    """); checkOutput("deprecated-list.html", true, """
    tomorrow
    tomorrow
    tomorrow
    """); checkOutput("deprecated-list.html", true, """
    tomorrow
    tomorrow
    tomorrow
    """); } @Test public void testPreview(Path base) throws IOException { // unlike that for other tests, here we cannot simulate ambiguity between // a type parameter and a like-named class, because for that the class // needs to be in the unnamed package, otherwise its FQN won't be T Path src = base.resolve("src"); tb.writeJavaFiles(src, """ package p; import jdk.internal.javac.PreviewFeature; public abstract class Foo { @PreviewFeature(feature=PreviewFeature.Feature.TEST) public Foo(T arg) { } @PreviewFeature(feature=PreviewFeature.Feature.TEST) public Foo(T arg) { } @PreviewFeature(feature=PreviewFeature.Feature.TEST) public abstract T m(T arg); @PreviewFeature(feature=PreviewFeature.Feature.TEST) public abstract T m(T arg); } class X { } class Y { } """); javadoc("-d", base.resolve("out").toString(), "--patch-module", "java.base=" + src.toAbsolutePath().toString(), src.resolve("p").resolve("Foo.java").toString()); checkExit(Exit.OK); checkOutput("preview-list.html", true, """
    Test Feature
    Test Feature
    """); checkOutput("preview-list.html", true, """
    Test Feature
    Test Feature
    """); } }