8236048: Cleanup use of Utils.normalizeNewlines

Reviewed-by: hannesw
This commit is contained in:
Jonathan Gibbons 2022-08-18 21:57:05 +00:00
parent 97e2689470
commit 1b756bfa3a
26 changed files with 170 additions and 169 deletions

View File

@ -42,8 +42,8 @@ import jdk.javadoc.internal.doclets.formats.html.markup.Entity;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
import jdk.javadoc.internal.doclets.formats.html.markup.TagName;
import jdk.javadoc.internal.doclets.formats.html.markup.Text;
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
import static jdk.javadoc.internal.doclets.formats.html.HtmlLinkInfo.Kind.EXECUTABLE_MEMBER_PARAM;
import static jdk.javadoc.internal.doclets.formats.html.HtmlLinkInfo.Kind.MEMBER;
@ -211,7 +211,7 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite
TypeMirror rcvrType = member.getReceiverType();
if (includeAnnotations && rcvrType != null && isAnnotatedReceiver(rcvrType)) {
addReceiver(member, rcvrType, result);
sep = "," + DocletConstants.NL + " ";
sep = "," + Text.NL + " ";
}
int paramstart;
ExecutableType instMeth = utils.asInstantiatedMethodType(typeElement, member);
@ -225,7 +225,7 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite
Content annotationInfo = writer.getAnnotationInfo(param, false);
if (!annotationInfo.isEmpty()) {
result.add(annotationInfo)
.add(DocletConstants.NL)
.add(Text.NL)
.add(" ");
}
}
@ -237,14 +237,14 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite
for (int i = paramstart + 1; i < parameters.size(); i++) {
result.add(",");
result.add(DocletConstants.NL);
result.add(Text.NL);
result.add(" ");
if (includeAnnotations) {
Content annotationInfo = writer.getAnnotationInfo(parameters.get(i), false);
if (!annotationInfo.isEmpty()) {
result.add(annotationInfo)
.add(DocletConstants.NL)
.add(Text.NL)
.add(" ");
}
}
@ -268,7 +268,7 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite
for (TypeMirror t : exceptions) {
if (!result.isEmpty()) {
result.add(",");
result.add(DocletConstants.NL);
result.add(Text.NL);
}
Content link = writer.getLink(new HtmlLinkInfo(configuration, THROWS_TYPE, t));
result.add(link);

View File

@ -38,7 +38,6 @@ import jdk.javadoc.internal.doclets.toolkit.util.DocFile;
import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
import jdk.javadoc.internal.doclets.toolkit.util.Utils;
import jdk.javadoc.internal.doclint.HtmlTag;
@ -232,7 +231,7 @@ public class DocFilesHandlerImpl implements DocFilesHandler {
default:
if (inHead) {
localTags.add(startElem);
localTags.add(docTreeFactory.newTextTree(DocletConstants.NL));
localTags.add(docTreeFactory.newTextTree("\n"));
}
}
break;
@ -248,7 +247,7 @@ public class DocFilesHandlerImpl implements DocFilesHandler {
default:
if (inHead) {
localTags.add(endElem);
localTags.add(docTreeFactory.newTextTree(DocletConstants.NL));
localTags.add(docTreeFactory.newTextTree("\n"));
}
}
break;

View File

@ -104,7 +104,6 @@ import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
import jdk.javadoc.internal.doclets.toolkit.util.DocLink;
import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
import jdk.javadoc.internal.doclets.toolkit.util.Utils;
import jdk.javadoc.internal.doclets.toolkit.util.Utils.DeclarationPreviewLanguageFeatures;
import jdk.javadoc.internal.doclets.toolkit.util.Utils.ElementFlag;
@ -1169,7 +1168,7 @@ public class HtmlDocletWriter {
final Content result = new ContentBuilder() {
@Override
public ContentBuilder add(CharSequence text) {
return super.add(utils.normalizeNewlines(text));
return super.add(Text.normalizeNewlines(text));
}
};
CommentHelper ch = utils.getCommentHelper(element);
@ -1357,7 +1356,7 @@ public class HtmlDocletWriter {
@Override
public Boolean visitLiteral(LiteralTree node, Content content) {
String s = node.getBody().getBody();
Content t = Text.of(utils.normalizeNewlines(s));
Content t = Text.of(Text.normalizeNewlines(s));
content.add(node.getKind() == CODE ? HtmlTree.CODE(t) : t);
return false;
}
@ -1405,7 +1404,7 @@ public class HtmlDocletWriter {
text = text.stripTrailing();
}
text = utils.replaceTabs(text);
return utils.normalizeNewlines(text);
return Text.normalizeNewlines(text);
}
@Override
@ -1732,7 +1731,7 @@ public class HtmlDocletWriter {
else {
addAnnotations(annotationElement, linkInfo, annotation, pairs, lineBreak);
}
annotation.add(lineBreak ? DocletConstants.NL : "");
annotation.add(lineBreak ? Text.NL : "");
results.add(annotation);
}
return results;
@ -1764,7 +1763,7 @@ public class HtmlDocletWriter {
} else {
annotation.add(",");
if (linkBreak) {
annotation.add(DocletConstants.NL);
annotation.add(Text.NL);
int spaces = annotationDoc.getSimpleName().length() + 2;
for (int k = 0; k < (spaces); k++) {
annotation.add(" ");

View File

@ -39,12 +39,12 @@ import javax.lang.model.type.TypeMirror;
import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
import jdk.javadoc.internal.doclets.formats.html.markup.TagName;
import jdk.javadoc.internal.doclets.formats.html.markup.Text;
import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.Resources;
import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
import jdk.javadoc.internal.doclets.toolkit.util.Utils.ElementFlag;
import jdk.javadoc.internal.doclets.toolkit.util.links.LinkFactory;
import jdk.javadoc.internal.doclets.toolkit.util.links.LinkInfo;
@ -178,7 +178,7 @@ public class HtmlLinkFactory extends LinkFactory {
links.add(",");
links.add(new HtmlTree(TagName.WBR));
if (((HtmlLinkInfo) linkInfo).getContext() == HtmlLinkInfo.Kind.MEMBER_TYPE_PARAMS) {
links.add(DocletConstants.NL);
links.add(Text.NL);
}
}
links.add(getTypeParameterLink(linkInfo, t));

View File

@ -33,7 +33,6 @@ import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
import jdk.javadoc.internal.doclets.formats.html.markup.Text;
import jdk.javadoc.internal.doclets.formats.html.markup.TagName;
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
import jdk.javadoc.internal.doclets.toolkit.util.Utils;
import javax.lang.model.element.Element;
@ -150,7 +149,7 @@ public class Signatures {
if (!utils.isPlainInterface(typeElement)) {
TypeMirror superclass = utils.getFirstVisibleSuperClass(typeElement);
if (superclass != null) {
content.add(DocletConstants.NL);
content.add(Text.NL);
extendsImplements.add("extends ");
Content link = writer.getLink(new HtmlLinkInfo(configuration,
HtmlLinkInfo.Kind.CLASS_SIGNATURE_PARENT_NAME,
@ -167,7 +166,7 @@ public class Signatures {
continue;
}
if (isFirst) {
extendsImplements.add(DocletConstants.NL);
extendsImplements.add(Text.NL);
extendsImplements.add(utils.isPlainInterface(typeElement) ? "extends " : "implements ");
isFirst = false;
} else {
@ -192,7 +191,7 @@ public class Signatures {
boolean isFirst = true;
for (TypeMirror type : linkablePermits) {
if (isFirst) {
content.add(DocletConstants.NL);
content.add(Text.NL);
permitsSpan.add("permits");
permitsSpan.add(" ");
isFirst = false;
@ -221,7 +220,7 @@ public class Signatures {
for (RecordComponentElement e : typeElement.getRecordComponents()) {
content.add(sep);
writer.getAnnotations(e.getAnnotationMirrors(), false)
.forEach(a -> { content.add(a).add(" "); });
.forEach(a -> content.add(a).add(" "));
Content link = writer.getLink(new HtmlLinkInfo(configuration, HtmlLinkInfo.Kind.RECORD_COMPONENT,
e.asType()));
content.add(link);
@ -544,7 +543,7 @@ public class Signatures {
// sum below includes length of modifiers plus type params added above
if (lineLength + returnType.charCount() > RETURN_TYPE_MAX_LINE_LENGTH) {
target.add(DocletConstants.NL);
target.add(Text.NL);
newLastLineSeparator = target.charCount();
} else {
target.add(Entity.NO_BREAK_SPACE);
@ -574,7 +573,7 @@ public class Signatures {
// Exceptions
if (exceptions != null && !exceptions.isEmpty()) {
CharSequence indent = " ".repeat(Math.max(0, indentSize + 1 - 7));
target.add(DocletConstants.NL)
target.add(Text.NL)
.add(indent)
.add("throws ")
.add(HtmlTree.SPAN(HtmlStyle.exceptions, exceptions));

View File

@ -50,7 +50,6 @@ import jdk.javadoc.internal.doclets.toolkit.util.DocFile;
import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
import jdk.javadoc.internal.doclets.toolkit.util.SimpleDocletException;
import jdk.javadoc.internal.doclets.toolkit.util.Utils;
@ -69,7 +68,7 @@ public class SourceToHTMLConverter {
/**
* New line to be added to the documentation.
*/
private static final String NEW_LINE = DocletConstants.NL;
private static final String NEW_LINE = Text.NL;
private final HtmlConfiguration configuration;
private final HtmlOptions options;
@ -289,9 +288,9 @@ public class SourceToHTMLConverter {
private static void addLineNo(Content pre, int lineno) {
var span = HtmlTree.SPAN(HtmlStyle.sourceLineNo);
if (lineno < 10) {
span.add("00" + Integer.toString(lineno));
span.add("00" + lineno);
} else if (lineno < 100) {
span.add("0" + Integer.toString(lineno));
span.add("0" + lineno);
} else {
span.add(Integer.toString(lineno));
}

View File

@ -30,9 +30,7 @@ import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;
@ -354,8 +352,8 @@ public class Table extends Content {
}
@Override
public boolean write(Writer out, boolean atNewline) throws IOException {
return toContent().write(out, atNewline);
public boolean write(Writer out, String newline, boolean atNewline) throws IOException {
return toContent().write(out, newline, atNewline);
}
/**

View File

@ -140,8 +140,8 @@ public class TableHeader extends Content {
}
@Override
public boolean write(Writer out, boolean atNewline) throws IOException {
return toContent().write(out, atNewline);
public boolean write(Writer out, String newline, boolean atNewline) throws IOException {
return toContent().write(out, newline, atNewline);
}
/**

View File

@ -208,7 +208,7 @@ public class TagletWriterImpl extends TagletWriter {
@Override
protected Content codeTagOutput(Element element, LiteralTree tag) {
return HtmlTree.CODE(Text.of(utils.normalizeNewlines(tag.getBody().getBody())));
return HtmlTree.CODE(Text.of(Text.normalizeNewlines(tag.getBody().getBody())));
}
@Override
@ -309,18 +309,17 @@ public class TagletWriterImpl extends TagletWriter {
@Override
protected Content literalTagOutput(Element element, LiteralTree tag) {
return Text.of(utils.normalizeNewlines(tag.getBody().getBody()));
return Text.of(Text.normalizeNewlines(tag.getBody().getBody()));
}
@Override
public Content getParamHeader(ParamTaglet.ParamKind kind) {
Content header;
switch (kind) {
case PARAMETER: header = contents.parameters ; break;
case TYPE_PARAMETER: header = contents.typeParameters ; break;
case RECORD_COMPONENT: header = contents.recordComponents ; break;
default: throw new IllegalArgumentException(kind.toString());
}
Content header = switch (kind) {
case PARAMETER -> contents.parameters;
case TYPE_PARAMETER -> contents.typeParameters;
case RECORD_COMPONENT -> contents.recordComponents;
default -> throw new IllegalArgumentException(kind.toString());
};
return HtmlTree.DT(header);
}
@ -384,9 +383,9 @@ public class TagletWriterImpl extends TagletWriter {
// Use a different style if any link label is longer than 30 chars or contains commas.
boolean hasLongLabels = links.stream().anyMatch(this::isLongOrHasComma);
var seeList = HtmlTree.UL(hasLongLabels ? HtmlStyle.seeListLong : HtmlStyle.seeList);
links.stream().filter(Predicate.not(Content::isEmpty)).forEach(item -> {
seeList.add(HtmlTree.LI(item));
});
links.stream()
.filter(Predicate.not(Content::isEmpty))
.forEach(item -> seeList.add(HtmlTree.LI(item)));
return new ContentBuilder(
HtmlTree.DT(contents.seeAlso),
@ -630,7 +629,7 @@ public class TagletWriterImpl extends TagletWriter {
}
content.consumeBy((styles, sequence) -> {
CharSequence text = utils.normalizeNewlines(sequence);
CharSequence text = Text.normalizeNewlines(sequence);
if (styles.isEmpty()) {
code.add(text);
} else {
@ -778,7 +777,7 @@ public class TagletWriterImpl extends TagletWriter {
return htmlWriter.invalidTagOutput(summary,
detail.isEmpty() || detail.get().isEmpty()
? Optional.empty()
: Optional.of(Text.of(utils.normalizeNewlines(detail.get()))));
: Optional.of(Text.of(Text.normalizeNewlines(detail.get()))));
}
@Override

View File

@ -42,7 +42,7 @@ import java.util.Objects;
*/
public class BodyContents extends Content {
private List<Content> mainContents = new ArrayList<>();
private final List<Content> mainContents = new ArrayList<>();
private HtmlTree header = null;
private HtmlTree footer = null;
@ -74,8 +74,8 @@ public class BodyContents extends Content {
}
@Override
public boolean write(Writer out, boolean atNewline) throws IOException {
return toContent().write(out, atNewline);
public boolean write(Writer out, String newline, boolean atNewline) throws IOException {
return toContent().write(out, newline, atNewline);
}
/**

View File

@ -30,14 +30,13 @@ import java.io.Writer;
import java.util.Objects;
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
/**
* Class for generating a comment for HTML pages of javadoc output.
*/
public class Comment extends Content {
private String commentText;
private final String commentText;
/**
* Constructor to construct a Comment object.
@ -54,12 +53,14 @@ public class Comment extends Content {
}
@Override
public boolean write(Writer out, boolean atNewline) throws IOException {
if (!atNewline)
out.write(DocletConstants.NL);
public boolean write(Writer out, String newline, boolean atNewline) throws IOException {
if (!atNewline) {
out.write(newline);
}
out.write("<!-- ");
out.write(commentText);
out.write(" -->" + DocletConstants.NL);
out.write(commentText.replace("\n", newline));
out.write(" -->");
out.write(newline);
return true;
}
}

View File

@ -76,9 +76,9 @@ public class ContentBuilder extends Content {
}
@Override
public boolean write(Writer writer, boolean atNewline) throws IOException {
public boolean write(Writer writer, String newline, boolean atNewline) throws IOException {
for (Content content: contents) {
atNewline = content.write(writer, atNewline);
atNewline = content.write(writer, newline, atNewline);
}
return atNewline;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2022, 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
@ -56,7 +56,7 @@ public class Entity extends Content {
}
@Override
public boolean write(Writer writer, boolean atNewline) throws IOException {
public boolean write(Writer writer, String newline, boolean atNewline) throws IOException {
writer.write(text);
return false;
}
@ -86,10 +86,11 @@ public class Entity extends Content {
char ch = str.charAt(i);
switch (ch) {
// only start building a new string if we need to
case '<': case '>': case '&':
case '<', '>', '&' -> {
StringBuilder sb = new StringBuilder(str.substring(0, i));
escapeHtmlChars(str, i, sb);
return sb.toString();
}
}
}
return str;
@ -110,10 +111,10 @@ public class Entity extends Content {
for (int i = start ; i < s.length(); i++) {
char ch = s.charAt(i);
switch (ch) {
case '<': sb.append(Entity.LESS_THAN.text); break;
case '>': sb.append(Entity.GREATER_THAN.text); break;
case '&': sb.append(Entity.AMPERSAND.text); break;
default: sb.append(ch); break;
case '<' -> sb.append(Entity.LESS_THAN.text);
case '>' -> sb.append(Entity.GREATER_THAN.text);
case '&' -> sb.append(Entity.AMPERSAND.text);
default -> sb.append(ch);
}
}
}

View File

@ -31,7 +31,6 @@ import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Locale;
@ -254,8 +253,8 @@ public class Head extends Content {
}
@Override
public boolean write(Writer out, boolean atNewline) throws IOException {
return toContent().write(out, atNewline);
public boolean write(Writer out, String newline, boolean atNewline) throws IOException {
return toContent().write(out, newline, atNewline);
}
/**

View File

@ -28,12 +28,10 @@ package jdk.javadoc.internal.doclets.formats.html.markup;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.*;
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.util.DocFile;
import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
/**
* Class for generating an HTML document for javadoc output.
@ -53,13 +51,14 @@ public class HtmlDocument {
/**
* Writes the content of this document to the specified file.
* Newlines are written using the platform line separator.
*
* @param docFile the file
* @throws DocFileIOException if an {@code IOException} occurs while writing the file
*/
public void write(DocFile docFile) throws DocFileIOException {
try (Writer writer = docFile.openWriter()) {
write(writer);
write(writer, DocFile.PLATFORM_LINE_SEPARATOR);
} catch (IOException e) {
throw new DocFileIOException(docFile, DocFileIOException.Mode.WRITE, e);
}
@ -68,16 +67,16 @@ public class HtmlDocument {
@Override
public String toString() {
try (Writer writer = new StringWriter()) {
write(writer);
write(writer, "\n");
return writer.toString();
} catch (IOException e) {
throw new Error(e);
}
}
private void write(Writer writer) throws IOException {
private void write(Writer writer, String newline) throws IOException {
writer.write(docType.text);
writer.write(DocletConstants.NL);
docContent.write(writer, true);
writer.write(newline);
docContent.write(writer, newline, true);
}
}

View File

@ -32,7 +32,6 @@ import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@ -41,7 +40,6 @@ import java.util.function.Function;
import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr.Role;
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
/**
* A tree node representing an HTML element, containing the name of the element,
@ -1051,19 +1049,17 @@ public class HtmlTree extends Content {
}
@Override
public boolean write(Writer out, boolean atNewline) throws IOException {
public boolean write(Writer out, String newline, boolean atNewline) throws IOException {
boolean isInline = isInline();
if (!isInline && !atNewline)
out.write(DocletConstants.NL);
if (!isInline && !atNewline) {
out.write(newline);
}
String tagString = tagName.toString();
out.write("<");
out.write(tagString);
Iterator<HtmlAttr> iterator = attrs.keySet().iterator();
HtmlAttr key;
String value;
while (iterator.hasNext()) {
key = iterator.next();
value = attrs.get(key);
for (var attr : attrs.entrySet()) {
var key = attr.getKey();
var value = attr.getValue();
out.write(" ");
out.write(key.toString());
if (!value.isEmpty()) {
@ -1074,15 +1070,16 @@ public class HtmlTree extends Content {
}
out.write(">");
boolean nl = false;
for (Content c : content)
nl = c.write(out, nl);
for (Content c : content) {
nl = c.write(out, newline, nl);
}
if (!isVoid()) {
out.write("</");
out.write(tagString);
out.write(">");
}
if (!isInline) {
out.write(DocletConstants.NL);
out.write(newline);
return true;
} else {
return false;

View File

@ -29,7 +29,6 @@ import java.io.IOException;
import java.io.Writer;
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
/**
* Class for generating raw HTML content to be added to HTML pages of javadoc output.
@ -121,6 +120,7 @@ public class RawHtml extends Content {
* @param rawHtml raw HTML text to be added
*/
private RawHtml(CharSequence rawHtml) {
assert Text.checkNewlines(rawHtml);
rawHtmlContent = rawHtml.toString();
}
@ -151,14 +151,6 @@ public class RawHtml extends Content {
state = State.ENTITY;
count++;
break;
case '\r':
// Windows uses "\r\n" as line separator while UNIX uses "\n".
// Skip the "\r" to get consistent results across platforms.
if (i + 1 < htmlText.length() && htmlText.charAt(i + 1) == '\n') {
i++;
}
count++;
break;
default:
count++;
}
@ -192,8 +184,8 @@ public class RawHtml extends Content {
}
@Override
public boolean write(Writer out, boolean atNewline) throws IOException {
out.write(rawHtmlContent);
return rawHtmlContent.endsWith(DocletConstants.NL);
public boolean write(Writer out, String newline, boolean atNewline) throws IOException {
out.write(rawHtmlContent.replace("\n", newline));
return rawHtmlContent.endsWith("\n");
}
}

View File

@ -197,9 +197,9 @@ public class Script {
}
@Override
public boolean write(Writer writer, boolean atNewline) throws IOException {
public boolean write(Writer writer, String newline, boolean atNewline) throws IOException {
String s = sb.toString();
writer.write(s.replace("\n", DocletConstants.NL));
writer.write(s.replace("\n", newline));
return s.endsWith("\n");
}

View File

@ -29,13 +29,14 @@ import java.io.IOException;
import java.io.Writer;
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
/**
* Class for containing immutable string content for HTML tags of javadoc output.
* Newlines are always represented by {@code \n}.
* Any special HTML characters will be escaped if and when the content is written out.
*/
public class Text extends Content {
private final String string;
public static final Text EMPTY = Text.of("");
@ -56,6 +57,7 @@ public class Text extends Content {
* @param content content for the object
*/
private Text(CharSequence content) {
assert checkNewlines(content);
string = content.toString();
}
@ -70,16 +72,7 @@ public class Text extends Content {
}
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;
return cs.length();
}
@Override
@ -88,9 +81,57 @@ public class Text extends Content {
}
@Override
public boolean write(Writer out, boolean atNewline) throws IOException {
out.write(Entity.escapeHtmlChars(string));
return string.endsWith(DocletConstants.NL);
public boolean write(Writer out, String newline, boolean atNewline) throws IOException {
out.write(Entity.escapeHtmlChars(string).replace("\n", newline));
return string.endsWith("\n");
}
/**
* The newline character, to be used when creating {@code Content} nodes.
*/
public static final String NL = "\n";
/**
* Returns a given string with all newlines in the form {@code \n}.
*
* The sequences of interest are {@code \n}, {@code \r\n}, and {@code \r}.
* {@code \n} is already in the right form, so can be ignored,
* leaving code to handle {@code \r\n}, and {@code \r}.
*
* @param text the string
* @return the string with newlines in the form {@code \n}
*/
public static CharSequence normalizeNewlines(CharSequence text) {
// fast-track when the input is a string with no \r characters
if (text instanceof String s && s.indexOf('\r') != -1) {
return text;
} else {
var sb = new StringBuilder();
var s = text.toString();
int sLen = s.length();
int start = 0;
int pos;
while ((pos = s.indexOf('\r', start)) != -1) {
sb.append(s, start, pos);
sb.append('\n');
pos++;
if (pos < sLen && s.charAt(pos) == '\n') {
pos++;
}
start = pos;
}
sb.append(s.substring(start));
return sb;
}
}
/**
* Check for the absence of {@code \r} characters.
* @param cs the characters to be checked
* @return {@code true} if there are no {@code \r} characters, and {@code false} otherwise
*/
static boolean checkNewlines(CharSequence cs) {
return !cs.toString().contains("\r");
}
}

View File

@ -29,11 +29,11 @@ import java.io.IOException;
import java.io.Writer;
import jdk.javadoc.internal.doclets.toolkit.Content;
import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
/**
* Class for generating string content for HTML tags of javadoc output.
* The content is mutable to the extent that additional content may be added.
* Newlines are always represented by {@code \n}.
* Any special HTML characters will be escaped if and when the content is written out.
*/
public class TextBuilder extends Content {
@ -53,6 +53,7 @@ public class TextBuilder extends Content {
* @param initialContent initial content for the object
*/
public TextBuilder(CharSequence initialContent) {
assert Text.checkNewlines(initialContent);
stringBuilder = new StringBuilder(initialContent);
}
@ -63,6 +64,7 @@ public class TextBuilder extends Content {
*/
@Override
public TextBuilder add(CharSequence strContent) {
assert Text.checkNewlines(strContent);
stringBuilder.append(strContent);
return this;
}
@ -74,7 +76,7 @@ public class TextBuilder extends Content {
@Override
public int charCount() {
return Text.charCount(stringBuilder);
return stringBuilder.length();
}
@Override
@ -83,9 +85,9 @@ public class TextBuilder extends Content {
}
@Override
public boolean write(Writer out, boolean atNewline) throws IOException {
public boolean write(Writer out, String newline, boolean atNewline) throws IOException {
String s = Entity.escapeHtmlChars(stringBuilder);
out.write(s);
return s.endsWith(DocletConstants.NL);
out.write(s.replace("\n", newline));
return s.endsWith("\n");
}
}

View File

@ -320,12 +320,17 @@ public abstract class BaseOptions {
private final BaseConfiguration config;
/**
* The default amount of space between tab stops.
*/
public static final int DEFAULT_TAB_STOP_LENGTH = 8;
protected BaseOptions(BaseConfiguration config) {
this.config = config;
excludedDocFileDirs = new HashSet<>();
excludedQualifiers = new HashSet<>();
sourceTabSize = DocletConstants.DEFAULT_TAB_STOP_LENGTH;
sourceTabSize = DEFAULT_TAB_STOP_LENGTH;
groupPairs = new ArrayList<>(0);
}
@ -597,7 +602,7 @@ public abstract class BaseOptions {
}
if (sourceTabSize <= 0) {
messages.warning("doclet.sourcetab_warning");
sourceTabSize = DocletConstants.DEFAULT_TAB_STOP_LENGTH;
sourceTabSize = DEFAULT_TAB_STOP_LENGTH;
}
return true;
}

View File

@ -38,6 +38,7 @@ public abstract class Content {
/**
* Returns a string representation of the content.
* Newlines are represented by {@code \n}.
*
* @return string representation of the content
*/
@ -45,7 +46,7 @@ public abstract class Content {
public String toString() {
StringWriter out = new StringWriter();
try {
write(out, true);
write(out, "\n", true);
} catch (IOException e) {
// cannot happen from StringWriter
throw new AssertionError(e);
@ -106,14 +107,16 @@ public abstract class Content {
}
/**
* Writes content to a writer.
* Writes content to a writer, using a given newline sequence, which should be
* either {@code \n} or the platform line separator.
*
* @param writer the writer
* @param newline the newline sequence to use
* @param atNewline whether the writer has just written a newline
* @return whether the writer has just written a newline
* @throws IOException if an error occurs while writing the output
*/
public abstract boolean write(Writer writer, boolean atNewline) throws IOException;
public abstract boolean write(Writer writer, String newline, boolean atNewline) throws IOException;
/**
* Returns true if the content is empty.

View File

@ -51,6 +51,12 @@ import jdk.javadoc.internal.doclets.toolkit.Resources;
*/
public abstract class DocFile {
/**
* The line separator for the current platform.
* Use this when writing to external files.
*/
public static final String PLATFORM_LINE_SEPARATOR = System.getProperty("line.separator");
/** Create a DocFile for a directory. */
public static DocFile createFileForDirectory(BaseConfiguration configuration, String file) {
return DocFileFactory.getFactory(configuration).createFileForDirectory(file);
@ -214,7 +220,7 @@ public abstract class DocFile {
String line;
while ((line = readResourceLine(resource, reader)) != null) {
write(this, writer, resources == null ? line : localize(line, resources));
write(this, writer, DocletConstants.NL);
write(this, writer, PLATFORM_LINE_SEPARATOR);
}
} catch (IOException e) {
throw new DocFileIOException(this, DocFileIOException.Mode.WRITE, e);

View File

@ -31,16 +31,6 @@ package jdk.javadoc.internal.doclets.toolkit.util;
*/
public class DocletConstants {
/**
* The default amount of space between tab stops.
*/
public static final int DEFAULT_TAB_STOP_LENGTH = 8;
/**
* The line separator for the current operating system.
*/
public static final String NL = System.getProperty("line.separator");
/**
* The default module or a package name.
*/

View File

@ -1235,32 +1235,6 @@ public class Utils {
return result.toString();
}
public CharSequence normalizeNewlines(CharSequence text) {
StringBuilder sb = new StringBuilder();
final int textLength = text.length();
final String NL = DocletConstants.NL;
int pos = 0;
for (int i = 0; i < textLength; i++) {
char ch = text.charAt(i);
switch (ch) {
case '\n' -> {
sb.append(text, pos, i);
sb.append(NL);
pos = i + 1;
}
case '\r' -> {
sb.append(text, pos, i);
sb.append(NL);
if (i + 1 < textLength && text.charAt(i + 1) == '\n')
i++;
pos = i + 1;
}
}
}
sb.append(text, pos, textLength);
return sb;
}
/**
* Returns a locale independent lower cased String. That is, it
* always uses US locale, this is a clone of the one in StringUtils.

View File

@ -36,8 +36,6 @@
import jdk.javadoc.internal.doclets.formats.html.markup.*;
import static jdk.javadoc.internal.doclets.toolkit.util.DocletConstants.NL;
/**
* The class reads each file, complete with newlines, into a string to easily
* compare the existing markup with the generated markup.
@ -56,7 +54,7 @@ public class TestHtmlDocument extends JavadocTester {
public void test() {
checking("markup");
// Check whether the generated markup is same as the existing markup.
String expected = readFile(testSrc, "testMarkup.html").replace("\n", NL);
String expected = readFile(testSrc, "testMarkup.html");
String actual = generateHtmlTree();
if (actual.equals(expected)) {
passed("");