1/*
2 * Copyright (c) 2010, 2015, 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     6519115
27 * @summary Verify MirroredTypeException vs MirroredTypesException is thrown
28 * @library /tools/javac/lib
29 * @modules java.compiler
30 *          jdk.compiler
31 * @build JavacTestingAbstractProcessor
32 * @compile Plurality.java
33 * @compile -processor Plurality -proc:only Plurality.java
34 * @author  Joseph D. Darcy
35 */
36import java.lang.annotation.*;
37import java.math.BigDecimal;
38import java.util.*;
39import javax.annotation.processing.*;
40import javax.lang.model.*;
41import javax.lang.model.element.*;
42import javax.lang.model.type.*;
43import javax.lang.model.util.*;
44
45@P0
46@P1
47@P2
48@S1
49public class Plurality extends JavacTestingAbstractProcessor {
50    private boolean executed = false;
51
52    public boolean process(Set<? extends TypeElement> annotations,
53                           RoundEnvironment roundEnv) {
54        if (!roundEnv.processingOver()) {
55            executed = true;
56            // Processing just this type
57            Element e = elements.getTypeElement("Plurality");
58            Class[] classes = null;
59
60            P0 p0 = e.getAnnotation(P0.class);
61            try {
62                classes = p0.value();
63            } catch (MirroredTypesException mtse) {
64                if (mtse instanceof MirroredTypeException) {
65                    throw new RuntimeException("Wrong exception type!");
66                }
67
68                List<? extends TypeMirror> types = mtse.getTypeMirrors();
69                if (types.size() != 0)
70                    throw new RuntimeException("List size != 0: " +
71                                               types);
72            }
73
74            P1 p1 = e.getAnnotation(P1.class);
75            try {
76                classes = p1.value();
77            } catch (MirroredTypesException mtse) {
78                if (mtse instanceof MirroredTypeException) {
79                    throw new RuntimeException("Wrong exception type!");
80                }
81
82                List<? extends TypeMirror> types = mtse.getTypeMirrors();
83                if (types.size() != 1)
84                    throw new RuntimeException("List size != 1: " +
85                                               types);
86                checkTypeListMatchesClasses(types,
87                                            this.getClass().getAnnotation(P1.class).value());
88            }
89
90
91            P2 p2 = e.getAnnotation(P2.class);
92            try {
93                classes = p2.value();
94            } catch(MirroredTypesException mtse) {
95                if (mtse instanceof MirroredTypeException) {
96                    throw new RuntimeException("Wrong exception type!");
97                }
98
99                List<? extends TypeMirror> types = mtse.getTypeMirrors();
100                if (types.size() != 2)
101                    throw new RuntimeException("List size != 2: " +
102                                               types);
103                checkTypeListMatchesClasses(types,
104                                            this.getClass().getAnnotation(P2.class).value());
105            }
106
107            Class<?> clazz = null;
108            S1 s1 = e.getAnnotation(S1.class);
109            try {
110                clazz = s1.value();
111            } catch(MirroredTypesException mtse) {
112                List<? extends TypeMirror> types = mtse.getTypeMirrors();
113                if (types.size() != 1)
114                    throw new RuntimeException("List size != 1: " +
115                                               types);
116                Class<?>[] clazzes = new Class<?>[1];
117                clazzes[0] = this.getClass().getAnnotation(S1.class).value();
118                checkTypeListMatchesClasses(types,
119                                            clazzes);
120            }
121
122            try {
123                clazz = s1.value();
124            } catch(MirroredTypeException mte) {
125                TypeMirror type = mte.getTypeMirror();
126                if (type == null) {
127                    throw new RuntimeException("Expected null");
128                }
129                List<TypeMirror> types = new ArrayList<>();
130                types.add(type);
131                Class<?>[] clazzes = new Class<?>[1];
132                clazzes[0] = this.getClass().getAnnotation(S1.class).value();
133                checkTypeListMatchesClasses(types, clazzes);
134            }
135        } else {
136            if (!executed) {
137                throw new RuntimeException("Didn't seem to do anything!");
138            }
139        }
140        return true;
141    }
142
143    private static void checkTypeListMatchesClasses(List<? extends TypeMirror> types,
144                                               Class<?>[] classes) {
145        if (types.size() != classes.length)
146            throw new RuntimeException("Size mismatch:\n\t" + types +
147                                       "\n\t" + Arrays.toString(classes));
148        int i = -1;
149        for(Class<?> clazz : classes) {
150            i++;
151            String canonicalName = clazz.getCanonicalName();
152            String toStringName = types.get(i).toString();
153            if (!canonicalName.equals(toStringName))
154                throw new RuntimeException("Mismatched names: " +
155                                           canonicalName + "\t" +
156                                           toStringName);
157        }
158    }
159}
160
161@Retention(RetentionPolicy.RUNTIME)
162@interface P0 {
163    Class[] value() default {};
164}
165
166@Retention(RetentionPolicy.RUNTIME)
167@interface P1 {
168    Class[] value() default {Integer.class};
169}
170
171@Retention(RetentionPolicy.RUNTIME)
172@interface P2 {
173    Class[] value() default {String.class, Number.class};
174}
175
176@Retention(RetentionPolicy.RUNTIME)
177@interface S1 {
178    Class value() default BigDecimal.class;
179}
180