TypeAnnotationsPretty.java revision 2702:b9daa6475f12
1/*
2 * Copyright (c) 2013, 2014, 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 8023522
27 * @summary test Pretty print of type annotations
28 * @author wmdietl
29 */
30
31import com.sun.source.tree.ClassTree;
32import com.sun.source.tree.CompilationUnitTree;
33import com.sun.tools.javac.api.JavacTaskImpl;
34import com.sun.tools.javac.tree.JCTree;
35
36import java.io.IOException;
37import java.net.URI;
38import java.util.Arrays;
39import java.util.List;
40import java.util.LinkedList;
41
42import javax.tools.JavaCompiler;
43import javax.tools.JavaFileManager;
44import javax.tools.JavaFileObject;
45import javax.tools.SimpleJavaFileObject;
46import javax.tools.ToolProvider;
47
48public class TypeAnnotationsPretty {
49    private final JavaCompiler tool;
50
51    TypeAnnotationsPretty() {
52        tool = ToolProvider.getSystemJavaCompiler();
53    }
54
55    private List<String> matches = new LinkedList<String>();
56    private List<String> mismatches = new LinkedList<String>();
57
58    public static void main(String... args) throws Exception {
59        TypeAnnotationsPretty tap = new TypeAnnotationsPretty();
60
61        tap.runField("@TA()\nObject cls = null");
62        tap.runField("@TA()\nObject cls = new @TA() Object()");
63
64        tap.runField("@TA()\nList<@TB() Object> cls = null");
65        tap.runField("@TA()\nList<@TB() Object> cls = new @TA() LinkedList<@TB() Object>()");
66
67        tap.runField("Class[] cls = null");
68        tap.runField("@TA()\nClass[] cls = null");
69        tap.runField("Class @TA() [] cls = null");
70        tap.runField("@TA()\nClass @TB() [] cls = null");
71
72        tap.runField("Class[] cls = new Class[]{Object.class}");
73        tap.runField("@TA()\nClass[] cls = new @TA() Class[]{Object.class}");
74        tap.runField("Class @TB() [] cls = new Class @TB() []{Object.class}");
75        tap.runField("@TA()\nClass @TB() [] cls = new @TA() Class @TB() []{Object.class}");
76        tap.runField("@TA()\nClass @TB() [] @TC() [] cls = new @TA() Class @TB() [10] @TC() []");
77        tap.runField("Class @TB() [] @TC() [] cls = new Class @TB() [10] @TC() []");
78        tap.runField("@TA()\nClass @TB() [] @TC() [] @TD() [] cls = new @TA() Class @TB() [10] @TC() [] @TD() []");
79
80        tap.runMethod("\n@TA()\nObject test(@TB()\nList<@TC() String> p) {\n" +
81                "    return null;\n" +
82                "}");
83
84
85        if (!tap.matches.isEmpty()) {
86            for (String m : tap.matches)
87                System.out.println(m);
88        }
89        if (!tap.mismatches.isEmpty()) {
90            for (String mm : tap.mismatches)
91                System.err.println(mm + NL);
92            throw new RuntimeException("Tests failed!");
93        }
94    }
95
96    private static final String prefix =
97            "import java.lang.annotation.*;" +
98            "import java.util.*;" +
99            "public class Test {";
100
101    private static final String postfix =
102            "@Target(ElementType.TYPE_USE)" +
103            "@interface TA {}" +
104            "@Target(ElementType.TYPE_USE)" +
105            "@interface TB {}" +
106            "@Target(ElementType.TYPE_USE)" +
107            "@interface TC {}" +
108            "@Target(ElementType.TYPE_USE)" +
109            "@interface TD {}";
110
111    private static final String NL = System.getProperty("line.separator");
112
113    private void runField(String code) throws IOException {
114        String src = prefix +
115                code + "; }" +
116                postfix;
117
118        try (JavaFileManager fm = tool.getStandardFileManager(null, null, null)) {
119            JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, null,
120                    null, Arrays.asList(new MyFileObject(src)));
121
122            for (CompilationUnitTree cut : ct.parse()) {
123                JCTree.JCVariableDecl var =
124                        (JCTree.JCVariableDecl) ((ClassTree) cut.getTypeDecls().get(0)).getMembers().get(0);
125                checkMatch(code, var);
126            }
127        }
128    }
129
130    private void runMethod(String code) throws IOException {
131        String src = prefix +
132                code + "}" +
133                postfix;
134
135        try (JavaFileManager fm = tool.getStandardFileManager(null, null, null)) {
136            JavacTaskImpl ct = (JavacTaskImpl) tool.getTask(null, fm, null, null,
137                    null, Arrays.asList(new MyFileObject(src)));
138
139
140            for (CompilationUnitTree cut : ct.parse()) {
141                JCTree.JCMethodDecl meth =
142                        (JCTree.JCMethodDecl) ((ClassTree) cut.getTypeDecls().get(0)).getMembers().get(0);
143                checkMatch(code, meth);
144            }
145        }
146    }
147
148    void checkMatch(String code, JCTree tree) {
149        String expect = code.replace("\n", NL);
150        String found = tree.toString();
151        if (!expect.equals(found)) {
152            mismatches.add("Expected: " + expect + NL +
153                    "Obtained: " + found);
154        } else {
155            matches.add("Passed: " + expect);
156        }
157    }
158}
159
160
161class MyFileObject extends SimpleJavaFileObject {
162
163    private String text;
164
165    public MyFileObject(String text) {
166        super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
167        this.text = text;
168    }
169
170    @Override
171    public CharSequence getCharContent(boolean ignoreEncodingErrors) {
172        return text;
173    }
174}
175