jjg@988: /* jjg@988: * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. jjg@988: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jjg@988: * jjg@988: * This code is free software; you can redistribute it and/or modify it jjg@988: * under the terms of the GNU General Public License version 2 only, as jjg@988: * published by the Free Software Foundation. jjg@988: * jjg@988: * This code is distributed in the hope that it will be useful, but WITHOUT jjg@988: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jjg@988: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jjg@988: * version 2 for more details (a copy is included in the LICENSE file that jjg@988: * accompanied this code). jjg@988: * jjg@988: * You should have received a copy of the GNU General Public License version jjg@988: * 2 along with this work; if not, write to the Free Software Foundation, jjg@988: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jjg@988: * jjg@988: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA jjg@988: * or visit www.oracle.com if you need additional information or have any jjg@988: * questions. jjg@988: */ jjg@988: jjg@988: /* jjg@988: * @test darcy@1054: * @bug 7029150 7025809 jjg@988: * @summary Test support for union types jjg@988: * @library ../../../lib jjg@988: */ jjg@988: jjg@988: import java.net.URI; jjg@988: import java.util.*; jjg@988: import javax.annotation.processing.*; jjg@988: import javax.lang.model.element.*; jjg@988: import javax.lang.model.type.*; jjg@988: import javax.lang.model.util.*; jjg@988: import javax.tools.*; jjg@988: jjg@988: import com.sun.source.tree.*; jjg@988: import com.sun.source.util.*; jjg@988: jjg@988: public class TestUnionType extends JavacTestingAbstractProcessor { jjg@988: enum TestKind { jjg@988: SingleType("E1", "E1", jjg@988: "VariableTree: E1 e", jjg@988: "VariableTree: elem EXCEPTION_PARAMETER e", jjg@988: "VariableTree: elem.type DECLARED", jjg@988: "VariableTree: elem.type.elem CLASS E1", jjg@988: "VariableTree: type DECLARED", jjg@988: "VariableTree: type.elem CLASS E1", jjg@988: "VariableTree: type.elem.type DECLARED"), jjg@988: jjg@988: ValidTypes("E1, E2", "E1 | E2", jjg@988: "VariableTree: E1 | E2 e", jjg@988: "VariableTree: elem EXCEPTION_PARAMETER e", jjg@988: "VariableTree: elem.type UNION Test.E1,Test.E2", jjg@988: "VariableTree: elem.type.elem null", jjg@988: "VariableTree: type UNION Test.E1,Test.E2", jjg@988: "VariableTree: type.elem null"), jjg@988: jjg@988: InvalidTypes("E1, E2", "E1 | EMissing", jjg@988: "VariableTree: E1 | EMissing e", jjg@988: "VariableTree: elem EXCEPTION_PARAMETER e", jjg@988: "VariableTree: elem.type UNION Test.E1,EMissing", jjg@988: "VariableTree: elem.type.elem null", jjg@988: "VariableTree: type UNION Test.E1,EMissing", jjg@988: "VariableTree: type.elem null"), jjg@988: jjg@988: Uncaught("E1", "E1 | E2", jjg@988: "VariableTree: E1 | E2 e", jjg@988: "VariableTree: elem EXCEPTION_PARAMETER e", jjg@988: "VariableTree: elem.type UNION Test.E1,Test.E2", jjg@988: "VariableTree: elem.type.elem null", jjg@988: "VariableTree: type UNION Test.E1,Test.E2", jjg@988: "VariableTree: type.elem null"); jjg@988: jjg@988: TestKind(String throwsTypes, String catchTypes, String... gold) { jjg@988: this.throwsTypes = throwsTypes; jjg@988: this.catchTypes = catchTypes; jjg@988: this.gold = Arrays.asList(gold); jjg@988: } jjg@988: jjg@988: final String throwsTypes; jjg@988: final String catchTypes; jjg@988: final List gold; jjg@988: } jjg@988: jjg@988: static class TestFileObject extends SimpleJavaFileObject { jjg@988: public static final String template = jjg@988: "class Test {\n" jjg@988: + " class E1 extends Exception { }\n" jjg@988: + " class E2 extends Exception { }\n" jjg@988: + " void doSomething() throws #T { }\n" jjg@988: + " void test() {\n" jjg@988: + " try {\n" jjg@988: + " doSomething();\n" jjg@988: + " } catch (#C e) {\n" jjg@988: + " }\n" jjg@988: + " }\n" jjg@988: + "}\n"; jjg@988: jjg@988: public TestFileObject(TestKind tk) { jjg@988: super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE); jjg@988: this.tk = tk; jjg@988: } jjg@988: jjg@988: @Override jjg@988: public CharSequence getCharContent(boolean ignoreEncodingErrors) { jjg@988: return template jjg@988: .replace("#T", tk.throwsTypes) jjg@988: .replace("#C", tk.catchTypes); jjg@988: } jjg@988: final TestKind tk; jjg@988: } jjg@988: jjg@988: public static void main(String... args) throws Exception { jjg@988: JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); jjg@988: List options = Arrays.asList("-proc:only"); jjg@988: for (TestKind tk: TestKind.values()) { jjg@988: System.err.println("Test: " + tk); jjg@988: TestUnionType p = new TestUnionType(); jjg@988: JavaFileObject fo = new TestFileObject(tk); jjg@988: JavaCompiler.CompilationTask task = comp.getTask(null, null, null, options, null, Arrays.asList(fo)); jjg@988: task.setProcessors(Arrays.asList(p)); jjg@988: boolean ok = task.call(); jjg@988: System.err.println("compilation " + (ok ? "passed" : "failed")); jjg@988: if (!ok) jjg@988: throw new Exception("compilation failed unexpectedly"); jjg@988: if (!p.log.equals(tk.gold)) { jjg@988: System.err.println("Expected output:"); jjg@988: for (String g: tk.gold) jjg@988: System.err.println(g); jjg@988: throw new Exception("unexpected output from test"); jjg@988: } jjg@988: System.err.println(); jjg@988: } jjg@988: } jjg@988: jjg@988: Trees trees; jjg@988: List log; jjg@988: jjg@988: @Override jjg@988: public void init(ProcessingEnvironment env) { jjg@988: super.init(env); jjg@988: trees = Trees.instance(env); jjg@988: log = new ArrayList(); jjg@988: } jjg@988: jjg@988: @Override jjg@988: public boolean process(Set annotations, RoundEnvironment roundEnv) { jjg@988: if (!roundEnv.processingOver()) { jjg@988: for (Element e: roundEnv.getRootElements()) { jjg@988: scan(trees.getPath(e)); jjg@988: } jjg@988: } jjg@988: return true; jjg@988: } jjg@988: jjg@988: void scan(TreePath path) { jjg@988: new Scanner().scan(path, null); jjg@988: } jjg@988: jjg@988: class Scanner extends TreePathScanner { jjg@988: @Override jjg@988: public Void visitVariable(VariableTree tree, Void ignore) { jjg@988: TreePath p = getCurrentPath(); jjg@988: Element e = trees.getElement(p); jjg@988: if (e.getKind() == ElementKind.EXCEPTION_PARAMETER) { jjg@988: log("VariableTree: " + tree); jjg@988: log("VariableTree: elem " + print(e)); jjg@988: log("VariableTree: elem.type " + print(e.asType())); jjg@988: log("VariableTree: elem.type.elem " + print(types.asElement(e.asType()))); jjg@988: TypeMirror tm = trees.getTypeMirror(p); jjg@988: log("VariableTree: type " + print(tm)); jjg@988: log("VariableTree: type.elem " + print(types.asElement(tm))); jjg@988: if (types.asElement(tm) != null) jjg@988: log("VariableTree: type.elem.type " + print(types.asElement(tm).asType())); jjg@988: } jjg@988: return super.visitVariable(tree, null); jjg@988: } jjg@988: jjg@988: String print(TypeMirror tm) { jjg@988: return (tm == null) ? null : new TypePrinter().visit(tm); jjg@988: } jjg@988: jjg@988: String print(Element e) { jjg@988: return (e == null) ? null : (e.getKind() + " " + e.getSimpleName()); jjg@988: } jjg@988: jjg@988: void log(String msg) { jjg@988: System.err.println(msg); jjg@988: log.add(msg); jjg@988: } jjg@988: } jjg@988: darcy@1054: class TypePrinter extends SimpleTypeVisitor { jjg@988: @Override jjg@988: protected String defaultAction(TypeMirror tm, Void ignore) { jjg@988: return String.valueOf(tm.getKind()); jjg@988: } jjg@988: jjg@988: @Override jjg@988: public String visitUnion(UnionType t, Void ignore) { jjg@988: return (t.getKind() + " " + t.getAlternatives()); jjg@988: } jjg@988: } jjg@988: }