mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8187521: In some corner cases the javadoc tool can reuse id attribute
Reviewed-by: bpatel, ksrini
This commit is contained in:
parent
b890c3ce83
commit
f386e419c3
8 changed files with 326 additions and 66 deletions
|
@ -313,7 +313,8 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite
|
|||
* @return the 1.4.x style anchor for the executable element.
|
||||
*/
|
||||
protected String getErasureAnchor(ExecutableElement executableElement) {
|
||||
final StringBuilder buf = new StringBuilder(name(executableElement) + "(");
|
||||
final StringBuilder buf = new StringBuilder(writer.anchorName(executableElement));
|
||||
buf.append("(");
|
||||
List<? extends VariableElement> parameters = executableElement.getParameters();
|
||||
boolean foundTypeVariable = false;
|
||||
for (int i = 0; i < parameters.size(); i++) {
|
||||
|
|
|
@ -33,6 +33,7 @@ import java.util.regex.Pattern;
|
|||
import javax.lang.model.element.AnnotationMirror;
|
||||
import javax.lang.model.element.AnnotationValue;
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ElementKind;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.element.ModuleElement;
|
||||
import javax.lang.model.element.Name;
|
||||
|
@ -74,6 +75,7 @@ import jdk.javadoc.internal.doclets.formats.html.markup.HtmlDocument;
|
|||
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
|
||||
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
|
||||
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
|
||||
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlVersion;
|
||||
import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
|
||||
import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
|
||||
import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeWriter;
|
||||
|
@ -1468,20 +1470,18 @@ public class HtmlDocletWriter extends HtmlDocWriter {
|
|||
if (isProperty) {
|
||||
return executableElement.getSimpleName().toString();
|
||||
}
|
||||
String signature = utils.signature(executableElement);
|
||||
StringBuilder signatureParsed = new StringBuilder();
|
||||
int counter = 0;
|
||||
for (int i = 0; i < signature.length(); i++) {
|
||||
char c = signature.charAt(i);
|
||||
if (c == '<') {
|
||||
counter++;
|
||||
} else if (c == '>') {
|
||||
counter--;
|
||||
} else if (counter == 0) {
|
||||
signatureParsed.append(c);
|
||||
}
|
||||
String member = anchorName(executableElement);
|
||||
String erasedSignature = utils.makeSignature(executableElement, true, true);
|
||||
return member + erasedSignature;
|
||||
}
|
||||
|
||||
public String anchorName(Element member) {
|
||||
if (member.getKind() == ElementKind.CONSTRUCTOR
|
||||
&& configuration.isOutputHtml5()) {
|
||||
return "<init>";
|
||||
} else {
|
||||
return utils.getSimpleName(member);
|
||||
}
|
||||
return utils.getSimpleName(executableElement) + signatureParsed.toString();
|
||||
}
|
||||
|
||||
public Content seeTagToContent(Element element, DocTree see) {
|
||||
|
|
|
@ -59,7 +59,8 @@ public abstract class HtmlDocWriter extends HtmlWriter {
|
|||
|
||||
public static final String CONTENT_TYPE = "text/html";
|
||||
|
||||
DocPath pathToRoot;
|
||||
private final HtmlConfiguration configuration;
|
||||
private final DocPath pathToRoot;
|
||||
|
||||
/**
|
||||
* Constructor. Initializes the destination file name through the super
|
||||
|
@ -68,8 +69,9 @@ public abstract class HtmlDocWriter extends HtmlWriter {
|
|||
* @param configuration the configuration for this doclet
|
||||
* @param filename String file name.
|
||||
*/
|
||||
public HtmlDocWriter(BaseConfiguration configuration, DocPath filename) {
|
||||
public HtmlDocWriter(HtmlConfiguration configuration, DocPath filename) {
|
||||
super(configuration, filename);
|
||||
this.configuration = configuration;
|
||||
this.pathToRoot = filename.parent().invert();
|
||||
Messages messages = configuration.getMessages();
|
||||
messages.notice("doclet.Generating_0",
|
||||
|
@ -80,7 +82,9 @@ public abstract class HtmlDocWriter extends HtmlWriter {
|
|||
* Accessor for configuration.
|
||||
* @return the configuration for this doclet
|
||||
*/
|
||||
public abstract BaseConfiguration configuration();
|
||||
public BaseConfiguration configuration() {
|
||||
return configuration;
|
||||
}
|
||||
|
||||
public Content getHyperLink(DocPath link, String label) {
|
||||
return getHyperLink(link, new StringContent(label), false, "", "", "");
|
||||
|
@ -166,8 +170,6 @@ public abstract class HtmlDocWriter extends HtmlWriter {
|
|||
* @return a valid HTML name string.
|
||||
*/
|
||||
public String getName(String name) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
char ch;
|
||||
/* The HTML 4 spec at http://www.w3.org/TR/html4/types.html#h-6.2 mentions
|
||||
* that the name/id should begin with a letter followed by other valid characters.
|
||||
* The HTML 5 spec (draft) is more permissive on names/ids where the only restriction
|
||||
|
@ -178,8 +180,14 @@ public abstract class HtmlDocWriter extends HtmlWriter {
|
|||
* substitute it accordingly, "_" and "$" can appear at the beginning of a member name.
|
||||
* The method substitutes "$" with "Z:Z:D" and will prefix "_" with "Z:Z".
|
||||
*/
|
||||
|
||||
if (configuration.isOutputHtml5()) {
|
||||
return name.replaceAll(" +", "");
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < name.length(); i++) {
|
||||
ch = name.charAt(i);
|
||||
char ch = name.charAt(i);
|
||||
switch (ch) {
|
||||
case '(':
|
||||
case ')':
|
||||
|
|
|
@ -181,36 +181,63 @@ public class HtmlTree extends Content {
|
|||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* A set of ASCII URI characters to be left unencoded.
|
||||
/*
|
||||
* The sets of ASCII URI characters to be left unencoded.
|
||||
* See "Uniform Resource Identifier (URI): Generic Syntax"
|
||||
* IETF RFC 3986. https://tools.ietf.org/html/rfc3986
|
||||
*/
|
||||
public static final BitSet NONENCODING_CHARS = new BitSet(256);
|
||||
public static final BitSet MAIN_CHARS;
|
||||
public static final BitSet QUERY_FRAGMENT_CHARS;
|
||||
|
||||
static {
|
||||
// alphabetic characters
|
||||
for (int i = 'a'; i <= 'z'; i++) {
|
||||
NONENCODING_CHARS.set(i);
|
||||
}
|
||||
for (int i = 'A'; i <= 'Z'; i++) {
|
||||
NONENCODING_CHARS.set(i);
|
||||
}
|
||||
// numeric characters
|
||||
for (int i = '0'; i <= '9'; i++) {
|
||||
NONENCODING_CHARS.set(i);
|
||||
}
|
||||
// Reserved characters as per RFC 3986. These are set of delimiting characters.
|
||||
String noEnc = ":/?#[]@!$&'()*+,;=";
|
||||
// Unreserved characters as per RFC 3986 which should not be percent encoded.
|
||||
noEnc += "-._~";
|
||||
for (int i = 0; i < noEnc.length(); i++) {
|
||||
NONENCODING_CHARS.set(noEnc.charAt(i));
|
||||
}
|
||||
BitSet alphaDigit = bitSet(bitSet('A', 'Z'), bitSet('a', 'z'), bitSet('0', '9'));
|
||||
BitSet unreserved = bitSet(alphaDigit, bitSet("-._~"));
|
||||
BitSet genDelims = bitSet(":/?#[]@");
|
||||
BitSet subDelims = bitSet("!$&'()*+,;=");
|
||||
MAIN_CHARS = bitSet(unreserved, genDelims, subDelims);
|
||||
BitSet pchar = bitSet(unreserved, subDelims, bitSet(":@"));
|
||||
QUERY_FRAGMENT_CHARS = bitSet(pchar, bitSet("/?"));
|
||||
}
|
||||
|
||||
private static BitSet bitSet(String s) {
|
||||
BitSet result = new BitSet();
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
result.set(s.charAt(i));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static BitSet bitSet(char from, char to) {
|
||||
BitSet result = new BitSet();
|
||||
result.set(from, to + 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static BitSet bitSet(BitSet... sets) {
|
||||
BitSet result = new BitSet();
|
||||
for (BitSet set : sets) {
|
||||
result.or(set);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply percent-encoding to a URL.
|
||||
* This is similar to {@link java.net.URLEncoder} but
|
||||
* is less aggressive about encoding some characters,
|
||||
* like '(', ')', ',' which are used in the anchor
|
||||
* names for Java methods in HTML5 mode.
|
||||
*/
|
||||
private static String encodeURL(String url) {
|
||||
BitSet nonEncodingChars = MAIN_CHARS;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte c : url.getBytes(Charset.forName("UTF-8"))) {
|
||||
if (NONENCODING_CHARS.get(c & 0xFF)) {
|
||||
if (c == '?' || c == '#') {
|
||||
sb.append((char) c);
|
||||
// switch to the more restrictive set inside
|
||||
// the query and/or fragment
|
||||
nonEncodingChars = QUERY_FRAGMENT_CHARS;
|
||||
} else if (nonEncodingChars.get(c & 0xFF)) {
|
||||
sb.append((char) c);
|
||||
} else {
|
||||
sb.append(String.format("%%%02X", c & 0xFF));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue