Tue, 14 May 2013 15:04:06 -0700
8013852: update reference impl for type-annotations
Reviewed-by: jjg
Contributed-by: wdietl@gmail.com, steve.sides@oracle.com, joel.franck@oracle.com, alex.buckley@oracle.com
jjg@988 | 1 | /* |
jjg@988 | 2 | * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. |
jjg@988 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
jjg@988 | 4 | * |
jjg@988 | 5 | * This code is free software; you can redistribute it and/or modify it |
jjg@988 | 6 | * under the terms of the GNU General Public License version 2 only, as |
jjg@988 | 7 | * published by the Free Software Foundation. |
jjg@988 | 8 | * |
jjg@988 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
jjg@988 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
jjg@988 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
jjg@988 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
jjg@988 | 13 | * accompanied this code). |
jjg@988 | 14 | * |
jjg@988 | 15 | * You should have received a copy of the GNU General Public License version |
jjg@988 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
jjg@988 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
jjg@988 | 18 | * |
jjg@988 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
jjg@988 | 20 | * or visit www.oracle.com if you need additional information or have any |
jjg@988 | 21 | * questions. |
jjg@988 | 22 | */ |
jjg@988 | 23 | |
jjg@988 | 24 | /* |
jjg@988 | 25 | * @test |
darcy@1054 | 26 | * @bug 7029150 7025809 |
jjg@988 | 27 | * @summary Test support for union types |
darcy@1466 | 28 | * @library /tools/javac/lib |
jjg@988 | 29 | */ |
jjg@988 | 30 | |
jjg@988 | 31 | import java.net.URI; |
jjg@988 | 32 | import java.util.*; |
jjg@988 | 33 | import javax.annotation.processing.*; |
jjg@988 | 34 | import javax.lang.model.element.*; |
jjg@988 | 35 | import javax.lang.model.type.*; |
jjg@988 | 36 | import javax.lang.model.util.*; |
jjg@988 | 37 | import javax.tools.*; |
jjg@988 | 38 | |
jjg@988 | 39 | import com.sun.source.tree.*; |
jjg@988 | 40 | import com.sun.source.util.*; |
jjg@988 | 41 | |
jjg@988 | 42 | public class TestUnionType extends JavacTestingAbstractProcessor { |
jjg@988 | 43 | enum TestKind { |
jjg@988 | 44 | SingleType("E1", "E1", |
jjg@988 | 45 | "VariableTree: E1 e", |
jjg@988 | 46 | "VariableTree: elem EXCEPTION_PARAMETER e", |
jjg@988 | 47 | "VariableTree: elem.type DECLARED", |
jjg@988 | 48 | "VariableTree: elem.type.elem CLASS E1", |
jjg@988 | 49 | "VariableTree: type DECLARED", |
jjg@988 | 50 | "VariableTree: type.elem CLASS E1", |
jjg@988 | 51 | "VariableTree: type.elem.type DECLARED"), |
jjg@988 | 52 | |
jjg@988 | 53 | ValidTypes("E1, E2", "E1 | E2", |
jjg@988 | 54 | "VariableTree: E1 | E2 e", |
jjg@988 | 55 | "VariableTree: elem EXCEPTION_PARAMETER e", |
jjg@988 | 56 | "VariableTree: elem.type UNION Test.E1,Test.E2", |
jjg@988 | 57 | "VariableTree: elem.type.elem null", |
jjg@988 | 58 | "VariableTree: type UNION Test.E1,Test.E2", |
jjg@988 | 59 | "VariableTree: type.elem null"), |
jjg@988 | 60 | |
jjg@988 | 61 | InvalidTypes("E1, E2", "E1 | EMissing", |
jjg@988 | 62 | "VariableTree: E1 | EMissing e", |
jjg@988 | 63 | "VariableTree: elem EXCEPTION_PARAMETER e", |
jjg@988 | 64 | "VariableTree: elem.type UNION Test.E1,EMissing", |
jjg@988 | 65 | "VariableTree: elem.type.elem null", |
jjg@988 | 66 | "VariableTree: type UNION Test.E1,EMissing", |
jjg@988 | 67 | "VariableTree: type.elem null"), |
jjg@988 | 68 | |
jjg@988 | 69 | Uncaught("E1", "E1 | E2", |
jjg@988 | 70 | "VariableTree: E1 | E2 e", |
jjg@988 | 71 | "VariableTree: elem EXCEPTION_PARAMETER e", |
jjg@988 | 72 | "VariableTree: elem.type UNION Test.E1,Test.E2", |
jjg@988 | 73 | "VariableTree: elem.type.elem null", |
jjg@988 | 74 | "VariableTree: type UNION Test.E1,Test.E2", |
jjg@988 | 75 | "VariableTree: type.elem null"); |
jjg@988 | 76 | |
jjg@988 | 77 | TestKind(String throwsTypes, String catchTypes, String... gold) { |
jjg@988 | 78 | this.throwsTypes = throwsTypes; |
jjg@988 | 79 | this.catchTypes = catchTypes; |
jjg@988 | 80 | this.gold = Arrays.asList(gold); |
jjg@988 | 81 | } |
jjg@988 | 82 | |
jjg@988 | 83 | final String throwsTypes; |
jjg@988 | 84 | final String catchTypes; |
jjg@988 | 85 | final List<String> gold; |
jjg@988 | 86 | } |
jjg@988 | 87 | |
jjg@988 | 88 | static class TestFileObject extends SimpleJavaFileObject { |
jjg@988 | 89 | public static final String template = |
jjg@988 | 90 | "class Test {\n" |
jjg@988 | 91 | + " class E1 extends Exception { }\n" |
jjg@988 | 92 | + " class E2 extends Exception { }\n" |
jjg@988 | 93 | + " void doSomething() throws #T { }\n" |
jjg@988 | 94 | + " void test() {\n" |
jjg@988 | 95 | + " try {\n" |
jjg@988 | 96 | + " doSomething();\n" |
jjg@988 | 97 | + " } catch (#C e) {\n" |
jjg@988 | 98 | + " }\n" |
jjg@988 | 99 | + " }\n" |
jjg@988 | 100 | + "}\n"; |
jjg@988 | 101 | |
jjg@988 | 102 | public TestFileObject(TestKind tk) { |
jjg@988 | 103 | super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); |
jjg@988 | 104 | this.tk = tk; |
jjg@988 | 105 | } |
jjg@988 | 106 | |
jjg@988 | 107 | @Override |
jjg@988 | 108 | public CharSequence getCharContent(boolean ignoreEncodingErrors) { |
jjg@988 | 109 | return template |
jjg@988 | 110 | .replace("#T", tk.throwsTypes) |
jjg@988 | 111 | .replace("#C", tk.catchTypes); |
jjg@988 | 112 | } |
jjg@988 | 113 | final TestKind tk; |
jjg@988 | 114 | } |
jjg@988 | 115 | |
jjg@988 | 116 | public static void main(String... args) throws Exception { |
jjg@988 | 117 | JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); |
jjg@988 | 118 | List<String> options = Arrays.asList("-proc:only"); |
jjg@988 | 119 | for (TestKind tk: TestKind.values()) { |
jjg@988 | 120 | System.err.println("Test: " + tk); |
jjg@988 | 121 | TestUnionType p = new TestUnionType(); |
jjg@988 | 122 | JavaFileObject fo = new TestFileObject(tk); |
jjg@988 | 123 | JavaCompiler.CompilationTask task = comp.getTask(null, null, null, options, null, Arrays.asList(fo)); |
jjg@988 | 124 | task.setProcessors(Arrays.asList(p)); |
jjg@988 | 125 | boolean ok = task.call(); |
jjg@988 | 126 | System.err.println("compilation " + (ok ? "passed" : "failed")); |
jjg@988 | 127 | if (!ok) |
jjg@988 | 128 | throw new Exception("compilation failed unexpectedly"); |
jjg@988 | 129 | if (!p.log.equals(tk.gold)) { |
jjg@988 | 130 | System.err.println("Expected output:"); |
jjg@988 | 131 | for (String g: tk.gold) |
jjg@988 | 132 | System.err.println(g); |
jjg@988 | 133 | throw new Exception("unexpected output from test"); |
jjg@988 | 134 | } |
jjg@988 | 135 | System.err.println(); |
jjg@988 | 136 | } |
jjg@988 | 137 | } |
jjg@988 | 138 | |
jjg@988 | 139 | Trees trees; |
jjg@988 | 140 | List<String> log; |
jjg@988 | 141 | |
jjg@988 | 142 | @Override |
jjg@988 | 143 | public void init(ProcessingEnvironment env) { |
jjg@988 | 144 | super.init(env); |
jjg@988 | 145 | trees = Trees.instance(env); |
jjg@988 | 146 | log = new ArrayList<String>(); |
jjg@988 | 147 | } |
jjg@988 | 148 | |
jjg@988 | 149 | @Override |
jjg@988 | 150 | public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { |
jjg@988 | 151 | if (!roundEnv.processingOver()) { |
jjg@988 | 152 | for (Element e: roundEnv.getRootElements()) { |
jjg@988 | 153 | scan(trees.getPath(e)); |
jjg@988 | 154 | } |
jjg@988 | 155 | } |
jjg@988 | 156 | return true; |
jjg@988 | 157 | } |
jjg@988 | 158 | |
jjg@988 | 159 | void scan(TreePath path) { |
jjg@988 | 160 | new Scanner().scan(path, null); |
jjg@988 | 161 | } |
jjg@988 | 162 | |
jjg@988 | 163 | class Scanner extends TreePathScanner<Void,Void> { |
jjg@988 | 164 | @Override |
jjg@988 | 165 | public Void visitVariable(VariableTree tree, Void ignore) { |
jjg@988 | 166 | TreePath p = getCurrentPath(); |
jjg@988 | 167 | Element e = trees.getElement(p); |
jjg@988 | 168 | if (e.getKind() == ElementKind.EXCEPTION_PARAMETER) { |
jjg@988 | 169 | log("VariableTree: " + tree); |
jjg@988 | 170 | log("VariableTree: elem " + print(e)); |
jjg@988 | 171 | log("VariableTree: elem.type " + print(e.asType())); |
jjg@988 | 172 | log("VariableTree: elem.type.elem " + print(types.asElement(e.asType()))); |
jjg@988 | 173 | TypeMirror tm = trees.getTypeMirror(p); |
jjg@988 | 174 | log("VariableTree: type " + print(tm)); |
jjg@988 | 175 | log("VariableTree: type.elem " + print(types.asElement(tm))); |
jjg@988 | 176 | if (types.asElement(tm) != null) |
jjg@988 | 177 | log("VariableTree: type.elem.type " + print(types.asElement(tm).asType())); |
jjg@988 | 178 | } |
jjg@988 | 179 | return super.visitVariable(tree, null); |
jjg@988 | 180 | } |
jjg@988 | 181 | |
jjg@988 | 182 | String print(TypeMirror tm) { |
jjg@988 | 183 | return (tm == null) ? null : new TypePrinter().visit(tm); |
jjg@988 | 184 | } |
jjg@988 | 185 | |
jjg@988 | 186 | String print(Element e) { |
jjg@988 | 187 | return (e == null) ? null : (e.getKind() + " " + e.getSimpleName()); |
jjg@988 | 188 | } |
jjg@988 | 189 | |
jjg@988 | 190 | void log(String msg) { |
jjg@988 | 191 | System.err.println(msg); |
jjg@988 | 192 | log.add(msg); |
jjg@988 | 193 | } |
jjg@988 | 194 | } |
jjg@988 | 195 | |
darcy@1054 | 196 | class TypePrinter extends SimpleTypeVisitor<String, Void> { |
jjg@988 | 197 | @Override |
jjg@988 | 198 | protected String defaultAction(TypeMirror tm, Void ignore) { |
jjg@988 | 199 | return String.valueOf(tm.getKind()); |
jjg@988 | 200 | } |
jjg@988 | 201 | |
jjg@988 | 202 | @Override |
jjg@988 | 203 | public String visitUnion(UnionType t, Void ignore) { |
jjg@988 | 204 | return (t.getKind() + " " + t.getAlternatives()); |
jjg@988 | 205 | } |
jjg@988 | 206 | } |
jjg@988 | 207 | } |