mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 12:09:14 +00:00
8367007: javadoc generation of JavaFX docs fails after fix for JDK-8350920
Reviewed-by: liach, nbenalla
This commit is contained in:
parent
34c3ac0316
commit
af18ff8d7c
@ -319,7 +319,7 @@ public abstract class AbstractMemberWriter {
|
||||
inheritedHeader.add(links);
|
||||
|
||||
if (utils.isIncluded(inheritedClass)) {
|
||||
var pHelper = writer.getPropertyHelper();
|
||||
var pHelper = configuration.propertyUtils.getPropertyHelper(inheritedClass);
|
||||
Table<Element> table = createInheritedSummaryTable(inheritedClass);
|
||||
|
||||
for (Element member : inheritedMembers) {
|
||||
|
||||
@ -96,7 +96,7 @@ public class ClassWriter extends SubWriterHolderWriter {
|
||||
this.typeElement = typeElement;
|
||||
this.classTree = classTree;
|
||||
|
||||
pHelper = new PropertyUtils.PropertyHelper(configuration, typeElement);
|
||||
pHelper = configuration.propertyUtils.getPropertyHelper(typeElement);
|
||||
|
||||
switch (typeElement.getKind()) {
|
||||
case ENUM -> setEnumDocumentation(typeElement);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2025, 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
|
||||
@ -54,6 +54,8 @@ import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.
|
||||
*/
|
||||
public class PropertyUtils {
|
||||
|
||||
final BaseConfiguration configuration;
|
||||
|
||||
final TypeMirror jbObservableType;
|
||||
|
||||
final Pattern fxMethodPatterns;
|
||||
@ -62,7 +64,10 @@ public class PropertyUtils {
|
||||
|
||||
final Types typeUtils;
|
||||
|
||||
final Map<TypeElement, PropertyHelper> propertyHelpers = new HashMap<>();
|
||||
|
||||
PropertyUtils(BaseConfiguration configuration) {
|
||||
this.configuration = configuration;
|
||||
BaseOptions options = configuration.getOptions();
|
||||
javafx = options.javafx();
|
||||
|
||||
@ -82,30 +87,37 @@ public class PropertyUtils {
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a property helper for the given type element.
|
||||
* @param typeElement a type element
|
||||
* @return the property helper
|
||||
*/
|
||||
public PropertyHelper getPropertyHelper(TypeElement typeElement) {
|
||||
return propertyHelpers.computeIfAbsent(typeElement, te -> new PropertyHelper(configuration, te));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a base name for a property method. Supposing we
|
||||
* have {@code BooleanProperty acmeProperty()}, then "acme"
|
||||
* will be returned.
|
||||
* @param propertyMethod
|
||||
* @param propertyMethod a property method
|
||||
* @return the base name of a property method.
|
||||
*/
|
||||
public String getBaseName(ExecutableElement propertyMethod) {
|
||||
String name = propertyMethod.getSimpleName().toString();
|
||||
String baseName = name.substring(0, name.indexOf("Property"));
|
||||
return baseName;
|
||||
return name.substring(0, name.indexOf("Property"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a property getter's name. Supposing we have a property
|
||||
* method {@code DoubleProperty acmeProperty()}, then "getAcme"
|
||||
* will be returned.
|
||||
* @param propertyMethod
|
||||
* @param propertyMethod a property method
|
||||
* @return the property getter's name.
|
||||
*/
|
||||
public String getGetName(ExecutableElement propertyMethod) {
|
||||
String baseName = getBaseName(propertyMethod);
|
||||
String fnUppercased = "" +
|
||||
Character.toUpperCase(baseName.charAt(0)) + baseName.substring(1);
|
||||
String fnUppercased = Character.toUpperCase(baseName.charAt(0)) + baseName.substring(1);
|
||||
return "get" + fnUppercased;
|
||||
}
|
||||
|
||||
@ -113,20 +125,19 @@ public class PropertyUtils {
|
||||
* Returns an "is" method's name for a property method. Supposing
|
||||
* we have a property method {@code BooleanProperty acmeProperty()},
|
||||
* then "isAcme" will be returned.
|
||||
* @param propertyMethod
|
||||
* @param propertyMethod a property method
|
||||
* @return the property is getter's name.
|
||||
*/
|
||||
public String getIsName(ExecutableElement propertyMethod) {
|
||||
String baseName = getBaseName(propertyMethod);
|
||||
String fnUppercased = "" +
|
||||
Character.toUpperCase(baseName.charAt(0)) + baseName.substring(1);
|
||||
String fnUppercased = Character.toUpperCase(baseName.charAt(0)) + baseName.substring(1);
|
||||
return "is" + fnUppercased;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a property method could have an "is" method, meaning
|
||||
* {@code isAcme} could exist for a property method.
|
||||
* @param propertyMethod
|
||||
* @param propertyMethod a property method
|
||||
* @return true if the property could have an "is" method, false otherwise.
|
||||
*/
|
||||
public boolean hasIsMethod(ExecutableElement propertyMethod) {
|
||||
@ -139,20 +150,19 @@ public class PropertyUtils {
|
||||
* Returns a property setter's name. Supposing we have a property
|
||||
* method {@code DoubleProperty acmeProperty()}, then "setAcme"
|
||||
* will be returned.
|
||||
* @param propertyMethod
|
||||
* @param propertyMethod a property method
|
||||
* @return the property setter's method name.
|
||||
*/
|
||||
public String getSetName(ExecutableElement propertyMethod) {
|
||||
String baseName = getBaseName(propertyMethod);
|
||||
String fnUppercased = "" +
|
||||
Character.toUpperCase(baseName.charAt(0)) + baseName.substring(1);
|
||||
String fnUppercased = Character.toUpperCase(baseName.charAt(0)) + baseName.substring(1);
|
||||
return "set" + fnUppercased;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given setter method is a valid property setter
|
||||
* method.
|
||||
* @param setterMethod
|
||||
* @param setterMethod a setter method
|
||||
* @return true if setter method, false otherwise.
|
||||
*/
|
||||
public boolean isValidSetterMethod(ExecutableElement setterMethod) {
|
||||
@ -161,28 +171,28 @@ public class PropertyUtils {
|
||||
|
||||
/**
|
||||
* Returns true if the method is a property method.
|
||||
* @param propertyMethod
|
||||
* @param method a method
|
||||
* @return true if the method is a property method, false otherwise.
|
||||
*/
|
||||
public boolean isPropertyMethod(ExecutableElement propertyMethod) {
|
||||
public boolean isPropertyMethod(ExecutableElement method) {
|
||||
if (!javafx ||
|
||||
!propertyMethod.getParameters().isEmpty() ||
|
||||
!propertyMethod.getTypeParameters().isEmpty()) {
|
||||
!method.getParameters().isEmpty() ||
|
||||
!method.getTypeParameters().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
String methodName = propertyMethod.getSimpleName().toString();
|
||||
String methodName = method.getSimpleName().toString();
|
||||
if (!methodName.endsWith("Property") ||
|
||||
fxMethodPatterns.matcher(methodName).matches()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TypeMirror returnType = propertyMethod.getReturnType();
|
||||
TypeMirror returnType = method.getReturnType();
|
||||
if (jbObservableType == null) {
|
||||
// JavaFX references missing, make a lazy backward compatible check.
|
||||
return returnType.getKind() != TypeKind.VOID;
|
||||
} else {
|
||||
// Apply strict checks since JavaFX references are available
|
||||
returnType = typeUtils.erasure(propertyMethod.getReturnType());
|
||||
returnType = typeUtils.erasure(method.getReturnType());
|
||||
return typeUtils.isAssignable(returnType, jbObservableType);
|
||||
}
|
||||
}
|
||||
@ -202,20 +212,13 @@ public class PropertyUtils {
|
||||
* method. If any method does not have a comment, one will be provided.
|
||||
*/
|
||||
public static class PropertyHelper {
|
||||
private final BaseConfiguration configuration;
|
||||
private final Utils utils;
|
||||
private final TypeElement typeElement;
|
||||
private Map<Element, Element> classPropertiesMap = null;
|
||||
|
||||
private final Map<Element, Element> classPropertiesMap = new HashMap<>();
|
||||
|
||||
public PropertyHelper(BaseConfiguration configuration, TypeElement typeElement) {
|
||||
this.configuration = configuration;
|
||||
this.utils = configuration.utils;
|
||||
this.typeElement = typeElement;
|
||||
computeProperties();
|
||||
private PropertyHelper(BaseConfiguration configuration, TypeElement typeElement) {
|
||||
computeProperties(configuration, typeElement);
|
||||
}
|
||||
|
||||
private void computeProperties() {
|
||||
private void computeProperties(BaseConfiguration configuration, TypeElement typeElement) {
|
||||
VisibleMemberTable vmt = configuration.getVisibleMemberTable(typeElement);
|
||||
List<ExecutableElement> props = ElementFilter.methodsIn(vmt.getVisibleMembers(PROPERTIES));
|
||||
for (ExecutableElement propertyMethod : props) {
|
||||
@ -223,37 +226,42 @@ public class PropertyUtils {
|
||||
ExecutableElement setter = vmt.getPropertySetter(propertyMethod);
|
||||
VariableElement field = vmt.getPropertyField(propertyMethod);
|
||||
|
||||
addToPropertiesMap(propertyMethod, field, getter, setter);
|
||||
addToPropertiesMap(configuration, propertyMethod, field, getter, setter);
|
||||
}
|
||||
}
|
||||
|
||||
private void addToPropertiesMap(ExecutableElement propertyMethod,
|
||||
private void addToPropertiesMap(BaseConfiguration configuration,
|
||||
ExecutableElement propertyMethod,
|
||||
VariableElement field,
|
||||
ExecutableElement getter,
|
||||
ExecutableElement setter) {
|
||||
// determine the preferred element from which to derive the property description
|
||||
Element e = field == null || !utils.hasDocCommentTree(field)
|
||||
Element e = field == null || !configuration.utils.hasDocCommentTree(field)
|
||||
? propertyMethod : field;
|
||||
|
||||
if (e == field && utils.hasDocCommentTree(propertyMethod)) {
|
||||
if (e == field && configuration.utils.hasDocCommentTree(propertyMethod)) {
|
||||
configuration.getReporter().print(Diagnostic.Kind.WARNING,
|
||||
propertyMethod, configuration.getDocResources().getText("doclet.duplicate.comment.for.property"));
|
||||
}
|
||||
|
||||
addToPropertiesMap(propertyMethod, e);
|
||||
addToPropertiesMap(getter, e);
|
||||
addToPropertiesMap(setter, e);
|
||||
if (classPropertiesMap == null) {
|
||||
classPropertiesMap = new HashMap<>();
|
||||
}
|
||||
addToPropertiesMap(configuration, propertyMethod, e);
|
||||
addToPropertiesMap(configuration, getter, e);
|
||||
addToPropertiesMap(configuration, setter, e);
|
||||
}
|
||||
|
||||
private void addToPropertiesMap(Element propertyMethod,
|
||||
private void addToPropertiesMap(BaseConfiguration configuration,
|
||||
Element propertyMethod,
|
||||
Element commentSource) {
|
||||
Objects.requireNonNull(commentSource);
|
||||
if (propertyMethod == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
DocCommentTree docTree = utils.hasDocCommentTree(propertyMethod)
|
||||
? utils.getDocCommentTree(propertyMethod)
|
||||
DocCommentTree docTree = configuration.utils.hasDocCommentTree(propertyMethod)
|
||||
? configuration.utils.getDocCommentTree(propertyMethod)
|
||||
: null;
|
||||
|
||||
/* The second condition is required for the property buckets. In
|
||||
@ -271,7 +279,7 @@ public class PropertyUtils {
|
||||
* @return the element for the property documentation, null if there is none.
|
||||
*/
|
||||
public Element getPropertyElement(Element element) {
|
||||
return classPropertiesMap.get(element);
|
||||
return classPropertiesMap == null ? null : classPropertiesMap.get(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,7 +25,7 @@
|
||||
* @test
|
||||
* @bug 7112427 8012295 8025633 8026567 8061305 8081854 8150130 8162363
|
||||
* 8167967 8172528 8175200 8178830 8182257 8186332 8182765 8025091
|
||||
* 8203791 8184205 8249633 8261976 8350920
|
||||
* 8203791 8184205 8249633 8261976 8350920 8367007
|
||||
* @summary Test of the JavaFX doclet features.
|
||||
* @library ../../lib
|
||||
* @modules jdk.javadoc/jdk.javadoc.internal.tool
|
||||
@ -54,11 +54,18 @@ public class TestJavaFX extends JavadocTester {
|
||||
"-sourcepath", testSrc,
|
||||
"-javafx",
|
||||
"--disable-javafx-strict-checks",
|
||||
"-Xdoclint:all,-missing",
|
||||
"-package",
|
||||
"pkg1");
|
||||
checkExit(Exit.OK);
|
||||
|
||||
checkOutput(Output.OUT, true,
|
||||
"C.java:78: warning: no comment");
|
||||
checkOutput(Output.OUT, false,
|
||||
"C.java:59: warning: no comment",
|
||||
"C.java:61: warning: no comment",
|
||||
"C.java:63: warning: no comment",
|
||||
"C.java:67: warning: no comment");
|
||||
|
||||
checkOutput("pkg1/C.html", true,
|
||||
"""
|
||||
<dt>See Also:</dt>
|
||||
@ -266,6 +273,31 @@ public class TestJavaFX extends JavadocTester {
|
||||
</section>""");
|
||||
|
||||
checkOutput("pkg1/D.html", false, "shouldNotAppear");
|
||||
|
||||
// Test for inherited properties and property methods.
|
||||
checkOrder("pkg1/B.html",
|
||||
"""
|
||||
Properties inherited from class <a href="C.html#property-summary" title="class in pkg1">C</a>""",
|
||||
"""
|
||||
<div class="block">Defines if paused.</div>""",
|
||||
"""
|
||||
<div class="block">Defines the direction/speed at which the <code>Timeline</code> is expected to
|
||||
be played.</div>""",
|
||||
"""
|
||||
Methods inherited from class <a href="C.html#method-summary" title="class in pkg1">C</a>""",
|
||||
"""
|
||||
<div class="block">Gets the value of the <code>rate</code> property.</div>""",
|
||||
"""
|
||||
<div class="block">Gets the value of the <code>paused</code> property.</div>""",
|
||||
"""
|
||||
<div class="block">Defines if paused.</div>""",
|
||||
"""
|
||||
<div class="block">Defines the direction/speed at which the <code>Timeline</code> is expected to
|
||||
be played.</div>""",
|
||||
"""
|
||||
<div class="block">Sets the value of the <code>paused</code> property.</div>""",
|
||||
"""
|
||||
<div class="block">Sets the value of the <code>rate</code> property.</div>""");
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
27
test/langtools/jdk/javadoc/doclet/testJavaFX/pkg1/B.java
Normal file
27
test/langtools/jdk/javadoc/doclet/testJavaFX/pkg1/B.java
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2025, 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.
|
||||
*/
|
||||
|
||||
package pkg1;
|
||||
|
||||
public class B extends C {
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user