8261079: Fix support for @hidden in classes and interfaces

Reviewed-by: jjg
This commit is contained in:
Hannes Wallnöfer 2021-02-12 09:26:42 +00:00
parent 9c0ec8d848
commit 3210095a17
16 changed files with 404 additions and 133 deletions

@ -265,7 +265,7 @@ public class HtmlConfiguration extends BaseConfiguration {
}
docPaths = new DocPaths(utils);
setCreateOverview();
setTopFile(docEnv);
setTopFile();
initDocLint(options.doclintOpts(), tagletManager.getAllTagletNames());
return true;
}
@ -277,11 +277,9 @@ public class HtmlConfiguration extends BaseConfiguration {
* "package-summary.html" of the respective package if there is only one
* package to document. It will be a class page(first in the sorted order),
* if only classes are provided on the command line.
*
* @param docEnv the doclet environment
*/
protected void setTopFile(DocletEnvironment docEnv) {
if (!checkForDeprecation(docEnv)) {
protected void setTopFile() {
if (!checkForDeprecation()) {
return;
}
if (options.createOverview()) {
@ -313,7 +311,7 @@ public class HtmlConfiguration extends BaseConfiguration {
return null;
}
protected boolean checkForDeprecation(DocletEnvironment docEnv) {
protected boolean checkForDeprecation() {
for (TypeElement te : getIncludedTypeElements()) {
if (isGeneratedDoc(te)) {
return true;

@ -313,7 +313,7 @@ public class HtmlDocletWriter {
// printed. If no overridden or implementation info needs to be
// printed, do not print this section.
if ((!intfacs.isEmpty()
&& vmt.getImplementedMethods(method).isEmpty() == false)
&& !vmt.getImplementedMethods(method).isEmpty())
|| overriddenMethod != null) {
MethodWriterImpl.addImplementsInfo(this, method, dl);
if (overriddenMethod != null) {
@ -806,13 +806,6 @@ public class HtmlDocletWriter {
return null;
}
public boolean isClassLinkable(TypeElement typeElement) {
if (utils.isIncluded(typeElement)) {
return configuration.isGeneratedDoc(typeElement);
}
return configuration.extern.isExternal(typeElement);
}
public DocLink getCrossPackageLink(PackageElement element) {
return configuration.extern.getExternalLink(element, pathToRoot,
DocPaths.PACKAGE_SUMMARY.getPath());

@ -105,7 +105,7 @@ public class HtmlLinkFactory extends LinkFactory {
Content link = new ContentBuilder();
if (utils.isIncluded(typeElement)) {
if (configuration.isGeneratedDoc(typeElement)) {
if (configuration.isGeneratedDoc(typeElement) && !utils.hasHiddenTag(typeElement)) {
DocPath filename = getPath(classLinkInfo);
if (linkInfo.linkToSelf ||
!(docPaths.forName(typeElement)).equals(m_writer.filename)) {

@ -149,20 +149,22 @@ public class MethodWriterImpl extends AbstractExecutableMemberWriter
utils.isLinkable(holder))) {
writer.addInlineComment(method, methodDocTree);
} else {
Content link =
writer.getDocLink(HtmlLinkInfo.Kind.EXECUTABLE_ELEMENT_COPY,
holder, method,
utils.isIncluded(holder)
? utils.getSimpleName(holder)
: utils.getFullyQualifiedName(holder));
Content codeLink = HtmlTree.CODE(link);
Content descfrmLabel = HtmlTree.SPAN(HtmlStyle.descfrmTypeLabel,
utils.isClass(holder)
? contents.descfrmClassLabel
: contents.descfrmInterfaceLabel);
descfrmLabel.add(Entity.NO_BREAK_SPACE);
descfrmLabel.add(codeLink);
methodDocTree.add(HtmlTree.DIV(HtmlStyle.block, descfrmLabel));
if (!utils.hasHiddenTag(holder) && !utils.hasHiddenTag(method)) {
Content link =
writer.getDocLink(HtmlLinkInfo.Kind.EXECUTABLE_ELEMENT_COPY,
holder, method,
utils.isIncluded(holder)
? utils.getSimpleName(holder)
: utils.getFullyQualifiedName(holder));
Content codeLink = HtmlTree.CODE(link);
Content descfrmLabel = HtmlTree.SPAN(HtmlStyle.descfrmTypeLabel,
utils.isClass(holder)
? contents.descfrmClassLabel
: contents.descfrmInterfaceLabel);
descfrmLabel.add(Entity.NO_BREAK_SPACE);
descfrmLabel.add(codeLink);
methodDocTree.add(HtmlTree.DIV(HtmlStyle.block, descfrmLabel));
}
writer.addInlineComment(method, methodDocTree);
}
}
@ -265,36 +267,37 @@ public class MethodWriterImpl extends AbstractExecutableMemberWriter
//is not visible so don't document this.
return;
}
if (method != null) {
Contents contents = writer.contents;
Content label;
HtmlLinkInfo.Kind context;
if (utils.isAbstract(holder) && utils.isAbstract(method)){
//Abstract method is implemented from abstract class,
//not overridden
label = contents.specifiedByLabel;
context = HtmlLinkInfo.Kind.METHOD_SPECIFIED_BY;
} else {
label = contents.overridesLabel;
context = HtmlLinkInfo.Kind.METHOD_OVERRIDES;
}
dl.add(HtmlTree.DT(label));
Content overriddenTypeLink =
writer.getLink(new HtmlLinkInfo(writer.configuration, context, overriddenType));
Content codeOverriddenTypeLink = HtmlTree.CODE(overriddenTypeLink);
Content methlink = writer.getLink(
new HtmlLinkInfo(writer.configuration, HtmlLinkInfo.Kind.MEMBER, holder)
.where(writer.htmlIds.forMember(method).name())
.label(method.getSimpleName()));
Content codeMethLink = HtmlTree.CODE(methlink);
Content dd = HtmlTree.DD(codeMethLink);
dd.add(Entity.NO_BREAK_SPACE);
dd.add(contents.inClass);
dd.add(Entity.NO_BREAK_SPACE);
dd.add(codeOverriddenTypeLink);
dl.add(dd);
if (utils.hasHiddenTag(holder) || utils.hasHiddenTag(method)) {
return;
}
Contents contents = writer.contents;
Content label;
HtmlLinkInfo.Kind context;
if (utils.isAbstract(holder) && utils.isAbstract(method)) {
//Abstract method is implemented from abstract class,
//not overridden
label = contents.specifiedByLabel;
context = HtmlLinkInfo.Kind.METHOD_SPECIFIED_BY;
} else {
label = contents.overridesLabel;
context = HtmlLinkInfo.Kind.METHOD_OVERRIDES;
}
dl.add(HtmlTree.DT(label));
Content overriddenTypeLink =
writer.getLink(new HtmlLinkInfo(writer.configuration, context, overriddenType));
Content codeOverriddenTypeLink = HtmlTree.CODE(overriddenTypeLink);
Content methlink = writer.getLink(
new HtmlLinkInfo(writer.configuration, HtmlLinkInfo.Kind.MEMBER, holder)
.where(writer.htmlIds.forMember(method).name())
.label(method.getSimpleName()));
Content codeMethLink = HtmlTree.CODE(methlink);
Content dd = HtmlTree.DD(codeMethLink);
dd.add(Entity.NO_BREAK_SPACE);
dd.add(contents.inClass);
dd.add(Entity.NO_BREAK_SPACE);
dd.add(codeOverriddenTypeLink);
dl.add(dd);
}
/**

@ -111,19 +111,21 @@ public class PropertyWriterImpl extends AbstractMemberWriter
(!utils.isPublic(holder) || utils.isLinkable(holder))) {
writer.addInlineComment(property, propertyDocTree);
} else {
Content link =
writer.getDocLink(HtmlLinkInfo.Kind.PROPERTY_COPY,
holder, property,
utils.isIncluded(holder)
? holder.getSimpleName() : holder.getQualifiedName());
Content codeLink = HtmlTree.CODE(link);
Content descfrmLabel = HtmlTree.SPAN(HtmlStyle.descfrmTypeLabel,
utils.isClass(holder)
? contents.descfrmClassLabel
: contents.descfrmInterfaceLabel);
descfrmLabel.add(Entity.NO_BREAK_SPACE);
descfrmLabel.add(codeLink);
propertyDocTree.add(HtmlTree.DIV(HtmlStyle.block, descfrmLabel));
if (!utils.hasHiddenTag(holder) && !utils.hasHiddenTag(property)) {
Content link =
writer.getDocLink(HtmlLinkInfo.Kind.PROPERTY_COPY,
holder, property,
utils.isIncluded(holder)
? holder.getSimpleName() : holder.getQualifiedName());
Content codeLink = HtmlTree.CODE(link);
Content descfrmLabel = HtmlTree.SPAN(HtmlStyle.descfrmTypeLabel,
utils.isClass(holder)
? contents.descfrmClassLabel
: contents.descfrmInterfaceLabel);
descfrmLabel.add(Entity.NO_BREAK_SPACE);
descfrmLabel.add(codeLink);
propertyDocTree.add(HtmlTree.DIV(HtmlStyle.block, descfrmLabel));
}
writer.addInlineComment(property, propertyDocTree);
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 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
@ -137,7 +137,8 @@ public class SerializedFormWriterImpl extends SubWriterHolderWriter
* @return true if the class, that is being processed, is generated and is visible.
*/
public boolean isVisibleClass(TypeElement typeElement) {
return visibleClasses.contains(typeElement) && configuration.isGeneratedDoc(typeElement);
return visibleClasses.contains(typeElement) && configuration.isGeneratedDoc(typeElement)
&& !utils.hasHiddenTag(typeElement);
}
/**

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 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
@ -409,6 +409,9 @@ public abstract class MemberSummaryBuilder extends AbstractMemberBuilder {
if (inheritedClass == typeElement) {
continue;
}
if (utils.hasHiddenTag(inheritedClass)) {
continue;
}
List<Element> members = inheritedMembersFromMap.stream()
.filter(e -> utils.getEnclosingTypeElement(e) == inheritedClass)

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 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
@ -552,10 +552,8 @@ public class SerializedFormBuilder extends AbstractBuilder {
if (utils.isSerializable(te)) {
if (utils.hasDocCommentTree(te) && !utils.getSerialTrees(te).isEmpty()) {
return serialDocInclude(utils, te);
} else if (utils.isPublic(te) || utils.isProtected(te)) {
return true;
} else {
return false;
return utils.isPublic(te) || utils.isProtected(te);
}
}
return false;

@ -609,7 +609,8 @@ public class Utils {
}
public boolean isUndocumentedEnclosure(TypeElement enclosingTypeElement) {
return (isPackagePrivate(enclosingTypeElement) || isPrivate(enclosingTypeElement))
return (isPackagePrivate(enclosingTypeElement) || isPrivate(enclosingTypeElement)
|| hasHiddenTag(enclosingTypeElement))
&& !isLinkable(enclosingTypeElement);
}
@ -1157,10 +1158,11 @@ public class Utils {
*/
public boolean isLinkable(TypeElement typeElem) {
return
(typeElem != null &&
(isIncluded(typeElem) && configuration.isGeneratedDoc(typeElem))) ||
typeElem != null &&
((isIncluded(typeElem) && configuration.isGeneratedDoc(typeElem) &&
!hasHiddenTag(typeElem)) ||
(configuration.extern.isExternal(typeElem) &&
(isPublic(typeElem) || isProtected(typeElem)));
(isPublic(typeElem) || isProtected(typeElem))));
}
/**
@ -1183,7 +1185,7 @@ public class Utils {
return isLinkable((TypeElement) elem); // defer to existing behavior
}
if (isIncluded(elem)) {
if (isIncluded(elem) && !hasHiddenTag(elem)) {
return true;
}
@ -1553,16 +1555,17 @@ public class Utils {
}
/**
* Returns true if the element is included, contains &#64;hidden tag,
* Returns true if the element is included or selected, contains &#64;hidden tag,
* or if javafx flag is present and element contains &#64;treatAsPrivate
* tag.
* @param e the queried element
* @return true if it exists, false otherwise
*/
public boolean hasHiddenTag(Element e) {
// prevent needless tests on elements which are not included
// Non-included elements may still be visible via "transclusion" from undocumented enclosures,
// but we don't want to run doclint on them, possibly causing warnings or errors.
if (!isIncluded(e)) {
return false;
return hasBlockTagUnchecked(e, HIDDEN);
}
if (options.javafx() &&
hasBlockTag(e, DocTree.Kind.UNKNOWN_BLOCK_TAG, "treatAsPrivate")) {
@ -2265,12 +2268,14 @@ public class Utils {
}
public TypeElement getEnclosingTypeElement(Element e) {
if (e.getKind() == ElementKind.PACKAGE)
if (isPackage(e) || isModule(e)) {
return null;
}
Element encl = e.getEnclosingElement();
ElementKind kind = encl.getKind();
if (kind == ElementKind.PACKAGE)
if (isPackage(encl)) {
return null;
}
ElementKind kind = encl.getKind();
while (!(kind.isClass() || kind.isInterface())) {
encl = encl.getEnclosingElement();
kind = encl.getKind();
@ -2591,7 +2596,10 @@ public class Utils {
}
public List<? extends DocTree> getBlockTags(Element element) {
DocCommentTree dcTree = getDocCommentTree(element);
return getBlockTags(getDocCommentTree(element));
}
public List<? extends DocTree> getBlockTags(DocCommentTree dcTree) {
return dcTree == null ? Collections.emptyList() : dcTree.getBlockTags();
}
@ -2641,14 +2649,26 @@ public class Utils {
public boolean hasBlockTag(Element element, DocTree.Kind kind, final String tagName) {
if (hasDocCommentTree(element)) {
CommentHelper ch = getCommentHelper(element);
String tname = tagName != null && tagName.startsWith("@")
? tagName.substring(1)
: tagName;
for (DocTree dt : getBlockTags(element, kind)) {
for (DocTree dt : getBlockTags(ch.dcTree)) {
if (dt.getKind() == kind && (tagName == null || ch.getTagName(dt).equals(tagName))) {
return true;
}
}
}
return false;
}
/*
* Tests whether an element's doc comment contains a block tag without caching it or
* running doclint on it. This is done by using getDocCommentInfo(Element) to retrieve
* the doc comment info.
*/
boolean hasBlockTagUnchecked(Element element, DocTree.Kind kind) {
DocCommentInfo dcInfo = getDocCommentInfo(element);
if (dcInfo != null && dcInfo.dcTree != null) {
for (DocTree dt : getBlockTags(dcInfo.dcTree)) {
if (dt.getKind() == kind) {
if (tname == null || ch.getTagName(dt).equals(tname)) {
return true;
}
return true;
}
}
}
@ -2701,7 +2721,7 @@ public class Utils {
/**
* Retrieves the doc comments for a given element.
* @param element
* @param element the element
* @return DocCommentTree for the Element
*/
public DocCommentTree getDocCommentTree0(Element element) {
@ -2759,7 +2779,7 @@ public class Utils {
private DocCommentInfo getDocCommentInfo0(Element element) {
// prevent nasty things downstream with overview element
if (element.getKind() != ElementKind.OTHER) {
if (!isOverviewElement(element)) {
TreePath path = getTreePath(element);
if (path != null) {
DocCommentTree docCommentTree = docTrees.getDocCommentTree(path);

@ -126,7 +126,7 @@ public class VisibleMemberTable {
private Map<ExecutableElement, PropertyMembers> propertyMap = new HashMap<>();
// Keeps track of method overrides
Map<ExecutableElement, OverridingMethodInfo> overriddenMethodTable
Map<ExecutableElement, OverriddenMethodInfo> overriddenMethodTable
= new LinkedHashMap<>();
protected VisibleMemberTable(TypeElement typeElement, BaseConfiguration configuration,
@ -240,10 +240,10 @@ public class VisibleMemberTable {
public ExecutableElement getOverriddenMethod(ExecutableElement e) {
ensureInitialized();
OverridingMethodInfo found = overriddenMethodTable.get(e);
OverriddenMethodInfo found = overriddenMethodTable.get(e);
if (found != null
&& (found.simpleOverride || utils.isUndocumentedEnclosure(utils.getEnclosingTypeElement(e)))) {
return found.overrider;
return found.overridden;
}
return null;
}
@ -256,9 +256,9 @@ public class VisibleMemberTable {
public ExecutableElement getSimplyOverriddenMethod(ExecutableElement e) {
ensureInitialized();
OverridingMethodInfo found = overriddenMethodTable.get(e);
OverriddenMethodInfo found = overriddenMethodTable.get(e);
if (found != null && found.simpleOverride) {
return found.overrider;
return found.overridden;
}
return null;
}
@ -475,9 +475,9 @@ public class VisibleMemberTable {
for (VisibleMemberTable pvmt : parents) {
// Merge the lineage overrides into local table
pvmt.overriddenMethodTable.entrySet().forEach(e -> {
OverridingMethodInfo p = e.getValue();
OverriddenMethodInfo p = e.getValue();
if (!p.simpleOverride) { // consider only real overrides
List<ExecutableElement> list = overriddenByTable.computeIfAbsent(p.overrider,
List<ExecutableElement> list = overriddenByTable.computeIfAbsent(p.overridden,
k -> new ArrayList<>());
list.add(e.getKey());
}
@ -486,19 +486,19 @@ public class VisibleMemberTable {
}
// Filter out inherited methods that:
// a. cannot override (private instance members)
// a. cannot be overridden (private instance members)
// b. are overridden and should not be visible in this type
// c. are hidden in the type being considered
// see allowInheritedMethods, which performs the above actions
// see allowInheritedMethod, which performs the above actions
List<Element> list = inheritedMethods.stream()
.filter(e -> allowInheritedMethods((ExecutableElement) e, overriddenByTable, lmt))
.filter(e -> allowInheritedMethod((ExecutableElement) e, overriddenByTable, lmt))
.collect(Collectors.toList());
// Filter out the local methods, that do not override or simply
// overrides a super method, or those methods that should not
// be visible.
Predicate<ExecutableElement> isVisible = m -> {
OverridingMethodInfo p = overriddenMethodTable.getOrDefault(m, null);
OverriddenMethodInfo p = overriddenMethodTable.getOrDefault(m, null);
return p == null || !p.simpleOverride;
};
List<Element> localList = lmt.getOrderedMembers(Kind.METHODS)
@ -529,9 +529,9 @@ public class VisibleMemberTable {
return utils.isInterface(enclosing);
}
boolean allowInheritedMethods(ExecutableElement inheritedMethod,
Map<ExecutableElement, List<ExecutableElement>> inheritedOverriddenTable,
LocalMemberTable lmt) {
boolean allowInheritedMethod(ExecutableElement inheritedMethod,
Map<ExecutableElement, List<ExecutableElement>> overriddenByTable,
LocalMemberTable lmt) {
if (!isInherited(inheritedMethod))
return false;
@ -552,7 +552,7 @@ public class VisibleMemberTable {
// in favor of concrete overriding methods, for instance those that have
// API documentation and are not abstract OR default methods.
if (inInterface) {
List<ExecutableElement> list = inheritedOverriddenTable.get(inheritedMethod);
List<ExecutableElement> list = overriddenByTable.get(inheritedMethod);
if (list != null) {
boolean found = list.stream()
.anyMatch(this::isEnclosureInterface);
@ -586,16 +586,19 @@ public class VisibleMemberTable {
TypeElement encl = utils.getEnclosingTypeElement(inheritedMethod);
if (utils.isUndocumentedEnclosure(encl)) {
overriddenMethodTable.computeIfAbsent(lMethod,
l -> new OverridingMethodInfo(inheritedMethod, false));
l -> new OverriddenMethodInfo(inheritedMethod, false));
return false;
}
// Even with --override-methods=summary we want to include details of
// overriding method if something noteworthy has been added or changed.
// overriding method if something noteworthy has been added or changed
// either in the local overriding method or an in-between overriding method
// (as evidenced by an entry in overriddenByTable).
boolean simpleOverride = utils.isSimpleOverride(lMethod)
&& !overridingSignatureChanged(lMethod, inheritedMethod);
&& !overridingSignatureChanged(lMethod, inheritedMethod)
&& !overriddenByTable.containsKey(inheritedMethod);
overriddenMethodTable.computeIfAbsent(lMethod,
l -> new OverridingMethodInfo(inheritedMethod, simpleOverride));
l -> new OverriddenMethodInfo(inheritedMethod, simpleOverride));
return simpleOverride;
}
}
@ -1031,21 +1034,21 @@ public class VisibleMemberTable {
}
/**
* A simple container to encapsulate an overriding method
* A simple container to encapsulate an overridden method
* and the type of override.
*/
static class OverridingMethodInfo {
final ExecutableElement overrider;
static class OverriddenMethodInfo {
final ExecutableElement overridden;
final boolean simpleOverride;
public OverridingMethodInfo(ExecutableElement overrider, boolean simpleOverride) {
this.overrider = overrider;
public OverriddenMethodInfo(ExecutableElement overridden, boolean simpleOverride) {
this.overridden = overridden;
this.simpleOverride = simpleOverride;
}
@Override
public String toString() {
return "OverridingMethodInfo[" + overrider + ",simple:" + simpleOverride + "]";
return "OverriddenMethodInfo[" + overridden + ",simple:" + simpleOverride + "]";
}
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 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
@ -23,7 +23,7 @@
/*
* @test
* @bug 8073100 8182765 8196202
* @bug 8073100 8182765 8196202 8261079
* @summary ensure the hidden tag works as intended
* @library ../../lib
* @modules jdk.javadoc/jdk.javadoc.internal.tool
@ -63,9 +63,8 @@ public class TestHiddenTag extends JavadocTester {
n pkg1">A.VisibleInnerExtendsInvisibleInner</a></code></dd>""");
checkOutput("pkg1/A.html", false,
"<h3 id=\"inVisibleField\">",
"""
<h3><span id="inVisibleMethod()">""");
"invisibleField",
"invisibleMethod()");
checkOutput("pkg1/A.VisibleInner.html", true,
"""
@ -82,8 +81,8 @@ public class TestHiddenTag extends JavadocTester {
checkOutput("pkg1/A.VisibleInner.html", false,
"../pkg1/A.VisibleInner.html#VisibleInner()",
"<a id=\"inVisibleField\">",
"<a id=\"inVisibleMethod()\">");
"invisibleField",
"invisibleMethod()");
checkOutput("pkg1/A.VisibleInnerExtendsInvisibleInner.html", true,
"""
@ -100,12 +99,63 @@ public class TestHiddenTag extends JavadocTester {
"invisibleMethod",
"A.InvisibleInner");
checkOutput("pkg1/Intf.html", true,
"""
<section class="detail" id="visibleDefaultMethod()">""",
"""
<section class="detail" id="visibleInterfaceMethod()">""",
"""
<dt>All Known Implementing Classes:</dt>
<dd><code><a href="Child.html" title="class in pkg1">Child</a></code></dd>
</dl>""");
checkOutput("pkg1/Intf.html", false,
"InvisibleParent",
"invisibleDefaultMethod",
"invisibleInterfaceMethod");
checkOutput("pkg1/Child.html", true,
"""
<a href="InvisibleParent.VisibleInner.html" class="type-name-link" title="class \
in pkg1">InvisibleParent.VisibleInner</a>""",
"""
<a href="#visibleField" class="member-name-link">visibleField</a>""",
"""
<a href="#invisibleInterfaceMethod()" class="member-name-link">invisibleInterfaceMethod</a>""",
"""
<a href="#visibleInterfaceMethod()" class="member-name-link">visibleInterfaceMethod</a>""",
"""
<a href="#visibleMethod(pkg1.InvisibleParent)" class="member-name-link">visibleMethod</a>""",
"""
<a href="Intf.html#visibleDefaultMethod()">visibleDefaultMethod</a>""",
// Invisible return or parameter types must not be linked
"""
<span class="return-type">pkg1.InvisibleParent</span>""",
"""
<span class="parameters">(pkg1.InvisibleParent&lt;? extends pkg1.InvisibleParent&gt;&nbsp;p)</span>""");
checkOutput("pkg1/Child.html", false,
"InvisibleParent.InvisibleInner",
"invisibleField",
"invisibleMethod",
"invisibleDefaultMethod");
checkOutput("pkg1/InvisibleParent.VisibleInner.html", true,
"""
<dt>Enclosing class:</dt>
<dd>pkg1.InvisibleParent&lt;T extends pkg1.InvisibleParent&gt;</dd>
</dl>""");
checkOutput("pkg1/package-summary.html", false, "A.InvisibleInner");
checkOutput("pkg1/package-tree.html", false, "A.InvisibleInner");
checkOutput("pkg1/package-tree.html", false, "InvisibleParent.html");
checkFiles(false,
"pkg1/A.InvisibleInner.html",
"pkg1/A.InvisibleInnerExtendsVisibleInner.html");
"pkg1/A.InvisibleInnerExtendsVisibleInner.html",
"pkg1/InvisibleParent.html",
"pkg1/InvisibleParent.InvisibleInner.html");
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 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

@ -0,0 +1,33 @@
/*
* 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.
*/
package pkg1;
import pkg2.UndocumentedParent;
/**
* A visible class, extending invisible classes.
*/
public class Child extends UndocumentedParent<Child> {
}

@ -0,0 +1,53 @@
/*
* 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.
*/
package pkg1;
/**
* An visible interface
*/
public interface Intf {
/**
* A visible interface method.
*/
void visibleInterfaceMethod();
/**
* An invisible interface method.
* @hidden
*/
void invisibleInterfaceMethod();
/**
* A visible default method.
*/
default void visibleDefaultMethod() {}
/**
* An invisible default method.
* @hidden
*/
default void invisibleDefaultMethod() {}
}

@ -0,0 +1,58 @@
/*
* 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.
*/
package pkg1;
/**
* @hidden
* @param <T>
*/
public abstract class InvisibleParent<T extends InvisibleParent> implements Intf {
@Override
public void visibleInterfaceMethod() {}
/**
* An invisible method made visible in an implementing class.
*/
@Override
public void invisibleInterfaceMethod() {}
/**
* A visible inner class.
*/
public static class VisibleInner {
/**
* An invisible constructor
* @hidden invisible
*/
public VisibleInner() {}
}
/**
* An invisible inner class.
* @hidden
*/
public static class InvisibleInner {}
}

@ -0,0 +1,56 @@
/*
* 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.
*/
package pkg2;
import pkg1.InvisibleParent;
/**
* @hidden
* @param <T>
*/
public class UndocumentedParent<T extends InvisibleParent> extends InvisibleParent<T> {
/**
* A visible field.
*/
public InvisibleParent visibleField;
/**
* An invisible field.
* @hidden
*/
public InvisibleParent invisibleField;
/**
* A visible method with an invisible parameter type.
*/
public void visibleMethod(InvisibleParent<? extends InvisibleParent> p) {}
/**
* An invisible method.
* @hidden
*/
public void invisibleMethod() {}
}