--- old/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/util/ClassUseMapper.java Fri Jan 22 12:20:23 2016 +++ /dev/null Fri Jan 22 12:20:23 2016 @@ -1,484 +0,0 @@ -/* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.tools.doclets.internal.toolkit.util; - -import java.util.*; - -import com.sun.javadoc.*; -import com.sun.tools.doclets.formats.html.ConfigurationImpl; - -/** - * Map all class uses for a given class. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - * - * @since 1.2 - * @author Robert G. Field - */ -public class ClassUseMapper { - - private final ClassTree classtree; - - /** - * Mapping of ClassDocs to set of PackageDoc used by that class. - * Entries may be null. - */ - public Map> classToPackage = new HashMap<>(); - - /** - * Mapping of Annotations to set of PackageDoc that use the annotation. - */ - public Map> classToPackageAnnotations = new HashMap<>(); - - /** - * Mapping of ClassDocs to set of ClassDoc used by that class. - * Entries may be null. - */ - public Map> classToClass = new HashMap<>(); - - /** - * Mapping of ClassDocs to list of ClassDoc which are direct or - * indirect subclasses of that class. - * Entries may be null. - */ - public Map> classToSubclass = new HashMap<>(); - - /** - * Mapping of ClassDocs to list of ClassDoc which are direct or - * indirect subinterfaces of that interface. - * Entries may be null. - */ - public Map> classToSubinterface = new HashMap<>(); - - /** - * Mapping of ClassDocs to list of ClassDoc which implement - * this interface. - * Entries may be null. - */ - public Map> classToImplementingClass = new HashMap<>(); - - /** - * Mapping of ClassDocs to list of FieldDoc declared as that class. - * Entries may be null. - */ - public Map> classToField = new HashMap<>(); - - /** - * Mapping of ClassDocs to list of MethodDoc returning that class. - * Entries may be null. - */ - public Map> classToMethodReturn = new HashMap<>(); - - /** - * Mapping of ClassDocs to list of MethodDoc having that class - * as an arg. - * Entries may be null. - */ - public Map> classToMethodArgs = new HashMap<>(); - - /** - * Mapping of ClassDocs to list of MethodDoc which throws that class. - * Entries may be null. - */ - public Map> classToMethodThrows = new HashMap<>(); - - /** - * Mapping of ClassDocs to list of ConstructorDoc having that class - * as an arg. - * Entries may be null. - */ - public Map> classToConstructorArgs = new HashMap<>(); - - /** - * Mapping of ClassDocs to list of ConstructorDoc which throws that class. - * Entries may be null. - */ - public Map> classToConstructorThrows = new HashMap<>(); - - /** - * The mapping of AnnotationTypeDocs to constructors that use them. - */ - public Map> classToConstructorAnnotations = new HashMap<>(); - - /** - * The mapping of AnnotationTypeDocs to Constructor parameters that use them. - */ - public Map> classToConstructorParamAnnotation = new HashMap<>(); - - /** - * The mapping of ClassDocs to Constructor arguments that use them as type parameters. - */ - public Map> classToConstructorDocArgTypeParam = new HashMap<>(); - - /** - * The mapping of ClassDocs to ClassDocs that use them as type parameters. - */ - public Map> classToClassTypeParam = new HashMap<>(); - - /** - * The mapping of AnnotationTypeDocs to ClassDocs that use them. - */ - public Map> classToClassAnnotations = new HashMap<>(); - - /** - * The mapping of ClassDocs to ExecutableMemberDocs that use them as type parameters. - */ - public Map> classToExecMemberDocTypeParam = new HashMap<>(); - - /** - * The mapping of ClassDocs to ExecutableMemberDocs arguments that use them as type parameters. - */ - public Map> classToExecMemberDocArgTypeParam = new HashMap<>(); - - /** - * The mapping of AnnotationTypeDocs to ExecutableMemberDocs that use them. - */ - public Map> classToExecMemberDocAnnotations = new HashMap<>(); - - /** - * The mapping of ClassDocs to ExecutableMemberDocs that have return type - * with type parameters of that class. - */ - public Map> classToExecMemberDocReturnTypeParam = new HashMap<>(); - - /** - * The mapping of AnnotationTypeDocs to MethodDoc parameters that use them. - */ - public Map> classToExecMemberDocParamAnnotation = new HashMap<>(); - - /** - * The mapping of ClassDocs to FieldDocs that use them as type parameters. - */ - public Map> classToFieldDocTypeParam = new HashMap<>(); - - /** - * The mapping of AnnotationTypeDocs to FieldDocs that use them. - */ - public Map> annotationToFieldDoc = new HashMap<>(); - - private final Utils utils; - public ClassUseMapper(ConfigurationImpl configuration, ClassTree classtree) { - RootDoc root = configuration.root; - this.classtree = classtree; - utils = configuration.utils; - // Map subclassing, subinterfacing implementing, ... - for (ClassDoc doc : classtree.baseclasses()) { - subclasses(doc); - } - for (ClassDoc doc : classtree.baseinterfaces()) { - // does subinterfacing as side-effect - implementingClasses(doc); - } - // Map methods, fields, constructors using a class. - ClassDoc[] classes = root.classes(); - for (ClassDoc aClass : classes) { - PackageDoc pkg = aClass.containingPackage(); - mapAnnotations(classToPackageAnnotations, pkg, pkg); - ClassDoc cd = aClass; - mapTypeParameters(classToClassTypeParam, cd, cd); - mapAnnotations(classToClassAnnotations, cd, cd); - FieldDoc[] fields = cd.fields(); - for (FieldDoc fd : fields) { - mapTypeParameters(classToFieldDocTypeParam, fd, fd); - mapAnnotations(annotationToFieldDoc, fd, fd); - if (!fd.type().isPrimitive()) { - add(classToField, fd.type().asClassDoc(), fd); - } - } - ConstructorDoc[] cons = cd.constructors(); - for (ConstructorDoc con : cons) { - mapAnnotations(classToConstructorAnnotations, con, con); - mapExecutable(con); - } - MethodDoc[] meths = cd.methods(); - for (MethodDoc md : meths) { - mapExecutable(md); - mapTypeParameters(classToExecMemberDocTypeParam, md, md); - mapAnnotations(classToExecMemberDocAnnotations, md, md); - if (!(md.returnType().isPrimitive() || md.returnType() instanceof TypeVariable)) { - mapTypeParameters(classToExecMemberDocReturnTypeParam, - md.returnType(), md); - add(classToMethodReturn, md.returnType().asClassDoc(), md); - } - } - } - } - - /** - * Return all subclasses of a class AND fill-in classToSubclass map. - */ - private Collection subclasses(ClassDoc cd) { - Collection ret = classToSubclass.get(cd.qualifiedName()); - if (ret == null) { - ret = new TreeSet<>(utils.makeComparatorForClassUse()); - SortedSet subs = classtree.subclasses(cd); - if (subs != null) { - ret.addAll(subs); - for (ClassDoc sub : subs) { - ret.addAll(subclasses(sub)); - } - } - addAll(classToSubclass, cd, ret); - } - return ret; - } - - /** - * Return all subinterfaces of an interface AND fill-in classToSubinterface map. - */ - private Collection subinterfaces(ClassDoc cd) { - Collection ret = classToSubinterface.get(cd.qualifiedName()); - if (ret == null) { - ret = new TreeSet<>(utils.makeComparatorForClassUse()); - SortedSet subs = classtree.subinterfaces(cd); - if (subs != null) { - ret.addAll(subs); - for (ClassDoc sub : subs) { - ret.addAll(subinterfaces(sub)); - } - } - addAll(classToSubinterface, cd, ret); - } - return ret; - } - - /** - * Return all implementing classes of an interface (including - * all subclasses of implementing classes and all classes - * implementing subinterfaces) AND fill-in both classToImplementingClass - * and classToSubinterface maps. - */ - private Collection implementingClasses(ClassDoc cd) { - Collection ret = classToImplementingClass.get(cd.qualifiedName()); - if (ret == null) { - ret = new TreeSet<>(utils.makeComparatorForClassUse()); - SortedSet impl = classtree.implementingclasses(cd); - if (impl != null) { - ret.addAll(impl); - for (ClassDoc anImpl : impl) { - ret.addAll(subclasses(anImpl)); - } - } - for (ClassDoc doc : subinterfaces(cd)) { - ret.addAll(implementingClasses(doc)); - } - addAll(classToImplementingClass, cd, ret); - } - return ret; - } - - /** - * Determine classes used by a method or constructor, so they can be - * inverse mapped. - */ - private void mapExecutable(ExecutableMemberDoc em) { - boolean isConstructor = em.isConstructor(); - Set classArgs = new TreeSet<>(utils.makeTypeComparator()); - for (Parameter param : em.parameters()) { - Type pcd = param.type(); - // ignore primitives and typevars, typevars are handled elsewhere - if ((!param.type().isPrimitive()) && !(pcd instanceof TypeVariable)) { - // avoid dups - if (classArgs.add(pcd)) { - add(isConstructor ? classToConstructorArgs : classToMethodArgs, - pcd.asClassDoc(), em); - mapTypeParameters(isConstructor - ? classToConstructorDocArgTypeParam - : classToExecMemberDocArgTypeParam, - pcd, em); - } - } - mapAnnotations(isConstructor - ? classToConstructorParamAnnotation - : classToExecMemberDocParamAnnotation, - param, em); - - } - for (ClassDoc anException : em.thrownExceptions()) { - add(isConstructor ? classToConstructorThrows : classToMethodThrows, - anException, em); - } - } - - private List refList(Map> map, ClassDoc cd) { - List list = map.get(cd.qualifiedName()); - if (list == null) { - list = new ArrayList<>(); - map.put(cd.qualifiedName(), list); - } - return list; - } - - private Set packageSet(ClassDoc cd) { - Set pkgSet = classToPackage.get(cd.qualifiedName()); - if (pkgSet == null) { - pkgSet = new TreeSet<>(); - classToPackage.put(cd.qualifiedName(), pkgSet); - } - return pkgSet; - } - - private Set classSet(ClassDoc cd) { - Set clsSet = classToClass.get(cd.qualifiedName()); - if (clsSet == null) { - clsSet = new TreeSet<>(); - classToClass.put(cd.qualifiedName(), clsSet); - } - return clsSet; - } - - private void add(Map> map, ClassDoc cd, T ref) { - // add to specified map - refList(map, cd).add(ref); - - // add ref's package to package map and class map - packageSet(cd).add(ref.containingPackage()); - - classSet(cd).add(ref instanceof MemberDoc? - ((MemberDoc)ref).containingClass() : - (ClassDoc)ref); - } - - private void addAll(Map> map, ClassDoc cd, Collection refs) { - if (refs == null) { - return; - } - // add to specified map - refList(map, cd).addAll(refs); - - Set pkgSet = packageSet(cd); - Set clsSet = classSet(cd); - // add ref's package to package map and class map - for (ClassDoc cls : refs) { - pkgSet.add(cls.containingPackage()); - clsSet.add(cls); - - } - } - - /** - * Map the ClassDocs to the ProgramElementDocs that use them as - * type parameters. - * - * @param map the map the insert the information into. - * @param doc the doc whose type parameters are being checked. - * @param holder the holder that owns the type parameters. - */ - private void mapTypeParameters(Map> map, Object doc, - T holder) { - TypeVariable[] typeVariables; - if (doc instanceof ClassDoc) { - typeVariables = ((ClassDoc) doc).typeParameters(); - } else if (doc instanceof WildcardType) { - for (Type extendsBound : ((WildcardType) doc).extendsBounds()) { - addTypeParameterToMap(map, extendsBound, holder); - } - for (Type superBound : ((WildcardType) doc).superBounds()) { - addTypeParameterToMap(map, superBound, holder); - } - return; - } else if (doc instanceof ParameterizedType) { - for (Type typeArgument : ((ParameterizedType) doc).typeArguments()) { - addTypeParameterToMap(map, typeArgument, holder); - } - return; - } else if (doc instanceof ExecutableMemberDoc) { - typeVariables = ((ExecutableMemberDoc) doc).typeParameters(); - } else if (doc instanceof FieldDoc) { - Type fieldType = ((FieldDoc) doc).type(); - mapTypeParameters(map, fieldType, holder); - return; - } else { - return; - } - for (TypeVariable typeVariable : typeVariables) { - for (Type bound : typeVariable.bounds()) { - addTypeParameterToMap(map, bound, holder); - } - } - } - - /** - * Map the AnnotationType to the ProgramElementDocs that use them as - * type parameters. - * - * @param map the map the insert the information into. - * @param doc the doc whose type parameters are being checked. - * @param holder the holder that owns the type parameters. - */ - private void mapAnnotations(Map> map, Object doc, - T holder) { - AnnotationDesc[] annotations; - boolean isPackage = false; - if (doc instanceof ProgramElementDoc) { - annotations = ((ProgramElementDoc) doc).annotations(); - } else if (doc instanceof PackageDoc) { - annotations = ((PackageDoc) doc).annotations(); - isPackage = true; - } else if (doc instanceof Parameter) { - annotations = ((Parameter) doc).annotations(); - } else { - throw new DocletAbortException("should not happen"); - } - for (AnnotationDesc annotation : annotations) { - AnnotationTypeDoc annotationDoc = annotation.annotationType(); - if (isPackage) - refList(map, annotationDoc).add(holder); - else - add(map, annotationDoc, holder); - } - } - - - /** - * Map the AnnotationType to the ProgramElementDocs that use them as - * type parameters. - * - * @param map the map the insert the information into. - * @param doc the doc whose type parameters are being checked. - * @param holder the holder that owns the type parameters. - */ - private void mapAnnotations(Map> map, PackageDoc doc, - T holder) { - for (AnnotationDesc annotation : doc.annotations()) { - AnnotationTypeDoc annotationDoc = annotation.annotationType(); - refList(map, annotationDoc).add(holder); - } - } - - private void addTypeParameterToMap(Map> map, Type type, - T holder) { - if (type instanceof ClassDoc) { - add(map, (ClassDoc) type, holder); - } else if (type instanceof ParameterizedType) { - add(map, ((ParameterizedType) type).asClassDoc(), holder); - } - mapTypeParameters(map, type, holder); - } -} --- /dev/null Fri Jan 22 12:20:23 2016 +++ new/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/ClassUseMapper.java Fri Jan 22 12:20:23 2016 @@ -0,0 +1,611 @@ +/* + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.javadoc.internal.doclets.toolkit.util; + +import java.util.*; + +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.TypeParameterElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.ArrayType; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.ErrorType; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.type.TypeVariable; +import javax.lang.model.type.WildcardType; +import javax.lang.model.util.Elements; +import javax.lang.model.util.SimpleElementVisitor9; +import javax.lang.model.util.SimpleTypeVisitor9; +import javax.lang.model.util.Types; + +import com.sun.tools.javac.util.DefinedBy; +import com.sun.tools.javac.util.DefinedBy.Api; +import jdk.javadoc.doclet.DocletEnvironment; +import jdk.javadoc.internal.doclets.formats.html.ConfigurationImpl; + +/** + * Map all class uses for a given class. + * + *

+ * This is NOT part of any supported API. If you write code that depends on this, you do so at + * your own risk. This code and its internal interfaces are subject to change or deletion without + * notice. + * + * @since 1.2 + * @author Robert G. Field + */ +public class ClassUseMapper { + + private final ClassTree classtree; + + /** + * Mapping of TypeElements to set of PackageElements used by that class. + * Entries may be null. + */ + public final Map> classToPackage; + + /** + * Mapping of TypeElements representing annotations to a set of PackageElements that use the annotation. + */ + public final Map> classToPackageAnnotations = new HashMap<>(); + + /** + * Mapping of TypeElements to a set of TypeElements used by that class. + * Entries may be null. + */ + public final Map> classToClass = new HashMap<>(); + + /** + * Mapping of TypeElements to a list of TypeElements which are direct or indirect subClasses of + * that class. Entries may be null. + */ + public final Map> classToSubclass = new HashMap<>(); + + /** + * Mapping of TypeElements to list of TypeElements which are direct or indirect subInterfaces of + * that interface. Entries may be null. + */ + public final Map> classToSubinterface = new HashMap<>(); + + /** + * Mapping of TypeElements to list of TypeElements which implement this interface. + * Entries may be null. + */ + public Map> classToImplementingClass = new HashMap<>(); + + /** + * Mapping of TypeElements to list of VariableElements declared as that class. + * Entries may be null. + */ + public final Map> classToField = new HashMap<>(); + + /** + * Mapping of TypeElements to list of ExecutableElements returning that class. + * Entries may be null. + */ + public final Map> classToMethodReturn = new HashMap<>(); + + /** + * Mapping of TypeElements to list of ExecutableElements having that class as an arg. + * Entries may be null. + */ + public final Map> classToMethodArgs = new HashMap<>(); + + /** + * Mapping of TypeElements to list of ExecutableElements which throws that class. + * Entries may be null. + */ + public final Map> classToMethodThrows = new HashMap<>(); + + /** + * Mapping of TypeElements to list of ExecutableElements (constructors) having that + * class as an arg. Entries may be null. + */ + public final Map> classToConstructorArgs = new HashMap<>(); + + /** + * Mapping of TypeElements to list of constructors which throws that class. Entries may be null. + */ + public final Map> classToConstructorThrows = new HashMap<>(); + + /** + * The mapping of TypeElements representing annotations to constructors that use them. + */ + public final Map> classToConstructorAnnotations = new HashMap<>(); + + /** + * The mapping of TypeElement representing annotations to constructor parameters that use them. + */ + public final Map> classToConstructorParamAnnotation = new HashMap<>(); + + /** + * The mapping of TypeElements to constructor arguments that use them as type parameters. + */ + public final Map> classToConstructorArgTypeParam = new HashMap<>(); + + /** + * The mapping of TypeElement to TypeElement that use them as type parameters. + */ + public final Map> classToClassTypeParam = new HashMap<>(); + + /** + * The mapping of TypeElement representing annotation to TypeElements that use them. + */ + public final Map> classToClassAnnotations = new HashMap<>(); + + /** + * The mapping of TypeElement to methods that use them as type parameters. + */ + public final Map> classToMethodTypeParam = new HashMap<>(); + + /** + * The mapping of TypeElement to method arguments that use them as type parameters. + */ + public final Map> classToMethodArgTypeParam = new HashMap<>(); + + /** + * The mapping of TypeElement representing annotation to methods that use them. + */ + public final Map> classToMethodAnnotations = new HashMap<>(); + + /** + * The mapping of TypeElements to methods that have return type with type parameters + * of that class. + */ + public final Map> classToMethodReturnTypeParam = new HashMap<>(); + + /** + * The mapping of TypeElements representing annotations to method parameters that use them. + */ + public final Map> classToMethodParamAnnotation = new HashMap<>(); + + /** + * The mapping of TypeElements to fields that use them as type parameters. + */ + public final Map> classToFieldTypeParam = new HashMap<>(); + + /** + * The mapping of TypeElements representing annotation to fields that use them. + */ + public final Map> annotationToField = new HashMap<>(); + + private final DocletEnvironment root; + private final Elements elements; + private final Types typeutils; + private final Utils utils; + + public ClassUseMapper(ConfigurationImpl configuration, ClassTree classtree) { + root = configuration.root; + elements = root.getElementUtils(); + typeutils = root.getTypeUtils(); + utils = configuration.utils; + this.classtree = classtree; + classToPackage = new TreeMap<>(utils.makeClassUseComparator()); + // Map subclassing, subinterfacing implementing, ... + for (TypeElement te : classtree.baseClasses()) { + subclasses(te); + } + for (TypeElement intfc : classtree.baseInterfaces()) { + // does subinterfacing as side-effect + implementingClasses(intfc); + } + // Map methods, fields, constructors using a class. + Set classes = root.getIncludedClasses(); + for (TypeElement aClass : classes) { + PackageElement pkg = elements.getPackageOf(aClass); + mapAnnotations(classToPackageAnnotations, pkg, pkg); + mapTypeParameters(classToClassTypeParam, aClass, aClass); + mapAnnotations(classToClassAnnotations, aClass, aClass); + List fields = utils.getFields(aClass); + for (VariableElement fd : fields) { + mapTypeParameters(classToFieldTypeParam, fd, fd); + mapAnnotations(annotationToField, fd, fd); + SimpleTypeVisitor9 stv = new SimpleTypeVisitor9() { + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Void visitArray(ArrayType t, VariableElement p) { + return visit(t.getComponentType(), p); + } + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Void visitDeclared(DeclaredType t, VariableElement p) { + add(classToField, (TypeElement) t.asElement(), p); + return null; + } + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Void visitTypeVariable(TypeVariable t, VariableElement p) { + return visit(typeutils.erasure(t), p); + } + }; + stv.visit(fd.asType(), fd); + } + + List ctors = utils.getConstructors(aClass); + for (ExecutableElement ctor : ctors) { + mapAnnotations(classToConstructorAnnotations, ctor, ctor); + mapExecutable(ctor); + } + + List meths = utils.getMethods(aClass); + for (ExecutableElement md : meths) { + mapExecutable(md); + mapTypeParameters(classToMethodTypeParam, md, md); + mapAnnotations(classToMethodAnnotations, md, md); + SimpleTypeVisitor9 stv = new SimpleTypeVisitor9() { + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Void visitArray(ArrayType t, ExecutableElement p) { + TypeMirror componentType = t.getComponentType(); + return visit(utils.isTypeVariable(componentType) + ? typeutils.erasure(componentType) + : componentType, p); + } + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Void visitDeclared(DeclaredType t, ExecutableElement p) { + mapTypeParameters(classToMethodReturnTypeParam, t, p); + add(classToMethodReturn, (TypeElement) t.asElement(), p); + return null; + } + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + protected Void defaultAction(TypeMirror e, ExecutableElement p) { + return null; + } + }; + stv.visit(md.getReturnType(), md); + } + } + } + + /** + * Return all subClasses of a class AND fill-in classToSubclass map. + */ + private Collection subclasses(TypeElement te) { + Collection ret = classToSubclass.get(te); + if (ret == null) { + ret = new TreeSet<>(utils.makeClassUseComparator()); + Set subs = classtree.subClasses(te); + if (subs != null) { + ret.addAll(subs); + for (TypeElement sub : subs) { + ret.addAll(subclasses(sub)); + } + } + addAll(classToSubclass, te, ret); + } + return ret; + } + + /** + * Return all subInterfaces of an interface AND fill-in classToSubinterface map. + */ + private Collection subinterfaces(TypeElement te) { + Collection ret = classToSubinterface.get(te); + if (ret == null) { + ret = new TreeSet<>(utils.makeClassUseComparator()); + Set subs = classtree.subInterfaces(te); + if (subs != null) { + ret.addAll(subs); + for (TypeElement sub : subs) { + ret.addAll(subinterfaces(sub)); + } + } + addAll(classToSubinterface, te, ret); + } + return ret; + } + + /** + * Return all implementing classes of an interface (including all subClasses of implementing + * classes and all classes implementing subInterfaces) AND fill-in both classToImplementingClass + * and classToSubinterface maps. + */ + private Collection implementingClasses(TypeElement te) { + Collection ret = classToImplementingClass.get(te); + if (ret == null) { + ret = new TreeSet<>(utils.makeClassUseComparator()); + Set impl = classtree.implementingclasses(te); + if (impl != null) { + ret.addAll(impl); + for (TypeElement anImpl : impl) { + ret.addAll(subclasses(anImpl)); + } + } + for (TypeElement intfc : subinterfaces(te)) { + ret.addAll(implementingClasses(intfc)); + } + addAll(classToImplementingClass, te, ret); + } + return ret; + } + + /** + * Determine classes used by a method or constructor, so they can be inverse mapped. + */ + private void mapExecutable(ExecutableElement ee) { + final boolean isConstructor = utils.isConstructor(ee); + Set classArgs = new TreeSet<>(utils.makeTypeMirrorClassUseComparator()); + for (VariableElement param : ee.getParameters()) { + TypeMirror pType = param.asType(); + // primitives don't get mapped and type variables are mapped elsewhere + if (!pType.getKind().isPrimitive() && !utils.isTypeVariable(pType)) { + // no duplicates please + if (classArgs.add(pType)) { + new SimpleTypeVisitor9() { + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Void visitArray(ArrayType t, ExecutableElement p) { + return visit(t.getComponentType(), p); + } + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Void visitDeclared(DeclaredType t, ExecutableElement p) { + add(isConstructor + ? classToConstructorArgs + : classToMethodArgs, + (TypeElement) t.asElement(), p); + return null; + } + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Void visitTypeVariable(TypeVariable t, ExecutableElement p) { + visit(typeutils.erasure(t), p); + return null; + } + }.visit(pType, ee); + mapTypeParameters(isConstructor + ? classToConstructorArgTypeParam + : classToMethodArgTypeParam, + pType, ee); + } + } + mapAnnotations(isConstructor + ? classToConstructorParamAnnotation + : classToMethodParamAnnotation, + param, ee); + + } + for (TypeMirror anException : ee.getThrownTypes()) { + SimpleTypeVisitor9 stv = new SimpleTypeVisitor9() { + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Void visitArray(ArrayType t, ExecutableElement p) { + super.visit(t.getComponentType(), p); + return null; + } + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Void visitDeclared(DeclaredType t, ExecutableElement p) { + add(isConstructor ? classToConstructorThrows : classToMethodThrows, + (TypeElement) t.asElement(), p); + return null; + } + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Void visitError(ErrorType t, ExecutableElement p) { + add(isConstructor ? classToConstructorThrows : classToMethodThrows, + (TypeElement) t.asElement(), p); + return null; + } + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + protected Void defaultAction(TypeMirror e, ExecutableElement p) { + throw new AssertionError("this should not happen"); + } + }; + + stv.visit(typeutils.erasure(anException), ee); + } + } + + private List refList(Map> map, Element element) { + List list = map.get(element); + if (list == null) { + list = new ArrayList<>(); + map.put((TypeElement) element, list); + } + return list; + } + + private Set packageSet(TypeElement te) { + Set pkgSet = classToPackage.get(te); + if (pkgSet == null) { + pkgSet = new TreeSet<>(utils.makeClassUseComparator()); + classToPackage.put(te, pkgSet); + } + return pkgSet; + } + + private Set classSet(TypeElement te) { + Set clsSet = classToClass.get(te); + if (clsSet == null) { + clsSet = new TreeSet<>(utils.makeClassUseComparator()); + classToClass.put(te, clsSet); + } + return clsSet; + } + + private void add(Map> map, TypeElement te, T ref) { + // add to specified map + refList(map, te).add(ref); + // add ref's package to package map and class map + packageSet(te).add(elements.getPackageOf(ref)); + TypeElement entry = (utils.isField((Element) ref) + || utils.isConstructor((Element) ref) + || utils.isMethod((Element) ref)) + ? (TypeElement) ref.getEnclosingElement() + : (TypeElement) ref; + classSet(te).add(entry); + } + + private void addAll(Map> map, TypeElement te, Collection refs) { + if (refs == null) { + return; + } + // add to specified map + refList(map, te).addAll(refs); + + Set pkgSet = packageSet(te); + Set clsSet = classSet(te); + // add ref's package to package map and class map + for (TypeElement cls : refs) { + pkgSet.add(utils.containingPackage(cls)); + clsSet.add(cls); + } + } + + /** + * Map the TypeElements to the members that use them as type parameters. + * + * @param map the map the insert the information into. + * @param element the te whose type parameters are being checked. + * @param holder the holder that owns the type parameters. + */ + private void mapTypeParameters(final Map> map, + Element element, final T holder) { + + SimpleElementVisitor9 elementVisitor + = new SimpleElementVisitor9() { + + private void addParameters(TypeParameterElement e) { + for (TypeMirror type : utils.getBounds(e)) { + addTypeParameterToMap(map, type, holder); + } + } + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Void visitType(TypeElement e, Void p) { + for (TypeParameterElement param : e.getTypeParameters()) { + addParameters(param); + } + return null; + } + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Void visitExecutable(ExecutableElement e, Void p) { + for (TypeParameterElement param : e.getTypeParameters()) { + addParameters(param); + } + return null; + } + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + protected Void defaultAction(Element e, Void p) { + mapTypeParameters(map, e.asType(), holder); + return null; + } + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Void visitTypeParameter(TypeParameterElement e, Void p) { + addParameters(e); + return null; + } + }; + elementVisitor.visit(element); + } + + private void mapTypeParameters(final Map> map, + TypeMirror aType, final T holder) { + + SimpleTypeVisitor9 tv = new SimpleTypeVisitor9() { + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Void visitWildcard(WildcardType t, Void p) { + TypeMirror bound = t.getExtendsBound(); + if (bound != null) { + addTypeParameterToMap(map, bound, holder); + } + bound = t.getSuperBound(); + if (bound != null) { + addTypeParameterToMap(map, bound, holder); + } + return null; + } + + // ParameterizedType + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Void visitDeclared(DeclaredType t, Void p) { + for (TypeMirror targ : t.getTypeArguments()) { + addTypeParameterToMap(map, targ, holder); + } + return null; + } + }; + tv.visit(aType); + } + + /** + * Map the AnnotationType to the members that use them as type parameters. + * + * @param map the map the insert the information into. + * @param element whose type parameters are being checked. + * @param holder the holder that owns the type parameters. + */ + private void mapAnnotations(final Map> map, + Element e, final T holder) { + new SimpleElementVisitor9() { + + void addAnnotations(Element e) { + for (AnnotationMirror a : e.getAnnotationMirrors()) { + add(map, (TypeElement) a.getAnnotationType().asElement(), holder); + } + } + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Void visitPackage(PackageElement e, Void p) { + for (AnnotationMirror a : e.getAnnotationMirrors()) { + refList(map, a.getAnnotationType().asElement()).add(holder); + } + return null; + } + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + protected Void defaultAction(Element e, Void p) { + addAnnotations(e); + return null; + } + }.visit(e); + } + + private void addTypeParameterToMap(final Map> map, + TypeMirror type, final T holder) { + new SimpleTypeVisitor9() { + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + protected Void defaultAction(TypeMirror e, Void p) { + return super.defaultAction(e, p); + } + + @Override @DefinedBy(Api.LANGUAGE_MODEL) + public Void visitDeclared(DeclaredType t, Void p) { + add(map, (TypeElement) t.asElement(), holder); + return null; + } + + }.visit(type); + mapTypeParameters(map, type, holder); + } +}