29 import java.util.List; 30 import java.util.Set; 31 import java.util.TreeSet; 32 import java.util.stream.Collectors; 33 34 import javax.lang.model.element.Element; 35 import javax.lang.model.element.ExecutableElement; 36 import javax.lang.model.element.Modifier; 37 import javax.lang.model.element.TypeElement; 38 import javax.lang.model.element.TypeParameterElement; 39 import javax.lang.model.type.TypeMirror; 40 41 import com.sun.source.doctree.DocTree; 42 43 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; 44 import jdk.javadoc.internal.doclets.formats.html.markup.Entity; 45 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; 46 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; 47 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; 48 import jdk.javadoc.internal.doclets.formats.html.markup.Links; 49 import jdk.javadoc.internal.doclets.formats.html.markup.Table; 50 import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; 51 import jdk.javadoc.internal.doclets.toolkit.Content; 52 import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter; 53 import jdk.javadoc.internal.doclets.toolkit.Resources; 54 import jdk.javadoc.internal.doclets.toolkit.taglets.DeprecatedTaglet; 55 import jdk.javadoc.internal.doclets.toolkit.util.Utils; 56 57 import static javax.lang.model.element.Modifier.ABSTRACT; 58 import static javax.lang.model.element.Modifier.NATIVE; 59 import static javax.lang.model.element.Modifier.PUBLIC; 60 import static javax.lang.model.element.Modifier.STRICTFP; 61 import static javax.lang.model.element.Modifier.SYNCHRONIZED; 62 63 /** 64 * The base class for member writers. 65 * 66 * <p><b>This is NOT part of any supported API. 67 * If you write code that depends on this, you do so at your own risk. 68 * This code and its internal interfaces are subject to change or 69 * deletion without notice.</b> 70 * 71 * @author Robert Field 72 * @author Atul M Dambalkar 73 * @author Jamie Ho (Re-write) 74 * @author Bhavesh Patel (Modified) 202 TypeElement typeElement, Element member, Content tdSummary); 203 204 /** 205 * Add the inherited summary link for the member. 206 * 207 * @param typeElement the TypeElement to be documented 208 * @param member the member to be documented 209 * @param linksTree the content tree to which the inherited summary link will be added 210 */ 211 protected abstract void addInheritedSummaryLink(TypeElement typeElement, 212 Element member, Content linksTree); 213 214 /** 215 * Get the deprecated link. 216 * 217 * @param member the member being linked to 218 * @return a content tree representing the link 219 */ 220 protected abstract Content getDeprecatedLink(Element member); 221 222 /** 223 * Add the member name to the content tree. 224 * 225 * @param name the member name to be added to the content tree. 226 * @param htmltree the content tree to which the name will be added. 227 */ 228 protected void addName(String name, Content htmltree) { 229 htmltree.add(name); 230 } 231 232 /** 233 * Add the modifier for the member. The modifiers are ordered as specified 234 * by <em>The Java Language Specification</em>. 235 * 236 * @param member the member for which the modifier will be added. 237 * @param htmltree the content tree to which the modifier information will be added. 238 */ 239 protected void addModifiers(Element member, Content htmltree) { 240 Set<Modifier> set = new TreeSet<>(member.getModifiers()); 241 242 // remove the ones we really don't need 243 set.remove(NATIVE); 244 set.remove(SYNCHRONIZED); 245 set.remove(STRICTFP); 246 247 // According to JLS, we should not be showing public modifier for 248 // interface methods. 249 if ((utils.isField(member) || utils.isMethod(member)) 250 && ((writer instanceof ClassWriterImpl 251 && utils.isInterface(((ClassWriterImpl) writer).getTypeElement()) || 252 writer instanceof AnnotationTypeWriterImpl) )) { 253 // Remove the implicit abstract and public modifiers 254 if (utils.isMethod(member) && 255 (utils.isInterface(member.getEnclosingElement()) || 256 utils.isAnnotationType(member.getEnclosingElement()))) { 257 set.remove(ABSTRACT); 258 set.remove(PUBLIC); 259 } 260 if (!utils.isMethod(member)) { 261 set.remove(PUBLIC); 262 } 263 } 264 if (!set.isEmpty()) { 265 String mods = set.stream().map(Modifier::toString).collect(Collectors.joining(" ")); 266 htmltree.add(mods); 267 htmltree.add(Entity.NO_BREAK_SPACE); 268 } 269 } 270 271 protected CharSequence makeSpace(int len) { 272 if (len <= 0) { 273 return ""; 274 } 275 StringBuilder sb = new StringBuilder(len); 276 for (int i = 0; i < len; i++) { 277 sb.append(' '); 278 } 279 return sb; 280 } 281 282 /** 283 * Add the modifier and type for the member in the member summary. 284 * 285 * @param member the member to add the type for 286 * @param type the type to add 287 * @param tdSummaryType the content tree to which the modified and type will be added 288 */ 289 protected void addModifierAndType(Element member, TypeMirror type, 290 Content tdSummaryType) { 546 * @return a content tree that will be added to the class documentation 547 */ 548 @Override 549 public Content getMemberTree(Content memberTree) { 550 return writer.getMemberTree(memberTree); 551 } 552 553 /** 554 * Get the member tree to be documented. 555 * 556 * @param memberTree the content tree of member to be documented 557 * @param isLastContent true if the content to be added is the last content 558 * @return a content tree that will be added to the class documentation 559 */ 560 public Content getMemberTree(Content memberTree, boolean isLastContent) { 561 if (isLastContent) 562 return HtmlTree.LI(HtmlStyle.blockListLast, memberTree); 563 else 564 return HtmlTree.LI(HtmlStyle.blockList, memberTree); 565 } 566 } | 29 import java.util.List; 30 import java.util.Set; 31 import java.util.TreeSet; 32 import java.util.stream.Collectors; 33 34 import javax.lang.model.element.Element; 35 import javax.lang.model.element.ExecutableElement; 36 import javax.lang.model.element.Modifier; 37 import javax.lang.model.element.TypeElement; 38 import javax.lang.model.element.TypeParameterElement; 39 import javax.lang.model.type.TypeMirror; 40 41 import com.sun.source.doctree.DocTree; 42 43 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder; 44 import jdk.javadoc.internal.doclets.formats.html.markup.Entity; 45 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; 46 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; 47 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; 48 import jdk.javadoc.internal.doclets.formats.html.markup.Links; 49 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent; 50 import jdk.javadoc.internal.doclets.formats.html.markup.Table; 51 import jdk.javadoc.internal.doclets.formats.html.markup.TableHeader; 52 import jdk.javadoc.internal.doclets.toolkit.Content; 53 import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter; 54 import jdk.javadoc.internal.doclets.toolkit.Resources; 55 import jdk.javadoc.internal.doclets.toolkit.taglets.DeprecatedTaglet; 56 import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants; 57 import jdk.javadoc.internal.doclets.toolkit.util.Utils; 58 59 import static javax.lang.model.element.Modifier.ABSTRACT; 60 import static javax.lang.model.element.Modifier.NATIVE; 61 import static javax.lang.model.element.Modifier.PUBLIC; 62 import static javax.lang.model.element.Modifier.STRICTFP; 63 import static javax.lang.model.element.Modifier.SYNCHRONIZED; 64 65 /** 66 * The base class for member writers. 67 * 68 * <p><b>This is NOT part of any supported API. 69 * If you write code that depends on this, you do so at your own risk. 70 * This code and its internal interfaces are subject to change or 71 * deletion without notice.</b> 72 * 73 * @author Robert Field 74 * @author Atul M Dambalkar 75 * @author Jamie Ho (Re-write) 76 * @author Bhavesh Patel (Modified) 204 TypeElement typeElement, Element member, Content tdSummary); 205 206 /** 207 * Add the inherited summary link for the member. 208 * 209 * @param typeElement the TypeElement to be documented 210 * @param member the member to be documented 211 * @param linksTree the content tree to which the inherited summary link will be added 212 */ 213 protected abstract void addInheritedSummaryLink(TypeElement typeElement, 214 Element member, Content linksTree); 215 216 /** 217 * Get the deprecated link. 218 * 219 * @param member the member being linked to 220 * @return a content tree representing the link 221 */ 222 protected abstract Content getDeprecatedLink(Element member); 223 224 protected CharSequence makeSpace(int len) { 225 if (len <= 0) { 226 return ""; 227 } 228 StringBuilder sb = new StringBuilder(len); 229 for (int i = 0; i < len; i++) { 230 sb.append(' '); 231 } 232 return sb; 233 } 234 235 /** 236 * Add the modifier and type for the member in the member summary. 237 * 238 * @param member the member to add the type for 239 * @param type the type to add 240 * @param tdSummaryType the content tree to which the modified and type will be added 241 */ 242 protected void addModifierAndType(Element member, TypeMirror type, 243 Content tdSummaryType) { 499 * @return a content tree that will be added to the class documentation 500 */ 501 @Override 502 public Content getMemberTree(Content memberTree) { 503 return writer.getMemberTree(memberTree); 504 } 505 506 /** 507 * Get the member tree to be documented. 508 * 509 * @param memberTree the content tree of member to be documented 510 * @param isLastContent true if the content to be added is the last content 511 * @return a content tree that will be added to the class documentation 512 */ 513 public Content getMemberTree(Content memberTree, boolean isLastContent) { 514 if (isLastContent) 515 return HtmlTree.LI(HtmlStyle.blockListLast, memberTree); 516 else 517 return HtmlTree.LI(HtmlStyle.blockList, memberTree); 518 } 519 520 /** 521 * A content builder for member signatures. 522 */ 523 class MemberSignature { 524 525 private Element element; 526 private Content typeParameters; 527 private Content returnType; 528 private Content parameters; 529 private Content exceptions; 530 531 // Threshold for length of type parameters before switching from inline to block representation. 532 private final static int TYPE_PARAMS_MAX_INLINE_LENGTH = 50; 533 534 // Threshold for combined length of modifiers, type params and return type before breaking 535 // it up with a line break before the return type. 536 private final static int RETURN_TYPE_MAX_LINE_LENGTH = 50; 537 538 /** 539 * Create a new member signature builder. 540 * 541 * @param element The element for which to create a signature. 542 */ 543 MemberSignature(Element element) { 544 this.element = element; 545 } 546 547 /** 548 * Add the type parameters for an executable member. 549 * 550 * @param typeParameters the content tree containing the type parameters to add. 551 * @return this MemberSignature instance 552 */ 553 MemberSignature addTypeParameters(Content typeParameters) { 554 this.typeParameters = typeParameters; 555 return this; 556 } 557 558 /** 559 * Add the return type for an executable member. 560 * 561 * @param returnType the content tree containing the return type to add. 562 * @return this MemberSignature instance 563 */ 564 MemberSignature addReturnType(Content returnType) { 565 this.returnType = returnType; 566 return this; 567 } 568 569 /** 570 * Add the type information for a non-executable member. 571 * 572 * @param type the type of the member. 573 * @return this MemberSignature instance 574 */ 575 MemberSignature addType(TypeMirror type) { 576 this.returnType = writer.getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.MEMBER, type)); 577 return this; 578 } 579 580 /** 581 * Add the parameter information of an executable member. 582 * 583 * @param paramTree the content tree containing the parameter information. 584 * @return this MemberSignature instance 585 */ 586 MemberSignature addParameters(Content paramTree) { 587 this.parameters = paramTree; 588 return this; 589 } 590 591 /** 592 * Add the exception information of an executable member. 593 * 594 * @param exceptionTree the content tree containing the exception information 595 * @return this MemberSignature instance 596 */ 597 MemberSignature addExceptions(Content exceptionTree) { 598 this.exceptions = exceptionTree; 599 return this; 600 } 601 602 /** 603 * Return a HTML tree containing the member signature. 604 * 605 * @return a HTML tree containing the member signature 606 */ 607 Content toContent() { 608 Content content = new ContentBuilder(); 609 // Position of last line separator. 610 int lastLineSeparator = 0; 611 612 // Annotations 613 Content annotationInfo = writer.getAnnotationInfo(element.getAnnotationMirrors(), true); 614 if (!annotationInfo.isEmpty()) { 615 content.add(HtmlTree.SPAN(HtmlStyle.annotations, annotationInfo)); 616 lastLineSeparator = content.charCount(); 617 } 618 619 // Modifiers 620 appendModifiers(content); 621 622 // Type parameters 623 if (typeParameters != null && !typeParameters.isEmpty()) { 624 lastLineSeparator = appendTypeParameters(content, lastLineSeparator); 625 } 626 627 // Return type 628 if (returnType != null) { 629 content.add(HtmlTree.SPAN(HtmlStyle.returnType, returnType)); 630 content.add(Entity.NO_BREAK_SPACE); 631 } 632 633 // Name 634 HtmlTree nameSpan = new HtmlTree(HtmlTag.SPAN); 635 nameSpan.setStyle(HtmlStyle.memberName); 636 if (configuration.linksource) { 637 Content name = new StringContent(name(element)); 638 writer.addSrcLink(element, name, nameSpan); 639 } else { 640 nameSpan.add(name(element)); 641 } 642 content.add(nameSpan); 643 644 645 // Parameters and exceptions 646 if (parameters != null) { 647 appendParametersAndExceptions(content, lastLineSeparator); 648 } 649 650 return HtmlTree.DIV(HtmlStyle.memberSignature, content); 651 } 652 653 /** 654 * Add the modifier for the member. The modifiers are ordered as specified 655 * by <em>The Java Language Specification</em>. 656 * 657 * @param htmltree the content tree to which the modifier information will be added. 658 */ 659 private void appendModifiers(Content htmltree) { 660 Set<Modifier> set = new TreeSet<>(element.getModifiers()); 661 662 // remove the ones we really don't need 663 set.remove(NATIVE); 664 set.remove(SYNCHRONIZED); 665 set.remove(STRICTFP); 666 667 // According to JLS, we should not be showing public modifier for 668 // interface methods. 669 if ((utils.isField(element) || utils.isMethod(element)) 670 && ((writer instanceof ClassWriterImpl 671 && utils.isInterface(((ClassWriterImpl) writer).getTypeElement()) || 672 writer instanceof AnnotationTypeWriterImpl) )) { 673 // Remove the implicit abstract and public modifiers 674 if (utils.isMethod(element) && 675 (utils.isInterface(element.getEnclosingElement()) || 676 utils.isAnnotationType(element.getEnclosingElement()))) { 677 set.remove(ABSTRACT); 678 set.remove(PUBLIC); 679 } 680 if (!utils.isMethod(element)) { 681 set.remove(PUBLIC); 682 } 683 } 684 if (!set.isEmpty()) { 685 String mods = set.stream().map(Modifier::toString).collect(Collectors.joining(" ")); 686 htmltree.add(HtmlTree.SPAN(HtmlStyle.modifiers, new StringContent(mods))); 687 htmltree.add(Entity.NO_BREAK_SPACE); 688 } 689 } 690 691 /** 692 * Append the type parameter information to the HTML tree. 693 * 694 * @param htmltree the HTML tree 695 * @param lastLineSeparator index of last line separator in HTML tree 696 * @return the new index of the last line separator 697 */ 698 private int appendTypeParameters(Content htmltree, int lastLineSeparator) { 699 // Apply different wrapping strategies for type parameters 700 // depending of combined length of type parameters and return type. 701 int typeParamLength = typeParameters.charCount(); 702 703 if (typeParamLength >= TYPE_PARAMS_MAX_INLINE_LENGTH) { 704 htmltree.add(HtmlTree.SPAN(HtmlStyle.typeParametersLong, typeParameters)); 705 } else { 706 htmltree.add(HtmlTree.SPAN(HtmlStyle.typeParameters, typeParameters)); 707 } 708 709 int lineLength = htmltree.charCount() - lastLineSeparator; 710 int newLastLineSeparator = lastLineSeparator; 711 712 // sum below includes length of modifiers plus type params added above 713 if (lineLength + returnType.charCount()> RETURN_TYPE_MAX_LINE_LENGTH) { 714 htmltree.add(DocletConstants.NL); 715 newLastLineSeparator = htmltree.charCount(); 716 } else { 717 htmltree.add(Entity.NO_BREAK_SPACE); 718 } 719 720 return newLastLineSeparator; 721 } 722 723 /** 724 * Append the parameters and exceptions information to the HTML tree. 725 * 726 * @param htmltree the HTML tree 727 * @param lastLineSeparator the index of the last line separator in HTML tree 728 */ 729 private void appendParametersAndExceptions(Content htmltree, int lastLineSeparator) { 730 // Record current position for indentation of exceptions 731 int indentSize = htmltree.charCount() - lastLineSeparator; 732 733 if (parameters.isEmpty()) { 734 htmltree.add("()"); 735 } else { 736 parameters.add(")"); 737 htmltree.add(Entity.ZERO_WIDTH_SPACE); 738 htmltree.add("("); 739 htmltree.add(HtmlTree.SPAN(HtmlStyle.arguments, parameters)); 740 } 741 742 // Exceptions 743 if (exceptions != null && !exceptions.isEmpty()) { 744 CharSequence indent = makeSpace(indentSize + 1 - 7); 745 htmltree.add(DocletConstants.NL); 746 htmltree.add(indent); 747 htmltree.add("throws "); 748 htmltree.add(HtmlTree.SPAN(HtmlStyle.exceptions, exceptions)); 749 } 750 } 751 } 752 } |