1 /*
   2  * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @bug 8042261
  27  * @summary Checking what attribute is generated by annotation Deprecated
  28  *          or javadoc deprecated for field, method, class(inner/local), interface.
  29  * @library /tools/lib /tools/javac/lib ../lib
  30  * @modules jdk.compiler/com.sun.tools.classfile
  31  *          jdk.compiler/com.sun.tools.javac.api
  32  *          jdk.compiler/com.sun.tools.javac.file
  33  *          jdk.compiler/com.sun.tools.javac.main
  34  * @build ToolBox TestBase TestResult InMemoryFileManager
  35  * @run main DeprecatedTest
  36  */
  37 
  38 import com.sun.tools.classfile.Attribute;
  39 import com.sun.tools.classfile.ClassFile;
  40 import com.sun.tools.classfile.ConstantPoolException;
  41 import com.sun.tools.classfile.Deprecated_attribute;
  42 import com.sun.tools.classfile.Field;
  43 import com.sun.tools.classfile.InnerClasses_attribute;
  44 import com.sun.tools.classfile.InnerClasses_attribute.Info;
  45 import com.sun.tools.classfile.Method;
  46 
  47 import javax.tools.JavaFileObject;
  48 import java.io.IOException;
  49 import java.util.Map;
  50 
  51 public class DeprecatedTest extends TestResult {
  52 
  53     private static final String[] sources = new String[]{
  54             "@Deprecated public class deprecated {\n"
  55             + "@Deprecated class deprecatedInner01 {}\n"
  56             + "@Deprecated interface deprecatedInner02 {}\n"
  57             + "@Deprecated enum deprecatedInner03 {}\n"
  58             + "@Deprecated @interface deprecatedInner04 {}\n"
  59             + "class notDeprecatedInner01 {}\n"
  60             + "interface notDeprecatedInner02 {}\n"
  61             + "enum notDeprecatedInner03 {}\n"
  62             + "@interface notDeprecatedInner04 {}\n"
  63             + "@Deprecated public void deprecated() {}\n"
  64             + "@Deprecated public int deprecated;\n"
  65             + "public void notDeprecated() {}\n"
  66             + "public int notDeprecated;\n"
  67             + "public void f() {\n"
  68             + "    @Deprecated class deprecatedLocal {\n"
  69             + "        @Deprecated int deprecated;\n"
  70             + "        @Deprecated void deprecated() {}\n"
  71             + "        int notDeprecated;\n"
  72             + "        void notDeprecated(){}\n"
  73             + "    }\n"
  74             + "    class notDeprecatedLocal {\n"
  75             + "        @Deprecated int deprecated;\n"
  76             + "        @Deprecated void deprecated() {}\n"
  77             + "        int notDeprecated;\n"
  78             + "        void notDeprecated(){}\n"
  79             + "    }}\n"
  80             + "}",
  81             "@Deprecated public interface deprecated {\n"
  82             + "@Deprecated class deprecatedInner01 {}\n"
  83             + "@Deprecated interface deprecatedInner02 {}\n"
  84             + "@Deprecated enum deprecatedInner03 {}\n"
  85             + "@Deprecated @interface deprecatedInner04 {}\n"
  86             + "class notDeprecatedInner01 {}\n"
  87             + "interface notDeprecatedInner02 {}\n"
  88             + "enum notDeprecatedInner03 {}\n"
  89             + "@interface notDeprecatedInner04 {}\n"
  90             + "@Deprecated void deprecated01();\n"
  91             + "void notDeprecated01();\n"
  92             + "@Deprecated default void deprecated02() {}\n"
  93             + "default void notDeprecated02() {}\n"
  94             + "@Deprecated int deprecated = 0;\n"
  95             + "int notDeprecated = 0;\n"
  96             + "}",
  97             "@Deprecated public enum deprecated {\n"
  98             + "@Deprecated deprecated, notDeprecated;\n"
  99             + "@Deprecated class deprecatedInner01 {}\n"
 100             + "@Deprecated interface deprecatedInner02 {}\n"
 101             + "@Deprecated enum deprecatedInner03 {}\n"
 102             + "@Deprecated @interface deprecatedInner04 {}\n"
 103             + "class notDeprecatedInner01 {}\n"
 104             + "interface notDeprecatedInner02 {}\n"
 105             + "enum notDeprecatedInner03 {}\n"
 106             + "@interface notDeprecatedInner04 {}\n"
 107             + "@Deprecated public void deprecated() {}\n"
 108             + "public void notDeprecated() {}\n"
 109             + "public void f() {\n"
 110             + "    @Deprecated class deprecatedLocal {\n"
 111             + "        @Deprecated int deprecated;\n"
 112             + "        @Deprecated void deprecated() {}\n"
 113             + "        int notDeprecated;\n"
 114             + "        void notDeprecated(){}\n"
 115             + "    }\n"
 116             + "    class notDeprecatedLocal {\n"
 117             + "        @Deprecated int deprecated;\n"
 118             + "        @Deprecated void deprecated() {}\n"
 119             + "        int notDeprecated;\n"
 120             + "        void notDeprecated(){}\n"
 121             + "    }}\n"
 122             + "}",
 123             "@Deprecated public @interface deprecated {\n"
 124             + "@Deprecated class deprecatedInner01 {}\n"
 125             + "@Deprecated interface deprecatedInner02 {}\n"
 126             + "@Deprecated enum deprecatedInner03 {}\n"
 127             + "@Deprecated @interface deprecatedInner04 {}\n"
 128             + "class notDeprecatedInner01 {}\n"
 129             + "interface notDeprecatedInner02 {}\n"
 130             + "enum notDeprecatedInner03 {}\n"
 131             + "@interface notDeprecatedInner04 {}\n"
 132             + "@Deprecated int deprecated() default 0;\n"
 133             + "int notDeprecated() default 0;\n"
 134             + "@Deprecated int deprecated = 0;\n"
 135             + "int notDeprecated = 0;\n"
 136             + "}",
 137             "public class notDeprecated {\n"
 138             + "@Deprecated class deprecatedInner01 {}\n"
 139             + "@Deprecated interface deprecatedInner02 {}\n"
 140             + "@Deprecated enum deprecatedInner03 {}\n"
 141             + "@Deprecated @interface deprecatedInner04 {}\n"
 142             + "class notDeprecatedInner01 {}\n"
 143             + "interface notDeprecatedInner02 {}\n"
 144             + "enum notDeprecatedInner03 {}\n"
 145             + "@interface notDeprecatedInner04 {}\n"
 146             + "@Deprecated public void deprecated() {}\n"
 147             + "@Deprecated public int deprecated;\n"
 148             + "public void notDeprecated() {}\n"
 149             + "public int notDeprecated;\n"
 150             + "public void f() {\n"
 151             + "    @Deprecated class deprecatedLocal {\n"
 152             + "        @Deprecated int deprecated;\n"
 153             + "        @Deprecated void deprecated() {}\n"
 154             + "        int notDeprecated;\n"
 155             + "        void notDeprecated(){}\n"
 156             + "    }\n"
 157             + "    class notDeprecatedLocal {\n"
 158             + "        @Deprecated int deprecated;\n"
 159             + "        @Deprecated void deprecated() {}\n"
 160             + "        int notDeprecated;\n"
 161             + "        void notDeprecated(){}\n"
 162             + "    }}\n"
 163             + "}",
 164             "public interface notDeprecated {\n"
 165             + "@Deprecated class deprecatedInner01 {}\n"
 166             + "@Deprecated interface deprecatedInner02 {}\n"
 167             + "@Deprecated enum deprecatedInner03 {}\n"
 168             + "@Deprecated @interface deprecatedInner04 {}\n"
 169             + "class notDeprecatedInner01 {}\n"
 170             + "interface notDeprecatedInner02 {}\n"
 171             + "enum notDeprecatedInner03 {}\n"
 172             + "@interface notDeprecatedInner04 {}\n"
 173             + "@Deprecated void deprecated01();\n"
 174             + "void notDeprecated01();\n"
 175             + "@Deprecated default void deprecated02() {}\n"
 176             + "default void notDeprecated02() {}\n"
 177             + "@Deprecated int deprecated = 0;\n"
 178             + "int notDeprecated = 0;\n"
 179             + "}",
 180             "public enum notDeprecated {\n"
 181             + "@Deprecated deprecated, notDeprecated;\n"
 182             + "@Deprecated class deprecatedInner01 {}\n"
 183             + "@Deprecated interface deprecatedInner02 {}\n"
 184             + "@Deprecated enum deprecatedInner03 {}\n"
 185             + "@Deprecated @interface deprecatedInner04 {}\n"
 186             + "class notDeprecatedInner01 {}\n"
 187             + "interface notDeprecatedInner02 {}\n"
 188             + "enum notDeprecatedInner03 {}\n"
 189             + "@interface notDeprecatedInner04 {}\n"
 190             + "@Deprecated public void deprecated() {}\n"
 191             + "public void notDeprecated() {}\n"
 192             + "public void f() {\n"
 193             + "    @Deprecated class deprecatedLocal {\n"
 194             + "        @Deprecated int deprecated;\n"
 195             + "        @Deprecated void deprecated() {}\n"
 196             + "        int notDeprecated;\n"
 197             + "        void notDeprecated(){}\n"
 198             + "    }\n"
 199             + "    class notDeprecatedLocal {\n"
 200             + "        @Deprecated int deprecated;\n"
 201             + "        @Deprecated void deprecated() {}\n"
 202             + "        int notDeprecated;\n"
 203             + "        void notDeprecated(){}\n"
 204             + "    }}\n"
 205             + "}",
 206             "public @interface notDeprecated {\n"
 207             + "@Deprecated class deprecatedInner01 {}\n"
 208             + "@Deprecated interface deprecatedInner02 {}\n"
 209             + "@Deprecated enum deprecatedInner03 {}\n"
 210             + "@Deprecated @interface deprecatedInner04 {}\n"
 211             + "class notDeprecatedInner01 {}\n"
 212             + "interface notDeprecatedInner02 {}\n"
 213             + "enum notDeprecatedInner03 {}\n"
 214             + "@interface notDeprecatedInner04 {}\n"
 215             + "@Deprecated int deprecated() default 0;\n"
 216             + "int notDeprecated() default 0;\n"
 217             + "@Deprecated int deprecated = 0;\n"
 218             + "int notDeprecated = 0;\n"
 219             + "}"};
 220 
 221     public static void main(String[] args) throws TestFailedException {
 222         new DeprecatedTest().test();
 223     }
 224 
 225     public void test() throws TestFailedException {
 226         try {
 227             for (String src : sources) {
 228                 test(src);
 229                 test(src.replaceAll("@Deprecated", "/** @deprecated */"));
 230             }
 231         } catch (Exception e) {
 232             addFailure(e);
 233         } finally {
 234             checkStatus();
 235         }
 236     }
 237 
 238     private void test(String src) {
 239         addTestCase(src);
 240         printf("Testing test case :\n%s\n", src);
 241         try {
 242             Map<String, ? extends JavaFileObject> classes = compile(src).getClasses();
 243             String outerClassName = classes.containsKey("deprecated")
 244                     ? "deprecated"
 245                     : "notDeprecated";
 246             echo("Testing outer class : " + outerClassName);
 247             ClassFile cf = readClassFile(classes.get(outerClassName));
 248             Deprecated_attribute attr = (Deprecated_attribute)
 249                     cf.getAttribute(Attribute.Deprecated);
 250             testAttribute(outerClassName, attr, cf);
 251             testInnerClasses(cf, classes);
 252             testMethods(cf);
 253             testFields(cf);
 254         } catch (Exception e) {
 255             addFailure(e);
 256         }
 257     }
 258 
 259     private void testInnerClasses(ClassFile cf, Map<String, ? extends JavaFileObject> classes)
 260             throws ConstantPoolException, IOException {
 261         InnerClasses_attribute innerAttr = (InnerClasses_attribute)
 262                 cf.getAttribute(Attribute.InnerClasses);
 263         for (Info innerClass : innerAttr.classes) {
 264             String innerClassName = cf.constant_pool.
 265                     getClassInfo(innerClass.inner_class_info_index).getName();
 266             echo("Testing inner class : " + innerClassName);
 267             ClassFile innerCf = readClassFile(classes.get(innerClassName));
 268             Deprecated_attribute attr = (Deprecated_attribute)
 269                     innerCf.getAttribute(Attribute.Deprecated);
 270             String innerClassSimpleName = innerClass.getInnerName(cf.constant_pool);
 271             testAttribute(innerClassSimpleName, attr, innerCf);
 272             if (innerClassName.contains("Local")) {
 273                 testMethods(innerCf);
 274                 testFields(innerCf);
 275             }
 276         }
 277     }
 278 
 279     private void testMethods(ClassFile cf)
 280             throws ConstantPoolException {
 281         for (Method m : cf.methods) {
 282             String methodName = cf.constant_pool.getUTF8Value(m.name_index);
 283             echo("Testing method : " + methodName);
 284             Deprecated_attribute attr = (Deprecated_attribute)
 285                     m.attributes.get(Attribute.Deprecated);
 286             testAttribute(methodName, attr, cf);
 287         }
 288     }
 289 
 290     private void testFields(ClassFile cf) throws ConstantPoolException {
 291         for (Field f : cf.fields) {
 292             String fieldName = cf.constant_pool.getUTF8Value(f.name_index);
 293             echo("Testing field : " + fieldName);
 294             Deprecated_attribute attr = (Deprecated_attribute)
 295                     f.attributes.get(Attribute.Deprecated);
 296             testAttribute(fieldName, attr, cf);
 297         }
 298     }
 299 
 300     private void testAttribute(String name, Deprecated_attribute attr, ClassFile cf)
 301             throws ConstantPoolException {
 302         if (name.contains("deprecated")) {
 303             testDeprecatedAttribute(name, attr, cf);
 304         } else {
 305             checkNull(attr, name + " should not have deprecated attribute");
 306         }
 307     }
 308 
 309     private void testDeprecatedAttribute(String name, Deprecated_attribute attr, ClassFile cf)
 310             throws ConstantPoolException {
 311         if (checkNotNull(attr, name + " must have deprecated attribute")) {
 312             checkEquals(0, attr.attribute_length,
 313                     "attribute_length should equal to 0");
 314             checkEquals("Deprecated",
 315                     cf.constant_pool.getUTF8Value(attr.attribute_name_index),
 316                     name + " attribute_name_index");
 317         }
 318     }
 319 }