TestTrees.java revision 3294:9adfb22ff08f
1/*
2 * Copyright (c) 2006, 2016, 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 6346249 6392177 6411385
27 * @summary new Trees API
28 * @modules jdk.compiler/com.sun.tools.javac.tree
29 */
30
31import java.io.*;
32import java.lang.annotation.*;
33import java.util.*;
34import javax.annotation.processing.*;
35import javax.lang.model.SourceVersion;
36import javax.lang.model.element.*;
37import javax.lang.model.type.*;
38import javax.tools.*;
39
40import com.sun.source.tree.*;
41import com.sun.source.util.*;
42import com.sun.tools.javac.tree.JCTree;
43import com.sun.tools.javac.tree.TreeInfo;
44
45@Anno
46@SupportedAnnotationTypes("*")
47public class TestTrees extends AbstractProcessor {
48    @Anno
49    void annoMethod() { }
50
51    @Anno
52    int annoField;
53
54    @Anno
55    public TestTrees() {
56    }
57
58    static final String testSrcDir = System.getProperty("test.src");
59    static final String testClassDir = System.getProperty("test.classes");
60    static final String self = TestTrees.class.getName();
61    static PrintWriter out = new PrintWriter(System.err, true);
62
63    public static void main(String[] args) throws IOException {
64        new TestTrees().run();
65    }
66
67    void run() throws IOException {
68
69        JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
70
71        DiagnosticListener<JavaFileObject> dl = new DiagnosticListener<JavaFileObject>() {
72                public void report(Diagnostic d) {
73                    error(d.toString());
74                }
75            };
76
77        try (StandardJavaFileManager fm = tool.getStandardFileManager(dl, null, null)) {
78            Iterable<? extends JavaFileObject> files =
79                fm.getJavaFileObjectsFromFiles(Arrays.asList(new File(testSrcDir, self + ".java")));
80
81            Iterable<String> opts = Arrays.asList(
82                "-XaddExports:"
83                + "jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED",
84                "-d", ".",
85                "-XDcompilePolicy=simple");
86
87            System.err.println("simple compilation, no processing");
88            JavacTask task = (JavacTask) tool.getTask(out, fm, dl, opts, null, files);
89            task.setTaskListener(new MyTaskListener(task));
90            if (!task.call())
91                throw new AssertionError("compilation failed");
92
93            opts =  Arrays.asList(
94                "-XaddExports:"
95                + "jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED",
96                "-XDaccessInternalAPI",
97                "-d", ".",
98                "-processorpath", testClassDir,
99                "-processor", self,
100                "-XDcompilePolicy=simple");
101
102            System.err.println();
103            System.err.println("compilation with processing");
104            task = (JavacTask) tool.getTask(out, fm, dl,opts, null, files);
105            if (!task.call())
106                throw new AssertionError("compilation failed");
107
108            if (errors > 0)
109                throw new AssertionError(errors + " errors occurred");
110        }
111    }
112
113    void testElement(Trees trees, Element e) {
114        trees.getClass();
115        e.getClass();
116
117        System.err.println("testElement: " + e);
118        Tree tree = trees.getTree(e);
119        //System.err.println(tree);
120
121        if (TreeInfo.symbolFor((JCTree)tree) != e)
122            error("bad result from getTree");
123
124        TreePath path = trees.getPath(e);
125        if (path == null) {
126            error("getPath returned null");
127            return;
128        }
129        if (path.getLeaf() != tree)
130            error("bad result from getPath");
131
132        Element e2 = trees.getElement(path);
133        if (e2 == null) {
134            error("getElement returned null");
135            return;
136        }
137        if (e2 != e)
138            error("bad result from getElement");
139
140        // The TypeMirror is not available yet when annotation processing;
141        // it is set up later during ANALYSE.
142        TypeMirror t = trees.getTypeMirror(path);
143        if (t != null && t.getKind() == TypeKind.DECLARED &&
144                ((DeclaredType)t).asElement() != e2)
145            error("bad result from getTypeMirror");
146
147        for (AnnotationMirror m: e.getAnnotationMirrors()) {
148            testAnnotation(trees, e, m);
149        }
150    }
151
152    void testAnnotation(Trees trees, Element e, AnnotationMirror a) {
153        System.err.println("testAnnotation: " + e + " " + a);
154        Tree tree = trees.getTree(e, a);
155
156        if (tree.getKind() != Tree.Kind.ANNOTATION && tree.getKind() != Tree.Kind.TYPE_ANNOTATION)
157            error("bad result from getTree");
158
159        TreePath path = trees.getPath(e, a);
160        if (path.getLeaf() != tree)
161            error("bad result from getPath");
162    }
163
164    void testAllDeclarations(Trees trees, CompilationUnitTree cut) {
165        new TreePathScanner<Void, Void>() {
166            @Override public Void scan(Tree tree, Void p) {
167                if (tree == null) return null;
168                switch (tree.getKind()) {
169                    case METHOD: case CLASS: case VARIABLE: case TYPE_PARAMETER:
170                        TreePath path = new TreePath(getCurrentPath(), tree);
171                        Element el = trees.getElement(path);
172                        if (el == null) {
173                            error("null element");
174                        } else {
175                            TreePath inferred = trees.getPath(el);
176                            if (inferred == null) {
177                                error("null path");
178                            } else {
179                                if (inferred.getLeaf() != path.getLeaf())
180                                    error("bad result from getPath");
181                            }
182                            if (trees.getTree(el) != path.getLeaf())
183                                error("bad result from getTree");
184                            for (AnnotationMirror m: el.getAnnotationMirrors()) {
185                                testAnnotation(trees, el, m);
186                            }
187                        }
188                }
189                return super.scan(tree, p);
190            }
191        }.scan(cut, null);
192    }
193
194    void error(String msg) {
195        if (messager != null)
196            // annotation processing will happen in a separate instance/classloader
197            // so pass the message back to the calling instance.
198            messager.printMessage(Diagnostic.Kind.ERROR, msg);
199        else {
200            System.err.println(msg);
201            errors++;
202        }
203
204    }
205
206    Messager messager;
207    int errors;
208
209
210    public boolean process(Set<? extends TypeElement> annos, RoundEnvironment rEnv) {
211        Trees trees = Trees.instance(processingEnv);
212        messager = processingEnv.getMessager();
213
214        for (Element e: rEnv.getRootElements()) {
215            testElement(trees, e);
216        }
217
218        for (TypeElement anno: annos) {
219            Set<? extends Element> elts = rEnv.getElementsAnnotatedWith(anno);
220            System.err.println("anno: " + anno);
221            System.err.println("elts: " + elts);
222            if (elts != null) { // 6397298, should return empty set
223                for (Element e: rEnv.getElementsAnnotatedWith(anno))
224                    testElement(trees, e);
225            }
226        }
227
228        return true;
229    }
230
231    @Override
232    public SourceVersion getSupportedSourceVersion() {
233        return SourceVersion.latest();
234    }
235
236    class MyTaskListener implements TaskListener {
237        MyTaskListener(JavacTask task) {
238            this.task = task;
239        }
240
241        public void started(TaskEvent e) {
242            System.err.println("started " + e);
243        }
244
245        public void finished(TaskEvent e) {
246            //System.err.println("finished " + e);
247            switch (e.getKind()) {
248            case ANALYZE:
249                testElement(Trees.instance(task), e.getTypeElement());
250                testAllDeclarations(Trees.instance(task), e.getCompilationUnit());
251                break;
252            }
253        }
254
255        private final JavacTask task;
256    }
257
258    public static class TestTypeParams<@Anno T extends CharSequence> {
259        public <@Anno T extends Object> TestTypeParams(T param) { }
260        public <@Anno T extends Number> void m(T param) {
261            int local;
262            try {
263                new String();
264            } catch (Exception exc) { }
265        }
266    }
267}
268
269@Retention(RetentionPolicy.SOURCE)
270@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.TYPE_PARAMETER,
271         ElementType.FIELD, ElementType.LOCAL_VARIABLE})
272@interface Anno {
273}
274