package jdk.javadoc.internal.doclets.formats.html;
import java.util.List;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.ExecutableType;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVariable;
import javax.lang.model.util.SimpleTypeVisitor9;
import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
import static jdk.javadoc.internal.doclets.formats.html.LinkInfoImpl.Kind.EXECUTABLE_MEMBER_PARAM;
import static jdk.javadoc.internal.doclets.formats.html.LinkInfoImpl.Kind.MEMBER;
import static jdk.javadoc.internal.doclets.formats.html.LinkInfoImpl.Kind.MEMBER_TYPE_PARAMS;
import static jdk.javadoc.internal.doclets.formats.html.LinkInfoImpl.Kind.RECEIVER_TYPE;
public abstract class AbstractExecutableMemberWriter extends AbstractMemberWriter {
public AbstractExecutableMemberWriter(SubWriterHolderWriter writer, TypeElement typeElement) {
super(writer, typeElement);
}
public AbstractExecutableMemberWriter(SubWriterHolderWriter writer) {
super(writer);
}
protected Content getTypeParameters(ExecutableElement member) {
LinkInfoImpl linkInfo = new LinkInfoImpl(configuration, MEMBER_TYPE_PARAMS, member);
return writer.getTypeParameterLinks(linkInfo);
}
@Override
protected Content getDeprecatedLink(Element member) {
Content deprecatedLinkContent = new ContentBuilder();
deprecatedLinkContent.add(utils.getFullyQualifiedName(member));
if (!utils.isConstructor(member)) {
deprecatedLinkContent.add(".");
deprecatedLinkContent.add(member.getSimpleName());
}
String signature = utils.flatSignature((ExecutableElement) member);
if (signature.length() > 2) {
deprecatedLinkContent.add(Entity.ZERO_WIDTH_SPACE);
}
deprecatedLinkContent.add(signature);
return writer.getDocLink(MEMBER, utils.getEnclosingTypeElement(member), member, deprecatedLinkContent);
}
@Override
protected void addSummaryLink(LinkInfoImpl.Kind context, TypeElement te, Element member,
Content tdSummary) {
ExecutableElement ee = (ExecutableElement)member;
Content memberLink = HtmlTree.SPAN(HtmlStyle.memberNameLink,
writer.getDocLink(context, te, ee,
name(ee), false));
Content code = HtmlTree.CODE(memberLink);
addParameters(ee, code);
tdSummary.add(code);
}
@Override
protected void addInheritedSummaryLink(TypeElement te, Element member, Content linksTree) {
linksTree.add(writer.getDocLink(MEMBER, te, member, name(member), false));
}
protected void addParam(ExecutableElement member, VariableElement param, TypeMirror paramType,
boolean isVarArg, Content tree) {
Content link = writer.getLink(new LinkInfoImpl(configuration, EXECUTABLE_MEMBER_PARAM,
paramType).varargs(isVarArg));
tree.add(link);
if(name(param).length() > 0) {
tree.add(Entity.NO_BREAK_SPACE);
tree.add(name(param));
}
}
protected void addReceiverAnnotations(ExecutableElement member, TypeMirror rcvrType,
List<? extends AnnotationMirror> annotationMirrors, Content tree) {
writer.addReceiverAnnotationInfo(member, rcvrType, annotationMirrors, tree);
tree.add(Entity.NO_BREAK_SPACE);
tree.add(utils.getTypeName(rcvrType, false));
LinkInfoImpl linkInfo = new LinkInfoImpl(configuration, RECEIVER_TYPE, rcvrType);
tree.add(writer.getTypeParameterLinks(linkInfo));
tree.add(Entity.NO_BREAK_SPACE);
tree.add("this");
}
protected void addParameters(ExecutableElement member, Content htmltree) {
Content paramTree = getParameters(member, false);
if (paramTree.isEmpty()) {
htmltree.add("()");
} else {
htmltree.add(Entity.ZERO_WIDTH_SPACE);
htmltree.add("(");
htmltree.add(paramTree);
paramTree.add(")");
}
}
protected Content getParameters(ExecutableElement member, boolean includeAnnotations) {
Content paramTree = new ContentBuilder();
String sep = "";
List<? extends VariableElement> parameters = member.getParameters();
TypeMirror rcvrType = member.getReceiverType();
if (includeAnnotations && rcvrType != null && utils.isAnnotated(rcvrType)) {
List<? extends AnnotationMirror> annotationMirrors = rcvrType.getAnnotationMirrors();
addReceiverAnnotations(member, rcvrType, annotationMirrors, paramTree);
sep = "," + DocletConstants.NL;
}
int paramstart;
ExecutableType instMeth = utils.asInstantiatedMethodType(typeElement, member);
for (paramstart = 0; paramstart < parameters.size(); paramstart++) {
paramTree.add(sep);
VariableElement param = parameters.get(paramstart);
TypeMirror paramType = instMeth.getParameterTypes().get(paramstart);
if (param.getKind() != ElementKind.INSTANCE_INIT) {
if (includeAnnotations) {
boolean foundAnnotations =
writer.addAnnotationInfo(param, paramTree);
if (foundAnnotations) {
paramTree.add(DocletConstants.NL);
}
}
addParam(member, param, paramType,
(paramstart == parameters.size() - 1) && member.isVarArgs(), paramTree);
break;
}
}
for (int i = paramstart + 1; i < parameters.size(); i++) {
paramTree.add(",");
paramTree.add(DocletConstants.NL);
if (includeAnnotations) {
boolean foundAnnotations =
writer.addAnnotationInfo(parameters.get(i),
paramTree);
if (foundAnnotations) {
paramTree.add(DocletConstants.NL);
}
}
addParam(member, parameters.get(i), instMeth.getParameterTypes().get(i),
(i == parameters.size() - 1) && member.isVarArgs(),
paramTree);
}
return paramTree;
}
protected Content getExceptions(ExecutableElement member) {
List<? extends TypeMirror> exceptions = utils.asInstantiatedMethodType(typeElement, member).getThrownTypes();
Content htmltree = new ContentBuilder();
if (!exceptions.isEmpty()) {
Content link = writer.getLink(new LinkInfoImpl(configuration, MEMBER, exceptions.get(0)));
htmltree.add(link);
for(int i = 1; i < exceptions.size(); i++) {
htmltree.add(",");
htmltree.add(DocletConstants.NL);
Content exceptionLink = writer.getLink(new LinkInfoImpl(configuration, MEMBER,
exceptions.get(i)));
htmltree.add(exceptionLink);
}
}
return htmltree;
}
protected TypeElement implementsMethodInIntfac(ExecutableElement method,
List<TypeElement> intfacs) {
for (TypeElement intf : intfacs) {
List<ExecutableElement> methods = utils.getMethods(intf);
if (!methods.isEmpty()) {
for (ExecutableElement md : methods) {
if (name(md).equals(name(method)) &&
md.toString().equals(method.toString())) {
return intf;
}
}
}
}
return null;
}
protected String getErasureAnchor(ExecutableElement executableElement) {
final StringBuilder buf = new StringBuilder(writer.anchorName(executableElement));
buf.append("(");
List<? extends VariableElement> parameters = executableElement.getParameters();
boolean foundTypeVariable = false;
for (int i = 0; i < parameters.size(); i++) {
if (i > 0) {
buf.append(",");
}