31 import javax.lang.model.element.VariableElement;
32 import javax.lang.model.type.TypeKind;
33 import javax.lang.model.type.TypeMirror;
34 import javax.lang.model.util.Elements;
35 import javax.lang.model.util.SimpleElementVisitor14;
36 import java.lang.ref.SoftReference;
37 import java.util.ArrayList;
38 import java.util.Collections;
39 import java.util.EnumMap;
40 import java.util.EnumSet;
41 import java.util.HashMap;
42 import java.util.LinkedHashMap;
43 import java.util.LinkedHashSet;
44 import java.util.List;
45 import java.util.Map;
46 import java.util.Set;
47 import java.util.function.Predicate;
48 import java.util.stream.Collectors;
49
50 import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
51 import jdk.javadoc.internal.doclets.toolkit.PropertyUtils;
52
53 /**
54 * This class computes the main data structure for the doclet's
55 * operations. Essentially, the implementation encapsulating the
56 * javax.lang.models view of what can be documented about a
57 * type element's members.
58 * <p>
59 * The general operations are as follows:
60 * <p>
61 * Members: these are the members from jx.l.m's view but
62 * are structured along the kinds of this class.
63 * <p>
64 * Extra Members: these are members enclosed in an undocumented
65 * package-private type element, and may not be linkable (or documented),
66 * however, the members of such a type element may be documented, as if
67 * declared in the sub type, only if the enclosing type is not being
68 * documented by a filter such as -public, -protected, etc.
69 * <p>
70 * Visible Members: these are the members that are "visible"
89
90 public enum Kind {
91 INNER_CLASSES,
92 ENUM_CONSTANTS,
93 FIELDS,
94 CONSTRUCTORS,
95 METHODS,
96 ANNOTATION_TYPE_FIELDS,
97 ANNOTATION_TYPE_MEMBER_OPTIONAL,
98 ANNOTATION_TYPE_MEMBER_REQUIRED,
99 PROPERTIES;
100
101 public static final EnumSet<Kind> summarySet = EnumSet.range(INNER_CLASSES, METHODS);
102 public static final EnumSet<Kind> detailSet = EnumSet.range(ENUM_CONSTANTS, METHODS);
103 }
104
105 final TypeElement te;
106 final TypeElement parent;
107
108 final BaseConfiguration config;
109 final Utils utils;
110 final VisibleMemberCache mcache;
111
112 private List<VisibleMemberTable> allSuperclasses;
113 private List<VisibleMemberTable> allSuperinterfaces;
114 private List<VisibleMemberTable> parents;
115
116
117 private Map<Kind, List<Element>> extraMembers = new EnumMap<>(Kind.class);
118 private Map<Kind, List<Element>> visibleMembers = null;
119 private Map<ExecutableElement, PropertyMembers> propertyMap = new HashMap<>();
120
121 // Keeps track of method overrides
122 Map<ExecutableElement, OverridingMethodInfo> overriddenMethodTable
123 = new LinkedHashMap<>();
124
125 protected VisibleMemberTable(TypeElement typeElement, BaseConfiguration configuration,
126 VisibleMemberCache mcache) {
127 config = configuration;
128 utils = configuration.utils;
129 te = typeElement;
130 parent = utils.getSuperClass(te);
131 this.mcache = mcache;
132 allSuperclasses = new ArrayList<>();
133 allSuperinterfaces = new ArrayList<>();
134 parents = new ArrayList<>();
135 }
136
137 private synchronized void ensureInitialized() {
138 if (visibleMembers != null)
139 return;
140
141 visibleMembers = new EnumMap<>(Kind.class);
142 for (Kind kind : Kind.values()) {
143 visibleMembers.put(kind, new ArrayList<>());
144 }
145 computeParents();
146 computeVisibleMembers();
147 }
148
641 * contains the members in the declaration order, additionally a
642 * HashMap is maintained for performance optimization to lookup
643 * members. As a future enhancement is perhaps to consolidate the ordering
644 * into a Map, capturing the insertion order, thereby eliminating an
645 * ordered list.
646 */
647 class LocalMemberTable {
648
649 // Maintains declaration order
650 private final Map<Kind, List<Element>> orderedMembers;
651
652 // Performance optimization
653 private final Map<Kind, Map<String, List<Element>>> memberMap;
654
655 LocalMemberTable() {
656 orderedMembers = new EnumMap<>(Kind.class);
657 memberMap = new EnumMap<>(Kind.class);
658
659 List<? extends Element> elements = te.getEnclosedElements();
660 for (Element e : elements) {
661 if (config.nodeprecated && utils.isDeprecated(e)) {
662 continue;
663 }
664 switch (e.getKind()) {
665 case CLASS:
666 case INTERFACE:
667 case ENUM:
668 case ANNOTATION_TYPE:
669 case RECORD:
670 addMember(e, Kind.INNER_CLASSES);
671 break;
672 case FIELD:
673 addMember(e, Kind.FIELDS);
674 addMember(e, Kind.ANNOTATION_TYPE_FIELDS);
675 break;
676 case METHOD:
677 ExecutableElement ee = (ExecutableElement)e;
678 if (utils.isAnnotationType(te)) {
679 addMember(e, ee.getDefaultValue() == null
680 ? Kind.ANNOTATION_TYPE_MEMBER_REQUIRED
681 : Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL);
783 * Property field, one may or may not exist and could be private, and
784 * should match the property-method.
785 *
786 * A property-setter is a method starting with "set", and the
787 * first character of the upper-cased starting character of the property name, the
788 * method must take 1 argument and must return a <code>void</code>.
789 *
790 * Using the above example {@code void setAcme(Something s)} can be
791 * considered as a property-setter of the property "acme".
792 *
793 * A property-getter is a method starting with "get" and the first character
794 * upper-cased property-name, having no parameters. A method that does not take any
795 * parameters and starting with "is" and an upper-cased property-name,
796 * returning a primitive type boolean or BooleanProperty can also be
797 * considered as a getter, however there must be only one getter for every property.
798 *
799 * For example {@code Object getAcme()} is a property-getter, and
800 * {@code boolean isFoo()}
801 */
802 private void computeVisibleProperties(LocalMemberTable lmt) {
803 if (!config.javafx)
804 return;
805
806 PropertyUtils pUtils = config.propertyUtils;
807 List<ExecutableElement> list = visibleMembers.getOrDefault(Kind.METHODS, Collections.emptyList())
808 .stream()
809 .map(m -> (ExecutableElement)m)
810 .filter(pUtils::isPropertyMethod)
811 .collect(Collectors.toList());
812
813 visibleMembers.put(Kind.PROPERTIES, Collections.unmodifiableList(list));
814
815 List<ExecutableElement> propertyMethods = list.stream()
816 .filter(e -> utils.getEnclosingTypeElement(e) == te)
817 .collect(Collectors.toList());
818
819 // Compute additional properties related sundries.
820 for (ExecutableElement propertyMethod : propertyMethods) {
821 String baseName = pUtils.getBaseName(propertyMethod);
822 List<Element> flist = lmt.getMembers(baseName, Kind.FIELDS);
823 Element field = flist.isEmpty() ? null : flist.get(0);
|
31 import javax.lang.model.element.VariableElement;
32 import javax.lang.model.type.TypeKind;
33 import javax.lang.model.type.TypeMirror;
34 import javax.lang.model.util.Elements;
35 import javax.lang.model.util.SimpleElementVisitor14;
36 import java.lang.ref.SoftReference;
37 import java.util.ArrayList;
38 import java.util.Collections;
39 import java.util.EnumMap;
40 import java.util.EnumSet;
41 import java.util.HashMap;
42 import java.util.LinkedHashMap;
43 import java.util.LinkedHashSet;
44 import java.util.List;
45 import java.util.Map;
46 import java.util.Set;
47 import java.util.function.Predicate;
48 import java.util.stream.Collectors;
49
50 import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
51 import jdk.javadoc.internal.doclets.toolkit.BaseOptions;
52 import jdk.javadoc.internal.doclets.toolkit.PropertyUtils;
53
54 /**
55 * This class computes the main data structure for the doclet's
56 * operations. Essentially, the implementation encapsulating the
57 * javax.lang.models view of what can be documented about a
58 * type element's members.
59 * <p>
60 * The general operations are as follows:
61 * <p>
62 * Members: these are the members from jx.l.m's view but
63 * are structured along the kinds of this class.
64 * <p>
65 * Extra Members: these are members enclosed in an undocumented
66 * package-private type element, and may not be linkable (or documented),
67 * however, the members of such a type element may be documented, as if
68 * declared in the sub type, only if the enclosing type is not being
69 * documented by a filter such as -public, -protected, etc.
70 * <p>
71 * Visible Members: these are the members that are "visible"
90
91 public enum Kind {
92 INNER_CLASSES,
93 ENUM_CONSTANTS,
94 FIELDS,
95 CONSTRUCTORS,
96 METHODS,
97 ANNOTATION_TYPE_FIELDS,
98 ANNOTATION_TYPE_MEMBER_OPTIONAL,
99 ANNOTATION_TYPE_MEMBER_REQUIRED,
100 PROPERTIES;
101
102 public static final EnumSet<Kind> summarySet = EnumSet.range(INNER_CLASSES, METHODS);
103 public static final EnumSet<Kind> detailSet = EnumSet.range(ENUM_CONSTANTS, METHODS);
104 }
105
106 final TypeElement te;
107 final TypeElement parent;
108
109 final BaseConfiguration config;
110 final BaseOptions options;
111 final Utils utils;
112 final VisibleMemberCache mcache;
113
114 private List<VisibleMemberTable> allSuperclasses;
115 private List<VisibleMemberTable> allSuperinterfaces;
116 private List<VisibleMemberTable> parents;
117
118
119 private Map<Kind, List<Element>> extraMembers = new EnumMap<>(Kind.class);
120 private Map<Kind, List<Element>> visibleMembers = null;
121 private Map<ExecutableElement, PropertyMembers> propertyMap = new HashMap<>();
122
123 // Keeps track of method overrides
124 Map<ExecutableElement, OverridingMethodInfo> overriddenMethodTable
125 = new LinkedHashMap<>();
126
127 protected VisibleMemberTable(TypeElement typeElement, BaseConfiguration configuration,
128 VisibleMemberCache mcache) {
129 config = configuration;
130 utils = configuration.utils;
131 options = configuration.getOptions();
132 te = typeElement;
133 parent = utils.getSuperClass(te);
134 this.mcache = mcache;
135 allSuperclasses = new ArrayList<>();
136 allSuperinterfaces = new ArrayList<>();
137 parents = new ArrayList<>();
138 }
139
140 private synchronized void ensureInitialized() {
141 if (visibleMembers != null)
142 return;
143
144 visibleMembers = new EnumMap<>(Kind.class);
145 for (Kind kind : Kind.values()) {
146 visibleMembers.put(kind, new ArrayList<>());
147 }
148 computeParents();
149 computeVisibleMembers();
150 }
151
644 * contains the members in the declaration order, additionally a
645 * HashMap is maintained for performance optimization to lookup
646 * members. As a future enhancement is perhaps to consolidate the ordering
647 * into a Map, capturing the insertion order, thereby eliminating an
648 * ordered list.
649 */
650 class LocalMemberTable {
651
652 // Maintains declaration order
653 private final Map<Kind, List<Element>> orderedMembers;
654
655 // Performance optimization
656 private final Map<Kind, Map<String, List<Element>>> memberMap;
657
658 LocalMemberTable() {
659 orderedMembers = new EnumMap<>(Kind.class);
660 memberMap = new EnumMap<>(Kind.class);
661
662 List<? extends Element> elements = te.getEnclosedElements();
663 for (Element e : elements) {
664 if (options.noDeprecated && utils.isDeprecated(e)) {
665 continue;
666 }
667 switch (e.getKind()) {
668 case CLASS:
669 case INTERFACE:
670 case ENUM:
671 case ANNOTATION_TYPE:
672 case RECORD:
673 addMember(e, Kind.INNER_CLASSES);
674 break;
675 case FIELD:
676 addMember(e, Kind.FIELDS);
677 addMember(e, Kind.ANNOTATION_TYPE_FIELDS);
678 break;
679 case METHOD:
680 ExecutableElement ee = (ExecutableElement)e;
681 if (utils.isAnnotationType(te)) {
682 addMember(e, ee.getDefaultValue() == null
683 ? Kind.ANNOTATION_TYPE_MEMBER_REQUIRED
684 : Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL);
786 * Property field, one may or may not exist and could be private, and
787 * should match the property-method.
788 *
789 * A property-setter is a method starting with "set", and the
790 * first character of the upper-cased starting character of the property name, the
791 * method must take 1 argument and must return a <code>void</code>.
792 *
793 * Using the above example {@code void setAcme(Something s)} can be
794 * considered as a property-setter of the property "acme".
795 *
796 * A property-getter is a method starting with "get" and the first character
797 * upper-cased property-name, having no parameters. A method that does not take any
798 * parameters and starting with "is" and an upper-cased property-name,
799 * returning a primitive type boolean or BooleanProperty can also be
800 * considered as a getter, however there must be only one getter for every property.
801 *
802 * For example {@code Object getAcme()} is a property-getter, and
803 * {@code boolean isFoo()}
804 */
805 private void computeVisibleProperties(LocalMemberTable lmt) {
806 if (!options.javafx)
807 return;
808
809 PropertyUtils pUtils = config.propertyUtils;
810 List<ExecutableElement> list = visibleMembers.getOrDefault(Kind.METHODS, Collections.emptyList())
811 .stream()
812 .map(m -> (ExecutableElement)m)
813 .filter(pUtils::isPropertyMethod)
814 .collect(Collectors.toList());
815
816 visibleMembers.put(Kind.PROPERTIES, Collections.unmodifiableList(list));
817
818 List<ExecutableElement> propertyMethods = list.stream()
819 .filter(e -> utils.getEnclosingTypeElement(e) == te)
820 .collect(Collectors.toList());
821
822 // Compute additional properties related sundries.
823 for (ExecutableElement propertyMethod : propertyMethods) {
824 String baseName = pUtils.getBaseName(propertyMethod);
825 List<Element> flist = lmt.getMembers(baseName, Kind.FIELDS);
826 Element field = flist.isEmpty() ? null : flist.get(0);
|