2024-05-24 15:58:34 +00:00

310 lines
14 KiB
Java

/*
* Copyright (c) 2014, 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 8042261 8298405
* @summary Checking what attribute is generated by annotation Deprecated
* or javadoc deprecated for field, method, class(inner/local), interface.
* @library /tools/lib /tools/javac/lib ../lib
* @enablePreview
* @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main
* jdk.compiler/com.sun.tools.javac.util
* java.base/jdk.internal.classfile.impl
* @build toolbox.ToolBox InMemoryFileManager TestResult TestBase
* @run main DeprecatedTest
*/
import java.lang.classfile.*;
import java.lang.classfile.attribute.*;
import jdk.internal.classfile.impl.BoundAttribute;
import javax.tools.JavaFileObject;
import java.io.IOException;
import java.util.Map;
public class DeprecatedTest extends TestResult {
private static final String[] sources = new String[]{
"@Deprecated public class deprecated {\n"
+ "@Deprecated class deprecatedInner01 {}\n"
+ "@Deprecated interface deprecatedInner02 {}\n"
+ "@Deprecated enum deprecatedInner03 {}\n"
+ "@Deprecated @interface deprecatedInner04 {}\n"
+ "class notDeprecatedInner01 {}\n"
+ "interface notDeprecatedInner02 {}\n"
+ "enum notDeprecatedInner03 {}\n"
+ "@interface notDeprecatedInner04 {}\n"
+ "@Deprecated public void deprecated() {}\n"
+ "@Deprecated public int deprecated;\n"
+ "public void notDeprecated() {}\n"
+ "public int notDeprecated;\n"
+ "public void f() {\n"
+ " @Deprecated class deprecatedLocal {\n"
+ " @Deprecated int deprecated;\n"
+ " @Deprecated void deprecated() {}\n"
+ " int notDeprecated;\n"
+ " void notDeprecated(){}\n"
+ " }\n"
+ " class notDeprecatedLocal {\n"
+ " @Deprecated int deprecated;\n"
+ " @Deprecated void deprecated() {}\n"
+ " int notDeprecated;\n"
+ " void notDeprecated(){}\n"
+ " }}\n"
+ "}",
"@Deprecated public interface deprecated {\n"
+ "@Deprecated class deprecatedInner01 {}\n"
+ "@Deprecated interface deprecatedInner02 {}\n"
+ "@Deprecated enum deprecatedInner03 {}\n"
+ "@Deprecated @interface deprecatedInner04 {}\n"
+ "class notDeprecatedInner01 {}\n"
+ "interface notDeprecatedInner02 {}\n"
+ "enum notDeprecatedInner03 {}\n"
+ "@interface notDeprecatedInner04 {}\n"
+ "@Deprecated void deprecated01();\n"
+ "void notDeprecated01();\n"
+ "@Deprecated default void deprecated02() {}\n"
+ "default void notDeprecated02() {}\n"
+ "@Deprecated int deprecated = 0;\n"
+ "int notDeprecated = 0;\n"
+ "}",
"@Deprecated public enum deprecated {\n"
+ "@Deprecated deprecated, notDeprecated;\n"
+ "@Deprecated class deprecatedInner01 {}\n"
+ "@Deprecated interface deprecatedInner02 {}\n"
+ "@Deprecated enum deprecatedInner03 {}\n"
+ "@Deprecated @interface deprecatedInner04 {}\n"
+ "class notDeprecatedInner01 {}\n"
+ "interface notDeprecatedInner02 {}\n"
+ "enum notDeprecatedInner03 {}\n"
+ "@interface notDeprecatedInner04 {}\n"
+ "@Deprecated public void deprecated() {}\n"
+ "public void notDeprecated() {}\n"
+ "public void f() {\n"
+ " @Deprecated class deprecatedLocal {\n"
+ " @Deprecated int deprecated;\n"
+ " @Deprecated void deprecated() {}\n"
+ " int notDeprecated;\n"
+ " void notDeprecated(){}\n"
+ " }\n"
+ " class notDeprecatedLocal {\n"
+ " @Deprecated int deprecated;\n"
+ " @Deprecated void deprecated() {}\n"
+ " int notDeprecated;\n"
+ " void notDeprecated(){}\n"
+ " }}\n"
+ "}",
"@Deprecated public @interface deprecated {\n"
+ "@Deprecated class deprecatedInner01 {}\n"
+ "@Deprecated interface deprecatedInner02 {}\n"
+ "@Deprecated enum deprecatedInner03 {}\n"
+ "@Deprecated @interface deprecatedInner04 {}\n"
+ "class notDeprecatedInner01 {}\n"
+ "interface notDeprecatedInner02 {}\n"
+ "enum notDeprecatedInner03 {}\n"
+ "@interface notDeprecatedInner04 {}\n"
+ "@Deprecated int deprecated() default 0;\n"
+ "int notDeprecated() default 0;\n"
+ "@Deprecated int deprecated = 0;\n"
+ "int notDeprecated = 0;\n"
+ "}",
"public class notDeprecated {\n"
+ "@Deprecated class deprecatedInner01 {}\n"
+ "@Deprecated interface deprecatedInner02 {}\n"
+ "@Deprecated enum deprecatedInner03 {}\n"
+ "@Deprecated @interface deprecatedInner04 {}\n"
+ "class notDeprecatedInner01 {}\n"
+ "interface notDeprecatedInner02 {}\n"
+ "enum notDeprecatedInner03 {}\n"
+ "@interface notDeprecatedInner04 {}\n"
+ "@Deprecated public void deprecated() {}\n"
+ "@Deprecated public int deprecated;\n"
+ "public void notDeprecated() {}\n"
+ "public int notDeprecated;\n"
+ "public void f() {\n"
+ " @Deprecated class deprecatedLocal {\n"
+ " @Deprecated int deprecated;\n"
+ " @Deprecated void deprecated() {}\n"
+ " int notDeprecated;\n"
+ " void notDeprecated(){}\n"
+ " }\n"
+ " class notDeprecatedLocal {\n"
+ " @Deprecated int deprecated;\n"
+ " @Deprecated void deprecated() {}\n"
+ " int notDeprecated;\n"
+ " void notDeprecated(){}\n"
+ " }}\n"
+ "}",
"public interface notDeprecated {\n"
+ "@Deprecated class deprecatedInner01 {}\n"
+ "@Deprecated interface deprecatedInner02 {}\n"
+ "@Deprecated enum deprecatedInner03 {}\n"
+ "@Deprecated @interface deprecatedInner04 {}\n"
+ "class notDeprecatedInner01 {}\n"
+ "interface notDeprecatedInner02 {}\n"
+ "enum notDeprecatedInner03 {}\n"
+ "@interface notDeprecatedInner04 {}\n"
+ "@Deprecated void deprecated01();\n"
+ "void notDeprecated01();\n"
+ "@Deprecated default void deprecated02() {}\n"
+ "default void notDeprecated02() {}\n"
+ "@Deprecated int deprecated = 0;\n"
+ "int notDeprecated = 0;\n"
+ "}",
"public enum notDeprecated {\n"
+ "@Deprecated deprecated, notDeprecated;\n"
+ "@Deprecated class deprecatedInner01 {}\n"
+ "@Deprecated interface deprecatedInner02 {}\n"
+ "@Deprecated enum deprecatedInner03 {}\n"
+ "@Deprecated @interface deprecatedInner04 {}\n"
+ "class notDeprecatedInner01 {}\n"
+ "interface notDeprecatedInner02 {}\n"
+ "enum notDeprecatedInner03 {}\n"
+ "@interface notDeprecatedInner04 {}\n"
+ "@Deprecated public void deprecated() {}\n"
+ "public void notDeprecated() {}\n"
+ "public void f() {\n"
+ " @Deprecated class deprecatedLocal {\n"
+ " @Deprecated int deprecated;\n"
+ " @Deprecated void deprecated() {}\n"
+ " int notDeprecated;\n"
+ " void notDeprecated(){}\n"
+ " }\n"
+ " class notDeprecatedLocal {\n"
+ " @Deprecated int deprecated;\n"
+ " @Deprecated void deprecated() {}\n"
+ " int notDeprecated;\n"
+ " void notDeprecated(){}\n"
+ " }}\n"
+ "}",
"public @interface notDeprecated {\n"
+ "@Deprecated class deprecatedInner01 {}\n"
+ "@Deprecated interface deprecatedInner02 {}\n"
+ "@Deprecated enum deprecatedInner03 {}\n"
+ "@Deprecated @interface deprecatedInner04 {}\n"
+ "class notDeprecatedInner01 {}\n"
+ "interface notDeprecatedInner02 {}\n"
+ "enum notDeprecatedInner03 {}\n"
+ "@interface notDeprecatedInner04 {}\n"
+ "@Deprecated int deprecated() default 0;\n"
+ "int notDeprecated() default 0;\n"
+ "@Deprecated int deprecated = 0;\n"
+ "int notDeprecated = 0;\n"
+ "}"};
public static void main(String[] args) throws TestFailedException {
new DeprecatedTest().test();
}
public void test() throws TestFailedException {
try {
for (String src : sources) {
test(src);
test(src.replaceAll("@Deprecated", "/** @deprecated */"));
test(src.replaceAll("deprecated", "notDeprecated2") // change element name
.replaceAll("@Deprecated", "/// @deprecated\n"));
}
} catch (Exception e) {
addFailure(e);
} finally {
checkStatus();
}
}
private void test(String src) {
addTestCase(src);
printf("Testing test case :\n%s\n", src);
try {
Map<String, ? extends JavaFileObject> classes = compile(src).getClasses();
String outerClassName = classes.keySet().stream()
.filter(n -> !n.contains("$"))
.findFirst().orElse(null);
echo("Testing outer class : " + outerClassName);
ClassModel cf = readClassFile(classes.get(outerClassName));
DeprecatedAttribute attr = cf.findAttribute(Attributes.deprecated()).orElse(null);
testAttribute(outerClassName, attr, cf);
testInnerClasses(cf, classes);
testMethods(cf);
testFields(cf);
} catch (Exception e) {
addFailure(e);
}
}
private void testInnerClasses(ClassModel cf, Map<String, ? extends JavaFileObject> classes)
throws IOException {
InnerClassesAttribute innerAttr = cf.findAttribute(Attributes.innerClasses()).orElse(null);
assert innerAttr != null;
for (InnerClassInfo innerClass : innerAttr.classes()) {
String innerClassName = innerClass.innerClass().name().stringValue();
echo("Testing inner class : " + innerClassName);
ClassModel innerCf = readClassFile(classes.get(innerClassName));
DeprecatedAttribute attr = innerCf.findAttribute(Attributes.deprecated()).orElse(null);
assert innerClass.innerName().isPresent();
String innerClassSimpleName = innerClass.innerName().get().stringValue();
testAttribute(innerClassSimpleName, attr, innerCf);
if (innerClassName.contains("Local")) {
testMethods(innerCf);
testFields(innerCf);
}
}
}
private void testMethods(ClassModel cf) {
for (MethodModel m : cf.methods()) {
String methodName = m.methodName().stringValue();
echo("Testing method : " + methodName);
DeprecatedAttribute attr = m.findAttribute(Attributes.deprecated()).orElse(null);
testAttribute(methodName, attr, cf);
}
}
private void testFields(ClassModel cm) {
for (FieldModel f : cm.fields()) {
String fieldName = f.fieldName().stringValue();
echo("Testing field : " + fieldName);
DeprecatedAttribute attr = f.findAttribute(Attributes.deprecated()).orElse(null);
testAttribute(fieldName, attr, cm);
}
}
private void testAttribute(String name, DeprecatedAttribute attr, ClassModel cf) {
if (name.contains("deprecated")) {
testDeprecatedAttribute(name, attr, cf);
} else {
checkNull(attr, name + " should not have deprecated attribute");
}
}
private void testDeprecatedAttribute(String name, DeprecatedAttribute attr, ClassModel cm) {
if (checkNotNull(attr, name + " must have deprecated attribute")) {
checkEquals(0, ((BoundAttribute<?>)attr).payloadLen(),
"attribute_length should equal to 0");
checkEquals("Deprecated", attr.attributeName(),
name + " attribute_name_index");
}
}
}