8050031: [javadoc] class-use pages have duplicates and missing entries

Reviewed-by: jjg
This commit is contained in:
Kumar Srinivasan 2014-08-27 06:56:29 -07:00
parent 6abfd1ee2d
commit 5f800435e3
11 changed files with 296 additions and 107 deletions

View File

@ -82,10 +82,9 @@ public abstract class AbstractTreeWriter extends HtmlDocletWriter {
* @param isEnum true if we are generating a tree for enums
* @param contentTree the content tree to which the level information will be added
*/
protected void addLevelInfo(ClassDoc parent, List<ClassDoc> list,
protected void addLevelInfo(ClassDoc parent, Collection<ClassDoc> list,
boolean isEnum, Content contentTree) {
int size = list.size();
if (size > 0) {
if (!list.isEmpty()) {
Content ul = new HtmlTree(HtmlTag.UL);
for (ClassDoc local : list) {
HtmlTree li = new HtmlTree(HtmlTag.LI);
@ -109,9 +108,9 @@ public abstract class AbstractTreeWriter extends HtmlDocletWriter {
* @param heading heading for the tree
* @param div the content tree to which the tree will be added
*/
protected void addTree(List<ClassDoc> list, String heading, Content div) {
if (list.size() > 0) {
ClassDoc firstClassDoc = list.get(0);
protected void addTree(SortedSet<ClassDoc> list, String heading, Content div) {
if (!list.isEmpty()) {
ClassDoc firstClassDoc = list.first();
Content headingContent = getResource(heading);
div.addContent(HtmlTree.HEADING(HtmlConstants.CONTENT_HEADING, true,
headingContent));

View File

@ -158,7 +158,7 @@ public class ClassUseWriter extends SubWriterHolderWriter {
*/
public static void generate(ConfigurationImpl configuration,
ClassTree classtree) {
ClassUseMapper mapper = new ClassUseMapper(configuration.root, classtree);
ClassUseMapper mapper = new ClassUseMapper(configuration, classtree);
for (ClassDoc aClass : configuration.root.classes()) {
// If -nodeprecated option is set and the containing package is marked
// as deprecated, do not generate the class-use page. We will still generate

View File

@ -411,8 +411,8 @@ public class ClassWriterImpl extends SubWriterHolderWriter
classDoc.qualifiedName().equals("org.omg.CORBA.Object")) {
return; // Don't generate the list, too huge
}
List<ClassDoc> subclasses = classtree.subs(classDoc, false);
if (subclasses.size() > 0) {
SortedSet<ClassDoc> subclasses = classtree.subs(classDoc, false);
if (!subclasses.isEmpty()) {
Content label = getResource(
"doclet.Subclasses");
Content dt = HtmlTree.DT(label);
@ -429,8 +429,8 @@ public class ClassWriterImpl extends SubWriterHolderWriter
*/
public void addSubInterfacesInfo(Content classInfoTree) {
if (classDoc.isInterface()) {
List<ClassDoc> subInterfaces = classtree.allSubs(classDoc, false);
if (subInterfaces.size() > 0) {
SortedSet<ClassDoc> subInterfaces = classtree.allSubs(classDoc, false);
if (!subInterfaces.isEmpty()) {
Content label = getResource(
"doclet.Subinterfaces");
Content dt = HtmlTree.DT(label);
@ -453,8 +453,8 @@ public class ClassWriterImpl extends SubWriterHolderWriter
classDoc.qualifiedName().equals("java.io.Serializable")) {
return; // Don't generate the list, too big
}
List<ClassDoc> implcl = classtree.implementingclasses(classDoc);
if (implcl.size() > 0) {
SortedSet<ClassDoc> implcl = classtree.implementingclasses(classDoc);
if (!implcl.isEmpty()) {
Content label = getResource(
"doclet.Implementing_Classes");
Content dt = HtmlTree.DT(label);
@ -580,21 +580,23 @@ public class ClassWriterImpl extends SubWriterHolderWriter
* @param list the list of classes
* @return a content tree for the class list
*/
private Content getClassLinks(LinkInfoImpl.Kind context, List<?> list) {
private Content getClassLinks(LinkInfoImpl.Kind context, Collection<?> list) {
Object[] typeList = list.toArray();
Content dd = new HtmlTree(HtmlTag.DD);
for (int i = 0; i < list.size(); i++) {
if (i > 0) {
boolean isFirst = true;
for (Object item : typeList) {
if (!isFirst) {
Content separator = new StringContent(", ");
dd.addContent(separator);
} else {
isFirst = false;
}
if (typeList[i] instanceof ClassDoc) {
Content link = getLink(
new LinkInfoImpl(configuration, context, (ClassDoc)(typeList[i])));
if (item instanceof ClassDoc) {
Content link = getLink(new LinkInfoImpl(configuration, context, (ClassDoc)item));
dd.addContent(link);
} else {
Content link = getLink(
new LinkInfoImpl(configuration, context, (Type)(typeList[i])));
Content link = getLink(new LinkInfoImpl(configuration, context, (Type)item));
dd.addContent(link);
}
}

View File

@ -51,38 +51,39 @@ public class ClassTree {
* List of baseclasses. Contains only java.lang.Object. Can be used to get
* the mapped listing of sub-classes.
*/
private List<ClassDoc> baseclasses = new ArrayList<>();
final private SortedSet<ClassDoc> baseclasses;
/**
* Mapping for each Class with their SubClasses
*/
private Map<ClassDoc,List<ClassDoc>> subclasses = new HashMap<>();
final private Map<ClassDoc, SortedSet<ClassDoc>> subclasses = new HashMap<>();
/**
* List of base-interfaces. Contains list of all the interfaces who do not
* have super-interfaces. Can be used to get the mapped listing of
* sub-interfaces.
*/
private List<ClassDoc> baseinterfaces = new ArrayList<>();
final private SortedSet<ClassDoc> baseinterfaces;
/**
* Mapping for each Interface with their SubInterfaces
*/
private Map<ClassDoc,List<ClassDoc>> subinterfaces = new HashMap<>();
final private Map<ClassDoc, SortedSet<ClassDoc>> subinterfaces = new HashMap<>();
private List<ClassDoc> baseEnums = new ArrayList<>();
private Map<ClassDoc,List<ClassDoc>> subEnums = new HashMap<>();
final private SortedSet<ClassDoc> baseEnums;
final private Map<ClassDoc, SortedSet<ClassDoc>> subEnums = new HashMap<>();
private List<ClassDoc> baseAnnotationTypes = new ArrayList<>();
private Map<ClassDoc,List<ClassDoc>> subAnnotationTypes = new HashMap<>();
final private SortedSet<ClassDoc> baseAnnotationTypes;
final private Map<ClassDoc, SortedSet<ClassDoc>> subAnnotationTypes = new HashMap<>();
/**
* Mapping for each Interface with classes who implement it.
*/
private Map<ClassDoc,List<ClassDoc>> implementingclasses = new HashMap<>();
final private Map<ClassDoc, SortedSet<ClassDoc>> implementingclasses = new HashMap<>();
private final Configuration configuration;
private final Utils utils;
private final Comparator<Doc> comparator;
/**
* Constructor. Build the Tree using the Root of this Javadoc run.
*
@ -94,7 +95,13 @@ public class ClassTree {
configuration.message.notice("doclet.Building_Tree");
this.configuration = configuration;
this.utils = configuration.utils;
comparator = utils.makeGeneralPurposeComparator();
baseAnnotationTypes = new TreeSet<>(comparator);
baseEnums = new TreeSet<>(comparator);
baseclasses = new TreeSet<>(comparator);
baseinterfaces = new TreeSet<>(comparator);
buildTree(configuration.root.classes());
}
/**
@ -106,6 +113,11 @@ public class ClassTree {
public ClassTree(RootDoc root, Configuration configuration) {
this.configuration = configuration;
this.utils = configuration.utils;
comparator = utils.makeGeneralPurposeComparator();
baseAnnotationTypes = new TreeSet<>(comparator);
baseEnums = new TreeSet<>(comparator);
baseclasses = new TreeSet<>(comparator);
baseinterfaces = new TreeSet<>(comparator);
buildTree(root.classes());
}
@ -113,11 +125,16 @@ public class ClassTree {
* Constructor. Build the tree for the given array of classes.
*
* @param classes Array of classes.
* @param configuration The curren configuration of the doclet.
* @param configuration The current configuration of the doclet.
*/
public ClassTree(ClassDoc[] classes, Configuration configuration) {
this.configuration = configuration;
this.utils = configuration.utils;
comparator = utils.makeGeneralPurposeComparator();
baseAnnotationTypes = new TreeSet<>(comparator);
baseEnums = new TreeSet<>(comparator);
baseclasses = new TreeSet<>(comparator);
baseinterfaces = new TreeSet<>(comparator);
buildTree(classes);
}
@ -152,23 +169,11 @@ public class ClassTree {
processType(aClass, configuration, baseclasses, subclasses);
} else if (aClass.isInterface()) {
processInterface(aClass);
List<ClassDoc> list = implementingclasses.get(aClass);
if (list != null) {
Collections.sort(list);
}
} else if (aClass.isAnnotationType()) {
processType(aClass, configuration, baseAnnotationTypes,
subAnnotationTypes);
}
}
Collections.sort(baseinterfaces);
for (List<ClassDoc> docs : subinterfaces.values()) {
Collections.sort(docs);
}
for (List<ClassDoc> docs : subclasses.values()) {
Collections.sort(docs);
}
}
/**
@ -184,7 +189,7 @@ public class ClassTree {
* @param configuration the current configurtation of the doclet.
*/
private void processType(ClassDoc cd, Configuration configuration,
List<ClassDoc> bases, Map<ClassDoc,List<ClassDoc>> subs) {
Collection<ClassDoc> bases, Map<ClassDoc, SortedSet<ClassDoc>> subs) {
ClassDoc superclass = utils.getFirstVisibleSuperClassCD(cd, configuration);
if (superclass != null) {
if (!add(subs, superclass, cd)) {
@ -239,10 +244,10 @@ public class ClassTree {
* @param cd sub-interface to be mapped.
* @returns boolean true if class added, false if class already processed.
*/
private boolean add(Map<ClassDoc,List<ClassDoc>> map, ClassDoc superclass, ClassDoc cd) {
List<ClassDoc> list = map.get(superclass);
private boolean add(Map<ClassDoc, SortedSet<ClassDoc>> map, ClassDoc superclass, ClassDoc cd) {
SortedSet<ClassDoc> list = map.get(superclass);
if (list == null) {
list = new ArrayList<>();
list = new TreeSet<>(comparator);
map.put(superclass, list);
}
if (list.contains(cd)) {
@ -261,12 +266,12 @@ public class ClassTree {
* @param cd class for which the sub-class list is requested.
* @returns List Sub-Class list for the class passed.
*/
private List<ClassDoc> get(Map<ClassDoc,List<ClassDoc>> map, ClassDoc cd) {
List<ClassDoc> list = map.get(cd);
if (list == null) {
return new ArrayList<>();
private SortedSet<ClassDoc> get(Map<ClassDoc, SortedSet<ClassDoc>> map, ClassDoc cd) {
SortedSet<ClassDoc> aset = map.get(cd);
if (aset == null) {
return new TreeSet<>(comparator);
}
return list;
return aset;
}
/**
@ -274,7 +279,7 @@ public class ClassTree {
*
* @param cd class whose sub-class list is required.
*/
public List<ClassDoc> subclasses(ClassDoc cd) {
public SortedSet<ClassDoc> subclasses(ClassDoc cd) {
return get(subclasses, cd);
}
@ -283,7 +288,7 @@ public class ClassTree {
*
* @param cd interface whose sub-interface list is required.
*/
public List<ClassDoc> subinterfaces(ClassDoc cd) {
public SortedSet<ClassDoc> subinterfaces(ClassDoc cd) {
return get(subinterfaces, cd);
}
@ -292,25 +297,23 @@ public class ClassTree {
*
* @param cd interface whose implementing-classes list is required.
*/
public List<ClassDoc> implementingclasses(ClassDoc cd) {
List<ClassDoc> result = get(implementingclasses, cd);
List<ClassDoc> subinterfaces = allSubs(cd, false);
public SortedSet<ClassDoc> implementingclasses(ClassDoc cd) {
SortedSet<ClassDoc> result = get(implementingclasses, cd);
SortedSet<ClassDoc> intfcs = allSubs(cd, false);
//If class x implements a subinterface of cd, then it follows
//that class x implements cd.
Iterator<ClassDoc> implementingClassesIter, subInterfacesIter = subinterfaces.listIterator();
ClassDoc c;
while(subInterfacesIter.hasNext()){
implementingClassesIter = implementingclasses(
subInterfacesIter.next()).listIterator();
while(implementingClassesIter.hasNext()){
c = implementingClassesIter.next();
if(! result.contains(c)){
Iterator<ClassDoc> subInterfacesIter = intfcs.iterator();
while (subInterfacesIter.hasNext()) {
Iterator<ClassDoc> implementingClassesIter
= implementingclasses(subInterfacesIter.next()).iterator();
while (implementingClassesIter.hasNext()) {
ClassDoc c = implementingClassesIter.next();
if (!result.contains(c)) {
result.add(c);
}
}
}
Collections.sort(result);
return result;
}
@ -321,7 +324,7 @@ public class ClassTree {
* @param isEnum true if the subclasses should be forced to come from the
* enum tree.
*/
public List<ClassDoc> subs(ClassDoc cd, boolean isEnum) {
public SortedSet<ClassDoc> subs(ClassDoc cd, boolean isEnum) {
if (isEnum) {
return get(subEnums, cd);
} else if (cd.isAnnotationType()) {
@ -344,19 +347,21 @@ public class ClassTree {
* @param isEnum true if the subclasses should be forced to come from the
* enum tree.
*/
public List<ClassDoc> allSubs(ClassDoc cd, boolean isEnum) {
List<ClassDoc> list = subs(cd, isEnum);
public SortedSet<ClassDoc> allSubs(ClassDoc cd, boolean isEnum) {
// new entries added to the list are searched as well
List<ClassDoc> list = new ArrayList<>(subs(cd, isEnum));
for (int i = 0; i < list.size(); i++) {
cd = list.get(i);
List<ClassDoc> tlist = subs(cd, isEnum);
SortedSet<ClassDoc> tlist = subs(cd, isEnum);
for (ClassDoc tcd : tlist) {
if (!list.contains(tcd)) {
list.add(tcd);
}
}
}
Collections.sort(list);
return list;
SortedSet<ClassDoc> oset = new TreeSet<>(comparator);
oset.addAll(list);
return oset;
}
/**
@ -364,7 +369,7 @@ public class ClassTree {
* thw classdoc for java.lang.Object, since this is the base class for all
* classes.
*/
public List<ClassDoc> baseclasses() {
public SortedSet<ClassDoc> baseclasses() {
return baseclasses;
}
@ -372,7 +377,7 @@ public class ClassTree {
* Return the list of base interfaces. This is the list of interfaces
* which do not have super-interface.
*/
public List<ClassDoc> baseinterfaces() {
public SortedSet<ClassDoc> baseinterfaces() {
return baseinterfaces;
}
@ -380,7 +385,7 @@ public class ClassTree {
* Return the list of base enums. This is the list of enums
* which do not have super-enums.
*/
public List<ClassDoc> baseEnums() {
public SortedSet<ClassDoc> baseEnums() {
return baseEnums;
}
@ -388,7 +393,7 @@ public class ClassTree {
* Return the list of base annotation types. This is the list of
* annotation types which do not have super-annotation types.
*/
public List<ClassDoc> baseAnnotationTypes() {
public SortedSet<ClassDoc> baseAnnotationTypes() {
return baseAnnotationTypes;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2014, 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
@ -28,6 +28,7 @@ package com.sun.tools.doclets.internal.toolkit.util;
import java.util.*;
import com.sun.javadoc.*;
import com.sun.tools.doclets.formats.html.ConfigurationImpl;
/**
* Map all class uses for a given class.
@ -181,10 +182,11 @@ public class ClassUseMapper {
*/
public Map<String,List<FieldDoc>> annotationToFieldDoc = new HashMap<>();
public ClassUseMapper(RootDoc root, ClassTree classtree) {
private final Utils utils;
public ClassUseMapper(ConfigurationImpl configuration, ClassTree classtree) {
RootDoc root = configuration.root;
this.classtree = classtree;
utils = configuration.utils;
// Map subclassing, subinterfacing implementing, ...
for (ClassDoc doc : classtree.baseclasses()) {
subclasses(doc);
@ -234,8 +236,8 @@ public class ClassUseMapper {
private Collection<ClassDoc> subclasses(ClassDoc cd) {
Collection<ClassDoc> ret = classToSubclass.get(cd.qualifiedName());
if (ret == null) {
ret = new TreeSet<>();
List<ClassDoc> subs = classtree.subclasses(cd);
ret = new TreeSet<>(utils.makeComparatorForClassUse());
SortedSet<ClassDoc> subs = classtree.subclasses(cd);
if (subs != null) {
ret.addAll(subs);
for (ClassDoc sub : subs) {
@ -253,8 +255,8 @@ public class ClassUseMapper {
private Collection<ClassDoc> subinterfaces(ClassDoc cd) {
Collection<ClassDoc> ret = classToSubinterface.get(cd.qualifiedName());
if (ret == null) {
ret = new TreeSet<>();
List<ClassDoc> subs = classtree.subinterfaces(cd);
ret = new TreeSet<>(utils.makeComparatorForClassUse());
SortedSet<ClassDoc> subs = classtree.subinterfaces(cd);
if (subs != null) {
ret.addAll(subs);
for (ClassDoc sub : subs) {
@ -275,8 +277,8 @@ public class ClassUseMapper {
private Collection<ClassDoc> implementingClasses(ClassDoc cd) {
Collection<ClassDoc> ret = classToImplementingClass.get(cd.qualifiedName());
if (ret == null) {
ret = new TreeSet<>();
List<ClassDoc> impl = classtree.implementingclasses(cd);
ret = new TreeSet<>(utils.makeComparatorForClassUse());
SortedSet<ClassDoc> impl = classtree.implementingclasses(cd);
if (impl != null) {
ret.addAll(impl);
for (ClassDoc anImpl : impl) {
@ -297,25 +299,26 @@ public class ClassUseMapper {
*/
private void mapExecutable(ExecutableMemberDoc em) {
boolean isConstructor = em.isConstructor();
List<Type> classArgs = new ArrayList<>();
Set<Type> classArgs = new TreeSet<>(utils.makeTypeComparator());
for (Parameter param : em.parameters()) {
Type pcd = param.type();
// primitives don't get mapped, also avoid dups
if ((!param.type().isPrimitive()) &&
!classArgs.contains(pcd) &&
!(pcd instanceof TypeVariable)) {
add(isConstructor ? classToConstructorArgs : classToMethodArgs,
pcd.asClassDoc(), em);
classArgs.add(pcd);
mapTypeParameters(isConstructor ?
classToConstructorDocArgTypeParam : classToExecMemberDocArgTypeParam,
pcd, em);
// ignore primitives and typevars, typevars are handled elsewhere
if ((!param.type().isPrimitive()) && !(pcd instanceof TypeVariable)) {
// avoid dups
if (classArgs.add(pcd)) {
add(isConstructor ? classToConstructorArgs : classToMethodArgs,
pcd.asClassDoc(), em);
mapTypeParameters(isConstructor
? classToConstructorDocArgTypeParam
: classToExecMemberDocArgTypeParam,
pcd, em);
}
}
mapAnnotations(
isConstructor ?
classToConstructorParamAnnotation :
classToExecMemberDocParamAnnotation,
mapAnnotations(isConstructor
? classToConstructorParamAnnotation
: classToExecMemberDocParamAnnotation,
param, em);
}
for (ClassDoc anException : em.thrownExceptions()) {
add(isConstructor ? classToConstructorThrows : classToMethodThrows,

View File

@ -248,15 +248,20 @@ public class Utils {
throw new DocletAbortException(exc);
}
}
/**
* Returns a TypeComparator object suitable for sorting Types.
* @return a TypeComparator objectt
*/
public Comparator<Type> makeTypeComparator() {
return new TypeComparator();
}
/**
* We want the list of types in alphabetical order. However, types are not
* comparable. We need a comparator for now.
*/
private static class TypeComparator implements Comparator<Type> {
public int compare(Type type1, Type type2) {
return type1.qualifiedTypeName().compareToIgnoreCase(
type2.qualifiedTypeName());
return compareStrings(type1.qualifiedTypeName(), type2.qualifiedTypeName());
}
}
@ -812,7 +817,15 @@ public class Utils {
collator.setStrength(caseSensitive ? Collator.TERTIARY : Collator.SECONDARY);
return collator.compare(s1, s2);
}
/**
* A simple comparator which compares simple names, then the fully qualified names
* and finally the kinds, ClassUse comparator works well for this purpose.
*
* @return a simple general purpose doc comparator
*/
public Comparator<Doc> makeGeneralPurposeComparator() {
return makeComparatorForClassUse();
}
/**
* A comparator for index file presentations, and are sorted as follows:
* 1. sort on simple names of entities

View File

@ -466,6 +466,31 @@ public abstract class JavadocTester {
}
}
/**
* Ensures that a series of strings appear only once, in the generated output,
* noting that, this test does not exhaustively check for all other possible
* duplicates once one is found.
* @param path the file to check
* @param strings ensure each are unique
*/
public void checkUnique(String path, String... strings) {
String fileString = readOutputFile(path);
for (String s : strings) {
int currentIndex = fileString.indexOf(s);
checking(s + " at index " + currentIndex);
if (currentIndex == -1) {
failed(s + " not found.");
continue;
}
int nextindex = fileString.indexOf(s, currentIndex + s.length());
if (nextindex == -1) {
passed(s + " is unique");
} else {
failed(s + " is not unique, found at " + nextindex);
}
}
}
/**
* Compare a set of files in each of two directories.
*

View File

@ -119,6 +119,8 @@ public class TestOrdering extends JavadocTester {
javadoc(cmdArgs.toArray(new String[cmdArgs.size()]));
checkExit(Exit.OK);
checkOrder("index-all.html", composeTestVectors());
checkOrder("add0/add/package-tree.html", expectedPackageTreeOrdering);
checkOrder("overview-tree.html", expectedOverviewOrdering);
}
@Test
@ -381,4 +383,44 @@ public class TestOrdering extends JavadocTester {
"add3/add/Add.html#ADDADD\"",
"add3/Add.html#ADDADD\""
};
final String expectedPackageTreeOrdering[] = {
"<a href=\"../../add0/add/Add.add.html\" title=\"enum in add0.add\">",
"<a href=\"../../add0/add/Add.ADD.html\" title=\"enum in add0.add\">"
};
final String expectedOverviewOrdering[] = {
"<a href=\"Add.add.html\" title=\"enum in &lt;Unnamed&gt;\">",
"<a href=\"add0/Add.add.html\" title=\"enum in add0\">",
"<a href=\"add0/add/Add.add.html\" title=\"enum in add0.add\">",
"<a href=\"add0/add/add/Add.add.html\" title=\"enum in add0.add.add\">",
"<a href=\"add0/add/add/add/Add.add.html\" title=\"enum in add0.add.add.add\">",
"<a href=\"add1/Add.add.html\" title=\"enum in add1\">",
"<a href=\"add1/add/Add.add.html\" title=\"enum in add1.add\">",
"<a href=\"add1/add/add/Add.add.html\" title=\"enum in add1.add.add\">",
"<a href=\"add1/add/add/add/Add.add.html\" title=\"enum in add1.add.add.add\">",
"<a href=\"add2/Add.add.html\" title=\"enum in add2\">",
"<a href=\"add2/add/Add.add.html\" title=\"enum in add2.add\">",
"<a href=\"add2/add/add/Add.add.html\" title=\"enum in add2.add.add\">",
"<a href=\"add2/add/add/add/Add.add.html\" title=\"enum in add2.add.add.add\">",
"<a href=\"add3/Add.add.html\" title=\"enum in add3\">",
"<a href=\"add3/add/Add.add.html\" title=\"enum in add3.add\">",
"<a href=\"add3/add/add/Add.add.html\" title=\"enum in add3.add.add\">",
"<a href=\"add3/add/add/add/Add.add.html\" title=\"enum in add3.add.add.add\">",
"<a href=\"Add.ADD.html\" title=\"enum in &lt;Unnamed&gt;\">",
"<a href=\"add0/Add.ADD.html\" title=\"enum in add0\">",
"<a href=\"add0/add/Add.ADD.html\" title=\"enum in add0.add\">",
"<a href=\"add0/add/add/Add.ADD.html\" title=\"enum in add0.add.add\">",
"<a href=\"add0/add/add/add/Add.ADD.html\" title=\"enum in add0.add.add.add\">",
"<a href=\"add1/Add.ADD.html\" title=\"enum in add1\">",
"<a href=\"add1/add/Add.ADD.html\" title=\"enum in add1.add\">",
"<a href=\"add1/add/add/Add.ADD.html\" title=\"enum in add1.add.add\">",
"<a href=\"add1/add/add/add/Add.ADD.html\" title=\"enum in add1.add.add.add\">",
"<a href=\"add2/Add.ADD.html\" title=\"enum in add2\">",
"<a href=\"add2/add/Add.ADD.html\" title=\"enum in add2.add\">",
"<a href=\"add2/add/add/Add.ADD.html\" title=\"enum in add2.add.add\">",
"<a href=\"add2/add/add/add/Add.ADD.html\" title=\"enum in add2.add.add.add\">",
"<a href=\"add3/Add.ADD.html\" title=\"enum in add3\">",
"<a href=\"add3/add/Add.ADD.html\" title=\"enum in add3.add\">",
"<a href=\"add3/add/add/Add.ADD.html\" title=\"enum in add3.add.add\">",
"<a href=\"add3/add/add/add/Add.ADD.html\" title=\"enum in add3.add.add.add\">",
};
}

View File

@ -23,8 +23,8 @@
/*
* @test
* @bug 4496290 4985072 7006178 7068595 8016328
* @summary A simple test to determine if -use works.
* @bug 4496290 4985072 7006178 7068595 8016328 8050031
* @summary A simple test to ensure class-use files are correct.
* @author jamieh
* @library ../lib
* @build JavadocTester
@ -139,4 +139,18 @@ public class TestUseOption extends JavadocTester {
+ "<a href=\"class-use/UsedInC.html#%3CUnnamed%3E\">UsedInC</a>&nbsp;</td>"
);
}
@Test
void test3() {
javadoc("-d", "out-3",
"-sourcepath", testSrc,
"-use",
"-package", "unique");
checkExit(Exit.OK);
checkUnique("unique/class-use/UseMe.html",
"<a href=\"../../unique/C1.html#umethod1-unique.UseMe-unique.UseMe:A-\">",
"<a href=\"../../unique/C1.html#umethod2-unique.UseMe-unique.UseMe-\">",
"<a href=\"../../unique/C1.html#umethod3-unique.UseMe-unique.UseMe-\">",
"<a href=\"../../unique/C1.html#C1-unique.UseMe-unique.UseMe-\">");
}
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2014, 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 unique;
/**
* A class to ensure we get unique entries in class-use for each of these,
* so make sure each method is uniquely named to avoid false positives
*/
public class C1 {
/**
* Ctor C1 to test uniqueness
* @param a param
* @param b param
*/
public C1(UseMe a, UseMe b){}
/**
* umethod1 to test uniqueness
* @param one param
* @param uarray param
*/
public void umethod1(UseMe<?> one, UseMe<?>[] uarray){}
/**
* umethod1 to test uniqueness
* @param one param
* @param two param
*/
public void umethod2(UseMe<?> one, UseMe<?> two){}
/**
* umethod1 to test uniqueness
* @param a param
* @param b param
*/
public void umethod3(UseMe a, UseMe b){}
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2014, 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 unique;
public class UseMe<T> {}