NestedTypeVars.java revision 3744:692418f52877
1/*
2 * Copyright (c) 2016, 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 * @modules jdk.compiler
27 * @build NestedTypeVars
28 * @compile/process/ref=NestedTypeVars.out -processor NestedTypeVars Test$1L1$L2$1L3$L4$L5 Test$1L1$CCheck Test$1L1 Test$1CCheck Test$CCheck Test
29 */
30
31import java.util.Set;
32import java.util.stream.Collectors;
33
34import javax.annotation.processing.AbstractProcessor;
35import javax.annotation.processing.RoundEnvironment;
36import javax.annotation.processing.SupportedAnnotationTypes;
37import javax.lang.model.SourceVersion;
38import javax.lang.model.element.Element;
39import javax.lang.model.element.ExecutableElement;
40import javax.lang.model.element.TypeElement;
41import javax.lang.model.element.TypeParameterElement;
42import javax.lang.model.type.TypeKind;
43import javax.lang.model.type.TypeMirror;
44import javax.lang.model.type.TypeVariable;
45import javax.lang.model.util.ElementFilter;
46
47@SupportedAnnotationTypes("*")
48public class NestedTypeVars extends AbstractProcessor{
49
50    @Override
51    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
52        for (TypeElement te : ElementFilter.typesIn(roundEnv.getRootElements())) {
53            System.out.print(processingEnv.getElementUtils().getBinaryName(te));
54            System.out.print("<");
55            String separator = "";
56            for (TypeParameterElement tp : te.getTypeParameters()) {
57                System.out.print(separator);
58                separator = ", ";
59                System.out.print(tp.getSimpleName());
60                System.out.print(" extends ");
61                System.out.print(tp.getBounds().stream().map(b -> toString(b)).collect(Collectors.joining("&")));
62            }
63            System.out.println(">");
64            for (ExecutableElement m : ElementFilter.methodsIn(te.getEnclosedElements())) {
65                System.out.print("  <");
66                separator = "";
67                for (TypeParameterElement tp : m.getTypeParameters()) {
68                    System.out.print(separator);
69                    separator = ", ";
70                    System.out.print(tp.getSimpleName());
71                    System.out.print(" extends ");
72                    System.out.print(tp.getBounds().
73                            stream().
74                            map(b -> toString(b)).
75                            collect(Collectors.joining("&")));
76                }
77                System.out.print(">");
78                System.out.println(m.getSimpleName());
79            }
80        }
81
82        return false;
83    }
84
85    String toString(TypeMirror bound) {
86        if (bound.getKind() == TypeKind.TYPEVAR) {
87            TypeVariable var = (TypeVariable) bound;
88            return toString(var.asElement());
89        }
90        return bound.toString();
91    }
92
93    String toString(Element el) {
94        switch (el.getKind()) {
95            case METHOD:
96                return toString(el.getEnclosingElement()) + "." + el.getSimpleName();
97            case CLASS:
98                return processingEnv.getElementUtils().getBinaryName((TypeElement) el).toString();
99            case TYPE_PARAMETER:
100                return toString(((TypeParameterElement) el).getGenericElement()) + "." + el.getSimpleName();
101            default:
102                throw new IllegalStateException("Unexpected element: " + el + "(" + el.getKind() + ")");
103        }
104    }
105    @Override
106    public SourceVersion getSupportedSourceVersion() {
107        return SourceVersion.latestSupported();
108    }
109
110
111}
112
113class Test<T1, C> {
114    <T2, C> void m() {
115        class L1<T3, C> {
116            class L2<T4, C> {
117                <T5, C> void m() {
118                    class L3<T6, C> {
119                        class L4<T7, C> {
120                            class L5<T1a extends T1,
121                                     T2a extends T2,
122                                     T3a extends T3,
123                                     T4a extends T4,
124                                     T5a extends T5,
125                                     T6a extends T6,
126                                     T7a extends T7> {}
127                        }
128                    }
129                }
130            }
131            class CCheck<T extends C> {}
132            <T extends C> void test() {}
133        }
134        class CCheck<T extends C> {}
135    }
136    class CCheck<T extends C> {}
137    <T extends C> void test() {}
138}
139