8270195: Add missing links between methods of JavaFX properties
Reviewed-by: kcr, hannesw
This commit is contained in:
parent
f608e81ad8
commit
d34f17c697
@ -90,10 +90,8 @@ import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
|
||||
import jdk.javadoc.internal.doclets.formats.html.markup.Script;
|
||||
import jdk.javadoc.internal.doclets.formats.html.markup.TagName;
|
||||
import jdk.javadoc.internal.doclets.formats.html.markup.Text;
|
||||
import jdk.javadoc.internal.doclets.toolkit.ClassWriter;
|
||||
import jdk.javadoc.internal.doclets.toolkit.Content;
|
||||
import jdk.javadoc.internal.doclets.toolkit.Messages;
|
||||
import jdk.javadoc.internal.doclets.toolkit.PackageSummaryWriter;
|
||||
import jdk.javadoc.internal.doclets.toolkit.Resources;
|
||||
import jdk.javadoc.internal.doclets.toolkit.taglets.DocRootTaglet;
|
||||
import jdk.javadoc.internal.doclets.toolkit.taglets.Taglet;
|
||||
@ -1228,10 +1226,10 @@ public class HtmlDocletWriter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the inline comment.
|
||||
* Adds the full-body content of the given element.
|
||||
*
|
||||
* @param element the Element for which the inline comments will be generated
|
||||
* @param htmltree the documentation tree to which the inline comments will be added
|
||||
* @param element the element for which the content will be added
|
||||
* @param htmltree the documentation tree to which the content will be added
|
||||
*/
|
||||
public void addInlineComment(Element element, Content htmltree) {
|
||||
addCommentTags(element, utils.getFullBody(element), false, false, false, htmltree);
|
||||
|
@ -23,14 +23,6 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A utility class.
|
||||
*
|
||||
* <p><b>This is NOT part of any supported API.
|
||||
* If you write code that depends on this, you do so at your own risk.
|
||||
* This code and its internal interfaces are subject to change or
|
||||
* deletion without notice.</b>
|
||||
*/
|
||||
|
||||
package jdk.javadoc.internal.doclets.toolkit;
|
||||
|
||||
@ -57,9 +49,13 @@ import com.sun.source.doctree.AttributeTree;
|
||||
import com.sun.source.doctree.DocCommentTree;
|
||||
import com.sun.source.doctree.DocTree;
|
||||
import com.sun.source.doctree.IdentifierTree;
|
||||
import com.sun.source.doctree.LiteralTree;
|
||||
import com.sun.source.doctree.ParamTree;
|
||||
import com.sun.source.doctree.ReferenceTree;
|
||||
import com.sun.source.doctree.ReturnTree;
|
||||
import com.sun.source.doctree.SinceTree;
|
||||
import com.sun.source.doctree.TextTree;
|
||||
import com.sun.source.doctree.UnknownBlockTagTree;
|
||||
import com.sun.source.util.DocTreeFactory;
|
||||
import com.sun.source.util.DocTreePath;
|
||||
import com.sun.source.util.DocTrees;
|
||||
@ -67,7 +63,16 @@ import com.sun.source.util.TreePath;
|
||||
import com.sun.tools.javac.util.DefinedBy;
|
||||
import com.sun.tools.javac.util.DefinedBy.Api;
|
||||
import jdk.javadoc.internal.doclets.toolkit.util.Utils;
|
||||
import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
|
||||
|
||||
/**
|
||||
* A utility class for handling documentation comments.
|
||||
*
|
||||
* <p><b>This is NOT part of any supported API.
|
||||
* If you write code that depends on this, you do so at your own risk.
|
||||
* This code and its internal interfaces are subject to change or
|
||||
* deletion without notice.</b>
|
||||
*/
|
||||
public class CommentUtils {
|
||||
|
||||
final BaseConfiguration configuration;
|
||||
@ -96,31 +101,28 @@ public class CommentUtils {
|
||||
}
|
||||
|
||||
public List<? extends DocTree> makePropertyDescriptionTree(List<? extends DocTree> content) {
|
||||
List<DocTree> out = new ArrayList<>();
|
||||
Name name = elementUtils.getName("propertyDescription");
|
||||
out.add(treeFactory.newUnknownBlockTagTree(name, content));
|
||||
return out;
|
||||
return List.of(treeFactory.newUnknownBlockTagTree(name, content));
|
||||
}
|
||||
|
||||
public List<? extends DocTree> makePropertyDescriptionTree(String content) {
|
||||
List<DocTree> inlist = new ArrayList<>();
|
||||
inlist.add(treeFactory.newCommentTree(content));
|
||||
List<DocTree> out = new ArrayList<>();
|
||||
Name name = elementUtils.getName("propertyDescription");
|
||||
out.add(treeFactory.newUnknownBlockTagTree(name, inlist));
|
||||
return out;
|
||||
public LiteralTree makeCodeTree(String text) {
|
||||
return treeFactory.newCodeTree(makeTextTree(text));
|
||||
}
|
||||
|
||||
public List<? extends DocTree> makeFirstSentenceTree(String content) {
|
||||
List<DocTree> out = new ArrayList<>();
|
||||
out.add(treeFactory.newTextTree(content));
|
||||
return out;
|
||||
return List.of(treeFactory.newTextTree(content));
|
||||
}
|
||||
|
||||
public ParamTree makeParamTree(Name name, List<? extends DocTree> description) {
|
||||
return treeFactory.newParamTree(false, treeFactory.newIdentifierTree(name), description);
|
||||
}
|
||||
|
||||
public ReturnTree makeReturnTree(List<? extends DocTree> description) {
|
||||
return treeFactory.newReturnTree(false, description);
|
||||
}
|
||||
|
||||
public DocTree makeSeeTree(String sig, Element e) {
|
||||
List<DocTree> list = new ArrayList<>();
|
||||
list.add(treeFactory.newReferenceTree(sig));
|
||||
return treeFactory.newSeeTree(list);
|
||||
return treeFactory.newSeeTree(List.of(treeFactory.newReferenceTree(sig)));
|
||||
}
|
||||
|
||||
public TextTree makeTextTree(String content) {
|
||||
@ -189,7 +191,6 @@ public class CommentUtils {
|
||||
makeDescriptionWithName("doclet.record_constructor_doc.fullbody", te.getSimpleName());
|
||||
|
||||
List<DocTree> tags = new ArrayList<>();
|
||||
java.util.List<? extends VariableElement> parameters = ee.getParameters();
|
||||
for (VariableElement param : ee.getParameters()) {
|
||||
Name name = param.getSimpleName();
|
||||
IdentifierTree id = treeFactory.newIdentifierTree(name);
|
||||
@ -318,6 +319,107 @@ public class CommentUtils {
|
||||
dcInfoMap.put(ve, new DocCommentInfo(null, docTree));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update the property method, property setter and/or property getter
|
||||
* comment text so that it contains the documentation from
|
||||
* the preferred property description (field or property method).
|
||||
* The method adds the leading sentence, copied documentation including
|
||||
* the defaultValue tag and the {@code @see} tags if the appropriate methods are
|
||||
* available.
|
||||
*
|
||||
* @param member the member which is to be augmented
|
||||
* @param property the element containing the preferred property description
|
||||
*/
|
||||
public void updatePropertyMethodComment(ExecutableElement member,
|
||||
Element property) {
|
||||
final String memberName = member.getSimpleName().toString();
|
||||
final boolean isSetter = memberName.startsWith("set");
|
||||
final boolean isGetter = memberName.startsWith("get") || memberName.startsWith("is");
|
||||
|
||||
List<DocTree> fullBody = new ArrayList<>();
|
||||
List<DocTree> blockTags = new ArrayList<>();
|
||||
|
||||
if (isGetter || isSetter) {
|
||||
DocTree propName = makeCodeTree(utils.propertyName(member));
|
||||
|
||||
if (isGetter) {
|
||||
// Set the body and @return
|
||||
fullBody.addAll(getComment("doclet.PropertyGetterWithName", propName));
|
||||
blockTags.add(makeReturnTree(
|
||||
getComment("doclet.PropertyGetterReturn", propName)));
|
||||
}
|
||||
|
||||
if (isSetter) {
|
||||
// Set the body and @param
|
||||
fullBody.addAll(getComment("doclet.PropertySetterWithName", propName));
|
||||
VariableElement arg0 = member.getParameters().get(0);
|
||||
blockTags.add(makeParamTree(arg0.getSimpleName(),
|
||||
getComment("doclet.PropertySetterParam", propName)));
|
||||
}
|
||||
|
||||
// Set the @propertyDescription
|
||||
List<? extends DocTree> propertyTags = utils.getBlockTags(property,
|
||||
t -> (t instanceof UnknownBlockTagTree tree)
|
||||
&& (tree.getTagName().equals("propertyDescription")));
|
||||
if (propertyTags.isEmpty()) {
|
||||
List<? extends DocTree> comment = utils.getFullBody(property);
|
||||
blockTags.addAll(makePropertyDescriptionTree(comment));
|
||||
}
|
||||
} else {
|
||||
// property method
|
||||
fullBody.addAll(utils.getFullBody(property));
|
||||
|
||||
// Set the @return
|
||||
DocTree propName = makeCodeTree(configuration.propertyUtils.getBaseName(member));
|
||||
List<? extends DocTree> returnTags = utils.getBlockTags(property, DocTree.Kind.RETURN);
|
||||
if (returnTags.isEmpty()) {
|
||||
blockTags.add(makeReturnTree(
|
||||
getComment("doclet.PropertyMethodReturn", propName)));
|
||||
} else {
|
||||
blockTags.addAll(returnTags);
|
||||
}
|
||||
}
|
||||
|
||||
// copy certain tags
|
||||
List<? extends SinceTree> sinceTags = utils.getBlockTags(property, DocTree.Kind.SINCE, SinceTree.class);
|
||||
blockTags.addAll(sinceTags);
|
||||
|
||||
List<? extends DocTree> bTags = utils.getBlockTags(property,
|
||||
t -> (t instanceof UnknownBlockTagTree tree)
|
||||
&& (tree.getTagName().equals("defaultValue")));
|
||||
blockTags.addAll(bTags);
|
||||
|
||||
//add @see tags
|
||||
TypeElement te = (TypeElement) member.getEnclosingElement();
|
||||
VisibleMemberTable vmt = configuration.getVisibleMemberTable(te);
|
||||
ExecutableElement getter = vmt.getPropertyGetter(member);
|
||||
ExecutableElement setter = vmt.getPropertySetter(member);
|
||||
ExecutableElement propMethod = vmt.getPropertyMethod(member);
|
||||
|
||||
if (getter != null && getter != member) {
|
||||
String sig = "#" + getter.getSimpleName() + "()";
|
||||
blockTags.add(makeSeeTree(sig, getter));
|
||||
}
|
||||
|
||||
if (setter != null && setter != member) {
|
||||
VariableElement param = setter.getParameters().get(0);
|
||||
StringBuilder sb = new StringBuilder("#");
|
||||
sb.append(setter.getSimpleName());
|
||||
if (!utils.isTypeVariable(param.asType())) {
|
||||
sb.append("(").append(utils.getTypeSignature(param.asType(), false, true)).append(")");
|
||||
}
|
||||
blockTags.add(makeSeeTree(sb.toString(), setter));
|
||||
}
|
||||
|
||||
if (propMethod != member) {
|
||||
String sig = "#" + propMethod.getSimpleName() + "()";
|
||||
blockTags.add(makeSeeTree(sig, propMethod));
|
||||
}
|
||||
|
||||
setDocCommentTree(member, fullBody, blockTags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a description that contains a reference to a state component of a record.
|
||||
* The description is looked up as a resource, and should contain {@code {0}} where the
|
||||
@ -401,6 +503,59 @@ public class CommentUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list containing the string for a given key in the doclet's resources,
|
||||
* formatted with given arguments.
|
||||
*
|
||||
* @param key the key for the desired string
|
||||
* @param o0 string or tree argument to be formatted into the result
|
||||
* @return a content tree for the text
|
||||
*/
|
||||
public List<? extends DocTree> getComment(String key, Object o0) {
|
||||
return getComment(key, o0, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list containing the string for a given key in the doclet's resources,
|
||||
* formatted with given arguments.
|
||||
*
|
||||
* @param key the key for the desired string
|
||||
* @param o0 string or tree argument to be formatted into the result
|
||||
* @param o1 string or tree argument to be formatted into the result
|
||||
* @param o2 string or tree argument to be formatted into the result
|
||||
* @return a content tree for the text
|
||||
*/
|
||||
public List<? extends DocTree> getComment(String key, Object o0, Object o1, Object o2) {
|
||||
List<DocTree> l = new ArrayList<>();
|
||||
Pattern p = Pattern.compile("\\{([012])\\}");
|
||||
String text = resources.getText(key);
|
||||
Matcher m = p.matcher(text);
|
||||
int start = 0;
|
||||
while (m.find(start)) {
|
||||
l.add(makeTextTree(text.substring(start, m.start())));
|
||||
|
||||
Object o = null;
|
||||
switch (m.group(1).charAt(0)) {
|
||||
case '0': o = o0; break;
|
||||
case '1': o = o1; break;
|
||||
case '2': o = o2; break;
|
||||
}
|
||||
|
||||
if (o == null) {
|
||||
l.add(makeTextTree("{" + m.group(1) + "}"));
|
||||
} else if (o instanceof String str) {
|
||||
l.add(makeTextTree(str));
|
||||
} else if (o instanceof DocTree t) {
|
||||
l.add(t);
|
||||
}
|
||||
|
||||
start = m.end();
|
||||
}
|
||||
|
||||
l.add(makeTextTree(text.substring(start)));
|
||||
return l;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the TreePath/DocCommentTree info that has been generated for an element.
|
||||
* @param e the element
|
||||
@ -453,13 +608,18 @@ public class CommentUtils {
|
||||
});
|
||||
}
|
||||
|
||||
public void setDocCommentTree(Element element, List<? extends DocTree> fullBody,
|
||||
public DocCommentInfo setDocCommentTree(Element element, List<? extends DocTree> fullBody,
|
||||
List<? extends DocTree> blockTags) {
|
||||
DocCommentTree docTree = treeFactory.newDocCommentTree(fullBody, blockTags);
|
||||
dcInfoMap.put(element, new DocCommentInfo(null, docTree));
|
||||
return setDocCommentInfo(element, new DocCommentInfo(null, docTree));
|
||||
}
|
||||
|
||||
public DocCommentInfo setDocCommentInfo(Element element, DocCommentInfo dci) {
|
||||
DocCommentInfo prev = dcInfoMap.put(element, dci);
|
||||
// A method having null comment (no comment) that might need to be replaced
|
||||
// with a generated comment, remove such a comment from the cache.
|
||||
utils.removeCommentHelper(element);
|
||||
return prev;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -74,7 +74,7 @@ public interface PropertyWriter extends MemberWriter {
|
||||
* Add the preview output for the given member.
|
||||
*
|
||||
* @param member the member being documented
|
||||
* @param annotationDocTree content tree to which the preview information will be added
|
||||
* @param contentTree content tree to which the preview information will be added
|
||||
*/
|
||||
void addPreview(ExecutableElement member, Content contentTree);
|
||||
|
||||
|
@ -25,20 +25,26 @@
|
||||
|
||||
package jdk.javadoc.internal.doclets.toolkit.builders;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.*;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.element.VariableElement;
|
||||
import javax.lang.model.util.ElementFilter;
|
||||
import javax.tools.Diagnostic;
|
||||
|
||||
import com.sun.source.doctree.DocCommentTree;
|
||||
import com.sun.source.doctree.DocTree;
|
||||
import com.sun.source.doctree.DocTree.Kind;
|
||||
import com.sun.source.doctree.SinceTree;
|
||||
import com.sun.source.doctree.UnknownBlockTagTree;
|
||||
import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
|
||||
import jdk.javadoc.internal.doclets.toolkit.ClassWriter;
|
||||
import jdk.javadoc.internal.doclets.toolkit.Content;
|
||||
import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
|
||||
@ -47,7 +53,6 @@ import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
|
||||
import jdk.javadoc.internal.doclets.toolkit.util.DocFinder;
|
||||
import jdk.javadoc.internal.doclets.toolkit.util.Utils;
|
||||
import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
|
||||
import jdk.javadoc.internal.doclets.toolkit.CommentUtils;
|
||||
|
||||
import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
|
||||
|
||||
@ -258,8 +263,8 @@ public abstract class MemberSummaryBuilder extends AbstractMemberBuilder {
|
||||
if (!members.isEmpty()) {
|
||||
for (Element member : members) {
|
||||
final Element property = pHelper.getPropertyElement(member);
|
||||
if (property != null) {
|
||||
processProperty(member, property);
|
||||
if (property != null && member instanceof ExecutableElement ee) {
|
||||
configuration.cmtUtils.updatePropertyMethodComment(ee, property);
|
||||
}
|
||||
List<? extends DocTree> firstSentenceTags = utils.getFirstSentenceTrees(member);
|
||||
if (utils.isExecutableElement(member) && firstSentenceTags.isEmpty()) {
|
||||
@ -279,104 +284,6 @@ public abstract class MemberSummaryBuilder extends AbstractMemberBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the property method, property setter and/or property getter
|
||||
* comment text so that it contains the documentation from
|
||||
* the property field. The method adds the leading sentence,
|
||||
* copied documentation including the defaultValue tag and
|
||||
* the see tags if the appropriate property getter and setter are
|
||||
* available.
|
||||
*
|
||||
* @param member the member which is to be augmented.
|
||||
* @param property the original property documentation.
|
||||
*/
|
||||
private void processProperty(Element member,
|
||||
Element property) {
|
||||
CommentUtils cmtutils = configuration.cmtUtils;
|
||||
final boolean isSetter = isSetter(member);
|
||||
final boolean isGetter = isGetter(member);
|
||||
|
||||
List<DocTree> fullBody = new ArrayList<>();
|
||||
List<DocTree> blockTags = new ArrayList<>();
|
||||
if (isGetter || isSetter) {
|
||||
//add "[GS]ets the value of the property PROPERTY_NAME."
|
||||
if (isSetter) {
|
||||
String text = MessageFormat.format(
|
||||
resources.getText("doclet.PropertySetterWithName"),
|
||||
utils.propertyName((ExecutableElement)member));
|
||||
fullBody.addAll(cmtutils.makeFirstSentenceTree(text));
|
||||
}
|
||||
if (isGetter) {
|
||||
String text = MessageFormat.format(
|
||||
resources.getText("doclet.PropertyGetterWithName"),
|
||||
utils.propertyName((ExecutableElement) member));
|
||||
fullBody.addAll(cmtutils.makeFirstSentenceTree(text));
|
||||
}
|
||||
List<? extends DocTree> propertyTags = utils.getBlockTags(property,
|
||||
t -> (t instanceof UnknownBlockTagTree tree)
|
||||
&& (tree.getTagName().equals("propertyDescription")));
|
||||
if (propertyTags.isEmpty()) {
|
||||
List<? extends DocTree> comment = utils.getFullBody(property);
|
||||
blockTags.addAll(cmtutils.makePropertyDescriptionTree(comment));
|
||||
}
|
||||
} else {
|
||||
fullBody.addAll(utils.getFullBody(property));
|
||||
}
|
||||
|
||||
// copy certain tags
|
||||
List<? extends SinceTree> tags = utils.getBlockTags(property, Kind.SINCE, SinceTree.class);
|
||||
blockTags.addAll(tags);
|
||||
|
||||
List<? extends DocTree> bTags = utils.getBlockTags(property,
|
||||
t -> (t instanceof UnknownBlockTagTree tree)
|
||||
&& (tree.getTagName().equals("defaultValue")));
|
||||
blockTags.addAll(bTags);
|
||||
|
||||
//add @see tags
|
||||
if (!isGetter && !isSetter) {
|
||||
ExecutableElement getter = pHelper.getGetterForProperty((ExecutableElement)member);
|
||||
ExecutableElement setter = pHelper.getSetterForProperty((ExecutableElement)member);
|
||||
|
||||
if (null != getter) {
|
||||
StringBuilder sb = new StringBuilder("#");
|
||||
sb.append(utils.getSimpleName(getter)).append("()");
|
||||
blockTags.add(cmtutils.makeSeeTree(sb.toString(), getter));
|
||||
}
|
||||
|
||||
if (null != setter) {
|
||||
VariableElement param = setter.getParameters().get(0);
|
||||
StringBuilder sb = new StringBuilder("#");
|
||||
sb.append(utils.getSimpleName(setter));
|
||||
if (!utils.isTypeVariable(param.asType())) {
|
||||
sb.append("(").append(utils.getTypeSignature(param.asType(), false, true)).append(")");
|
||||
}
|
||||
blockTags.add(cmtutils.makeSeeTree(sb.toString(), setter));
|
||||
}
|
||||
}
|
||||
cmtutils.setDocCommentTree(member, fullBody, blockTags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether the method is a getter.
|
||||
* @param element property method documentation. Needs to be either property
|
||||
* method, property getter, or property setter.
|
||||
* @return true if the given documentation belongs to a getter.
|
||||
*/
|
||||
private boolean isGetter(Element element) {
|
||||
final String pedName = element.getSimpleName().toString();
|
||||
return pedName.startsWith("get") || pedName.startsWith("is");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether the method is a setter.
|
||||
* @param element property method documentation. Needs to be either property
|
||||
* method, property getter, or property setter.
|
||||
* @return true if the given documentation belongs to a setter.
|
||||
*/
|
||||
private boolean isSetter(Element element) {
|
||||
return element.getSimpleName().toString().startsWith("set");
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the inherited member summary for the given methods.
|
||||
*
|
||||
@ -456,6 +363,19 @@ public abstract class MemberSummaryBuilder extends AbstractMemberBuilder {
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* A utility class to manage the property-related methods that should be
|
||||
* synthesized or updated.
|
||||
*
|
||||
* A property may comprise a field (that is typically private, if present),
|
||||
* a {@code fooProperty()} method (which is the defining characteristic for
|
||||
* a property), a {@code getFoo()} method and/or a {@code setFoo(Foo foo)} method.
|
||||
*
|
||||
* Either the field (if present) or the {@code fooProperty()} method should have a
|
||||
* comment. If there is no field, or no comment on the field, the description for
|
||||
* the property will be derived from the description of the {@code fooProperty()}
|
||||
* method. If any method does not have a comment, one will be provided.
|
||||
*/
|
||||
static class PropertyHelper {
|
||||
|
||||
private final Map<Element, Element> classPropertiesMap = new HashMap<>();
|
||||
@ -483,22 +403,28 @@ public abstract class MemberSummaryBuilder extends AbstractMemberBuilder {
|
||||
VariableElement field,
|
||||
ExecutableElement getter,
|
||||
ExecutableElement setter) {
|
||||
if (field == null || !builder.utils.hasDocCommentTree(field)) {
|
||||
addToPropertiesMap(propertyMethod, propertyMethod);
|
||||
addToPropertiesMap(getter, propertyMethod);
|
||||
addToPropertiesMap(setter, propertyMethod);
|
||||
} else {
|
||||
addToPropertiesMap(propertyMethod, field);
|
||||
addToPropertiesMap(getter, field);
|
||||
addToPropertiesMap(setter, field);
|
||||
// determine the preferred element from which to derive the property description
|
||||
Element e = field == null || !builder.utils.hasDocCommentTree(field)
|
||||
? propertyMethod : field;
|
||||
|
||||
if (e == field && builder.utils.hasDocCommentTree(propertyMethod)) {
|
||||
BaseConfiguration configuration = builder.configuration;
|
||||
configuration.getReporter().print(Diagnostic.Kind.WARNING,
|
||||
propertyMethod, configuration.getDocResources().getText("doclet.duplicate.comment.for.property"));
|
||||
}
|
||||
|
||||
addToPropertiesMap(propertyMethod, e);
|
||||
addToPropertiesMap(getter, e);
|
||||
addToPropertiesMap(setter, e);
|
||||
}
|
||||
|
||||
private void addToPropertiesMap(Element propertyMethod,
|
||||
Element commentSource) {
|
||||
if (null == propertyMethod || null == commentSource) {
|
||||
Objects.requireNonNull(commentSource);
|
||||
if (propertyMethod == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Utils utils = builder.utils;
|
||||
DocCommentTree docTree = utils.hasDocCommentTree(propertyMethod)
|
||||
? utils.getDocCommentTree(propertyMethod)
|
||||
@ -514,30 +440,12 @@ public abstract class MemberSummaryBuilder extends AbstractMemberBuilder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the property field documentation belonging to the given member.
|
||||
* Returns the element for the property documentation belonging to the given member.
|
||||
* @param element the member for which the property documentation is needed.
|
||||
* @return the property field documentation, null if there is none.
|
||||
* @return the element for the property documentation, null if there is none.
|
||||
*/
|
||||
public Element getPropertyElement(Element element) {
|
||||
return classPropertiesMap.get(element);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the getter documentation belonging to the given property method.
|
||||
* @param propertyMethod the method for which the getter is needed.
|
||||
* @return the getter documentation, null if there is none.
|
||||
*/
|
||||
public ExecutableElement getGetterForProperty(ExecutableElement propertyMethod) {
|
||||
return builder.getVisibleMemberTable().getPropertyGetter(propertyMethod);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the setter documentation belonging to the given property method.
|
||||
* @param propertyMethod the method for which the setter is needed.
|
||||
* @return the setter documentation, null if there is none.
|
||||
*/
|
||||
public ExecutableElement getSetterForProperty(ExecutableElement propertyMethod) {
|
||||
return builder.getVisibleMemberTable().getPropertySetter(propertyMethod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,18 +25,23 @@
|
||||
|
||||
package jdk.javadoc.internal.doclets.toolkit.builders;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
|
||||
import com.sun.source.doctree.DocCommentTree;
|
||||
import com.sun.source.doctree.DocTree;
|
||||
import jdk.javadoc.internal.doclets.toolkit.BaseOptions;
|
||||
import jdk.javadoc.internal.doclets.toolkit.CommentUtils;
|
||||
import jdk.javadoc.internal.doclets.toolkit.Content;
|
||||
import jdk.javadoc.internal.doclets.toolkit.DocletException;
|
||||
import jdk.javadoc.internal.doclets.toolkit.PropertyWriter;
|
||||
|
||||
import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
|
||||
import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.PROPERTIES;
|
||||
|
||||
/**
|
||||
* Builds documentation for a property.
|
||||
@ -179,7 +184,25 @@ public class PropertyBuilder extends AbstractMemberBuilder {
|
||||
* @param propertyDocTree the content tree to which the documentation will be added
|
||||
*/
|
||||
protected void buildTagInfo(Content propertyDocTree) {
|
||||
writer.addTags(currentProperty, propertyDocTree);
|
||||
CommentUtils cmtUtils = configuration.cmtUtils;
|
||||
DocCommentTree dct = utils.getDocCommentTree(currentProperty);
|
||||
var fullBody = dct.getFullBody();
|
||||
ArrayList<DocTree> blockTags = dct.getBlockTags().stream()
|
||||
.filter(t -> t.getKind() != DocTree.Kind.RETURN)
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
String sig = "#" + currentProperty.getSimpleName() + "()";
|
||||
blockTags.add(cmtUtils.makeSeeTree(sig, currentProperty));
|
||||
// The property method is used as a proxy for the property
|
||||
// (which does not have an explicit element of its own.)
|
||||
// Temporarily override the doc comment for the property method
|
||||
// by removing the `@return` tag, which should not be displayed for
|
||||
// the property.
|
||||
CommentUtils.DocCommentInfo prev = cmtUtils.setDocCommentTree(currentProperty, fullBody, blockTags);
|
||||
try {
|
||||
writer.addTags(currentProperty, propertyDocTree);
|
||||
} finally {
|
||||
cmtUtils.setDocCommentInfo(currentProperty, prev);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -86,7 +86,10 @@ doclet.Author=Author:
|
||||
doclet.DefaultValue=Default value:
|
||||
doclet.PropertyDescription=Property description:
|
||||
doclet.PropertyGetterWithName=Gets the value of the property {0}.
|
||||
doclet.PropertyGetterReturn=the value of the property {0}
|
||||
doclet.PropertySetterWithName=Sets the value of the property {0}.
|
||||
doclet.PropertySetterParam=the value for the property {0}
|
||||
doclet.PropertyMethodReturn=the property {0}
|
||||
doclet.Default=Default:
|
||||
doclet.Parameters=Parameters:
|
||||
doclet.TypeParameters=Type Parameters:
|
||||
@ -237,6 +240,8 @@ doclet.linkMismatch_PackagedLinkedtoModule=The code being documented uses packag
|
||||
doclet.linkMismatch_ModuleLinkedtoPackage=The code being documented uses modules but the packages defined \
|
||||
in {0} are in the unnamed module.
|
||||
doclet.urlRedirected=URL {0} was redirected to {1} -- Update the command-line options to suppress this warning.
|
||||
doclet.duplicate.comment.for.property=Duplicate comment for property.\n\
|
||||
Remove the comment on the property field or on this method to suppress this warning.
|
||||
|
||||
#Documentation for Enums
|
||||
doclet.enum_values_doc.fullbody=\
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -351,38 +351,57 @@ public class VisibleMemberTable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the property field associated with the property method.
|
||||
* @param propertyMethod the identifying property method
|
||||
* Returns the field for a property identified by any of the methods
|
||||
* for that property.
|
||||
*
|
||||
* @param ee the method
|
||||
* @return the field or null if absent
|
||||
*/
|
||||
public VariableElement getPropertyField(ExecutableElement propertyMethod) {
|
||||
public VariableElement getPropertyField(ExecutableElement ee) {
|
||||
ensureInitialized();
|
||||
PropertyMembers pm = propertyMap.get(propertyMethod);
|
||||
PropertyMembers pm = propertyMap.get(ee);
|
||||
return pm == null ? null : pm.field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the getter method associated with the property method.
|
||||
* @param propertyMethod the identifying property method
|
||||
* Returns the getter method for a property identified by any of the methods
|
||||
* for that property.
|
||||
*
|
||||
* @param ee the method
|
||||
* @return the getter or null if absent
|
||||
*/
|
||||
public ExecutableElement getPropertyGetter(ExecutableElement propertyMethod) {
|
||||
public ExecutableElement getPropertyGetter(ExecutableElement ee) {
|
||||
ensureInitialized();
|
||||
PropertyMembers pm = propertyMap.get(propertyMethod);
|
||||
PropertyMembers pm = propertyMap.get(ee);
|
||||
return pm == null ? null : pm.getter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the setter method associated with the property method.
|
||||
* @param propertyMethod the identifying property method
|
||||
* Returns the setter method for a property identified by any of the methods
|
||||
* for that property.
|
||||
*
|
||||
* @param ee the method
|
||||
* @return the setter or null if absent
|
||||
*/
|
||||
public ExecutableElement getPropertySetter(ExecutableElement propertyMethod) {
|
||||
public ExecutableElement getPropertySetter(ExecutableElement ee) {
|
||||
ensureInitialized();
|
||||
PropertyMembers pm = propertyMap.get(propertyMethod);
|
||||
PropertyMembers pm = propertyMap.get(ee);
|
||||
return pm == null ? null : pm.setter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the property method for a property identified by any of the methods
|
||||
* for that property.
|
||||
*
|
||||
* @param ee the method
|
||||
* @return the property method or null if absent
|
||||
*/
|
||||
public ExecutableElement getPropertyMethod(ExecutableElement ee) {
|
||||
ensureInitialized();
|
||||
PropertyMembers pm = propertyMap.get(ee);
|
||||
return pm == null ? null : pm.propertyMethod;
|
||||
}
|
||||
|
||||
private void computeParents() {
|
||||
// suppress parents of annotation types
|
||||
if (utils.isAnnotationType(te)) {
|
||||
@ -817,35 +836,28 @@ public class VisibleMemberTable {
|
||||
}
|
||||
|
||||
List<Element> getMembers(String key, Kind kind) {
|
||||
Map <String, List<Element>> map = memberMap.get(kind);
|
||||
Map<String, List<Element>> map = memberMap.get(kind);
|
||||
return map.getOrDefault(key, Collections.emptyList());
|
||||
}
|
||||
|
||||
List<Element> getPropertyMethods(String methodName, int argcount) {
|
||||
<T extends Element> List<T> getMembers(String key, Kind kind, Class<T> clazz) {
|
||||
Map<String, List<Element>> map = memberMap.get(kind);
|
||||
return map.getOrDefault(key, Collections.emptyList())
|
||||
.stream()
|
||||
.map(e -> clazz.cast(e))
|
||||
.toList();
|
||||
}
|
||||
|
||||
List<ExecutableElement> getPropertyMethods(String methodName, int argcount) {
|
||||
return getMembers(methodName + ":" + argcount, Kind.METHODS).stream()
|
||||
.filter(m -> (utils.isPublic(m) || utils.isProtected(m)))
|
||||
.map(m -> (ExecutableElement) m)
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The properties triad for a property method.
|
||||
*/
|
||||
static class PropertyMembers {
|
||||
final VariableElement field;
|
||||
final ExecutableElement getter;
|
||||
final ExecutableElement setter;
|
||||
|
||||
PropertyMembers(VariableElement field, ExecutableElement getter, ExecutableElement setter) {
|
||||
this.field = field;
|
||||
this.getter = getter;
|
||||
this.setter = setter;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return ("field: " + field + ", getter: " + getter + ", setter: " + setter);
|
||||
}
|
||||
}
|
||||
record PropertyMembers(ExecutableElement propertyMethod, VariableElement field,
|
||||
ExecutableElement getter, ExecutableElement setter) { }
|
||||
|
||||
/*
|
||||
* JavaFX convention notes.
|
||||
@ -901,11 +913,11 @@ public class VisibleMemberTable {
|
||||
// Compute additional properties related sundries.
|
||||
for (ExecutableElement propertyMethod : propertyMethods) {
|
||||
String baseName = pUtils.getBaseName(propertyMethod);
|
||||
List<Element> flist = lmt.getMembers(baseName, Kind.FIELDS);
|
||||
Element field = flist.isEmpty() ? null : flist.get(0);
|
||||
List<VariableElement> flist = lmt.getMembers(baseName, Kind.FIELDS, VariableElement.class);
|
||||
VariableElement field = flist.isEmpty() ? null : flist.get(0);
|
||||
|
||||
Element getter = null, setter = null;
|
||||
List<Element> found = lmt.getPropertyMethods(pUtils.getGetName(propertyMethod), 0);
|
||||
ExecutableElement getter = null, setter = null;
|
||||
List<ExecutableElement> found = lmt.getPropertyMethods(pUtils.getGetName(propertyMethod), 0);
|
||||
if (!found.isEmpty()) {
|
||||
// Getters have zero params, no overloads! pick the first.
|
||||
getter = found.get(0);
|
||||
@ -914,7 +926,6 @@ public class VisibleMemberTable {
|
||||
// Check if isProperty methods are present ?
|
||||
found = lmt.getPropertyMethods(pUtils.getIsName(propertyMethod), 0);
|
||||
if (!found.isEmpty()) {
|
||||
String propertyTypeName = propertyMethod.getReturnType().toString();
|
||||
// Check if the return type of property method matches an isProperty method.
|
||||
if (pUtils.hasIsMethod(propertyMethod)) {
|
||||
// Getters have zero params, no overloads!, pick the first.
|
||||
@ -924,16 +935,22 @@ public class VisibleMemberTable {
|
||||
}
|
||||
found = lmt.getPropertyMethods(pUtils.getSetName(propertyMethod), 1);
|
||||
if (found != null) {
|
||||
for (Element e : found) {
|
||||
if (pUtils.isValidSetterMethod((ExecutableElement)e)) {
|
||||
for (ExecutableElement e : found) {
|
||||
if (pUtils.isValidSetterMethod(e)) {
|
||||
setter = e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
propertyMap.put(propertyMethod, new PropertyMembers((VariableElement)field,
|
||||
(ExecutableElement)getter, (ExecutableElement)setter));
|
||||
PropertyMembers pm = new PropertyMembers(propertyMethod, field, getter, setter);
|
||||
propertyMap.put(propertyMethod, pm);
|
||||
if (getter != null) {
|
||||
propertyMap.put(getter, pm);
|
||||
}
|
||||
if (setter != null) {
|
||||
propertyMap.put(setter, pm);
|
||||
}
|
||||
|
||||
// Debugging purposes
|
||||
// System.out.println("te: " + te + ": " + utils.getEnclosingTypeElement(propertyMethod) +
|
||||
|
@ -54,6 +54,7 @@ public class TestJavaFX extends JavadocTester {
|
||||
"-sourcepath", testSrc,
|
||||
"-javafx",
|
||||
"--disable-javafx-strict-checks",
|
||||
"-Xdoclint:all,-missing",
|
||||
"-package",
|
||||
"pkg1");
|
||||
checkExit(Exit.OK);
|
||||
@ -71,14 +72,14 @@ public class TestJavaFX extends JavadocTester {
|
||||
<div class="member-signature"><span class="modifiers">public final</span> <\
|
||||
span class="return-type">void</span> <span class="element-name">setRate</span><wbr>\
|
||||
<span class="parameters">(double value)</span></div>
|
||||
<div class="block">Sets the value of the property rate.</div>
|
||||
<div class="block">Sets the value of the property <code>rate</code>.</div>
|
||||
<dl class="notes">
|
||||
<dt>Property description:</dt>""",
|
||||
"""
|
||||
<div class="member-signature"><span class="modifiers">public final</span> <\
|
||||
span class="return-type">double</span> <span class="element-name">getRate</span>()<\
|
||||
/div>
|
||||
<div class="block">Gets the value of the property rate.</div>
|
||||
<div class="block">Gets the value of the property <code>rate</code>.</div>
|
||||
<dl class="notes">
|
||||
<dt>Property description:</dt>""",
|
||||
"""
|
||||
@ -116,14 +117,14 @@ public class TestJavaFX extends JavadocTester {
|
||||
<div class="member-signature"><span class="modifiers">public final</span> <\
|
||||
span class="return-type">double</span> <span class="element-name">isPaused<\
|
||||
/span>()</div>
|
||||
<div class="block">Gets the value of the property paused.</div>""",
|
||||
<div class="block">Gets the value of the property <code>paused</code>.</div>""",
|
||||
"""
|
||||
<section class="detail" id="setPaused(boolean)">
|
||||
<h3>setPaused</h3>
|
||||
<div class="member-signature"><span class="modifiers">public final</span> <\
|
||||
span class="return-type">void</span> <span class="element-name">setPaused</\
|
||||
span><wbr><span class="parameters">(boolean value)</span></div>
|
||||
<div class="block">Sets the value of the property paused.</div>
|
||||
<div class="block">Sets the value of the property <code>paused</code>.</div>
|
||||
<dl class="notes">
|
||||
<dt>Property description:</dt>
|
||||
<dd>Defines if paused. The second line.</dd>
|
||||
@ -135,7 +136,7 @@ public class TestJavaFX extends JavadocTester {
|
||||
<div class="member-signature"><span class="modifiers">public final</span> <\
|
||||
span class="return-type">double</span> <span class="element-name">isPaused<\
|
||||
/span>()</div>
|
||||
<div class="block">Gets the value of the property paused.</div>
|
||||
<div class="block">Gets the value of the property <code>paused</code>.</div>
|
||||
<dl class="notes">
|
||||
<dt>Property description:</dt>
|
||||
<dd>Defines if paused. The second line.</dd>
|
||||
@ -150,35 +151,39 @@ public class TestJavaFX extends JavadocTester {
|
||||
<div class="block">Defines the direction/speed at which the <code>Timeline</code> is expected to
|
||||
be played. This is the second line.</div>""",
|
||||
"""
|
||||
<section class="detail" id="setRate(double)">
|
||||
<h3>setRate</h3>
|
||||
<div class="member-signature"><span class="modifiers">public final</span> <\
|
||||
span class="return-type">void</span> <span class="element-name">setRate</sp\
|
||||
an><wbr><span class="parameters">(double value)</span></div>
|
||||
<div class="block">Sets the value of the property rate.</div>
|
||||
<dl class="notes">
|
||||
<dt>Property description:</dt>
|
||||
<dd>Defines the direction/speed at which the <code>Timeline</code> is expected to
|
||||
be played. This is the second line.</dd>
|
||||
<dt>Default value:</dt>
|
||||
<dd>11</dd>
|
||||
<dt>Since:</dt>
|
||||
<dd>JavaFX 8.0</dd>""",
|
||||
<section class="detail" id="setRate(double)">
|
||||
<h3>setRate</h3>
|
||||
<div class="member-signature"><span class="modifiers">public final</span> <\
|
||||
span class="return-type">void</span> <span class="element-name">setRate</sp\
|
||||
an><wbr><span class="parameters">(double value)</span></div>
|
||||
<div class="block">Sets the value of the property <code>rate</code>.</div>
|
||||
<dl class="notes">
|
||||
<dt>Property description:</dt>
|
||||
<dd>Defines the direction/speed at which the <code>Timeline</code> is expected to
|
||||
be played. This is the second line.</dd>
|
||||
<dt>Default value:</dt>
|
||||
<dd>11</dd>
|
||||
<dt>Parameters:</dt>
|
||||
<dd><code>value</code> - the value for the property <code>rate</code></dd>
|
||||
<dt>Since:</dt>
|
||||
<dd>JavaFX 8.0</dd>""",
|
||||
"""
|
||||
<section class="detail" id="getRate()">
|
||||
<h3>getRate</h3>
|
||||
<div class="member-signature"><span class="modifiers">public final</span> <\
|
||||
span class="return-type">double</span> <span class="element-name">getRate</span>()<\
|
||||
/div>
|
||||
<div class="block">Gets the value of the property rate.</div>
|
||||
<dl class="notes">
|
||||
<dt>Property description:</dt>
|
||||
<dd>Defines the direction/speed at which the <code>Timeline</code> is expected to
|
||||
be played. This is the second line.</dd>
|
||||
<dt>Default value:</dt>
|
||||
<dd>11</dd>
|
||||
<dt>Since:</dt>
|
||||
<dd>JavaFX 8.0</dd>""",
|
||||
<section class="detail" id="getRate()">
|
||||
<h3>getRate</h3>
|
||||
<div class="member-signature"><span class="modifiers">public final</span> <\
|
||||
span class="return-type">double</span> <span class="element-name">getRate</span>()<\
|
||||
/div>
|
||||
<div class="block">Gets the value of the property <code>rate</code>.</div>
|
||||
<dl class="notes">
|
||||
<dt>Property description:</dt>
|
||||
<dd>Defines the direction/speed at which the <code>Timeline</code> is expected to
|
||||
be played. This is the second line.</dd>
|
||||
<dt>Default value:</dt>
|
||||
<dd>11</dd>
|
||||
<dt>Returns:</dt>
|
||||
<dd>the value of the property <code>rate</code></dd>
|
||||
<dt>Since:</dt>
|
||||
<dd>JavaFX 8.0</dd>""",
|
||||
"""
|
||||
<section class="property-summary" id="property-summary">
|
||||
<h2>Property Summary</h2>
|
||||
@ -221,7 +226,7 @@ public class TestJavaFX extends JavadocTester {
|
||||
|
||||
checkOutput("index-all.html", true,
|
||||
"""
|
||||
<div class="block">Gets the value of the property paused.</div>""",
|
||||
<div class="block">Gets the value of the property <code>paused</code>.</div>""",
|
||||
"""
|
||||
<div class="block">Defines if paused.</div>""");
|
||||
|
||||
@ -245,40 +250,65 @@ public class TestJavaFX extends JavadocTester {
|
||||
"-javafx",
|
||||
"--disable-javafx-strict-checks",
|
||||
"--no-platform-links",
|
||||
"-Xdoclint:all,-missing",
|
||||
"-package",
|
||||
"pkg2");
|
||||
checkExit(Exit.OK);
|
||||
checkOutput("pkg2/Test.html", true,
|
||||
"""
|
||||
<section class="property-details" id="property-detail">
|
||||
<h2>Property Details</h2>
|
||||
<ul class="member-list">
|
||||
<li>
|
||||
<section class="detail" id="betaProperty">
|
||||
<h3>beta</h3>
|
||||
<div class="member-signature"><span class="modifiers">public</span> <span c\
|
||||
lass="return-type">java.lang.Object</span> <span class="element-name">betaProperty<\
|
||||
/span></div>
|
||||
</section>
|
||||
</li>
|
||||
<li>
|
||||
<section class="detail" id="gammaProperty">
|
||||
<h3>gamma</h3>
|
||||
<div class="member-signature"><span class="modifiers">public final</span> <\
|
||||
span class="return-type">java.util.List<java.lang.String></span> <spa\
|
||||
n class="element-name">gammaProperty</span></div>
|
||||
</section>
|
||||
</li>
|
||||
<li>
|
||||
<section class="detail" id="deltaProperty">
|
||||
<h3>delta</h3>
|
||||
<div class="member-signature"><span class="modifiers">public final</span> <\
|
||||
span class="return-type">java.util.List<java.util.Set<? super java.lang.Ob\
|
||||
ject>></span> <span class="element-name">deltaProperty</span></div>
|
||||
</section>
|
||||
</li>
|
||||
</ul>
|
||||
</section>""",
|
||||
<section class="property-details" id="property-detail">
|
||||
<h2>Property Details</h2>
|
||||
<ul class="member-list">
|
||||
<li>
|
||||
<section class="detail" id="betaProperty">
|
||||
<h3>beta</h3>
|
||||
<div class="member-signature"><span class="modifiers">public</span> <span c\
|
||||
lass="return-type">java.lang.Object</span> <span class="element-name">betaProperty<\
|
||||
/span></div>
|
||||
<dl class="notes">
|
||||
<dt>See Also:</dt>
|
||||
<dd>
|
||||
<ul class="see-list">
|
||||
<li><a href="#betaProperty()"><code>betaProperty()</code></a></li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
</section>
|
||||
</li>
|
||||
<li>
|
||||
<section class="detail" id="gammaProperty">
|
||||
<h3>gamma</h3>
|
||||
<div class="member-signature"><span class="modifiers">public final</span> <\
|
||||
span class="return-type">java.util.List<java.lang.String></span> <spa\
|
||||
n class="element-name">gammaProperty</span></div>
|
||||
<dl class="notes">
|
||||
<dt>See Also:</dt>
|
||||
<dd>
|
||||
<ul class="see-list">
|
||||
<li><a href="#gammaProperty()"><code>gammaProperty()</code></a></li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
</section>
|
||||
</li>
|
||||
<li>
|
||||
<section class="detail" id="deltaProperty">
|
||||
<h3>delta</h3>
|
||||
<div class="member-signature"><span class="modifiers">public final</span> <\
|
||||
span class="return-type">java.util.List<java.util.Set<? super java.lang.Ob\
|
||||
ject>></span> <span class="element-name">deltaProperty</span></div>
|
||||
<dl class="notes">
|
||||
<dt>See Also:</dt>
|
||||
<dd>
|
||||
<ul class="see-list">
|
||||
<li><a href="#deltaProperty()"><code>deltaProperty()</code></a></li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
</section>
|
||||
</li>
|
||||
</ul>
|
||||
</section>""",
|
||||
"""
|
||||
<section class="property-summary" id="property-summary">
|
||||
<h2>Property Summary</h2>
|
||||
|
@ -0,0 +1,423 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8270195
|
||||
* @summary Add missing links between methods of JavaFX properties
|
||||
* @library /tools/lib ../../lib
|
||||
* @modules jdk.javadoc/jdk.javadoc.internal.tool
|
||||
* @build toolbox.ToolBox javadoc.tester.*
|
||||
* @run main TestJavaFXCombo
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javadoc.tester.JavadocTester;
|
||||
import toolbox.ToolBox;
|
||||
|
||||
/**
|
||||
* Combo-test for JavaFX properties and related methods.
|
||||
* The test generates instances of a class with various combinations of
|
||||
* a property field, property method, getter method and setter method,
|
||||
* each in combinations of with and without doc comments.
|
||||
* For each instance, it runs javadoc and verifies the generated
|
||||
* code and any diagnostics are as expected.
|
||||
*/
|
||||
public class TestJavaFXCombo extends JavadocTester {
|
||||
public static void main(String... args) throws Exception {
|
||||
TestJavaFXCombo tester = new TestJavaFXCombo(args);
|
||||
tester.runTests(m -> new Object[] { Path.of(m.getName())});
|
||||
}
|
||||
|
||||
ToolBox tb = new ToolBox();
|
||||
enum Kind { NONE, NO_COMMENT, COMMENT }
|
||||
|
||||
private final Set<Kind> fieldValues = EnumSet.allOf(Kind.class);
|
||||
private final Set<Kind> propertyMethodValues = EnumSet.allOf(Kind.class);
|
||||
private final Set<Kind> getterMethodValues = EnumSet.allOf(Kind.class);
|
||||
private final Set<Kind> setterMethodValues = EnumSet.allOf(Kind.class);
|
||||
|
||||
TestJavaFXCombo(String... args) {
|
||||
// for testing, allow subsets of combinations to be specified
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
String arg = args[1];
|
||||
switch (arg) {
|
||||
case "-f" -> set(fieldValues, args[++i]);
|
||||
case "-p" -> set(propertyMethodValues, args[++i]);
|
||||
case "-g" -> set(getterMethodValues, args[++i]);
|
||||
case "-s" -> set(setterMethodValues, args[++i]);
|
||||
}
|
||||
}
|
||||
|
||||
// A property method is always required for any property,
|
||||
propertyMethodValues.remove(Kind.NONE);
|
||||
|
||||
}
|
||||
|
||||
private void set(Set<Kind> set, String values) {
|
||||
set.clear();
|
||||
for (String v : values.split("[, ]")) {
|
||||
set.add(Kind.valueOf(v));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test(Path base) throws IOException {
|
||||
for (Kind pk : propertyMethodValues) {
|
||||
for (Kind fk : fieldValues) {
|
||||
for (Kind gk : getterMethodValues) {
|
||||
for (Kind sk: setterMethodValues) {
|
||||
test(base, fk, pk, gk, sk);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void test(Path base, Kind fk, Kind pk, Kind gk, Kind sk) throws IOException {
|
||||
String description = "Field:" + fk + " Property:" + pk + " Getter:" + gk + " Setter:" + sk;
|
||||
out.println("Test: " + description);
|
||||
Path sub = base.resolve(String.format("%s-%s-%s-%s", abbrev(fk), abbrev(pk), abbrev(gk), abbrev(sk)));
|
||||
Path src = sub.resolve("src");
|
||||
tb.writeJavaFiles(src, """
|
||||
package p;
|
||||
/** Dummy property class. */
|
||||
public class BooleanProperty { }
|
||||
""", """
|
||||
package p;
|
||||
/** Class comment. ## */
|
||||
public class C {
|
||||
""".replace("##", description)
|
||||
+ getFieldText(fk)
|
||||
+ getPropertyMethodText(pk)
|
||||
+ getGetterMethodText(gk)
|
||||
+ getSetterMethodText(sk)
|
||||
+ """
|
||||
}
|
||||
"""
|
||||
);
|
||||
|
||||
javadoc("-d", sub.resolve("api").toString(),
|
||||
"-javafx",
|
||||
"--disable-javafx-strict-checks",
|
||||
"-Xdoclint:all,-missing",
|
||||
"-nohelp", "-noindex",
|
||||
"-sourcepath", src.toString(),
|
||||
"p");
|
||||
checkExit(Exit.OK);
|
||||
checkField(fk, pk, gk, sk);
|
||||
checkGetter(fk, pk, gk, sk);
|
||||
checkSetter(fk, pk, gk, sk);
|
||||
checkPropertyMethod(fk, pk, gk, sk);
|
||||
checkDiags(fk, pk, gk, sk);
|
||||
}
|
||||
|
||||
void checkField(Kind fk, Kind pk, Kind gk, Kind sk) {
|
||||
// the field is private and so should never show up
|
||||
checkOutput("p/C.html", false,
|
||||
"field.detail");
|
||||
}
|
||||
|
||||
void checkGetter(Kind fk, Kind pk, Kind gk, Kind sk) {
|
||||
switch (gk) {
|
||||
case NONE ->
|
||||
checkOutput("p/C.html", false,
|
||||
"getExample");
|
||||
|
||||
case NO_COMMENT ->
|
||||
// comment gets auto-created
|
||||
checkOutput("p/C.html", true,
|
||||
"""
|
||||
<section class="detail" id="getExample()">
|
||||
<h3>getExample</h3>
|
||||
<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">boolean</span> <span class="element-name">getExample</span>()</div>
|
||||
<div class="block">Gets the value of the property <code>example</code>.</div>
|
||||
<dl class="notes">
|
||||
<dt>Property description:</dt>
|
||||
#DESC#
|
||||
<dt>Returns:</dt>
|
||||
<dd>the value of the property <code>example</code></dd>
|
||||
#SEE#
|
||||
</dl>
|
||||
</section>
|
||||
"""
|
||||
.replace("#DESC#", getPropertyDescription(fk, pk))
|
||||
.replace("#SEE#", getSee(pk, null, sk))
|
||||
.replaceAll("\n\n", "\n")
|
||||
);
|
||||
|
||||
case COMMENT ->
|
||||
// existing comments do not get modified
|
||||
checkOutput("p/C.html", true,
|
||||
"""
|
||||
<section class="detail" id="getExample()">
|
||||
<h3>getExample</h3>
|
||||
<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">boolean</span> <span class="element-name">getExample</span>()</div>
|
||||
<div class="block">Getter method description. More getter method description.</div>
|
||||
<dl class="notes">
|
||||
<dt>Returns:</dt>
|
||||
<dd>the property <code>example</code></dd>
|
||||
</dl>
|
||||
</section>
|
||||
""");
|
||||
}
|
||||
}
|
||||
|
||||
void checkSetter(Kind fk, Kind pk, Kind gk, Kind sk) {
|
||||
switch (sk) {
|
||||
case NONE ->
|
||||
checkOutput("p/C.html", false,
|
||||
"setExample");
|
||||
|
||||
case NO_COMMENT ->
|
||||
// comment gets auto-created
|
||||
checkOutput("p/C.html", true,
|
||||
"""
|
||||
<section class="detail" id="setExample(boolean)">
|
||||
<h3>setExample</h3>
|
||||
<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">void</span> <span class="element-name">setExample</span><wbr><span class="parameters">(boolean b)</span></div>
|
||||
<div class="block">Sets the value of the property <code>example</code>.</div>
|
||||
<dl class="notes">
|
||||
<dt>Property description:</dt>
|
||||
#DESC#
|
||||
<dt>Parameters:</dt>
|
||||
<dd><code>b</code> - the value for the property <code>example</code></dd>
|
||||
#SEE#
|
||||
</dl>
|
||||
</section>
|
||||
"""
|
||||
.replace("#DESC#", getPropertyDescription(fk, pk))
|
||||
.replace("#SEE#", getSee(pk, gk, null))
|
||||
.replaceAll("\n\n", "\n"));
|
||||
|
||||
case COMMENT ->
|
||||
// existing comments do not get modified
|
||||
checkOutput("p/C.html", true,
|
||||
"""
|
||||
<section class="detail" id="setExample(boolean)">
|
||||
<h3>setExample</h3>
|
||||
<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">void</span> <span class="element-name">setExample</span><wbr><span class="parameters">(boolean b)</span></div>
|
||||
<div class="block">Setter method description. More setter method description.</div>
|
||||
<dl class="notes">
|
||||
<dt>Parameters:</dt>
|
||||
<dd><code>b</code> - the new value for the property</dd>
|
||||
</dl>
|
||||
</section>
|
||||
""");
|
||||
}
|
||||
}
|
||||
|
||||
void checkPropertyMethod(Kind fk, Kind pk, Kind gk, Kind sk) {
|
||||
switch (pk) {
|
||||
case NONE ->
|
||||
// should not happen; there is always a property method
|
||||
throw new IllegalArgumentException();
|
||||
|
||||
case NO_COMMENT ->
|
||||
checkOutput("p/C.html", true,
|
||||
"""
|
||||
<section class="detail" id="exampleProperty()">
|
||||
<h3>exampleProperty</h3>
|
||||
<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="BooleanProperty.html" title="class in p">BooleanProperty</a></span> <span class="element-name">exampleProperty</span>()</div>
|
||||
#PCOMM#
|
||||
<dl class="notes">
|
||||
<dt>Returns:</dt>
|
||||
<dd>the property <code>example</code></dd>
|
||||
#SEE#
|
||||
</dl>
|
||||
</section>
|
||||
"""
|
||||
.replace("#PCOMM#", getPropertyMethodComment(fk, pk))
|
||||
.replace("#SEE#", getSee(null, gk, sk))
|
||||
.replaceAll("\n\n", "\n"));
|
||||
|
||||
case COMMENT ->
|
||||
// @see tags are added to an existing method if it is the primary source of info
|
||||
// for the property (i.e. there is no comment on a corresponding property field.
|
||||
checkOutput("p/C.html", true,
|
||||
"""
|
||||
<section class="detail" id="exampleProperty()">
|
||||
<h3>exampleProperty</h3>
|
||||
<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="BooleanProperty.html" title="class in p">BooleanProperty</a></span> <span class="element-name">exampleProperty</span>()</div>
|
||||
<div class="block">Property method description. More property method description.</div>
|
||||
<dl class="notes">
|
||||
<dt>Returns:</dt>
|
||||
<dd>the property <code>example</code></dd>
|
||||
#SEE#
|
||||
</dl>
|
||||
</section>
|
||||
"""
|
||||
.replace("#SEE#", (fk == Kind.COMMENT ? "" : getSee(null, gk, sk)))
|
||||
.replaceAll("\n\n", "\n"));
|
||||
}
|
||||
}
|
||||
|
||||
void checkDiags(Kind fk, Kind pk, Kind gk, Kind sk) {
|
||||
// A warning is generated if there is a comment on both the property field and property method
|
||||
checkOutput(Output.OUT, (fk == Kind.COMMENT && pk == Kind.COMMENT),
|
||||
"warning: Duplicate comment for property",
|
||||
"Remove the comment on the property field or on this method to suppress this warning.");
|
||||
}
|
||||
|
||||
String getPropertyComment(Kind fk, Kind pk) {
|
||||
return switch (fk) {
|
||||
case NONE, NO_COMMENT ->
|
||||
switch (pk) {
|
||||
case NONE, NO_COMMENT ->
|
||||
"";
|
||||
|
||||
case COMMENT ->
|
||||
"Property method description. More property method description.";
|
||||
};
|
||||
|
||||
case COMMENT ->
|
||||
"Field description. More field description.";
|
||||
};
|
||||
}
|
||||
|
||||
String getPropertyDescription(Kind fk, Kind pk) {
|
||||
String s = getPropertyComment(fk, pk);
|
||||
return s.isEmpty() ? s : "<dd>" + s + "</dd>";
|
||||
}
|
||||
|
||||
String getPropertyMethodComment(Kind fk, Kind pk) {
|
||||
String s = getPropertyComment(fk, pk);
|
||||
return s.isEmpty() ? s : "<div class=\"block\">" + s + "</div>";
|
||||
}
|
||||
|
||||
String getSee(Kind pk, Kind gk, Kind sk) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (gk != null && gk != Kind.NONE) {
|
||||
sb.append("""
|
||||
<li><a href="#getExample()"><code>getExample()</code></a></li>
|
||||
""");
|
||||
}
|
||||
if (sk != null && sk != Kind.NONE) {
|
||||
sb.append("""
|
||||
<li><a href="#setExample(boolean)"><code>setExample(boolean)</code></a></li>
|
||||
""");
|
||||
}
|
||||
if (pk != null && pk != Kind.NONE) {
|
||||
sb.append("""
|
||||
<li><a href="#exampleProperty()"><code>exampleProperty()</code></a></li>
|
||||
""");
|
||||
}
|
||||
return sb.isEmpty() ? "" : """
|
||||
<dt>See Also:</dt>
|
||||
<dd>
|
||||
<ul class="see-list">
|
||||
""" + sb + """
|
||||
</ul>
|
||||
</dd>""";
|
||||
}
|
||||
|
||||
String abbrev(Kind k) {
|
||||
return k.name().substring(0, 4);
|
||||
}
|
||||
|
||||
String getFieldText(Kind fk) {
|
||||
return switch (fk) {
|
||||
case NONE -> """
|
||||
// no field declaration
|
||||
""";
|
||||
|
||||
case NO_COMMENT -> """
|
||||
// no field comment
|
||||
private BooleanProperty example;
|
||||
""";
|
||||
|
||||
case COMMENT -> """
|
||||
/** Field description. More field description. */
|
||||
private BooleanProperty example;
|
||||
""";
|
||||
};
|
||||
}
|
||||
|
||||
String getPropertyMethodText(Kind fk) {
|
||||
return switch (fk) {
|
||||
case NONE -> """
|
||||
// no property method declaration
|
||||
""";
|
||||
|
||||
case NO_COMMENT -> """
|
||||
// no property method comment
|
||||
public BooleanProperty exampleProperty();
|
||||
""";
|
||||
|
||||
case COMMENT -> """
|
||||
/**
|
||||
* Property method description. More property method description.
|
||||
* @return the property {@code example}
|
||||
*/
|
||||
public BooleanProperty exampleProperty();
|
||||
""";
|
||||
};
|
||||
}
|
||||
|
||||
String getGetterMethodText(Kind fk) {
|
||||
return switch (fk) {
|
||||
case NONE -> """
|
||||
// no getter method declaration
|
||||
""";
|
||||
|
||||
case NO_COMMENT -> """
|
||||
// no getter method comment
|
||||
public boolean getExample();
|
||||
""";
|
||||
|
||||
case COMMENT -> """
|
||||
/**
|
||||
* Getter method description. More getter method description.
|
||||
* @return the property {@code example}
|
||||
*/
|
||||
public boolean getExample();
|
||||
""";
|
||||
};
|
||||
}
|
||||
|
||||
String getSetterMethodText(Kind fk) {
|
||||
return switch (fk) {
|
||||
case NONE -> """
|
||||
// no setter method declaration
|
||||
""";
|
||||
|
||||
case NO_COMMENT -> """
|
||||
// no setter method comment
|
||||
public void setExample(boolean b);
|
||||
""";
|
||||
|
||||
case COMMENT -> """
|
||||
/**
|
||||
* Setter method description. More setter method description.
|
||||
* @param b the new value for the property
|
||||
*/
|
||||
public void setExample(boolean b);
|
||||
""";
|
||||
};
|
||||
}
|
||||
|
||||
}
|
@ -92,10 +92,18 @@ public class TestJavaFXMissingPropComments extends JavadocTester {
|
||||
<div class="member-signature"><span class="modifiers">public</span> <span c\
|
||||
lass="return-type">boolean</span> <span class="element-name">getValue</span\
|
||||
>()</div>
|
||||
<div class="block">Gets the value of the property value.</div>
|
||||
<div class="block">Gets the value of the property <code>value</code>.</div>
|
||||
<dl class="notes">
|
||||
<dt>Property description:</dt>
|
||||
<dd>The value property (property method comment).</dd>
|
||||
<dt>Returns:</dt>
|
||||
<dd>the value of the property <code>value</code></dd>
|
||||
<dt>See Also:</dt>
|
||||
<dd>
|
||||
<ul class="see-list">
|
||||
<li><a href="#valueProperty()"><code>valueProperty()</code></a></li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
</section>"""
|
||||
);
|
||||
@ -148,10 +156,18 @@ public class TestJavaFXMissingPropComments extends JavadocTester {
|
||||
<div class="member-signature"><span class="modifiers">public</span> <span c\
|
||||
lass="return-type">boolean</span> <span class="element-name">getValue</span\
|
||||
>()</div>
|
||||
<div class="block">Gets the value of the property value.</div>
|
||||
<div class="block">Gets the value of the property <code>value</code>.</div>
|
||||
<dl class="notes">
|
||||
<dt>Property description:</dt>
|
||||
<dd>The value property (field comment).</dd>
|
||||
<dt>Returns:</dt>
|
||||
<dd>the value of the property <code>value</code></dd>
|
||||
<dt>See Also:</dt>
|
||||
<dd>
|
||||
<ul class="see-list">
|
||||
<li><a href="#valueProperty()"><code>valueProperty()</code></a></li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
</section>"""
|
||||
);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -26,10 +26,9 @@ package pkg2;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
public class Test {
|
||||
public <T> Object alphaProperty(List<T> foo) { return null; }
|
||||
public Object betaProperty() { return null; }
|
||||
public final List<String> gammaProperty() {return null;}
|
||||
public final List<Set<? super Object>> deltaProperty() {return null;}
|
||||
public final List<String> gammaProperty() { return null;}
|
||||
public final List<Set<? super Object>> deltaProperty() { return null;}
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ public class TestProperty extends JavadocTester {
|
||||
"--no-platform-links",
|
||||
"-javafx",
|
||||
"--disable-javafx-strict-checks",
|
||||
"-Xdoclint:all,-missing",
|
||||
"-sourcepath", testSrc,
|
||||
"pkg");
|
||||
checkExit(Exit.OK);
|
||||
@ -63,6 +64,7 @@ public class TestProperty extends JavadocTester {
|
||||
<ul class="see-list">
|
||||
<li><a href="#getGood()"><code>getGood()</code></a></li>
|
||||
<li><a href="#setGood(pkg.MyObj)"><code>setGood(MyObj)</code></a></li>
|
||||
<li><a href="#goodProperty()"><code>goodProperty()</code></a></li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>""",
|
||||
@ -79,6 +81,7 @@ public class TestProperty extends JavadocTester {
|
||||
<ul class="see-list">
|
||||
<li><a href="#getBad()"><code>getBad()</code></a></li>
|
||||
<li><a href="#setBad(pkg.MyObj%5B%5D)"><code>setBad(MyObj[])</code></a></li>
|
||||
<li><a href="#badProperty()"><code>badProperty()</code></a></li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>""",
|
||||
@ -117,6 +120,7 @@ public class TestProperty extends JavadocTester {
|
||||
<ul class="see-list">
|
||||
<li><a href="#getList()"><code>getList()</code></a></li>
|
||||
<li><a href="#setList(java.util.List)"><code>setList(List)</code></a></li>
|
||||
<li><a href="#listProperty()"><code>listProperty()</code></a></li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>"""
|
||||
|
Loading…
Reference in New Issue
Block a user