1/*
2 * Copyright (c) 1998, 2017, 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.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25package jdk.javadoc.internal.doclets.toolkit.util;
26
27import java.util.*;
28
29import javax.lang.model.element.AnnotationMirror;
30import javax.lang.model.element.Element;
31import javax.lang.model.element.ExecutableElement;
32import javax.lang.model.element.PackageElement;
33import javax.lang.model.element.TypeElement;
34import javax.lang.model.element.TypeParameterElement;
35import javax.lang.model.element.VariableElement;
36import javax.lang.model.type.ArrayType;
37import javax.lang.model.type.DeclaredType;
38import javax.lang.model.type.ErrorType;
39import javax.lang.model.type.TypeMirror;
40import javax.lang.model.type.TypeVariable;
41import javax.lang.model.type.WildcardType;
42import javax.lang.model.util.Elements;
43import javax.lang.model.util.SimpleElementVisitor9;
44import javax.lang.model.util.SimpleTypeVisitor9;
45import javax.lang.model.util.Types;
46
47import jdk.javadoc.doclet.DocletEnvironment;
48import jdk.javadoc.internal.doclets.formats.html.HtmlConfiguration;
49
50/**
51 * Map all class uses for a given class.
52 *
53 * <p>
54 * <b>This is NOT part of any supported API. If you write code that depends on this, you do so at
55 * your own risk. This code and its internal interfaces are subject to change or deletion without
56 * notice.</b>
57 *
58 * @author Robert G. Field
59 */
60public class ClassUseMapper {
61
62    private final ClassTree classtree;
63
64    /**
65     * Mapping of TypeElements to set of PackageElements used by that class.
66     */
67    public final Map<TypeElement, Set<PackageElement>> classToPackage;
68
69    /**
70     * Mapping of TypeElements representing annotations to a set of PackageElements that use the annotation.
71     */
72    public final Map<TypeElement, List<PackageElement>> classToPackageAnnotations = new HashMap<>();
73
74    /**
75     * Mapping of TypeElements to a set of TypeElements used by that class.
76     */
77    public final Map<TypeElement, Set<TypeElement>> classToClass = new HashMap<>();
78
79    /**
80     * Mapping of TypeElements to a list of TypeElements which are direct or indirect subClasses of
81     * that class.
82     */
83    public final Map<TypeElement, List<TypeElement>> classToSubclass = new HashMap<>();
84
85    /**
86     * Mapping of TypeElements to list of TypeElements which are direct or indirect subInterfaces of
87     * that interface.
88     */
89    public final Map<TypeElement, List<TypeElement>> classToSubinterface = new HashMap<>();
90
91    /**
92     * Mapping of TypeElements to list of TypeElements which implement this interface.
93     */
94    public Map<TypeElement, List<TypeElement>> classToImplementingClass = new HashMap<>();
95
96    /**
97     * Mapping of TypeElements to list of VariableElements declared as that class.
98     */
99    public final Map<TypeElement, List<VariableElement>> classToField = new HashMap<>();
100
101    /**
102     * Mapping of TypeElements to list of ExecutableElements returning that class.
103     */
104    public final Map<TypeElement, List<ExecutableElement>> classToMethodReturn = new HashMap<>();
105
106    /**
107     * Mapping of TypeElements to list of ExecutableElements having that class as an arg.
108     */
109    public final Map<TypeElement, List<ExecutableElement>> classToMethodArgs = new HashMap<>();
110
111    /**
112     * Mapping of TypeElements to list of ExecutableElements which throws that class.
113     */
114    public final Map<TypeElement, List<ExecutableElement>> classToMethodThrows = new HashMap<>();
115
116    /**
117     * Mapping of TypeElements to list of ExecutableElements (constructors) having that
118     * class as an arg.
119     */
120    public final Map<TypeElement, List<ExecutableElement>> classToConstructorArgs = new HashMap<>();
121
122    /**
123     * Mapping of TypeElements to list of constructors which throws that class.
124     */
125    public final Map<TypeElement, List<ExecutableElement>> classToConstructorThrows = new HashMap<>();
126
127    /**
128     * The mapping of TypeElements representing annotations to constructors that use them.
129     */
130    public final Map<TypeElement, List<ExecutableElement>> classToConstructorAnnotations = new HashMap<>();
131
132    /**
133     * The mapping of TypeElement representing annotations to constructor parameters that use them.
134     */
135    public final Map<TypeElement, List<ExecutableElement>> classToConstructorParamAnnotation = new HashMap<>();
136
137    /**
138     * The mapping of TypeElements to constructor arguments that use them as type parameters.
139     */
140    public final Map<TypeElement, List<ExecutableElement>> classToConstructorArgTypeParam = new HashMap<>();
141
142    /**
143     * The mapping of TypeElement to TypeElement that use them as type parameters.
144     */
145    public final Map<TypeElement, List<TypeElement>> classToClassTypeParam = new HashMap<>();
146
147    /**
148     * The mapping of TypeElement representing annotation to TypeElements that use them.
149     */
150    public final Map<TypeElement, List<TypeElement>> classToClassAnnotations = new HashMap<>();
151
152    /**
153     * The mapping of TypeElement to methods that use them as type parameters.
154     */
155    public final Map<TypeElement, List<ExecutableElement>> classToMethodTypeParam = new HashMap<>();
156
157    /**
158     * The mapping of TypeElement to method arguments that use them as type parameters.
159     */
160    public final Map<TypeElement, List<ExecutableElement>> classToMethodArgTypeParam = new HashMap<>();
161
162    /**
163     * The mapping of TypeElement representing annotation to methods that use them.
164     */
165    public final Map<TypeElement, List<ExecutableElement>> classToMethodAnnotations = new HashMap<>();
166
167    /**
168     * The mapping of TypeElements to methods that have return type with type parameters
169     * of that class.
170     */
171    public final Map<TypeElement, List<ExecutableElement>> classToMethodReturnTypeParam = new HashMap<>();
172
173    /**
174     * The mapping of TypeElements representing annotations to method parameters that use them.
175     */
176    public final Map<TypeElement, List<ExecutableElement>> classToMethodParamAnnotation = new HashMap<>();
177
178    /**
179     * The mapping of TypeElements to fields that use them as type parameters.
180     */
181    public final Map<TypeElement, List<VariableElement>> classToFieldTypeParam = new HashMap<>();
182
183    /**
184     * The mapping of TypeElements representing annotation to fields that use them.
185     */
186    public final Map<TypeElement, List<VariableElement>> annotationToField = new HashMap<>();
187
188    private final DocletEnvironment docEnv;
189    private final Elements elementUtils;
190    private final Types typeUtils;
191    private final Utils utils;
192
193    public ClassUseMapper(HtmlConfiguration configuration, ClassTree classtree) {
194        docEnv = configuration.docEnv;
195        elementUtils = docEnv.getElementUtils();
196        typeUtils = docEnv.getTypeUtils();
197        utils = configuration.utils;
198        this.classtree = classtree;
199        classToPackage = new TreeMap<>(utils.makeClassUseComparator());
200        // Map subclassing, subinterfacing implementing, ...
201        for (TypeElement te : classtree.baseClasses()) {
202            subclasses(te);
203        }
204        for (TypeElement intfc : classtree.baseInterfaces()) {
205            // does subinterfacing as side-effect
206            implementingClasses(intfc);
207        }
208        // Map methods, fields, constructors using a class.
209        Set<TypeElement> classes = configuration.getIncludedTypeElements();
210        for (TypeElement aClass : classes) {
211            PackageElement pkg = elementUtils.getPackageOf(aClass);
212            mapAnnotations(classToPackageAnnotations, pkg, pkg);
213            mapTypeParameters(classToClassTypeParam, aClass, aClass);
214            mapAnnotations(classToClassAnnotations, aClass, aClass);
215            List<VariableElement> fields = utils.getFields(aClass);
216            for (VariableElement fd : fields) {
217                mapTypeParameters(classToFieldTypeParam, fd, fd);
218                mapAnnotations(annotationToField, fd, fd);
219                SimpleTypeVisitor9<Void, VariableElement> stv = new SimpleTypeVisitor9<Void, VariableElement>() {
220                    @Override
221                    public Void visitArray(ArrayType t, VariableElement p) {
222                        return visit(t.getComponentType(), p);
223                    }
224
225                    @Override
226                    public Void visitDeclared(DeclaredType t, VariableElement p) {
227                        add(classToField, (TypeElement) t.asElement(), p);
228                        return null;
229                    }
230                    @Override
231                    public Void visitTypeVariable(TypeVariable t, VariableElement p) {
232                        return visit(typeUtils.erasure(t), p);
233                    }
234                };
235                stv.visit(fd.asType(), fd);
236            }
237
238            List<ExecutableElement> ctors = utils.getConstructors(aClass);
239            for (ExecutableElement ctor : ctors) {
240                mapAnnotations(classToConstructorAnnotations, ctor, ctor);
241                mapExecutable(ctor);
242            }
243
244            List<ExecutableElement> methods = utils.getMethods(aClass);
245            for (ExecutableElement method : methods) {
246                mapExecutable(method);
247                mapTypeParameters(classToMethodTypeParam, method, method);
248                mapAnnotations(classToMethodAnnotations, method, method);
249                SimpleTypeVisitor9<Void, ExecutableElement> stv = new SimpleTypeVisitor9<Void, ExecutableElement>() {
250                    @Override
251                    public Void visitArray(ArrayType t, ExecutableElement p) {
252                        TypeMirror componentType = t.getComponentType();
253                        return visit(utils.isTypeVariable(componentType)
254                                ? typeUtils.erasure(componentType)
255                                : componentType, p);
256                    }
257
258                    @Override
259                    public Void visitDeclared(DeclaredType t, ExecutableElement p) {
260                        mapTypeParameters(classToMethodReturnTypeParam, t, p);
261                        add(classToMethodReturn, (TypeElement) t.asElement(), p);
262                        return null;
263                    }
264
265                    @Override
266                    protected Void defaultAction(TypeMirror e, ExecutableElement p) {
267                        return null;
268                    }
269                };
270                stv.visit(method.getReturnType(), method);
271            }
272        }
273    }
274
275    /**
276     * Return all subClasses of a class AND fill-in classToSubclass map.
277     */
278    private Collection<TypeElement> subclasses(TypeElement te) {
279        Collection<TypeElement> ret = classToSubclass.get(te);
280        if (ret == null) {
281            ret = new TreeSet<>(utils.makeClassUseComparator());
282            Set<TypeElement> subs = classtree.subClasses(te);
283            if (subs != null) {
284                ret.addAll(subs);
285                for (TypeElement sub : subs) {
286                    ret.addAll(subclasses(sub));
287                }
288            }
289            addAll(classToSubclass, te, ret);
290        }
291        return ret;
292    }
293
294    /**
295     * Return all subInterfaces of an interface AND fill-in classToSubinterface map.
296     */
297    private Collection<TypeElement> subinterfaces(TypeElement te) {
298        Collection<TypeElement> ret = classToSubinterface.get(te);
299        if (ret == null) {
300            ret = new TreeSet<>(utils.makeClassUseComparator());
301            Set<TypeElement> subs = classtree.subInterfaces(te);
302            if (subs != null) {
303                ret.addAll(subs);
304                for (TypeElement sub : subs) {
305                    ret.addAll(subinterfaces(sub));
306                }
307            }
308            addAll(classToSubinterface, te, ret);
309        }
310        return ret;
311    }
312
313    /**
314     * Return all implementing classes of an interface (including all subClasses of implementing
315     * classes and all classes implementing subInterfaces) AND fill-in both classToImplementingClass
316     * and classToSubinterface maps.
317     */
318    private Collection<TypeElement> implementingClasses(TypeElement te) {
319        Collection<TypeElement> ret = classToImplementingClass.get(te);
320        if (ret == null) {
321            ret = new TreeSet<>(utils.makeClassUseComparator());
322            Set<TypeElement> impl = classtree.implementingClasses(te);
323            if (impl != null) {
324                ret.addAll(impl);
325                for (TypeElement anImpl : impl) {
326                    ret.addAll(subclasses(anImpl));
327                }
328            }
329            for (TypeElement intfc : subinterfaces(te)) {
330                ret.addAll(implementingClasses(intfc));
331            }
332            addAll(classToImplementingClass, te, ret);
333        }
334        return ret;
335    }
336
337    /**
338     * Determine classes used by a method or constructor, so they can be inverse mapped.
339     */
340    private void mapExecutable(ExecutableElement ee) {
341        final boolean isConstructor = utils.isConstructor(ee);
342        Set<TypeMirror> classArgs = new TreeSet<>(utils.makeTypeMirrorClassUseComparator());
343        for (VariableElement param : ee.getParameters()) {
344            TypeMirror pType = param.asType();
345            // primitives don't get mapped and type variables are mapped elsewhere
346            if (!pType.getKind().isPrimitive() && !utils.isTypeVariable(pType)) {
347                // no duplicates please
348                if (classArgs.add(pType)) {
349                    new SimpleTypeVisitor9<Void, ExecutableElement>() {
350                        @Override
351                        public Void visitArray(ArrayType t, ExecutableElement p) {
352                            return visit(t.getComponentType(), p);
353                        }
354
355                        @Override
356                        public Void visitDeclared(DeclaredType t, ExecutableElement p) {
357                            add(isConstructor
358                                    ? classToConstructorArgs
359                                    : classToMethodArgs,
360                                    (TypeElement) t.asElement(), p);
361                            return null;
362                        }
363                        @Override
364                        public Void visitTypeVariable(TypeVariable t, ExecutableElement p) {
365                            visit(typeUtils.erasure(t), p);
366                            return null;
367                        }
368                    }.visit(pType, ee);
369                    mapTypeParameters(isConstructor
370                            ? classToConstructorArgTypeParam
371                            : classToMethodArgTypeParam,
372                            pType, ee);
373                }
374            }
375            mapAnnotations(isConstructor
376                    ? classToConstructorParamAnnotation
377                    : classToMethodParamAnnotation,
378                    param, ee);
379
380        }
381        for (TypeMirror anException : ee.getThrownTypes()) {
382            SimpleTypeVisitor9<Void, ExecutableElement> stv = new SimpleTypeVisitor9<Void, ExecutableElement>() {
383
384                @Override
385                public Void visitArray(ArrayType t, ExecutableElement p) {
386                    super.visit(t.getComponentType(), p);
387                    return null;
388                }
389
390                @Override
391                public Void visitDeclared(DeclaredType t, ExecutableElement p) {
392                    add(isConstructor ? classToConstructorThrows : classToMethodThrows,
393                            (TypeElement) t.asElement(), p);
394                    return null;
395                }
396
397                @Override
398                public Void visitError(ErrorType t, ExecutableElement p) {
399                    add(isConstructor ? classToConstructorThrows : classToMethodThrows,
400                            (TypeElement) t.asElement(), p);
401                    return null;
402                }
403
404                @Override
405                protected Void defaultAction(TypeMirror e, ExecutableElement p) {
406                    throw new AssertionError("this should not happen");
407                }
408            };
409
410            stv.visit(typeUtils.erasure(anException), ee);
411        }
412    }
413
414    private <T> List<T> refList(Map<TypeElement, List<T>> map, Element element) {
415        List<T> list = map.get(element);
416        if (list == null) {
417            list = new ArrayList<>();
418            map.put((TypeElement) element, list);
419        }
420        return list;
421    }
422
423    private Set<PackageElement> packageSet(TypeElement te) {
424        Set<PackageElement> pkgSet = classToPackage.get(te);
425        if (pkgSet == null) {
426            pkgSet = new TreeSet<>(utils.makeClassUseComparator());
427            classToPackage.put(te, pkgSet);
428        }
429        return pkgSet;
430    }
431
432    private Set<TypeElement> classSet(TypeElement te) {
433        Set<TypeElement> clsSet = classToClass.get(te);
434        if (clsSet == null) {
435            clsSet = new TreeSet<>(utils.makeClassUseComparator());
436            classToClass.put(te, clsSet);
437        }
438        return clsSet;
439    }
440
441    private <T extends Element> void add(Map<TypeElement, List<T>> map, TypeElement te, T ref) {
442        // add to specified map
443        refList(map, te).add(ref);
444        // add ref's package to package map and class map
445        packageSet(te).add(elementUtils.getPackageOf(ref));
446        TypeElement entry = (utils.isField((Element) ref)
447                || utils.isConstructor((Element) ref)
448                || utils.isMethod((Element) ref))
449                ? (TypeElement) ref.getEnclosingElement()
450                : (TypeElement) ref;
451        classSet(te).add(entry);
452    }
453
454    private void addAll(Map<TypeElement, List<TypeElement>> map, TypeElement te, Collection<TypeElement> refs) {
455        if (refs == null) {
456            return;
457        }
458        // add to specified map
459        refList(map, te).addAll(refs);
460
461        Set<PackageElement> pkgSet = packageSet(te);
462        Set<TypeElement> clsSet = classSet(te);
463        // add ref's package to package map and class map
464        for (TypeElement cls : refs) {
465            pkgSet.add(utils.containingPackage(cls));
466            clsSet.add(cls);
467        }
468    }
469
470    /**
471     * Map the TypeElements to the members that use them as type parameters.
472     *
473     * @param map the map the insert the information into.
474     * @param element the te whose type parameters are being checked.
475     * @param holder the holder that owns the type parameters.
476     */
477    private <T extends Element> void mapTypeParameters(final Map<TypeElement, List<T>> map,
478            Element element, final T holder) {
479
480        SimpleElementVisitor9<Void, Void> elementVisitor
481                = new SimpleElementVisitor9<Void, Void>() {
482
483                    private void addParameters(TypeParameterElement e) {
484                        for (TypeMirror type : utils.getBounds(e)) {
485                            addTypeParameterToMap(map, type, holder);
486                        }
487                    }
488
489                    @Override
490                    public Void visitType(TypeElement e, Void p) {
491                        for (TypeParameterElement param : e.getTypeParameters()) {
492                            addParameters(param);
493                        }
494                        return null;
495                    }
496
497                    @Override
498                    public Void visitExecutable(ExecutableElement e, Void p) {
499                        for (TypeParameterElement param : e.getTypeParameters()) {
500                            addParameters(param);
501                        }
502                        return null;
503                    }
504
505                    @Override
506                    protected Void defaultAction(Element e, Void p) {
507                        mapTypeParameters(map, e.asType(), holder);
508                        return null;
509                    }
510
511                    @Override
512                    public Void visitTypeParameter(TypeParameterElement e, Void p) {
513                        addParameters(e);
514                        return null;
515                    }
516                };
517        elementVisitor.visit(element);
518    }
519
520    private <T extends Element> void mapTypeParameters(final Map<TypeElement, List<T>> map,
521            TypeMirror aType, final T holder) {
522
523        SimpleTypeVisitor9<Void, Void> tv = new SimpleTypeVisitor9<Void, Void>() {
524
525            @Override
526            public Void visitWildcard(WildcardType t, Void p) {
527                TypeMirror bound = t.getExtendsBound();
528                if (bound != null) {
529                    addTypeParameterToMap(map, bound, holder);
530                }
531                bound = t.getSuperBound();
532                if (bound != null) {
533                    addTypeParameterToMap(map, bound, holder);
534                }
535                return null;
536            }
537
538            // ParameterizedType
539            @Override
540            public Void visitDeclared(DeclaredType t, Void p) {
541                for (TypeMirror targ : t.getTypeArguments()) {
542                    addTypeParameterToMap(map, targ, holder);
543                }
544                return null;
545            }
546        };
547        tv.visit(aType);
548    }
549
550    /**
551     * Map the AnnotationType to the members that use them as type parameters.
552     *
553     * @param map the map the insert the information into.
554     * @param element whose type parameters are being checked.
555     * @param holder the holder that owns the type parameters.
556     */
557    private <T extends Element> void mapAnnotations(final Map<TypeElement, List<T>> map,
558            Element e, final T holder) {
559        new SimpleElementVisitor9<Void, Void>() {
560
561            void addAnnotations(Element e) {
562                for (AnnotationMirror a : e.getAnnotationMirrors()) {
563                    add(map, (TypeElement) a.getAnnotationType().asElement(), holder);
564                }
565            }
566
567            @Override
568            public Void visitPackage(PackageElement e, Void p) {
569                for (AnnotationMirror a : e.getAnnotationMirrors()) {
570                    refList(map, a.getAnnotationType().asElement()).add(holder);
571                }
572                return null;
573            }
574
575            @Override
576            protected Void defaultAction(Element e, Void p) {
577                addAnnotations(e);
578                return null;
579            }
580        }.visit(e);
581    }
582
583    private <T extends Element> void addTypeParameterToMap(final Map<TypeElement, List<T>> map,
584            TypeMirror type, final T holder) {
585        new SimpleTypeVisitor9<Void, Void>() {
586
587            @Override
588            protected Void defaultAction(TypeMirror e, Void p) {
589                return super.defaultAction(e, p);
590            }
591
592            @Override
593            public Void visitDeclared(DeclaredType t, Void p) {
594                add(map, (TypeElement) t.asElement(), holder);
595                return null;
596            }
597
598        }.visit(type);
599        mapTypeParameters(map, type, holder);
600    }
601}
602