1/*
2 * Copyright (c) 2013, 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 8004729
27 * @summary javac should generate method parameters correctly.
28 */
29
30import java.lang.*;
31import java.lang.reflect.*;
32import java.lang.annotation.*;
33import java.util.List;
34import java.util.Objects;
35
36import static java.lang.annotation.ElementType.*;
37
38public class WithoutParameters {
39    int errors = 0;
40
41    private WithoutParameters() {}
42
43    public static void main(String argv[]) throws Exception {
44        WithoutParameters wp = new WithoutParameters();
45        wp.runTests(Foo.class.getMethods());
46        wp.runTests(Foo.Inner.class.getConstructors());
47        wp.checkForErrors();
48    }
49
50    void runTests(Method[] methods) throws Exception {
51        for(Method m : methods) {runTest(m);}
52    }
53
54    void runTests(Constructor[] constructors) throws Exception {
55        for(Constructor c : constructors) {runTest(c);}
56    }
57
58    void runTest(Executable e) throws Exception {
59        System.err.println("Inspecting executable " + e);
60        Parameter[] parameters = e.getParameters();
61        Objects.requireNonNull(parameters, "getParameters should never be null");
62
63        ExpectedParameterInfo epi = e.getAnnotation(ExpectedParameterInfo.class);
64        if (epi != null) {
65            abortIfTrue(epi.parameterCount() != e.getParameterCount(), "Bad parameter count for "+ e);
66            abortIfTrue(epi.isVarArgs() != e.isVarArgs(),"Bad varargs value for "+ e);
67        }
68        abortIfTrue(e.getParameterCount() != parameters.length, "Mismatched of parameter counts.");
69
70        for(int i = 0; i < parameters.length; i++) {
71            Parameter p = parameters[i];
72            errorIfTrue(p.isNamePresent(), p + ".isNamePresent == true");
73            errorIfTrue(!p.getDeclaringExecutable().equals(e), p + ".getDeclaringExecutable != " + e);
74            Objects.requireNonNull(p.getType(), "getType() should not be null");
75            Objects.requireNonNull(p.getParameterizedType(), "getParameterizedType() should not be null");
76
77            if (epi != null) {
78                Class<?> expectedParameterType = epi.parameterTypes()[i];
79                errorIfTrue(!p.getType().equals(expectedParameterType),
80                            "Wrong parameter type for " + p + ": expected " + expectedParameterType  +
81                            ", but got " + p.getType());
82
83                ParameterizedInfo[] expectedParameterizedTypes = epi.parameterizedTypes();
84                if (expectedParameterizedTypes.length > 0) {
85                    Type parameterizedType = p.getParameterizedType();
86                    Class<? extends Type> expectedParameterziedTypeType = expectedParameterizedTypes[i].value();
87                    errorIfTrue(!expectedParameterziedTypeType.isAssignableFrom(parameterizedType.getClass()),
88                                "Wrong class of parameteried type of " + p + ": expected " + expectedParameterziedTypeType  +
89                                ", but got " + parameterizedType.getClass());
90
91                    if (expectedParameterziedTypeType.equals(Class.class)) {
92                        errorIfTrue(!parameterizedType.equals(expectedParameterType),
93                                    "Wrong parameteried type for " + p + ": expected " + expectedParameterType  +
94                                    ", but got " + parameterizedType);
95                    } else {
96                        if (expectedParameterziedTypeType.equals(ParameterizedType.class)) {
97                            ParameterizedType ptype = (ParameterizedType)parameterizedType;
98                            errorIfTrue(!ptype.getRawType().equals(expectedParameterType),
99                                        "Wrong raw type for " + p + ": expected " + expectedParameterType  +
100                                        ", but got " + ptype.getRawType());
101                        }
102
103                        // Check string representation
104                        String expectedStringOfType = epi.parameterizedTypes()[i].string();
105                        errorIfTrue(!expectedStringOfType.equals(parameterizedType.toString()),
106                                    "Bad type string" + p + ": expected " + expectedStringOfType  +
107                                    ", but got " + parameterizedType.toString());
108                    }
109                }
110            }
111        }
112    }
113
114    private void checkForErrors() {
115        if (errors > 0)
116            throw new RuntimeException("Failed " + errors + " tests");
117    }
118
119    private void errorIfTrue(boolean predicate, String errMessage) {
120        if (predicate) {
121            errors++;
122            System.err.println(errMessage);
123        }
124    }
125
126    private void abortIfTrue(boolean predicate, String errMessage) {
127        if (predicate) {
128            throw new RuntimeException(errMessage);
129        }
130    }
131
132    @Retention(RetentionPolicy.RUNTIME)
133    @Target({METHOD, CONSTRUCTOR})
134    @interface ExpectedParameterInfo {
135        int parameterCount() default 0;
136        Class<?>[] parameterTypes() default {};
137        ParameterizedInfo[] parameterizedTypes() default {};
138        boolean isVarArgs() default false;
139    }
140
141    @Target({})
142    @interface ParameterizedInfo {
143        Class<? extends Type> value() default Class.class;
144        String string() default "";
145    }
146
147    public class Foo {
148        int thing;
149        @ExpectedParameterInfo(parameterCount = 6,
150                               parameterTypes =
151                               {int.class, Foo.class,
152                                List.class, List.class,
153                                List.class, String[].class},
154                               parameterizedTypes =
155                                {@ParameterizedInfo(Class.class),
156                                 @ParameterizedInfo(Class.class),
157                                 @ParameterizedInfo(value=ParameterizedType.class, string="java.util.List<?>"),
158                                 @ParameterizedInfo(value=ParameterizedType.class, string="java.util.List<WithoutParameters$Foo>"),
159                                 @ParameterizedInfo(value=ParameterizedType.class, string="java.util.List<? extends WithoutParameters$Foo>"),
160                                 @ParameterizedInfo(Class.class)},
161                               isVarArgs = true)
162        public void qux(int quux, Foo quuux,
163                        List<?> l, List<Foo> l2,
164                        List<? extends Foo> l3,
165                        String... rest) {}
166        public class Inner {
167            int thang;
168            @ExpectedParameterInfo(parameterCount = 2,
169                                   parameterTypes = {Foo.class, int.class})
170            public Inner(int theng) {
171                thang = theng + thing;
172            }
173        }
174    }
175}
176