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