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