in java/java.source.base/src/org/netbeans/modules/java/source/save/Reformatter.java [4800:5424]
private void reformatComment() {
if (tokens.token().id() != BLOCK_COMMENT && tokens.token().id() != JAVADOC_COMMENT)
return;
TokenSequence<JavadocTokenId> javadocTokens = null;
TokenSequence<?> embedded = tokens.embedded();
if (embedded != null) {
if (JavadocTokenId.language().equals(embedded.language())) {
javadocTokens = (TokenSequence<JavadocTokenId>) embedded;
} else {
return;
}
}
final String text = tokens.token().text().toString();
final int offset = tokens.offset();
LinkedList<Pair<Integer, JavadocReformattingActionType>> marks = new LinkedList<>();
int maxParamNameLength = 0;
int maxExcNameLength = 0;
int initTextEndOffset = Integer.MAX_VALUE;
if (javadocTokens != null) {
JavadocReformattingState state = JavadocReformattingState.INITIAL_TEXT;
int currWSOffset = -1;
int lastWSOffset = -1;
int identStart = -1;
int lastNLOffset = -1;
int lastAddedNLOffset = -1;
boolean afterText = false;
boolean insideTag = false;
int nestedParenCnt = 0;
StringBuilder cseq = null;
Pair<Integer, JavadocReformattingActionType> marker = null;
Pair<Integer, JavadocReformattingActionType> nlAdd = null;
while (javadocTokens.moveNext()) {
switch (javadocTokens.token().id()) {
case TAG:
marker = null;
nlAdd = null;
String tokenText = javadocTokens.token().text().toString();
JavadocReformattingState newState;
if (hasInlineTagPrefix(text, tokenText, javadocTokens.offset() - offset)) {
insideTag = true;
addMark(Pair.of(currWSOffset, JavadocReformattingActionType.NO_FORMAT), marks, state);
lastWSOffset = currWSOffset = -1;
break;
} else if (JDOC_PARAM_TAG.equalsIgnoreCase(tokenText)) {
newState = JavadocReformattingState.AFTER_PARAM_TAG;
} else if (JDOC_RETURN_TAG.equalsIgnoreCase(tokenText)) {
newState = JavadocReformattingState.RETURN_DESCRIPTION;
} else if (JDOC_THROWS_TAG.equalsIgnoreCase(tokenText)
|| JDOC_EXCEPTION_TAG.equalsIgnoreCase(tokenText)) {
newState = JavadocReformattingState.AFTER_THROWS_TAG;
} else {
if (insideTag)
break;
newState = JavadocReformattingState.AFTER_OTHER_TAG;
}
if (lastWSOffset < initTextEndOffset && (newState != JavadocReformattingState.INITIAL_TEXT)) {
initTextEndOffset = lastWSOffset;
}
if (currWSOffset >= 0 && afterText) {
addMark(Pair.of(currWSOffset, state == JavadocReformattingState.INITIAL_TEXT && cs.blankLineAfterJavadocDescription()
|| state == JavadocReformattingState.PARAM_DESCRIPTION && newState != JavadocReformattingState.AFTER_PARAM_TAG && cs.blankLineAfterJavadocParameterDescriptions()
|| state == JavadocReformattingState.RETURN_DESCRIPTION && cs.blankLineAfterJavadocReturnTag() ? JavadocReformattingActionType.ADD_BLANK_LINE : JavadocReformattingActionType.ADD_NEW_LINE), marks, state);
}
state = newState;
if (state == JavadocReformattingState.RETURN_DESCRIPTION && cs.alignJavadocReturnDescription()) {
marker = Pair.of(javadocTokens.offset() + javadocTokens.token().length() - offset, JavadocReformattingActionType.ALIGN_RETURN);
}
lastWSOffset = currWSOffset = -1;
break;
case IDENT:
if (marker != null) {
addMark(marker, marks, state);
marker = null;
}
nlAdd = null;
if (identStart < 0 && (state == JavadocReformattingState.AFTER_PARAM_TAG || state == JavadocReformattingState.AFTER_THROWS_TAG))
identStart = javadocTokens.offset() - offset;
lastWSOffset = currWSOffset = -1;
afterText = true;
break;
case HTML_TAG:
if (marker != null) {
addMark(marker, marks, state);
}
nlAdd = null;
tokenText = javadocTokens.token().text().toString();
if (tokenText.endsWith(">")) { //NOI18N
if (P_TAG.equalsIgnoreCase(tokenText) || END_P_TAG.equalsIgnoreCase(tokenText)) {
if (currWSOffset >= 0 && currWSOffset > lastAddedNLOffset && (marker == null || marker.first() < currWSOffset)) {
addMark(Pair.of(currWSOffset, JavadocReformattingActionType.ADD_NEW_LINE), marks, state);
}
lastAddedNLOffset = javadocTokens.offset() + javadocTokens.token().length() - offset;
addMark(Pair.of(lastAddedNLOffset, JavadocReformattingActionType.ADD_NEW_LINE), marks, state);
afterText = false;
} else if (PRE_TAG.equalsIgnoreCase(tokenText)) {
if (currWSOffset >= 0 && state == JavadocReformattingState.INITIAL_TEXT && (marker == null || marker.first() < currWSOffset)) {
addMark(Pair.of(currWSOffset, JavadocReformattingActionType.ADD_NEW_LINE), marks, state);
}
addMark(Pair.of(javadocTokens.offset() - offset, JavadocReformattingActionType.NO_FORMAT), marks, state);
state = JavadocReformattingState.AFTER_PRE_TAG;
} else if (CODE_TAG.equalsIgnoreCase(tokenText)) {
addMark(Pair.of(javadocTokens.offset() - offset, JavadocReformattingActionType.NO_FORMAT), marks, state);
} else if (PRE_END_TAG.equalsIgnoreCase(tokenText)) {
state = JavadocReformattingState.INITIAL_TEXT;
addMark(Pair.of(currWSOffset >= 0 ? currWSOffset : javadocTokens.offset() - offset, JavadocReformattingActionType.FORMAT), marks, state);
} else if (CODE_END_TAG.equalsIgnoreCase(tokenText)) {
addMark(Pair.of(currWSOffset >= 0 ? currWSOffset : javadocTokens.offset() - offset, JavadocReformattingActionType.FORMAT), marks, state);
} else {
if (currWSOffset >= 0 && lastNLOffset >= currWSOffset
&& lastAddedNLOffset < currWSOffset && (marker == null || marker.first() < currWSOffset)) {
addMark(Pair.of(currWSOffset, JavadocReformattingActionType.ADD_NEW_LINE), marks, state);
}
addMark(Pair.of(javadocTokens.offset() - offset, JavadocReformattingActionType.NO_FORMAT), marks, state);
addMark(Pair.of(javadocTokens.offset() + javadocTokens.token().length() - offset - 1, JavadocReformattingActionType.FORMAT), marks, state);
nlAdd = Pair.of(javadocTokens.offset() + javadocTokens.token().length() - offset, JavadocReformattingActionType.ADD_NEW_LINE);
}
} else {
cseq = new StringBuilder(tokenText);
}
marker = null;
lastWSOffset = currWSOffset = -1;
break;
case OTHER_TEXT:
lastWSOffset = currWSOffset = -1;
if (cseq == null)
cseq = new StringBuilder();
cseq.append(javadocTokens.token().text());
int nlNum = 1;
int insideTagEndOffset = -1;
boolean addNow = false;
boolean nlFollows = false;
for (int i = cseq.length(); i >= 0; i--) {
if (i == 0) {
if (lastWSOffset < 0)
lastWSOffset = javadocTokens.offset() - offset;
if (currWSOffset < 0 && nlNum >= 0)
currWSOffset = javadocTokens.offset() - offset;
} else {
char c = cseq.charAt(i - 1);
if (Character.isWhitespace(c)) {
if (c == '\n') {
nlNum--;
nlFollows = true;
int off = javadocTokens.offset() + i - offset;
if (off > lastNLOffset)
lastNLOffset = off;
}
if (lastWSOffset < 0 && currWSOffset >= 0)
lastWSOffset = -2;
} else {
nlFollows = false;
if (c != '*') {
if (marker != null) {
addMark(marker, marks, state);
marker = null;
} else {
addNow = true;
}
if (insideTag) {
if (c == '{') {
nestedParenCnt++;
} else if (c == '}') {
if (nestedParenCnt > 0) {
nestedParenCnt--;
} else {
insideTagEndOffset = javadocTokens.offset() + i - offset - 1;
insideTag = false;
}
}
}
if (lastWSOffset == -2)
lastWSOffset = javadocTokens.offset() + i - offset;
if (currWSOffset < 0 && nlNum >= 0)
currWSOffset = javadocTokens.offset() + i - offset;
afterText = true;
}
}
}
}
if (nlFollows && nlAdd != null) {
marker = nlAdd;
}
nlAdd = null;
if (identStart >= 0) {
int len = javadocTokens.offset() - offset - identStart;
for (int i = 0; i <= cseq.length(); i++) {
if (i == cseq.length() || Character.isWhitespace(cseq.charAt(i))) {
len += i;
break;
}
}
if (state == JavadocReformattingState.AFTER_PARAM_TAG) {
if (len > maxParamNameLength)
maxParamNameLength = len;
if (cs.alignJavadocParameterDescriptions())
marker = Pair.of(identStart + len, JavadocReformattingActionType.ALIGN_PARAMS);
state = JavadocReformattingState.PARAM_DESCRIPTION;
} else if (state == JavadocReformattingState.AFTER_THROWS_TAG) {
if (len > maxExcNameLength)
maxExcNameLength = len;
if (cs.alignJavadocExceptionDescriptions())
marker = Pair.of(identStart + len, JavadocReformattingActionType.ALIGN_EXCEPTIONS);
state = JavadocReformattingState.EXCEPTION_DESCRIPTION;
}
if (addNow && marker != null) {
addMark(marker, marks, state);
marker = null;
}
identStart = -1;
}
if (insideTagEndOffset >= 0) {
addMark(Pair.of(insideTagEndOffset, JavadocReformattingActionType.FORMAT), marks, state);
}
cseq = null;
break;
default:
if (marker != null) {
addMark(marker, marks, state);
marker = null;
}
nlAdd = null;
}
}
}
int markedOffset;
JavadocReformattingActionType actionType;
Iterator<Pair<Integer, JavadocReformattingActionType>> marksIterator = marks.iterator();
if (marksIterator.hasNext()) {
Pair<Integer, JavadocReformattingActionType> next = marksIterator.next();
markedOffset = next.first();
actionType = next.second();
} else {
markedOffset = Integer.MAX_VALUE;
actionType = JavadocReformattingActionType.NONE;
}
final String indentString = getIndent();
final String lineStartString = cs.addLeadingStarInComment() ? indentString + SPACE + LEADING_STAR + SPACE : indentString + SPACE;
String blankLineString;
int currNWSPos = -1;
int lastNWSPos = -1;
int currWSPos = -1;
int lastWSPos = -1;
int lastNewLinePos = -1;
Diff pendingDiff = null;
int start = javadocTokens != null ? 3 : 2;
int end = text.length() - 2;
col += start;
boolean preserveNewLines = true;
boolean firstLine = true;
boolean enableCommentFormatting = javadocTokens != null ? cs.enableJavadocFormatting() : cs.enableBlockCommentFormatting();
boolean noFormat = bof;
int align = -1;
for (int i = start; i < text.length(); i++) {
if (i >= initTextEndOffset) {
blankLineString = cs.addLeadingStarInComment() ? indentString + SPACE + LEADING_STAR : EMPTY;
} else if (javadocTokens != null && !noFormat && cs.generateParagraphTagOnBlankLines()) {
blankLineString = cs.addLeadingStarInComment() ? indentString + SPACE + LEADING_STAR + SPACE + P_TAG : indentString + SPACE + P_TAG;
} else {
blankLineString = cs.addLeadingStarInComment() ? indentString + SPACE + LEADING_STAR : EMPTY;
}
char c = text.charAt(i);
if (Character.isWhitespace(c)) {
if (enableCommentFormatting) {
if (currNWSPos >= 0) {
lastNWSPos = currNWSPos;
currNWSPos = -1;
}
if (currWSPos < 0) {
currWSPos = i;
if (noFormat) {
col++;
} else {
if (col > rightMargin && cs.wrapCommentText() && lastWSPos >= 0) {
int endOff = pendingDiff != null ? pendingDiff.getEndOffset() - offset : lastWSPos + 1;
String s = pendingDiff != null && pendingDiff.text != null && pendingDiff.text.charAt(0) == '\n' ? pendingDiff.text : NEWLINE + lineStartString;
col = getCol(lineStartString) + i - endOff;
if (align > 0) {
int num = align - getCol(lineStartString);
if (num > 0) {
s += getSpaces(num);
col += num;
}
}
col++;
if (endOff > lastWSPos && !s.equals(text.substring(lastWSPos, endOff)))
addDiff(new Diff(offset + lastWSPos, offset + endOff, s));
} else if (pendingDiff != null) {
String sub = text.substring(pendingDiff.start - offset, pendingDiff.end - offset);
if (!sub.equals(pendingDiff.text)) {
addDiff(pendingDiff);
}
col++;
} else {
col++;
}
pendingDiff = null;
}
}
}
if (c == '\n') {
if (lastNewLinePos >= 0) {
if (enableCommentFormatting) {
String subs = text.substring(lastNewLinePos + 1, i);
if (!blankLineString.equals(subs)) {
addDiff(new Diff(offset + lastNewLinePos + 1, offset + i, blankLineString));
}
}
preserveNewLines = true;
lastNewLinePos = i;
align = -1;
} else {
lastNewLinePos = currWSPos >= 0 ? currWSPos : i;
}
firstLine = false;
}
if (i >= markedOffset && actionType == JavadocReformattingActionType.NO_FORMAT) {
noFormat = true;
align = -1;
if (marksIterator.hasNext()) {
Pair<Integer, JavadocReformattingActionType> next = marksIterator.next();
markedOffset = next.first();
actionType = next.second();
} else {
markedOffset = Integer.MAX_VALUE;
actionType = JavadocReformattingActionType.NONE;
}
}
} else {
if (pendingDiff != null) {
String sub = text.substring(pendingDiff.start - offset, pendingDiff.end - offset);
if (sub.equals(pendingDiff.text)) {
pendingDiff = null;
}
}
if (enableCommentFormatting) {
if (currNWSPos < 0) {
currNWSPos = i;
}
if (i >= markedOffset) {
noFormat = false;
switch (actionType) {
case ADD_BLANK_LINE:
pendingDiff = new Diff(currWSPos >= 0 ? offset + currWSPos : offset + i, offset + i, NEWLINE + blankLineString + NEWLINE);
lastNewLinePos = i - 1;
preserveNewLines = true;
align = -1;
break;
case ADD_NEW_LINE:
pendingDiff = new Diff(currWSPos >= 0 ? offset + currWSPos : offset + i, offset + i, NEWLINE);
lastNewLinePos = i - 1;
preserveNewLines = true;
align = -1;
break;
case ALIGN_PARAMS:
col += (maxParamNameLength + lastNWSPos - currWSPos);
align = col;
currWSPos = -1;
if (lastNewLinePos < 0) {
int num = maxParamNameLength + lastNWSPos + 1 - i;
if (num > 0) {
addDiff(new Diff(offset + i, offset + i, getSpaces(num)));
} else if (num < 0) {
addDiff(new Diff(offset + i + num, offset + i, null));
}
}
break;
case ALIGN_RETURN:
align = col;
break;
case ALIGN_EXCEPTIONS:
col += (maxExcNameLength + lastNWSPos - currWSPos);
align = col;
currWSPos = -1;
if (lastNewLinePos < 0) {
int num = maxExcNameLength + lastNWSPos + 1 - i;
if (num > 0) {
addDiff(new Diff(offset + i, offset + i, getSpaces(num)));
} else if (num < 0) {
addDiff(new Diff(offset + i + num, offset + i, null));
}
}
break;
case NO_FORMAT:
noFormat = true;
if (currWSPos > 0)
lastWSPos = currWSPos;
break;
case FORMAT:
preserveNewLines = true;
break;
}
if (marksIterator.hasNext()) {
Pair<Integer, JavadocReformattingActionType> next = marksIterator.next();
markedOffset = next.first();
actionType = next.second();
} else {
markedOffset = Integer.MAX_VALUE;
actionType = JavadocReformattingActionType.NONE;
}
}
}
if (lastNewLinePos >= 0) {
if (!preserveNewLines && !noFormat && i < text.length() - 2 && enableCommentFormatting && !cs.preserveNewLinesInComments() && cs.wrapCommentText()) {
lastWSPos = lastNewLinePos;
if (pendingDiff != null) {
pendingDiff.text += SPACE;
} else {
pendingDiff = new Diff(offset + lastNewLinePos, offset + i, SPACE);
}
lastNewLinePos = -1;
if (c == '*') {
int diff = 0;
while(++i < text.length()) {
col++;
c = text.charAt(i);
if (c == '\n') {
pendingDiff.text = NEWLINE + blankLineString + NEWLINE;
diff++;
preserveNewLines = true;
lastNewLinePos = i;
align = -1;
break;
} else if (!Character.isWhitespace(c)) {
break;
}
}
if (pendingDiff != null) {
diff += offset + i - pendingDiff.end;
pendingDiff.end += diff;
col -= diff;
}
}
} else {
if (pendingDiff != null) {
pendingDiff.text += indentString + SPACE;
String subs = text.substring(pendingDiff.start - offset, i);
if (pendingDiff.text.equals(subs)) {
lastNewLinePos = pendingDiff.start - offset;
pendingDiff = null;
}
} else {
// do format last line with only whitespaces and end-comment marker, even though
// comment formatting is disabled. Do properly indent javadoc, if the line nonblank text
// starts with * (as javadoc should)
if (enableCommentFormatting || i == end || (javadocTokens != null && c == '*')) {
String s = NEWLINE + indentString + SPACE;
String subs = text.substring(lastNewLinePos, i);
if (!s.equals(subs))
pendingDiff = new Diff(offset + lastNewLinePos, offset + i, s);
}
}
lastWSPos = currWSPos = -1;
col = getCol(indentString + SPACE);
if (enableCommentFormatting) {
if (c == '*') {
col++;
while (++i < text.length()) {
c = text.charAt(i);
if (c == '\n') {
if (!cs.addLeadingStarInComment()) {
String subs = text.substring(lastNewLinePos + 1, i);
if (blankLineString.equals(subs)) {
pendingDiff = null;
} else {
if (pendingDiff != null) {
pendingDiff.end = offset + i;
pendingDiff.text = NEWLINE + blankLineString;
} else {
pendingDiff = new Diff(offset + lastNewLinePos + 1, offset + i, blankLineString);
}
}
} else if (currWSPos >= 0) {
if (pendingDiff != null) {
String sub = text.substring(pendingDiff.start - offset, pendingDiff.end - offset);
if (!sub.equals(pendingDiff.text)) {
addDiff(pendingDiff);
}
}
pendingDiff = new Diff(offset + currWSPos, offset + i, javadocTokens != null && lastNWSPos >= 0 && i < initTextEndOffset && !noFormat && cs.generateParagraphTagOnBlankLines() ? SPACE + P_TAG : EMPTY);
} else if (javadocTokens != null && lastNWSPos >= 0 && i < initTextEndOffset && !noFormat && cs.generateParagraphTagOnBlankLines()) {
if (pendingDiff != null) {
String sub = text.substring(pendingDiff.start - offset, pendingDiff.end - offset);
if (!sub.equals(pendingDiff.text)) {
addDiff(pendingDiff);
}
}
pendingDiff = new Diff(offset + i, offset + i, SPACE + P_TAG);
}
currWSPos = -1;
lastNewLinePos = i;
align = -1;
break;
} else if (Character.isWhitespace(c)) {
if (currWSPos < 0) {
currWSPos = i;
col++;
}
} else if (c == '*' || c == '/') {
col++;
lastNewLinePos = -1;
break;
} else {
if (i >= markedOffset && actionType == JavadocReformattingActionType.FORMAT) {
noFormat = false;
preserveNewLines = true;
if (marksIterator.hasNext()) {
Pair<Integer, JavadocReformattingActionType> next = marksIterator.next();
markedOffset = next.first();
actionType = next.second();
} else {
markedOffset = Integer.MAX_VALUE;
actionType = JavadocReformattingActionType.NONE;
}
}
if (!cs.addLeadingStarInComment()) {
if (noFormat) {
if (pendingDiff != null) {
pendingDiff.end = currWSPos >= 0 ? offset + currWSPos + 1 : pendingDiff.end + 1;
} else {
pendingDiff = new Diff(offset + lastNewLinePos + 1, currWSPos >= 0 ? offset + currWSPos + 1 : offset + i, indentString + SPACE);
}
} else {
if (pendingDiff != null) {
pendingDiff.end = offset + i;
} else {
pendingDiff = new Diff(offset + lastNewLinePos + 1, offset + i, indentString + SPACE);
}
col = getCol(indentString + SPACE);
}
} else {
if (currWSPos < 0) {
currWSPos = i;
col++;
}
String subs = text.substring(currWSPos, i);
String s = getSpaces(align < 0 ? 1 : align - getCol(lineStartString) + 1);
if (!noFormat && !s.equals(subs)) {
if (pendingDiff != null) {
String sub = text.substring(pendingDiff.start - offset, pendingDiff.end - offset);
if (!sub.equals(pendingDiff.text)) {
addDiff(pendingDiff);
}
}
pendingDiff = new Diff(offset + currWSPos, offset + i, s);
}
}
lastNewLinePos = -1;
currWSPos = -1;
break;
}
}
} else {
if (cs.addLeadingStarInComment()) {
int num = Math.max(align - col - 1, 1);
String s = getSpaces(num);
if (pendingDiff != null) {
pendingDiff.text += (LEADING_STAR + s);
} else {
pendingDiff = new Diff(offset + i, offset + i, LEADING_STAR + s);
}
col += (num + 1);
} else if (align > col) {
int num = align - col;
String s = getSpaces(num);
if (pendingDiff != null) {
pendingDiff.text += s;
} else {
pendingDiff = new Diff(offset + i, offset + i, s);
}
col += num;
}
lastNewLinePos = -1;
}
} else {
lastNewLinePos = -1;
}
if (pendingDiff != null) {
String sub = text.substring(pendingDiff.start - offset, pendingDiff.end - offset);
if (!sub.equals(pendingDiff.text)) {
addDiff(pendingDiff);
}
pendingDiff = null;
}
}
} else if (enableCommentFormatting) {
if (firstLine) {
String s = !noFormat && cs.wrapOneLineComments() ? NEWLINE + lineStartString : SPACE;
String sub = currWSPos >= 0 ? text.substring(currWSPos, i) : null;
if (!s.equals(sub))
addDiff(new Diff(currWSPos >= 0 ? offset + currWSPos : offset + i, offset + i, s));
if (!noFormat && cs.wrapOneLineComments())
col = getCol(lineStartString);
firstLine = false;
} else if (currWSPos >= 0) {
if (!noFormat) {
lastWSPos = currWSPos;
if (currWSPos < i - 1)
pendingDiff = new Diff(offset + currWSPos + 1, offset + i, null);
}
} else if (c != '*') {
preserveNewLines = false;
}
} else if (c != '*') {
preserveNewLines = false;
}
currWSPos = -1;
col++;
}
}
if (enableCommentFormatting) {
for (int i = text.length() - 3; i >= 0; i--) {
char c = text.charAt(i);
if (c == '\n') {
break;
} else if (!Character.isWhitespace(c)) {
String s = !noFormat && cs.wrapOneLineComments() ? NEWLINE + indentString + SPACE : SPACE;
String sub = text.substring(i + 1, text.length() - 2);
if (!s.equals(sub))
addDiff(new Diff(offset + i + 1, offset + text.length() - 2, s));
break;
}
}
}
}