001/* 002 * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. Oracle designates this 008 * particular file as subject to the "Classpath" exception as provided 009 * by Oracle in the LICENSE file that accompanied this code. 010 * 011 * This code is distributed in the hope that it will be useful, but WITHOUT 012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 014 * version 2 for more details (a copy is included in the LICENSE file that 015 * accompanied this code). 016 * 017 * You should have received a copy of the GNU General Public License version 018 * 2 along with this work; if not, write to the Free Software Foundation, 019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 020 * 021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 022 * or visit www.oracle.com if you need additional information or have any 023 * questions. 024 */ 025 026package org.jdrupes.mdoclet.internal.doclets.toolkit.builders; 027 028import static org.jdrupes.mdoclet.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*; 029 030import java.util.*; 031 032import javax.lang.model.element.Element; 033import javax.lang.model.element.ExecutableElement; 034import javax.lang.model.element.TypeElement; 035import javax.lang.model.type.TypeMirror; 036 037import org.jdrupes.mdoclet.internal.doclets.toolkit.BaseOptions; 038import org.jdrupes.mdoclet.internal.doclets.toolkit.Content; 039import org.jdrupes.mdoclet.internal.doclets.toolkit.DocletException; 040import org.jdrupes.mdoclet.internal.doclets.toolkit.MethodWriter; 041import org.jdrupes.mdoclet.internal.doclets.toolkit.util.DocFinder; 042import org.jdrupes.mdoclet.internal.doclets.toolkit.util.DocFinder.Result; 043 044import com.sun.source.doctree.DocTree; 045 046/** 047 * Builds documentation for a method. 048 */ 049public class MethodBuilder extends AbstractMemberBuilder { 050 051 /** 052 * The index of the current field that is being documented at this point 053 * in time. 054 */ 055 private ExecutableElement currentMethod; 056 057 /** 058 * The writer to output the method documentation. 059 */ 060 private final MethodWriter writer; 061 062 /** 063 * The methods being documented. 064 */ 065 private final List<? extends Element> methods; 066 067 /** 068 * Construct a new MethodBuilder. 069 * 070 * @param context the build context. 071 * @param typeElement the class whose members are being documented. 072 * @param writer the doclet specific writer. 073 */ 074 private MethodBuilder(Context context, 075 TypeElement typeElement, 076 MethodWriter writer) { 077 super(context, typeElement); 078 this.writer = Objects.requireNonNull(writer); 079 methods = getVisibleMembers(METHODS); 080 } 081 082 /** 083 * Construct a new MethodBuilder. 084 * 085 * @param context the build context. 086 * @param typeElement the class whose members are being documented. 087 * @param writer the doclet specific writer. 088 * 089 * @return an instance of a MethodBuilder. 090 */ 091 public static MethodBuilder getInstance(Context context, 092 TypeElement typeElement, MethodWriter writer) { 093 return new MethodBuilder(context, typeElement, writer); 094 } 095 096 @Override 097 public boolean hasMembersToDocument() { 098 return !methods.isEmpty(); 099 } 100 101 @Override 102 public void build(Content target) throws DocletException { 103 buildMethodDoc(target); 104 } 105 106 /** 107 * Build the method documentation. 108 * 109 * @param detailsList the content to which the documentation will be added 110 * @throws DocletException if there is a problem while building the documentation 111 */ 112 protected void buildMethodDoc(Content detailsList) throws DocletException { 113 if (hasMembersToDocument()) { 114 Content methodDetailsHeader 115 = writer.getMethodDetailsHeader(detailsList); 116 Content memberList = writer.getMemberList(); 117 118 for (Element method : methods) { 119 currentMethod = (ExecutableElement) method; 120 Content methodContent = writer.getMethodHeader(currentMethod); 121 122 buildSignature(methodContent); 123 buildDeprecationInfo(methodContent); 124 buildPreviewInfo(methodContent); 125 buildMethodComments(methodContent); 126 buildTagInfo(methodContent); 127 128 memberList.add(writer.getMemberListItem(methodContent)); 129 } 130 Content methodDetails 131 = writer.getMethodDetails(methodDetailsHeader, memberList); 132 detailsList.add(methodDetails); 133 } 134 } 135 136 /** 137 * Build the signature. 138 * 139 * @param methodContent the content to which the documentation will be added 140 */ 141 protected void buildSignature(Content methodContent) { 142 methodContent.add(writer.getSignature(currentMethod)); 143 } 144 145 /** 146 * Build the deprecation information. 147 * 148 * @param methodContent the content to which the documentation will be added 149 */ 150 protected void buildDeprecationInfo(Content methodContent) { 151 writer.addDeprecated(currentMethod, methodContent); 152 } 153 154 /** 155 * Build the preview information. 156 * 157 * @param methodContent the content to which the documentation will be added 158 */ 159 protected void buildPreviewInfo(Content methodContent) { 160 writer.addPreview(currentMethod, methodContent); 161 } 162 163 /** 164 * Build the comments for the method. Do nothing if 165 * {@link BaseOptions#noComment()} is set to true. 166 * 167 * @param methodContent the content to which the documentation will be added 168 */ 169 protected void buildMethodComments(Content methodContent) { 170 if (!options.noComment()) { 171 assert utils.isMethod(currentMethod); // not all executables are 172 // methods 173 var docFinder = utils.docFinder(); 174 Optional<ExecutableElement> r = docFinder.search(currentMethod, 175 m -> Result.fromOptional( 176 utils.getFullBody(m).isEmpty() ? Optional.empty() 177 : Optional.of(m))) 178 .toOptional(); 179 ExecutableElement method = r.orElse(currentMethod); 180 TypeMirror containingType = method.getEnclosingElement().asType(); 181 writer.addComments(containingType, method, methodContent); 182 } 183 } 184 185 /** 186 * Build the tag information. 187 * 188 * @param methodContent the content to which the documentation will be added 189 */ 190 protected void buildTagInfo(Content methodContent) { 191 writer.addTags(currentMethod, methodContent); 192 } 193 194 /** 195 * Return the method writer for this builder. 196 * 197 * @return the method writer for this builder. 198 */ 199 public MethodWriter getWriter() { 200 return writer; 201 } 202}