Skip to content

Commit

Permalink
8288699: cleanup HTML tree in HtmlDocletWriter.commentTagsToContent
Browse files Browse the repository at this point in the history
Reviewed-by: hannesw
  • Loading branch information
jonathan-gibbons committed Jul 8, 2022
1 parent 6aaf141 commit 54b4576
Show file tree
Hide file tree
Showing 18 changed files with 342 additions and 167 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -877,6 +877,32 @@ private DCTree html() {
}
nextChar();
}
} else {
String CDATA = "[CDATA["; // full prefix is <![CDATA[
for (int i = 0; i < CDATA.length(); i++) {
if (ch == CDATA.charAt(i)) {
nextChar();
} else {
return erroneous("dc.invalid.html", p);
}
}
// suffix is ]]>
while (bp < buflen) {
if (ch == ']') {
int n = 0;
while (bp < buflen && ch == ']') {
n++;
nextChar();
}
if (n >= 2 && ch == '>') {
nextChar();
return m.at(p).newTextTree(newString(p, bp));
}
} else {
nextChar();
}
}
return erroneous("dc.invalid.html", p);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3339,6 +3339,9 @@ compiler.err.dc.bad.inline.tag=\
compiler.err.dc.identifier.expected=\
identifier expected

compiler.err.dc.invalid.html=\
invalid HTML

compiler.err.dc.malformed.html=\
malformed HTML

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ protected void buildOverviewIndexFile(String title, String description)
protected void addConfigurationTitle(Content target) {
String doctitle = configuration.getOptions().docTitle();
if (!doctitle.isEmpty()) {
var title = new RawHtml(doctitle);
var title = RawHtml.of(doctitle);
var heading = HtmlTree.HEADING(Headings.PAGE_TITLE_HEADING,
HtmlStyle.title, title);
var div = HtmlTree.DIV(HtmlStyle.header, heading);
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ public void addMemberDescription(VariableElement field, DocTree serialFieldTag,
CommentHelper ch = utils.getCommentHelper(field);
List<? extends DocTree> description = ch.getDescription(serialFieldTag);
if (!description.isEmpty()) {
Content serialFieldContent = new RawHtml(ch.getText(description));
Content serialFieldContent = RawHtml.of(ch.getText(description)); // should interpret tags
var div = HtmlTree.DIV(HtmlStyle.block, serialFieldContent);
content.add(div);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ private void appendModifiers(Content target) {
*/
private int appendTypeParameters(Content target, int lastLineSeparator) {
// Apply different wrapping strategies for type parameters
// depending of combined length of type parameters and return type.
// depending on the combined length of type parameters and return type.
int typeParamLength = typeParameters.charCount();

if (typeParamLength >= TYPE_PARAMS_MAX_INLINE_LENGTH) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
import com.sun.source.doctree.SeeTree;
import com.sun.source.doctree.SnippetTree;
import com.sun.source.doctree.SystemPropertyTree;
import com.sun.source.doctree.TextTree;
import com.sun.source.doctree.ThrowsTree;
import com.sun.source.util.DocTreePath;
import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
Expand Down Expand Up @@ -307,7 +308,7 @@ public Content paramTagOutput(Element element, ParamTree paramTag, String paramN
public Content returnTagOutput(Element element, ReturnTree returnTag, boolean inline) {
CommentHelper ch = utils.getCommentHelper(element);
List<? extends DocTree> desc = ch.getDescription(returnTag);
Content content = htmlWriter.commentTagsToContent(element, desc , context.within(returnTag));
Content content = htmlWriter.commentTagsToContent(element, desc, context.within(returnTag));
return inline
? new ContentBuilder(contents.getContent("doclet.Returns_0", content))
: new ContentBuilder(HtmlTree.DT(contents.returns), HtmlTree.DD(content));
Expand Down Expand Up @@ -371,7 +372,7 @@ public Content simpleBlockTagOutput(Element element, List<? extends DocTree> sim
many = true;
}
return new ContentBuilder(
HtmlTree.DT(new RawHtml(header)),
HtmlTree.DT(RawHtml.of(header)),
HtmlTree.DD(body));
}

Expand Down Expand Up @@ -504,9 +505,9 @@ public Content throwsTagOutput(Element element, ThrowsTree throwsTag, TypeMirror
excName = htmlWriter.getLink(new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.MEMBER,
substituteType));
} else if (exception == null) {
excName = new RawHtml(throwsTag.getExceptionName().toString());
excName = RawHtml.of(throwsTag.getExceptionName().toString());
} else if (exception.asType() == null) {
excName = new RawHtml(utils.getFullyQualifiedName(exception));
excName = Text.of(utils.getFullyQualifiedName(exception));
} else {
HtmlLinkInfo link = new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.MEMBER,
exception.asType());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ public class Entity extends Content {

public final String text;

/**
* Creates an entity with a given name or numeric value.
*
* @param name the name, or numeric value
* @return the entity
*/
public static Entity of(CharSequence name) {
return new Entity("&" + name + ";");
}

private Entity(String text) {
this.text = text;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,91 @@
*/
public class RawHtml extends Content {

private final String rawHtmlContent;
protected final String rawHtmlContent;

/**
* Creates HTML for an arbitrary string of HTML.
* The string is accepted as-is and is not validated in any way.
* It should be syntactically well-formed and contain matching {@code <} and {@code >},
* and matching quotes for attributes.
*
* @param rawHtml the string
* @return the HTML
*/
public static RawHtml of(CharSequence rawHtml) {
return new RawHtml(rawHtml) {
@Override
public int charCount() {
return charCount(rawHtmlContent);
}
};
}

/**
* Creates HTML for the start of an element.
*
* @param name the name of the element
* @param attrs content containing any attributes
* @param selfClosing whether this is a self-closing element.
* @return the HTML
*/
public static RawHtml startElement(CharSequence name, Content attrs, boolean selfClosing) {
StringBuilder sb = new StringBuilder("<" + name);
if (!attrs.isEmpty()) {
sb.append(" ");
sb.append(attrs);
}
sb.append(selfClosing ? "/>" : ">");
return new RawHtml(sb);
}

/**
* Creates HTML for the end of an element.
*
* @param name the name of the element
* @return the HTML
*/
public static RawHtml endElement(CharSequence name) {
return new RawHtml("</" + name + ">");
}

/**
* Creates HTML for an HTML comment.
*
* The body will be enclosed in {@code <!--} and {@code -->} if it does not
* already begin and end with those sequences.
*
* @param body the body of the comment
*
* @return the HTML
*/
public static RawHtml comment(String body) {
return section("<!--", body, "-->");
}
/**
* Creates HTML for an HTML CDATA section.
*
* The body will be enclosed in {@code <![CDATA]} and {@code ]]>} if it does not
* already begin and end with those sequences.
*
* @param body the body of the CDATA section
*
* @return the HTML
*/
public static RawHtml cdata(String body) {
return section("<![CDATA[", body, "]]>");
}

private static RawHtml section(String prefix, String body, String suffix) {
return new RawHtml(body.startsWith(prefix) && body.endsWith(suffix) ? body : prefix + body + suffix);
}

/**
* Constructor to construct a RawHtml object.
*
* @param rawHtml raw HTML text to be added
*/
public RawHtml(CharSequence rawHtml) {
private RawHtml(CharSequence rawHtml) {
rawHtmlContent = rawHtml.toString();
}

Expand All @@ -59,12 +136,7 @@ public String toString() {

private enum State { TEXT, ENTITY, TAG, STRING }

@Override
public int charCount() {
return charCount(rawHtmlContent);
}

static int charCount(CharSequence htmlText) {
protected static int charCount(CharSequence htmlText) {
State state = State.TEXT;
int count = 0;
for (int i = 0; i < htmlText.length(); i++) {
Expand All @@ -80,9 +152,12 @@ static int charCount(CharSequence htmlText) {
count++;
break;
case '\r':
case '\n':
// Windows uses "\r\n" as line separator while UNIX uses "\n".
// Ignore line separators to get consistent results across platforms.
// Skip the "\r" to get consistent results across platforms.
if (i + 1 < htmlText.length() && htmlText.charAt(i + 1) == '\n') {
i++;
}
count++;
break;
default:
count++;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

/**
* Class for containing immutable string content for HTML tags of javadoc output.
* Any special HTML characters will be escaped if and when the content is written out.
*/
public class Text extends Content {
private final String string;
Expand All @@ -55,7 +56,7 @@ public static Text of(CharSequence content) {
* @param content content for the object
*/
private Text(CharSequence content) {
string = Entity.escapeHtmlChars(content);
string = content.toString();
}

@Override
Expand All @@ -65,7 +66,20 @@ public boolean isEmpty() {

@Override
public int charCount() {
return RawHtml.charCount(string);
return charCount(string);
}

static int charCount(CharSequence cs) {
int count = 0;
for (int i = 0; i < cs.length(); i++) {
// Windows uses "\r\n" as line separator while UNIX uses "\n".
// Skip the "\r" to get consistent results across platforms.
if (cs.charAt(i) == '\r' && (i + 1 < cs.length()) && cs.charAt(i + 1) == '\n') {
i++;
}
count++;
}
return count;
}

@Override
Expand All @@ -75,7 +89,7 @@ public String toString() {

@Override
public boolean write(Writer out, boolean atNewline) throws IOException {
out.write(string);
out.write(Entity.escapeHtmlChars(string));
return string.endsWith(DocletConstants.NL);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
/**
* Class for generating string content for HTML tags of javadoc output.
* The content is mutable to the extent that additional content may be added.
* Any special HTML characters will be escaped if and when the content is written out.
*/
public class TextBuilder extends Content {

Expand All @@ -52,19 +53,17 @@ public TextBuilder() {
* @param initialContent initial content for the object
*/
public TextBuilder(CharSequence initialContent) {
stringBuilder = new StringBuilder();
Entity.escapeHtmlChars(initialContent, stringBuilder);
stringBuilder = new StringBuilder(initialContent);
}

/**
* Adds content for the StringContent object. The method escapes
* HTML characters for the string content that is added.
* Adds content for the StringContent object.
*
* @param strContent string content to be added
*/
@Override
public TextBuilder add(CharSequence strContent) {
Entity.escapeHtmlChars(strContent, stringBuilder);
stringBuilder.append(strContent);
return this;
}

Expand All @@ -75,7 +74,7 @@ public boolean isEmpty() {

@Override
public int charCount() {
return RawHtml.charCount(stringBuilder.toString());
return Text.charCount(stringBuilder);
}

@Override
Expand All @@ -85,7 +84,7 @@ public String toString() {

@Override
public boolean write(Writer out, boolean atNewline) throws IOException {
String s = stringBuilder.toString();
String s = Entity.escapeHtmlChars(stringBuilder);
out.write(s);
return s.endsWith(DocletConstants.NL);
}
Expand Down

1 comment on commit 54b4576

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.