VisibleMemberMap.java revision 3233:b5d08bc0d224
1/* 2 * Copyright (c) 1999, 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 */ 25 26package jdk.javadoc.internal.doclets.toolkit.util; 27 28import java.util.*; 29import java.util.regex.Pattern; 30 31import javax.lang.model.element.Element; 32import javax.lang.model.element.ExecutableElement; 33import javax.lang.model.element.TypeElement; 34import javax.lang.model.element.VariableElement; 35import javax.lang.model.type.TypeKind; 36import javax.lang.model.type.TypeMirror; 37 38import com.sun.source.doctree.DocCommentTree; 39import com.sun.source.doctree.DocTree; 40 41import jdk.javadoc.internal.doclets.toolkit.Configuration; 42 43/** 44 * A data structure that encapsulates the visible members of a particular 45 * type for a given class tree. To use this data structure, you must specify 46 * the type of member you are interested in (nested class, field, constructor 47 * or method) and the leaf of the class tree. The data structure will map 48 * all visible members in the leaf and classes above the leaf in the tree. 49 * 50 * <p><b>This is NOT part of any supported API. 51 * If you write code that depends on this, you do so at your own risk. 52 * This code and its internal interfaces are subject to change or 53 * deletion without notice.</b> 54 * 55 * @author Atul M Dambalkar 56 * @author Jamie Ho (rewrite) 57 */ 58public class VisibleMemberMap { 59 60 private boolean noVisibleMembers = true; 61 62 public static enum Kind { 63 INNER_CLASSES, 64 ENUM_CONSTANTS, 65 FIELDS, 66 CONSTRUCTORS, 67 METHODS, 68 ANNOTATION_TYPE_FIELDS, 69 ANNOTATION_TYPE_MEMBER_OPTIONAL, 70 ANNOTATION_TYPE_MEMBER_REQUIRED, 71 PROPERTIES; 72 73 public static final EnumSet<Kind> summarySet = EnumSet.range(INNER_CLASSES, METHODS); 74 public static final EnumSet<Kind> detailSet = EnumSet.range(ENUM_CONSTANTS, METHODS); 75 public static String getNavLinkLabels(Kind kind) { 76 switch (kind) { 77 case INNER_CLASSES: 78 return "doclet.navNested"; 79 case ENUM_CONSTANTS: 80 return "doclet.navEnum"; 81 case FIELDS: 82 return "doclet.navField"; 83 case CONSTRUCTORS: 84 return "doclet.navConstructor"; 85 case METHODS: 86 return "doclet.navMethod"; 87 default: 88 throw new AssertionError("unknown kind:" + kind); 89 } 90 } 91 } 92 93 public static final String STARTLEVEL = "start"; 94 95 // properties aren't named setA* or getA* 96 private static final Pattern GETTERSETTERPATTERN = Pattern.compile("[sg]et\\p{Upper}.*"); 97 /** 98 * List of TypeElement objects for which ClassMembers objects are built. 99 */ 100 private final Set<TypeElement> visibleClasses; 101 102 /** 103 * Map for each member name on to a map which contains members with same 104 * name-signature. The mapped map will contain mapping for each MemberDoc 105 * onto it's respecive level string. 106 */ 107 private final Map<Object, Map<Element, String>> memberNameMap = new HashMap<>(); 108 109 /** 110 * Map of class and it's ClassMembers object. 111 */ 112 private final Map<TypeElement, ClassMembers> classMap = new HashMap<>(); 113 114 /** 115 * Type whose visible members are requested. This is the leaf of 116 * the class tree being mapped. 117 */ 118 private final TypeElement typeElement; 119 120 /** 121 * Member kind: InnerClasses/Fields/Methods? 122 */ 123 private final Kind kind; 124 125 /** 126 * The configuration this VisibleMemberMap was created with. 127 */ 128 private final Configuration configuration; 129 private final Utils utils; 130 private final Comparator<Element> comparator; 131 132 private final Map<TypeElement, List<Element>> propertiesCache; 133 private final Map<Element, Element> classPropertiesMap; 134 private final Map<Element, GetterSetter> getterSetterMap; 135 136 /** 137 * Construct a VisibleMemberMap of the given type for the given class. 138 * 139 * @param typeElement whose members are being mapped. 140 * @param kind the kind of member that is being mapped. 141 * @param configuration the configuration to use to construct this 142 * VisibleMemberMap. If the field configuration.nodeprecated is true the 143 * deprecated members are excluded from the map. If the field 144 * configuration.javafx is true the JavaFX features are used. 145 */ 146 public VisibleMemberMap(TypeElement typeElement, 147 Kind kind, 148 Configuration configuration) { 149 this.typeElement = typeElement; 150 this.kind = kind; 151 this.configuration = configuration; 152 this.utils = configuration.utils; 153 propertiesCache = configuration.propertiesCache; 154 classPropertiesMap = configuration.classPropertiesMap; 155 getterSetterMap = configuration.getterSetterMap; 156 comparator = utils.makeGeneralPurposeComparator(); 157 visibleClasses = new LinkedHashSet<>(); 158 new ClassMembers(typeElement, STARTLEVEL).build(); 159 } 160 161 /** 162 * Return the list of visible classes in this map. 163 * 164 * @return the list of visible classes in this map. 165 */ 166 public SortedSet<TypeElement> getVisibleClasses() { 167 SortedSet<TypeElement> vClasses = new TreeSet<>(comparator); 168 vClasses.addAll(visibleClasses); 169 return vClasses; 170 } 171 172 /** 173 * Returns the property field documentation belonging to the given member. 174 * @param element the member for which the property documentation is needed. 175 * @return the property field documentation, null if there is none. 176 */ 177 public Element getPropertyMemberDoc(Element element) { 178 return classPropertiesMap.get(element); 179 } 180 181 /** 182 * Returns the getter documentation belonging to the given property method. 183 * @param propertyMethod the method for which the getter is needed. 184 * @return the getter documentation, null if there is none. 185 */ 186 public Element getGetterForProperty(Element propertyMethod) { 187 return getterSetterMap.get(propertyMethod).getGetter(); 188 } 189 190 /** 191 * Returns the setter documentation belonging to the given property method. 192 * @param propertyMethod the method for which the setter is needed. 193 * @return the setter documentation, null if there is none. 194 */ 195 public Element getSetterForProperty(Element propertyMethod) { 196 return getterSetterMap.get(propertyMethod).getSetter(); 197 } 198 199 /** 200 * Return the package private members inherited by the class. Only return 201 * if parent is package private and not documented. 202 * 203 * @return the package private members inherited by the class. 204 */ 205 private List<Element> getInheritedPackagePrivateMethods() { 206 List<Element> results = new ArrayList<>(); 207 for (TypeElement currentClass : visibleClasses) { 208 if (currentClass != typeElement && 209 utils.isPackagePrivate(currentClass) && 210 !utils.isLinkable(currentClass)) { 211 // Document these members in the child class because 212 // the parent is inaccessible. 213 results.addAll(classMap.get(currentClass).members); 214 } 215 } 216 return results; 217 } 218 219 /** 220 * Return the visible members of the class being mapped. Also append at the 221 * end of the list members that are inherited by inaccessible parents. We 222 * document these members in the child because the parent is not documented. 223 * 224 * @param configuration the current configuration of the doclet. 225 */ 226 public SortedSet<Element> getLeafClassMembers() { 227 SortedSet<Element> result = getMembersFor(typeElement); 228 result.addAll(getInheritedPackagePrivateMethods()); 229 return result; 230 } 231 232 public Set<Element> getLeafClassMembersSourceOrder() { 233 Set<Element> result = new LinkedHashSet<>(classMap.get(typeElement).members); 234 result.addAll(getInheritedPackagePrivateMethods()); 235 return result; 236 } 237 238 /** 239 * Retrn the list of members for the given class. 240 * 241 * @param typeElement the class to retrieve the list of visible members for. 242 * 243 * @return the list of members for the given class. 244 */ 245 public SortedSet<Element> getMembersFor(TypeElement typeElement) { 246 return asSortedSet(classMap.get(typeElement).members); 247 } 248 249 public boolean hasMembersFor(TypeElement typeElement) { 250 return !classMap.get(typeElement).members.isEmpty(); 251 } 252 253 private SortedSet<Element> asSortedSet(Collection<Element> in) { 254 if (in == null) { 255 return Collections.emptySortedSet(); 256 } 257 TreeSet<Element> out = new TreeSet<>(comparator); 258 out.addAll(in); 259 return out; 260 } 261 262 private void fillMemberLevelMap(List<? extends Element> list, String level) { 263 for (Element element : list) { 264 Object key = getMemberKey(element); 265 Map<Element, String> memberLevelMap = memberNameMap.get(key); 266 if (memberLevelMap == null) { 267 memberLevelMap = new HashMap<>(); 268 memberNameMap.put(key, memberLevelMap); 269 } 270 memberLevelMap.put(element, level); 271 } 272 } 273 274 private void purgeMemberLevelMap(Iterable<? extends Element> list, String level) { 275 for (Element element : list) { 276 Object key = getMemberKey(element); 277 Map<Element, String> memberLevelMap = memberNameMap.get(key); 278 if (memberLevelMap != null && level.equals(memberLevelMap.get(element))) 279 memberLevelMap.remove(element); 280 } 281 } 282 283 /** 284 * Represents a class member. 285 */ 286 private class ClassMember { 287 private Set<Element> members; 288 289 public ClassMember(Element element) { 290 members = new HashSet<>(); 291 members.add(element); 292 } 293 294 public boolean isEqual(ExecutableElement member) { 295 for (Element element : members) { 296 if (utils.executableMembersEqual(member, (ExecutableElement) element)) { 297 members.add(member); 298 return true; 299 } 300 } 301 return false; 302 } 303 } 304 305 /** 306 * A data structure that represents the class members for 307 * a visible class. 308 */ 309 private class ClassMembers { 310 311 /** 312 * The mapping class, whose inherited members are put in the 313 * {@link #members} list. 314 */ 315 private final TypeElement typeElement; 316 317 /** 318 * List of inherited members from the mapping class. 319 */ 320 private Set<Element> members = new LinkedHashSet<>(); 321 322 /** 323 * Level/Depth of inheritance. 324 */ 325 private final String level; 326 327 private ClassMembers(TypeElement mappingClass, String level) { 328 this.typeElement = mappingClass; 329 this.level = level; 330 if (classMap.containsKey(mappingClass) && 331 level.startsWith(classMap.get(mappingClass).level)) { 332 //Remove lower level class so that it can be replaced with 333 //same class found at higher level. 334 purgeMemberLevelMap(getClassMembers(mappingClass, false), 335 classMap.get(mappingClass).level); 336 classMap.remove(mappingClass); 337 visibleClasses.remove(mappingClass); 338 } 339 if (!classMap.containsKey(mappingClass)) { 340 classMap.put(mappingClass, this); 341 visibleClasses.add(mappingClass); 342 } 343 } 344 345 private void build() { 346 if (kind == Kind.CONSTRUCTORS) { 347 addMembers(typeElement); 348 } else { 349 mapClass(); 350 } 351 } 352 353 private void mapClass() { 354 addMembers(typeElement); 355 List<? extends TypeMirror> interfaces = typeElement.getInterfaces(); 356 for (TypeMirror anInterface : interfaces) { 357 String locallevel = level + 1; 358 ClassMembers cm = new ClassMembers(utils.asTypeElement(anInterface), locallevel); 359 cm.mapClass(); 360 } 361 if (utils.isClass(typeElement)) { 362 TypeElement superclass = utils.getSuperClass(typeElement); 363 if (!(superclass == null || typeElement.equals(superclass))) { 364 ClassMembers cm = new ClassMembers(superclass, level + "c"); 365 cm.mapClass(); 366 } 367 } 368 } 369 370 /** 371 * Get all the valid members from the mapping class. Get the list of 372 * members for the class to be included into(ctii), also get the level 373 * string for ctii. If mapping class member is not already in the 374 * inherited member list and if it is visible in the ctii and not 375 * overridden, put such a member in the inherited member list. 376 * Adjust member-level-map, class-map. 377 */ 378 private void addMembers(TypeElement fromClass) { 379 List<? extends Element> classMembers = getClassMembers(fromClass, true); 380 List<Element> incllist = new ArrayList<>(); 381 for (Element element : classMembers) { 382 if (!found(members, element)) { 383 if (memberIsVisible(element)) { 384 if (!isOverridden(element, level)) { 385 if (!isTreatedAsPrivate(element)) { 386 incllist.add(element); 387 } 388 } 389 } 390 } 391 } 392 if (!incllist.isEmpty()) { 393 noVisibleMembers = false; 394 } 395 members.addAll(incllist); 396 fillMemberLevelMap(getClassMembers(fromClass, false), level); 397 } 398 399 private boolean isTreatedAsPrivate(Element pgmelem) { 400 if (!configuration.javafx) { 401 return false; 402 } 403 404 List<? extends DocTree> aspTags = utils.getBlockTags(pgmelem, "@treatAsPrivate"); 405 boolean result = (aspTags != null) && (!aspTags.isEmpty()); 406 return result; 407 } 408 409 /** 410 * Is given element visible in given typeElement in terms of inheritance? The given element 411 * is visible in the given typeElement if it is public or protected and if it is 412 * package-private if it's containing class is in the same package as the given typeElement. 413 */ 414 private boolean memberIsVisible(Element element) { 415 if (utils.getEnclosingTypeElement(element).equals(VisibleMemberMap.this.typeElement)) { 416 //Member is in class that we are finding visible members for. 417 //Of course it is visible. 418 return true; 419 } else if (utils.isPrivate(element)) { 420 //Member is in super class or implemented interface. 421 //Private, so not inherited. 422 return false; 423 } else if (utils.isPackagePrivate(element)) { 424 //Member is package private. Only return true if its class is in 425 //same package. 426 return utils.containingPackage(element).equals(utils.containingPackage(VisibleMemberMap.this.typeElement)); 427 } else { 428 //Public members are always inherited. 429 return true; 430 } 431 } 432 433 /** 434 * Return all available class members. 435 */ 436 private List<? extends Element> getClassMembers(TypeElement te, boolean filter) { 437 if (utils.isEnum(te) && kind == Kind.CONSTRUCTORS) { 438 //If any of these rules are hit, return empty array because 439 //we don't document these members ever. 440 return Collections.emptyList(); 441 } 442 List<? extends Element> list; 443 switch (kind) { 444 case ANNOTATION_TYPE_FIELDS: 445 list = (filter) 446 ? utils.getAnnotationFields(te) 447 : utils.getAnnotationFieldsUnfiltered(te); 448 break; 449 case ANNOTATION_TYPE_MEMBER_OPTIONAL: 450 list = utils.isAnnotationType(te) 451 ? filterAnnotations(te, false) 452 : Collections.emptyList(); 453 break; 454 case ANNOTATION_TYPE_MEMBER_REQUIRED: 455 list = utils.isAnnotationType(te) 456 ? filterAnnotations(te, true) 457 : Collections.emptyList(); 458 break; 459 case INNER_CLASSES: 460 List<TypeElement> xlist = filter 461 ? utils.getInnerClasses(te) 462 : utils.getInnerClassesUnfiltered(te); 463 list = new ArrayList<>(xlist); 464 break; 465 case ENUM_CONSTANTS: 466 list = utils.getEnumConstants(te); 467 break; 468 case FIELDS: 469 if (filter) { 470 list = utils.isAnnotationType(te) 471 ? utils.getAnnotationFields(te) 472 : utils.getFields(te); 473 } else { 474 list = utils.isAnnotationType(te) 475 ? utils.getAnnotationFieldsUnfiltered(te) 476 : utils.getFieldsUnfiltered(te); 477 } 478 break; 479 case CONSTRUCTORS: 480 list = utils.getConstructors(te); 481 break; 482 case METHODS: 483 list = filter ? utils.getMethods(te) : utils.getMethodsUnfiltered(te); 484 checkOnPropertiesTags(list); 485 break; 486 case PROPERTIES: 487 list = properties(te, filter); 488 break; 489 default: 490 list = Collections.emptyList(); 491 } 492 // Deprected members should be excluded or not? 493 if (configuration.nodeprecated) { 494 return utils.excludeDeprecatedMembers(list); 495 } 496 return list; 497 } 498 499 /** 500 * Filter the annotation type members and return either the required 501 * members or the optional members, depending on the value of the 502 * required parameter. 503 * 504 * @param typeElement The annotation type to process. 505 * @param required 506 * @return the annotation type members and return either the required 507 * members or the optional members, depending on the value of the 508 * required parameter. 509 */ 510 private List<Element> filterAnnotations(TypeElement typeElement, boolean required) { 511 List<Element> members = utils.getAnnotationMethods(typeElement); 512 List<Element> targetMembers = new ArrayList<>(); 513 for (Element member : members) { 514 ExecutableElement ee = (ExecutableElement)member; 515 if ((required && ee.getDefaultValue() == null) 516 || ((!required) && ee.getDefaultValue() != null)) { 517 targetMembers.add(member); 518 } 519 } 520 return targetMembers; 521 } 522 523 private boolean found(Iterable<Element> list, Element elem) { 524 for (Element pgmelem : list) { 525 if (utils.matches(pgmelem, elem)) { 526 return true; 527 } 528 } 529 return false; 530 } 531 532 533 /** 534 * Is member overridden? The member is overridden if it is found in the 535 * same level hierarchy e.g. member at level "11" overrides member at 536 * level "111". 537 */ 538 private boolean isOverridden(Element element, String level) { 539 Object key = getMemberKey(element); 540 Map<?, String> memberLevelMap = (Map<?, String>) memberNameMap.get(key); 541 if (memberLevelMap == null) 542 return false; 543 for (String mappedlevel : memberLevelMap.values()) { 544 if (mappedlevel.equals(STARTLEVEL) 545 || (level.startsWith(mappedlevel) 546 && !level.equals(mappedlevel))) { 547 return true; 548 } 549 } 550 return false; 551 } 552 553 private List<Element> properties(final TypeElement typeElement, final boolean filter) { 554 final List<ExecutableElement> allMethods = filter 555 ? utils.getMethods(typeElement) 556 : utils.getMethodsUnfiltered(typeElement); 557 final List<VariableElement> allFields = utils.getFieldsUnfiltered(typeElement); 558 559 if (propertiesCache.containsKey(typeElement)) { 560 return propertiesCache.get(typeElement); 561 } 562 563 final List<Element> result = new ArrayList<>(); 564 565 for (final Element propertyMethod : allMethods) { 566 ExecutableElement ee = (ExecutableElement)propertyMethod; 567 if (!isPropertyMethod(ee)) { 568 continue; 569 } 570 571 final ExecutableElement getter = getterForField(allMethods, ee); 572 final ExecutableElement setter = setterForField(allMethods, ee); 573 final VariableElement field = fieldForProperty(allFields, ee); 574 575 addToPropertiesMap(setter, getter, ee, field); 576 getterSetterMap.put(propertyMethod, new GetterSetter(getter, setter)); 577 result.add(ee); 578 } 579 propertiesCache.put(typeElement, result); 580 return result; 581 } 582 583 private void addToPropertiesMap(ExecutableElement setter, 584 ExecutableElement getter, 585 ExecutableElement propertyMethod, 586 VariableElement field) { 587 if (field == null || utils.getDocCommentTree(field) == null) { 588 addToPropertiesMap(setter, propertyMethod); 589 addToPropertiesMap(getter, propertyMethod); 590 addToPropertiesMap(propertyMethod, propertyMethod); 591 } else { 592 addToPropertiesMap(getter, field); 593 addToPropertiesMap(setter, field); 594 addToPropertiesMap(propertyMethod, field); 595 } 596 } 597 598 private void addToPropertiesMap(Element propertyMethod, 599 Element commentSource) { 600 if (null == propertyMethod || null == commentSource) { 601 return; 602 } 603 DocCommentTree docTree = utils.getDocCommentTree(propertyMethod); 604 605 /* The second condition is required for the property buckets. In 606 * this case the comment is at the property method (not at the field) 607 * and it needs to be listed in the map. 608 */ 609 if ((docTree == null) || propertyMethod.equals(commentSource)) { 610 classPropertiesMap.put(propertyMethod, commentSource); 611 } 612 } 613 614 private ExecutableElement getterForField(List<ExecutableElement> methods, 615 ExecutableElement propertyMethod) { 616 final String propertyMethodName = utils.getSimpleName(propertyMethod); 617 final String fieldName = propertyMethodName.substring(0, 618 propertyMethodName.lastIndexOf("Property")); 619 final String fieldNameUppercased = 620 "" + Character.toUpperCase(fieldName.charAt(0)) 621 + fieldName.substring(1); 622 final String getterNamePattern; 623 final String fieldTypeName = propertyMethod.getReturnType().toString(); 624 if ("boolean".equals(fieldTypeName) 625 || fieldTypeName.endsWith("BooleanProperty")) { 626 getterNamePattern = "(is|get)" + fieldNameUppercased; 627 } else { 628 getterNamePattern = "get" + fieldNameUppercased; 629 } 630 631 for (ExecutableElement method : methods) { 632 if (Pattern.matches(getterNamePattern, utils.getSimpleName(method))) { 633 if (method.getParameters().isEmpty() && 634 utils.isPublic(method) || utils.isProtected(method)) { 635 return method; 636 } 637 } 638 } 639 return null; 640 } 641 642 private ExecutableElement setterForField(List<ExecutableElement> methods, 643 ExecutableElement propertyMethod) { 644 final String propertyMethodName = utils.getSimpleName(propertyMethod); 645 final String fieldName = 646 propertyMethodName.substring(0, 647 propertyMethodName.lastIndexOf("Property")); 648 final String fieldNameUppercased = 649 "" + Character.toUpperCase(fieldName.charAt(0)) 650 + fieldName.substring(1); 651 final String setter = "set" + fieldNameUppercased; 652 653 for (ExecutableElement method : methods) { 654 if (setter.equals(utils.getSimpleName(method))) { 655 if (method.getParameters().size() == 1 656 && method.getReturnType().getKind() == TypeKind.VOID 657 && (utils.isPublic(method) || utils.isProtected(method))) { 658 return method; 659 } 660 } 661 } 662 return null; 663 } 664 665 private VariableElement fieldForProperty(List<VariableElement> fields, ExecutableElement property) { 666 667 for (VariableElement field : fields) { 668 final String fieldName = utils.getSimpleName(field); 669 final String propertyName = fieldName + "Property"; 670 if (propertyName.equals(utils.getSimpleName(property))) { 671 return field; 672 } 673 } 674 return null; 675 } 676 677 private boolean isPropertyMethod(ExecutableElement method) { 678 if (!configuration.javafx) { 679 return false; 680 } 681 if (!utils.getSimpleName(method).endsWith("Property")) { 682 return false; 683 } 684 685 if (!memberIsVisible(method)) { 686 return false; 687 } 688 689 if (GETTERSETTERPATTERN.matcher(utils.getSimpleName(method)).matches()) { 690 return false; 691 } 692 if (!method.getTypeParameters().isEmpty()) { 693 return false; 694 } 695 return method.getParameters().isEmpty() 696 && method.getReturnType().getKind() != TypeKind.VOID; 697 } 698 699 private void checkOnPropertiesTags(List<? extends Element> members) { 700 for (Element e: members) { 701 ExecutableElement ee = (ExecutableElement)e; 702 if (utils.isIncluded(ee)) { 703 CommentHelper ch = utils.getCommentHelper(ee); 704 for (DocTree tree: utils.getBlockTags(ee)) { 705 String tagName = ch.getTagName(tree); 706 if (tagName.equals("@propertySetter") 707 || tagName.equals("@propertyGetter") 708 || tagName.equals("@propertyDescription")) { 709 if (!isPropertyGetterOrSetter(members, ee)) { 710 configuration.message.warning(ch.getDocTreePath(tree), 711 "doclet.javafx_tag_misuse"); 712 } 713 break; 714 } 715 } 716 } 717 } 718 } 719 720 private boolean isPropertyGetterOrSetter(List<? extends Element> members, 721 ExecutableElement method) { 722 String propertyName = utils.propertyName(method); 723 if (!propertyName.isEmpty()) { 724 String propertyMethodName = propertyName + "Property"; 725 for (Element member: members) { 726 if (utils.getSimpleName(member).equals(propertyMethodName)) { 727 return true; 728 } 729 } 730 } 731 return false; 732 } 733 } 734 735 public class GetterSetter { 736 private final Element getter; 737 private final Element setter; 738 739 public GetterSetter(Element getter, Element setter) { 740 this.getter = getter; 741 this.setter = setter; 742 } 743 744 public Element getGetter() { 745 return getter; 746 } 747 748 public Element getSetter() { 749 return setter; 750 } 751 } 752 753 /** 754 * Return true if this map has no visible members. 755 * 756 * @return true if this map has no visible members. 757 */ 758 public boolean noVisibleMembers() { 759 return noVisibleMembers; 760 } 761 762 private ClassMember getClassMember(ExecutableElement member) { 763 for (Object key : memberNameMap.keySet()) { 764 if (key instanceof String) { 765 continue; 766 } 767 if (((ClassMember) key).isEqual(member)) { 768 return (ClassMember) key; 769 } 770 } 771 return new ClassMember(member); 772 } 773 774 /** 775 * Return the key to the member map for the given member. 776 */ 777 private Object getMemberKey(Element element) { 778 if (utils.isConstructor(element)) { 779 return utils.getSimpleName(element) + utils.flatSignature((ExecutableElement)element); 780 } else if (utils.isMethod(element)) { 781 return getClassMember((ExecutableElement) element); 782 } else if (utils.isField(element) || utils.isEnumConstant(element) || utils.isAnnotationType(element)) { 783 return utils.getSimpleName(element); 784 } else { // it's a class or interface 785 String classOrIntName = utils.getSimpleName(element); 786 //Strip off the containing class name because we only want the member name. 787 classOrIntName = classOrIntName.indexOf('.') != 0 788 ? classOrIntName.substring(classOrIntName.lastIndexOf('.')) 789 : classOrIntName; 790 return "clint" + classOrIntName; 791 } 792 } 793} 794