### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core Index: formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor.java,v retrieving revision 1.232 diff -u -r1.232 CodeFormatterVisitor.java --- formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor.java 23 Apr 2010 10:04:25 -0000 1.232 +++ formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor.java 3 May 2010 11:30:12 -0000 @@ -4966,7 +4966,7 @@ ASTNode[] fragments = stringLiteral.literals; int fragmentsSize = stringLiteral.counter; Alignment binaryExpressionAlignment = this.scribe.createAlignment( - Alignment.BINARY_EXPRESSION, + Alignment.STRING_CONCATENATION, this.preferences.alignment_for_binary_expression, Alignment.R_OUTERMOST, fragmentsSize, Index: formatter/org/eclipse/jdt/internal/formatter/Scribe.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/formatter/org/eclipse/jdt/internal/formatter/Scribe.java,v retrieving revision 1.206 diff -u -r1.206 Scribe.java --- formatter/org/eclipse/jdt/internal/formatter/Scribe.java 25 Apr 2010 18:23:00 -0000 1.206 +++ formatter/org/eclipse/jdt/internal/formatter/Scribe.java 3 May 2010 11:30:13 -0000 @@ -83,6 +83,7 @@ // Line separator infos final private String lineSeparator; + final private String lineSeparatorAndSpace; final private char firstLS; final private int lsLength; @@ -138,6 +139,21 @@ OptimizedReplaceEdit previousDisabledEdit; private char[] disablingTag, enablingTag; + // Well know strings + private String[] newEmptyLines = new String[10]; + private static String[] COMMENT_INDENTATIONS = new String[20]; + + // final string buffers + private final StringBuffer tempBuffer= new StringBuffer(); + private final StringBuffer blockCommentBuffer = new StringBuffer(); + private final StringBuffer blockCommentTokensBuffer = new StringBuffer(); + private final StringBuffer codeSnippetBuffer = new StringBuffer(); + private final StringBuffer javadocBlockRefBuffer= new StringBuffer(); + private final StringBuffer javadocGapLinesBuffer = new StringBuffer(); + private StringBuffer[] javadocHtmlTagBuffers = new StringBuffer[5]; + private final StringBuffer javadocTextBuffer = new StringBuffer(); + private final StringBuffer javadocTokensBuffer = new StringBuffer(); + Scribe(CodeFormatterVisitor formatter, long sourceLevel, IRegion[] regions, CodeSnippetParsingUtil codeSnippetParsingUtil, boolean includeComments) { initializeScanner(sourceLevel, formatter.preferences); this.formatter = formatter; @@ -154,6 +170,7 @@ this.indentationSize = this.tabLength; } this.lineSeparator = formatter.preferences.line_separator; + this.lineSeparatorAndSpace = this.lineSeparator+' '; this.firstLS = this.lineSeparator.charAt(0); this.lsLength = this.lineSeparator.length(); this.indentationLevel = formatter.preferences.initial_indentation_level * this.indentationSize; @@ -427,11 +444,7 @@ if (linesCount == 0) { edit.replacement = ""; //$NON-NLS-1$ } else { - StringBuffer buffer = new StringBuffer(); - for (int j=0; j 0) { return Util.EMPTY_STRING; } - StringBuffer buffer = new StringBuffer(); + String emptyLines; if (this.lastNumberOfNewLines == 0) { linesNumber++; // add an extra line breaks - for (int i = 0; i < linesNumber; i++) { - if (this.indentEmptyLines) printIndentationIfNecessary(buffer); - buffer.append(this.lineSeparator); + if (this.indentEmptyLines) { + this.tempBuffer.setLength(0); + for (int i = 0; i < linesNumber; i++) { + printIndentationIfNecessary(this.tempBuffer); + this.tempBuffer.append(this.lineSeparator); + } + emptyLines = this.tempBuffer.toString(); + } else { + emptyLines = getNewLineString(linesNumber); } this.lastNumberOfNewLines += linesNumber; this.line += linesNumber; @@ -943,9 +962,15 @@ this.needSpace = false; this.pendingSpace = false; } else if (this.lastNumberOfNewLines == 1) { - for (int i = 0; i < linesNumber; i++) { - if (this.indentEmptyLines) printIndentationIfNecessary(buffer); - buffer.append(this.lineSeparator); + if (this.indentEmptyLines) { + this.tempBuffer.setLength(0); + for (int i = 0; i < linesNumber; i++) { + printIndentationIfNecessary(this.tempBuffer); + this.tempBuffer.append(this.lineSeparator); + } + emptyLines = this.tempBuffer.toString(); + } else { + emptyLines = getNewLineString(linesNumber); } this.lastNumberOfNewLines += linesNumber; this.line += linesNumber; @@ -958,9 +983,15 @@ return Util.EMPTY_STRING; } final int realNewLineNumber = linesNumber - this.lastNumberOfNewLines + 1; - for (int i = 0; i < realNewLineNumber; i++) { - if (this.indentEmptyLines) printIndentationIfNecessary(buffer); - buffer.append(this.lineSeparator); + if (this.indentEmptyLines) { + this.tempBuffer.setLength(0); + for (int i = 0; i < realNewLineNumber; i++) { + printIndentationIfNecessary(this.tempBuffer); + this.tempBuffer.append(this.lineSeparator); + } + emptyLines = this.tempBuffer.toString(); + } else { + emptyLines = getNewLineString(realNewLineNumber); } this.lastNumberOfNewLines += realNewLineNumber; this.line += realNewLineNumber; @@ -968,7 +999,7 @@ this.needSpace = false; this.pendingSpace = false; } - return String.valueOf(buffer); + return emptyLines; } private int getIndexOfAdaptedRegionAt(int offset) { @@ -1026,6 +1057,23 @@ return this.lineSeparator; } + private String getNewLineString(int linesCount) { + int length = this.newEmptyLines.length; + if (linesCount > length) { + System.arraycopy(this.newEmptyLines, 0, this.newEmptyLines = new String[linesCount+10], 0, length); + } + String newLineString = this.newEmptyLines[linesCount-1]; + if (newLineString == null) { + this.tempBuffer.setLength(0); + for (int j=0; j 0 && targetAlignment.kind == Alignment.MESSAGE_ARGUMENTS && + (!targetAlignment.wasReset() || previousKind != Alignment.MESSAGE_SEND)); if (couldBreak && targetAlignment.couldBreak()){ outerMostDepth = relativeDepth; } switch (targetAlignment.kind) { case Alignment.MESSAGE_ARGUMENTS: - insideMessageArguments = true; - break; case Alignment.MESSAGE_SEND: - insideMessageSend = true; + insideMessage++; + break; + case Alignment.STRING_CONCATENATION: + insideStringConcat = true; break; } previousKind = targetAlignment.kind; @@ -1251,6 +1302,7 @@ // do not throw the exception immediately to have a chance to reset // previously broken alignments (see bug 203588) alignmentException = new AlignmentException(AlignmentException.LINE_TOO_LONG, relativeDepth); + if (insideStringConcat) throw alignmentException; } } else if (targetAlignment.wasSplit) { // reset the nearest already broken outermost alignment. @@ -1532,13 +1584,8 @@ this.line++; isNewLine = false; - StringBuffer buffer = new StringBuffer(); + boolean addSpace = false; if (onFirstColumn) { - // simply insert indentation if necessary - buffer.append(this.lineSeparator); - if (indentComment) { - printIndentationIfNecessary(buffer); - } if (formatComment) { if (ScannerHelper.isWhitespace((char) currentCharacter)) { int previousStartPosition = this.scanner.currentPosition; @@ -1553,7 +1600,7 @@ } } if (currentCharacter != '\r' && currentCharacter != '\n') { - buffer.append(' '); + addSpace = true; } } } else { @@ -1587,10 +1634,6 @@ nextCharacterStart = previousStartPosition; } } - buffer.append(this.lineSeparator); - if (indentComment) { - printIndentationIfNecessary(buffer); - } if (formatComment) { int previousStartTemp = previousStart; int nextCharacterStartTemp = nextCharacterStart; @@ -1600,7 +1643,7 @@ nextCharacterStart = this.scanner.currentPosition; } if (currentCharacter == '*') { - buffer.append(' '); + addSpace = true; } else { previousStart = previousStartTemp; nextCharacterStart = nextCharacterStartTemp; @@ -1608,7 +1651,21 @@ this.scanner.currentPosition = nextCharacterStart; } } - addReplaceEdit(start, previousStart - 1, String.valueOf(buffer)); + String replacement; + if (indentComment) { + this.tempBuffer.setLength(0); + this.tempBuffer.append(this.lineSeparator); + if (this.indentationLevel > 0) { + printIndentationIfNecessary(this.tempBuffer); + } + if (addSpace) { + this.tempBuffer.append(' '); + } + replacement = this.tempBuffer.toString(); + } else { + replacement = addSpace ? this.lineSeparatorAndSpace : this.lineSeparator; + } + addReplaceEdit(start, previousStart - 1, replacement); } else { this.column += (nextCharacterStart - previousStart); } @@ -1670,12 +1727,12 @@ } // Consume the comment prefix - StringBuffer buffer = new StringBuffer(); + this.blockCommentBuffer.setLength(0); this.scanner.getNextChar(); this.scanner.getNextChar(); this.column += 2; this.scanner.skipComments = true; - StringBuffer tokensBuffer = new StringBuffer(); + this.blockCommentTokensBuffer.setLength(0); int editStart = this.scanner.currentPosition; int editEnd = -1; @@ -1713,14 +1770,14 @@ boolean isTokenStar = false; switch (token) { case TerminalTokens.TokenNameWHITESPACE: - if (tokensBuffer.length() > 0) { + if (this.blockCommentTokensBuffer.length() > 0) { if (hasTextOnFirstLine == 1 && multiLines) { - printBlockCommentHeaderLine(buffer); + printBlockCommentHeaderLine(this.blockCommentBuffer); hasTextOnFirstLine = -1; } - buffer.append(tokensBuffer); - this.column += tokensBuffer.length(); - tokensBuffer.setLength(0); + this.blockCommentBuffer.append(this.blockCommentTokensBuffer); + this.column += this.blockCommentTokensBuffer.length(); + this.blockCommentTokensBuffer.setLength(0); bufferHasTokens = true; bufferHasNewLine = false; } @@ -1741,25 +1798,25 @@ isTokenStar = true; lineNumber = Util.getLineNumber(this.scanner.currentPosition, this.lineEnds, scannerLine>1 ? scannerLine-2 : 0, this.maxLines); if (lineNumber == firstLine && previousToken == SKIP_FIRST_WHITESPACE_TOKEN) { - buffer.append(' '); + this.blockCommentBuffer.append(' '); } previousToken = token; if (this.scanner.currentCharacter == '/') { editEnd = this.scanner.startPosition - 1; // Add remaining buffered tokens - if (tokensBuffer.length() > 0) { - buffer.append(tokensBuffer); - this.column += tokensBuffer.length(); + if (this.blockCommentTokensBuffer.length() > 0) { + this.blockCommentBuffer.append(this.blockCommentTokensBuffer); + this.column += this.blockCommentTokensBuffer.length(); } // end of comment if (newLinesAtBoundaries) { if (multiLines || hasMultiLines) { - buffer.append(this.lineSeparator); + this.blockCommentBuffer.append(this.lineSeparator); this.column = 1; - printIndentationIfNecessary(buffer); + printIndentationIfNecessary(this.blockCommentBuffer); } } - buffer.append(' '); + this.blockCommentBuffer.append(' '); this.column += BLOCK_FOOTER_LENGTH + 1; this.scanner.getNextChar(); // reach the end of scanner continue; @@ -1824,19 +1881,19 @@ } for (int i=0; i 0) { + if (this.blockCommentTokensBuffer.length() > 0) { if (hasTextOnFirstLine == 1) { - printBlockCommentHeaderLine(buffer); + printBlockCommentHeaderLine(this.blockCommentBuffer); hasTextOnFirstLine = -1; } - buffer.append(tokensBuffer); - tokensBuffer.setLength(0); + this.blockCommentBuffer.append(this.blockCommentTokensBuffer); + this.blockCommentTokensBuffer.setLength(0); bufferHasTokens = true; } - buffer.append(this.lineSeparator); + this.blockCommentBuffer.append(this.lineSeparator); this.column = 1; - printIndentationIfNecessary(buffer); - buffer.append(BLOCK_LINE_PREFIX); + printIndentationIfNecessary(this.blockCommentBuffer); + this.blockCommentBuffer.append(BLOCK_LINE_PREFIX); this.column += BLOCK_LINE_PREFIX_LENGTH; firstWord = true; multiLines = true; @@ -1859,39 +1916,39 @@ hasTextOnFirstLine = -1; } } - int lastColumn = this.column + tokensBuffer.length() + tokenLength; + int lastColumn = this.column + this.blockCommentTokensBuffer.length() + tokenLength; if (insertSpace) lastColumn++; // Append next token inserting a new line if max line is reached if (lineHasTokens && !firstWord && lastColumn > maxColumn) { - String tokensString = tokensBuffer.toString().trim(); + String tokensString = this.blockCommentTokensBuffer.toString().trim(); int tokensStringLength = tokensString.length(); // not enough space on the line if (hasTextOnFirstLine == 1) { - printBlockCommentHeaderLine(buffer); + printBlockCommentHeaderLine(this.blockCommentBuffer); } if ((this.indentationLevel+tokensStringLength+tokenLength) > maxColumn) { // there won't be enough room even if we break the line before the buffered tokens // So add the buffered tokens now - buffer.append(tokensBuffer); - this.column += tokensBuffer.length(); - tokensBuffer.setLength(0); + this.blockCommentBuffer.append(this.blockCommentTokensBuffer); + this.column += this.blockCommentTokensBuffer.length(); + this.blockCommentTokensBuffer.setLength(0); bufferHasNewLine = false; bufferHasTokens = true; } if (bufferHasTokens && !bufferHasNewLine) { - buffer.append(this.lineSeparator); + this.blockCommentBuffer.append(this.lineSeparator); this.column = 1; - printIndentationIfNecessary(buffer); - buffer.append(BLOCK_LINE_PREFIX); + printIndentationIfNecessary(this.blockCommentBuffer); + this.blockCommentBuffer.append(BLOCK_LINE_PREFIX); this.column += BLOCK_LINE_PREFIX_LENGTH; } - if (tokensBuffer.length() > 0) { - buffer.append(tokensString); + if (this.blockCommentTokensBuffer.length() > 0) { + this.blockCommentBuffer.append(tokensString); this.column += tokensStringLength; - tokensBuffer.setLength(0); + this.blockCommentTokensBuffer.setLength(0); } - buffer.append(this.scanner.source, tokenStart, tokenLength); + this.blockCommentBuffer.append(this.scanner.source, tokenStart, tokenLength); bufferHasTokens = true; bufferHasNewLine = false; this.column += tokenLength; @@ -1900,9 +1957,9 @@ } else { // append token to the line if (insertSpace) { - tokensBuffer.append(' '); + this.blockCommentTokensBuffer.append(' '); } - tokensBuffer.append(this.scanner.source, tokenStart, tokenLength); + this.blockCommentTokensBuffer.append(this.scanner.source, tokenStart, tokenLength); } previousToken = token; newLine = false; @@ -1914,8 +1971,10 @@ // Replace block comment text if (this.nlsTagCounter == 0 || !multiLines) { if (hasTokens || multiLines) { - StringBuffer replacement = new StringBuffer(); + StringBuffer replacement; if (hasTextOnFirstLine == 1) { + this.blockCommentTokensBuffer.setLength(0); + replacement = this.blockCommentTokensBuffer; if ((hasMultiLines || multiLines)) { int col = this.column; replacement.append(this.lineSeparator); @@ -1923,11 +1982,13 @@ printIndentationIfNecessary(replacement); replacement.append(BLOCK_LINE_PREFIX); this.column = col; - } else if (buffer.length()==0 || buffer.charAt(0)!=' ') { + } else if (this.blockCommentBuffer.length()==0 || this.blockCommentBuffer.charAt(0)!=' ') { replacement.append(' '); } + replacement.append(this.blockCommentBuffer); + } else { + replacement = this.blockCommentBuffer; } - replacement.append(buffer); addReplaceEdit(editStart, editEnd, replacement.toString()); } } @@ -1954,13 +2015,13 @@ buffer.append(BLOCK_LINE_PREFIX); this.column += BLOCK_LINE_PREFIX_LENGTH; } else { - StringBuffer insert = new StringBuffer(); - insert.append(this.lineSeparator); + this.tempBuffer.setLength(0); + this.tempBuffer.append(this.lineSeparator); this.column = 1; - printIndentationIfNecessary(insert); - insert.append(BLOCK_LINE_PREFIX); + printIndentationIfNecessary(this.tempBuffer); + this.tempBuffer.append(BLOCK_LINE_PREFIX); this.column += BLOCK_LINE_PREFIX_LENGTH; - buffer.insert(0, insert.toString()); + buffer.insert(0, this.tempBuffer.toString()); } } @@ -2093,16 +2154,16 @@ // 1 - strip content prefix (@see JavaDocRegion#preprocessCodeSnippet) int firstLine = Util.getLineNumber(startPosition, this.lineEnds, 0, this.maxLines) - 1; int lastLine = Util.getLineNumber(endPosition, this.lineEnds, firstLine>1 ? firstLine-2 : 0, this.maxLines) - 1; - StringBuffer inputBuffer= new StringBuffer(); + this.codeSnippetBuffer.setLength(0); if (firstLine == lastLine && linesGap == 0) { - inputBuffer.append(snippet); + this.codeSnippetBuffer.append(snippet); } else { boolean hasCharsAfterStar = false; if (linesGap == 0) { - inputBuffer.append(this.scanner.source, startPosition, this.lineEnds[firstLine]+1-startPosition); + this.codeSnippetBuffer.append(this.scanner.source, startPosition, this.lineEnds[firstLine]+1-startPosition); firstLine++; } - int initialLength = inputBuffer.length(); + int initialLength = this.codeSnippetBuffer.length(); for (int currentLine=firstLine; currentLine<=lastLine; currentLine++) { this.scanner.resetTo(this.lineEnds[currentLine-1]+1, this.lineEnds[currentLine]); int lineStart = this.scanner.currentPosition; @@ -2149,7 +2210,7 @@ // consuming the space after the star hasCharsAfterStar = true; currentLine = firstLine-1; - inputBuffer.setLength(initialLength); + this.codeSnippetBuffer.setLength(initialLength); continue; } } @@ -2164,13 +2225,13 @@ } } int end = currentLine == lastLine ? endPosition : this.lineEnds[currentLine]; - inputBuffer.append(this.scanner.source, lineStart, end+1-lineStart); + this.codeSnippetBuffer.append(this.scanner.source, lineStart, end+1-lineStart); } } // 2 - convert HTML to Java (@see JavaDocRegion#convertHtml2Java) - HTMLEntity2JavaReader reader= new HTMLEntity2JavaReader(new StringReader(inputBuffer.toString())); - char[] buf= new char[inputBuffer.length()]; // html2text never gets longer, only shorter! + HTMLEntity2JavaReader reader= new HTMLEntity2JavaReader(new StringReader(this.codeSnippetBuffer.toString())); + char[] buf= new char[this.codeSnippetBuffer.length()]; // html2text never gets longer, only shorter! String convertedSnippet; try { int read= reader.read(buf); @@ -2191,7 +2252,7 @@ TextEdit edit= CommentFormatterUtil.format2(CodeFormatter.K_UNKNOWN | CodeFormatter.F_INCLUDE_COMMENTS, convertedSnippet, 0, this.lineSeparator, options); if (edit == null) { // 3.a - not a valid code to format, keep initial buffer - formattedSnippet = inputBuffer.toString(); + formattedSnippet = this.codeSnippetBuffer.toString(); } else { // 3.b - valid code formatted // 3.b.i - get the result @@ -2200,15 +2261,15 @@ // 3.b.ii- convert back to HTML (@see JavaDocRegion#convertJava2Html) Java2HTMLEntityReader javaReader= new Java2HTMLEntityReader(new StringReader(formattedSnippet)); buf= new char[256]; - StringBuffer conversionBuffer= new StringBuffer(); + this.codeSnippetBuffer.setLength(0); int l; try { do { l= javaReader.read(buf); if (l != -1) - conversionBuffer.append(buf, 0, l); + this.codeSnippetBuffer.append(buf, 0, l); } while (l > 0); - formattedSnippet = conversionBuffer.toString(); + formattedSnippet = this.codeSnippetBuffer.toString(); } catch (IOException e) { // should not happen CommentFormatterUtil.log(e); @@ -2217,32 +2278,32 @@ } // 4 - add the content prefix (@see JavaDocRegion#postprocessCodeSnippet) - StringBuffer outputBuffer = new StringBuffer(); + this.codeSnippetBuffer.setLength(0); ILineTracker tracker = new DefaultLineTracker(); this.column = 1; - printIndentationIfNecessary(outputBuffer); // append indentation - outputBuffer.append(BLOCK_LINE_PREFIX); - String linePrefix = outputBuffer.toString(); - outputBuffer.setLength(0); + printIndentationIfNecessary(this.codeSnippetBuffer); // append indentation + this.codeSnippetBuffer.append(BLOCK_LINE_PREFIX); + String linePrefix = this.codeSnippetBuffer.toString(); + this.codeSnippetBuffer.setLength(0); String replacement = formattedSnippet; tracker.set(formattedSnippet); int numberOfLines = tracker.getNumberOfLines(); if (numberOfLines > 1) { int lastLineOffset = -1; for (int i=0; i0) outputBuffer.append(linePrefix); + if (i>0) this.codeSnippetBuffer.append(linePrefix); try { lastLineOffset = tracker.getLineOffset(i+1); - outputBuffer.append(formattedSnippet.substring(tracker.getLineOffset(i), lastLineOffset)); + this.codeSnippetBuffer.append(formattedSnippet.substring(tracker.getLineOffset(i), lastLineOffset)); } catch (BadLocationException e) { // should not happen CommentFormatterUtil.log(e); return; } } - outputBuffer.append(linePrefix); - outputBuffer.append(formattedSnippet.substring(lastLineOffset)); - replacement = outputBuffer.toString(); + this.codeSnippetBuffer.append(linePrefix); + this.codeSnippetBuffer.append(formattedSnippet.substring(lastLineOffset)); + replacement = this.codeSnippetBuffer.toString(); } // 5 - replace old text with the formatted snippet @@ -2778,14 +2839,15 @@ this.lastNumberOfNewLines++; this.line++; if (newLineString == null) { - StringBuffer newLineBuffer = new StringBuffer(this.lineSeparator); + this.tempBuffer.setLength(0); + this.tempBuffer.append(this.lineSeparator); this.column = 1; if (!this.formatter.preferences.never_indent_line_comments_on_first_column) { - printIndentationIfNecessary(newLineBuffer); + printIndentationIfNecessary(this.tempBuffer); } - newLineBuffer.append(LINE_COMMENT_PREFIX); + this.tempBuffer.append(LINE_COMMENT_PREFIX); this.column += LINE_COMMENT_PREFIX_LENGTH; - newLineString = newLineBuffer.toString(); + newLineString = this.tempBuffer.toString(); firstColumn = this.column; } else { this.column = firstColumn; @@ -2850,10 +2912,10 @@ } void printIndentationIfNecessary() { - StringBuffer buffer = new StringBuffer(); - printIndentationIfNecessary(buffer); - if (buffer.length() > 0) { - addInsertEdit(this.scanner.getCurrentTokenStartPosition(), buffer.toString()); + this.tempBuffer.setLength(0); + printIndentationIfNecessary(this.tempBuffer); + if (this.tempBuffer.length() > 0) { + addInsertEdit(this.scanner.getCurrentTokenStartPosition(), this.tempBuffer.toString()); this.pendingSpace = false; } } @@ -2981,15 +3043,7 @@ commentIndentationLevel += this.indentationSize; } } - if (commentIndentationLevel == 0) { - this.commentIndentation = null; - } else { - StringBuffer indentationBuffer = new StringBuffer(); - for (int i=0; i 0) { for (int j=0; j textEndPosition) { if (newLines > 0) { - StringBuffer buffer = new StringBuffer(); + this.javadocGapLinesBuffer.setLength(0); for (int i=0; i 0) { - StringBuffer buffer = new StringBuffer(); + this.javadocGapLinesBuffer.setLength(0); if (lineCount > 0) { // TODO https://bugs.eclipse.org/bugs/show_bug.cgi?id=49619 - buffer.append( ' '); + this.javadocGapLinesBuffer.append( ' '); } for (int i = 0; i < linesGap ; i++) { if (clearBlankLines && lineCount >= newLines) { @@ -3523,21 +3578,21 @@ // so remove any remaining blanks and leave if (textEndPosition >= start) { if (output == null) { - addReplaceEdit(start, textEndPosition, buffer.toString()); + addReplaceEdit(start, textEndPosition, this.javadocGapLinesBuffer.toString()); } else { - output.append(buffer); + output.append(this.javadocGapLinesBuffer); } } return; } - buffer.append(this.lineSeparator); + this.javadocGapLinesBuffer.append(this.lineSeparator); this.column = 1; - printIndentationIfNecessary(buffer); + printIndentationIfNecessary(this.javadocGapLinesBuffer); if (i == (linesGap-1)) { - buffer.append(' '); + this.javadocGapLinesBuffer.append(' '); this.column++; } else { - buffer.append(BLOCK_LINE_PREFIX); + this.javadocGapLinesBuffer.append(BLOCK_LINE_PREFIX); this.column += BLOCK_LINE_PREFIX_LENGTH; } lineCount++; @@ -3545,9 +3600,9 @@ int currentTokenStartPosition = this.scanner.getCurrentTokenStartPosition(); int tokenLength = this.scanner.currentPosition - currentTokenStartPosition; if (output == null) { - addReplaceEdit(start, currentTokenStartPosition-1, buffer.toString()); + addReplaceEdit(start, currentTokenStartPosition-1, this.javadocGapLinesBuffer.toString()); } else { - output.append(buffer); + output.append(this.javadocGapLinesBuffer); output.append(this.scanner.source, currentTokenStartPosition, tokenLength); } this.column += tokenLength; @@ -3574,51 +3629,51 @@ // Format the last whitespaces if (lineCount < newLines) { // Insert new lines as not enough was encountered while scanning the whitespaces - StringBuffer buffer = new StringBuffer(); + this.javadocGapLinesBuffer.setLength(0); if (lineCount > 0) { // TODO https://bugs.eclipse.org/bugs/show_bug.cgi?id=49619 - buffer.append( ' '); + this.javadocGapLinesBuffer.append( ' '); } for (int i = lineCount; i < newLines-1; i++) { - printJavadocNewLine(buffer); + printJavadocNewLine(this.javadocGapLinesBuffer); } - buffer.append(this.lineSeparator); + this.javadocGapLinesBuffer.append(this.lineSeparator); this.column = 1; - printIndentationIfNecessary(buffer); + printIndentationIfNecessary(this.javadocGapLinesBuffer); if (footer) { - buffer.append(' '); + this.javadocGapLinesBuffer.append(' '); this.column++; } else { - buffer.append(BLOCK_LINE_PREFIX); + this.javadocGapLinesBuffer.append(BLOCK_LINE_PREFIX); this.column += BLOCK_LINE_PREFIX_LENGTH; } if (output == null) { if (textEndPosition >= start) { - addReplaceEdit(start, textEndPosition, buffer.toString()); + addReplaceEdit(start, textEndPosition, this.javadocGapLinesBuffer.toString()); } else { - addInsertEdit(textEndPosition+1, buffer.toString()); + addInsertEdit(textEndPosition+1, this.javadocGapLinesBuffer.toString()); } } else { - output.append(buffer); + output.append(this.javadocGapLinesBuffer); } } else { // Replace all remaining whitespaces by a single space if (textEndPosition >= start) { - StringBuffer buffer = new StringBuffer(); + this.javadocGapLinesBuffer.setLength(0); if (this.scanner.linePtr > linePtr) { if (lineCount > 0) { // TODO https://bugs.eclipse.org/bugs/show_bug.cgi?id=49619 - buffer.append( ' '); + this.javadocGapLinesBuffer.append(' '); } - buffer.append(this.lineSeparator); + this.javadocGapLinesBuffer.append(this.lineSeparator); this.column = 1; - printIndentationIfNecessary(buffer); + printIndentationIfNecessary(this.javadocGapLinesBuffer); } - buffer.append(' '); + this.javadocGapLinesBuffer.append(' '); if (output == null) { - addReplaceEdit(start, textEndPosition, buffer.toString()); + addReplaceEdit(start, textEndPosition, this.javadocGapLinesBuffer.toString()); } else { - output.append(buffer); + output.append(this.javadocGapLinesBuffer); } this.needSpace = false; } else if (endsOnMultiply) { @@ -3650,7 +3705,7 @@ // Iterate on text line separators int textLineStart = text.lineStart; this.scanner.tokenizeWhiteSpace = false; - StringBuffer buffer = null; + String newLineString = null; for (int idx=0, max=text.separatorsPtr; idx<=max ; idx++) { int start = (int) text.separators[idx]; int lineStart = Util.getLineNumber(start, this.lineEnds, textLineStart-1, this.maxLines); @@ -3668,14 +3723,15 @@ if (this.scanner.currentCharacter == ' ') { this.scanner.getNextChar(); } - if (buffer == null) { - buffer = new StringBuffer(); + if (newLineString == null) { + this.tempBuffer.setLength(0); this.column = 1; - printIndentationIfNecessary(buffer); - buffer.append(BLOCK_LINE_PREFIX); + printIndentationIfNecessary(this.tempBuffer); + this.tempBuffer.append(BLOCK_LINE_PREFIX); this.column += BLOCK_LINE_PREFIX_LENGTH; + newLineString = this.tempBuffer.toString(); } - addReplaceEdit(end+1, this.scanner.getCurrentTokenEndPosition(), buffer.toString()); + addReplaceEdit(end+1, this.scanner.getCurrentTokenEndPosition(), newLineString); textLineStart++; } } @@ -3713,7 +3769,7 @@ int lineEnd = Util.getLineNumber(block.nodes[0].sourceEnd, this.lineEnds, lineStart-1, this.maxLines); boolean multiLinesBlock = lineEnd > (lineStart+1); int previousPosition = this.scanner.currentPosition; - StringBuffer buffer = null; + String newLineString = null; int indentationColumn = 0; int leadingSpaces = -1; @@ -3747,17 +3803,18 @@ } // print indentation if there were spaces without any star on the line if (leadingSpaces > 0 && multiLinesBlock) { - if (buffer == null) { - buffer = new StringBuffer(); + if (newLineString == null) { this.column = 1; - printIndentationIfNecessary(buffer); - buffer.append(BLOCK_LINE_PREFIX); + this.tempBuffer.setLength(0); + printIndentationIfNecessary(this.tempBuffer); + this.tempBuffer.append(BLOCK_LINE_PREFIX); this.column += BLOCK_LINE_PREFIX_LENGTH; + newLineString = this.tempBuffer.toString(); indentationColumn = this.column; } else { this.column = indentationColumn; } - addReplaceEdit(newLineStart, newLineStart+indentationColumn-2, buffer.toString()); + addReplaceEdit(newLineStart, newLineStart+indentationColumn-2, newLineString); } // store line start and reset positions newLineStart = this.scanner.currentPosition; @@ -3785,17 +3842,18 @@ } else { // print indentation before the following characters if (offset == 0 && multiLinesBlock) { - if (buffer == null) { - buffer = new StringBuffer(); + if (newLineString == null) { + this.tempBuffer.setLength(0); this.column = 1; - printIndentationIfNecessary(buffer); - buffer.append(BLOCK_LINE_PREFIX); + printIndentationIfNecessary(this.tempBuffer); + this.tempBuffer.append(BLOCK_LINE_PREFIX); this.column += BLOCK_LINE_PREFIX_LENGTH; indentationColumn = this.column; + newLineString = this.tempBuffer.toString(); } else { this.column = indentationColumn; } - addReplaceEdit(newLineStart, secondLineStart-1, buffer.toString()); + addReplaceEdit(newLineStart, secondLineStart-1, newLineString); } offset++; } @@ -3824,30 +3882,32 @@ addReplaceEdit(firstLineEnd, end, " "); //$NON-NLS-1$ } else if (secondLineStart > 0) { - if (buffer == null) { - buffer = new StringBuffer(); + if (newLineString == null) { + this.tempBuffer.setLength(0); this.column = 1; - printIndentationIfNecessary(buffer); - buffer.append(BLOCK_LINE_PREFIX); + printIndentationIfNecessary(this.tempBuffer); + this.tempBuffer.append(BLOCK_LINE_PREFIX); this.column += BLOCK_LINE_PREFIX_LENGTH; + newLineString = this.tempBuffer.toString(); indentationColumn = this.column; } else { this.column = indentationColumn; } - addReplaceEdit(newLineStart, secondLineStart-1, buffer.toString()); + addReplaceEdit(newLineStart, secondLineStart-1, newLineString); } else if (leadingSpaces > 0) { - if (buffer == null) { - buffer = new StringBuffer(); + if (newLineString == null) { + this.tempBuffer.setLength(0); this.column = 1; - printIndentationIfNecessary(buffer); - buffer.append(BLOCK_LINE_PREFIX); + printIndentationIfNecessary(this.tempBuffer); + this.tempBuffer.append(BLOCK_LINE_PREFIX); this.column += BLOCK_LINE_PREFIX_LENGTH; + newLineString = this.tempBuffer.toString(); indentationColumn = this.column; } else { this.column = indentationColumn; } - addReplaceEdit(newLineStart, newLineStart+indentationColumn-2, buffer.toString()); + addReplaceEdit(newLineStart, newLineStart+indentationColumn-2, newLineString); } // Reset @@ -3868,7 +3928,17 @@ int nextStart = textStart; int startLine = Util.getLineNumber(textStart, this.lineEnds, 0, this.maxLines); int htmlTagID = text.getHtmlTagID(); - StringBuffer buffer = new StringBuffer(); + if (text.depth >= this.javadocHtmlTagBuffers.length) { + int length = this.javadocHtmlTagBuffers.length; + System.arraycopy(this.javadocHtmlTagBuffers, 0, this.javadocHtmlTagBuffers = new StringBuffer[text.depth+6], 0, length); + } + StringBuffer buffer = this.javadocHtmlTagBuffers[text.depth]; + if (buffer == null) { + buffer = new StringBuffer(); + this.javadocHtmlTagBuffers[text.depth] = buffer; + } else { + buffer.setLength(0); + } // New line will be added before next node int max = text.separatorsPtr; @@ -3911,7 +3981,7 @@ printJavadocGapLines(previousEnd+1, nodeStart-1, newLines, clearBlankLines, false, null); } if (newLines > 0) textOnNewLine = true; - buffer = new StringBuffer(); + buffer.setLength(0); if (node.isText()) { if (immutable) { // do not change immutable tags, just increment column @@ -4077,13 +4147,13 @@ this.column += BLOCK_LINE_PREFIX_LENGTH; this.line++; this.lastNumberOfNewLines++; - } + } private void printJavadocText(FormatJavadocText text, FormatJavadocBlock block, boolean textOnNewLine) { boolean clearBlankLines = this.formatter.preferences.comment_clear_blank_lines_in_javadoc_comment; boolean joinLines = this.formatter.preferences.join_lines_in_comments; - StringBuffer buffer = new StringBuffer(); + this.javadocTextBuffer.setLength(0); int textStart = text.sourceStart; int nextStart = textStart; int startLine = Util.getLineNumber(textStart, this.lineEnds, 0, this.maxLines); @@ -4100,7 +4170,7 @@ } } this.needSpace = idx > 0; - printJavadocTextLine(buffer, nextStart, end, block, idx==0 || (!joinLines && textOnNewLine)/*first text?*/, needIndentation, false /*not an html tag*/); + printJavadocTextLine(this.javadocTextBuffer, nextStart, end, block, idx==0 || (!joinLines && textOnNewLine)/*first text?*/, needIndentation, false /*not an html tag*/); textOnNewLine = false; // Replace with current buffer if there are several empty lines between text lines @@ -4111,9 +4181,9 @@ int gapLine = endLine; if (joinLines) gapLine++; // if not preserving line break then gap must be at least of one line if (startLine > gapLine) { - addReplaceEdit(textStart, end, buffer.toString()); + addReplaceEdit(textStart, end, this.javadocTextBuffer.toString()); textStart = nextStart; - buffer.setLength(0); + this.javadocTextBuffer.setLength(0); int newLines = startLine - endLine; if (clearBlankLines) newLines = 1; printJavadocGapLines(end+1, nextStart-1, newLines, this.formatter.preferences.comment_clear_blank_lines_in_javadoc_comment, false, null); @@ -4128,10 +4198,10 @@ // Replace remaining line boolean needIndentation = textOnNewLine; this.needSpace = text.separatorsPtr >= 0; - printJavadocTextLine(buffer, nextStart, text.sourceEnd, block, text.separatorsPtr==-1 /* first text?*/, needIndentation, false /*not an html tag*/); + printJavadocTextLine(this.javadocTextBuffer, nextStart, text.sourceEnd, block, text.separatorsPtr==-1 /* first text?*/, needIndentation, false /*not an html tag*/); // TODO Bring back following optimization // if (lastNewLines != this.lastNumberOfNewLines || (this.column - currentColumn) != (text.sourceEnd - text.sourceStart + 1)) { - addReplaceEdit(textStart, text.sourceEnd, buffer.toString()); + addReplaceEdit(textStart, text.sourceEnd, this.javadocTextBuffer.toString()); // } // Reset @@ -4147,7 +4217,7 @@ boolean headerLine = block.isHeaderLine() && this.lastNumberOfNewLines == 0; // First we need to know what is the indentation - StringBuffer tokensBuffer = new StringBuffer(); + this.javadocTokensBuffer.setLength(0); int firstColumn = 1 + this.indentationLevel + BLOCK_LINE_PREFIX_LENGTH; int maxColumn = this.formatter.preferences.comment_line_length + 1; if (headerLine) { @@ -4179,11 +4249,11 @@ } catch (InvalidInputException iie) { token = consumeInvalidToken(textEnd); } - int tokensBufferLength = tokensBuffer.length(); + int tokensBufferLength = this.javadocTokensBuffer.length(); int tokenStart = this.scanner.getCurrentTokenStartPosition(); int tokenLength = (this.scanner.atEnd() ? this.scanner.eofPosition : this.scanner.currentPosition) - tokenStart; boolean insertSpace = (previousToken == TerminalTokens.TokenNameWHITESPACE || this.needSpace) && !textOnNewLine; - String tokensBufferString = tokensBuffer.toString().trim(); + String tokensBufferString = this.javadocTokensBuffer.toString().trim(); switch (token) { case TerminalTokens.TokenNameWHITESPACE: if (tokensBufferLength > 0) { @@ -4195,17 +4265,18 @@ this.lastNumberOfNewLines++; this.line++; if (newLineString == null) { - StringBuffer newLineBuffer = new StringBuffer(this.lineSeparator); + this.tempBuffer.setLength(0); + this.tempBuffer.append(this.lineSeparator); this.column = 1; - printIndentationIfNecessary(newLineBuffer); - newLineBuffer.append(BLOCK_LINE_PREFIX); + printIndentationIfNecessary(this.tempBuffer); + this.tempBuffer.append(BLOCK_LINE_PREFIX); this.column += BLOCK_LINE_PREFIX_LENGTH; if (this.commentIndentation != null) { - newLineBuffer.append(this.commentIndentation); + this.tempBuffer.append(this.commentIndentation); this.column += this.commentIndentation.length(); } firstColumn = this.column; - newLineString = newLineBuffer.toString(); + newLineString = this.tempBuffer.toString(); } else { this.column = firstColumn; } @@ -4218,10 +4289,10 @@ headerLine = false; } } else { - buffer.append(tokensBuffer); + buffer.append(this.javadocTokensBuffer); this.column += tokensBufferLength; } - tokensBuffer.setLength(0); + this.javadocTokensBuffer.setLength(0); } textOnNewLine = false; previousToken = token; @@ -4238,15 +4309,15 @@ if (insertSpace) lastColumn++; boolean shouldSplit = lastColumn > maxColumn // the max length is reached && (!isHtmlTag || previousToken == -1) // not an html tag or just at the beginning of it - && token != TerminalTokens.TokenNameAT && (tokensBufferLength == 0 || tokensBuffer.charAt(tokensBufferLength-1) != '@'); // avoid to split just before a '@' + && token != TerminalTokens.TokenNameAT && (tokensBufferLength == 0 || this.javadocTokensBuffer.charAt(tokensBufferLength-1) != '@'); // avoid to split just before a '@' if (shouldSplit) { // not enough space on the line if ((tokensBufferLength > 0 || tokenLength < maxColumn) && !isHtmlTag && tokensBufferLength > 0 && (firstColumn+tokensBufferLength+tokenLength) >= maxColumn) { // there won't be enough room even if we break the line before the buffered tokens // So add the buffered tokens now - buffer.append(tokensBuffer); + buffer.append(this.javadocTokensBuffer); this.column += tokensBufferLength; - tokensBuffer.setLength(0); + this.javadocTokensBuffer.setLength(0); tokensBufferLength = 0; textOnNewLine = false; } @@ -4254,17 +4325,18 @@ this.lastNumberOfNewLines++; this.line++; if (newLineString == null) { - StringBuffer newLineBuffer = new StringBuffer(this.lineSeparator); + this.tempBuffer.setLength(0); + this.tempBuffer.append(this.lineSeparator); this.column = 1; - printIndentationIfNecessary(newLineBuffer); - newLineBuffer.append(BLOCK_LINE_PREFIX); + printIndentationIfNecessary(this.tempBuffer); + this.tempBuffer.append(BLOCK_LINE_PREFIX); this.column += BLOCK_LINE_PREFIX_LENGTH; if (this.commentIndentation != null) { - newLineBuffer.append(this.commentIndentation); + this.tempBuffer.append(this.commentIndentation); this.column += this.commentIndentation.length(); } firstColumn = this.column; - newLineString = newLineBuffer.toString(); + newLineString = this.tempBuffer.toString(); } else { this.column = firstColumn; } @@ -4274,7 +4346,7 @@ String tokensString = tokensBufferString; buffer.append(tokensString); this.column += tokensString.length(); - tokensBuffer.setLength(0); + this.javadocTokensBuffer.setLength(0); tokensBufferLength = 0; } buffer.append(this.scanner.source, tokenStart, tokenLength); @@ -4288,9 +4360,9 @@ } else { // append token to the line if (insertSpace) { - tokensBuffer.append(' '); + this.javadocTokensBuffer.append(' '); } - tokensBuffer.append(this.scanner.source, tokenStart, tokenLength); + this.javadocTokensBuffer.append(this.scanner.source, tokenStart, tokenLength); } previousToken = token; this.needSpace = false; @@ -4303,9 +4375,9 @@ finally { this.scanner.skipComments = false; // Add remaining buffered tokens - if (tokensBuffer.length() > 0) { - buffer.append(tokensBuffer); - this.column += tokensBuffer.length(); + if (this.javadocTokensBuffer.length() > 0) { + buffer.append(this.javadocTokensBuffer); + this.column += this.javadocTokensBuffer.length(); } } } @@ -4518,27 +4590,34 @@ // Split the existing edit to keep the change before the beginning of the last line // but change the indentation after. Note that at this stage, the add*Edit methods // cannot be longer used as the edits are disabled - StringBuffer indentationBuffer = new StringBuffer(); + String indentationString; int currentIndentation = getCurrentIndentation(this.scanner.currentPosition); if (currentIndentation > 0 && this.indentationLevel > 0) { int col = this.column; - printIndentationIfNecessary(indentationBuffer); + this.tempBuffer.setLength(0); + printIndentationIfNecessary(this.tempBuffer); + indentationString = this.tempBuffer.toString(); this.column = col; + } else { + indentationString = Util.EMPTY_STRING; } String replacement = currentEdit.replacement; if (replacement.length() == 0) { // previous edit was a delete, as we're sure to have a new line before // the comment, then the edit needs to be either replaced entirely with // the expected indentation - this.edits[this.editsIndex-1] = new OptimizedReplaceEdit(beginningOfLine, offset+length-beginningOfLine, indentationBuffer.toString()); + this.edits[this.editsIndex-1] = new OptimizedReplaceEdit(beginningOfLine, offset+length-beginningOfLine, indentationString); } else { int idx = replacement.lastIndexOf(this.lineSeparator); if (idx >= 0) { // replace current edit if it contains a line separator int start = idx + this.lsLength; - StringBuffer buffer = new StringBuffer(replacement.substring(0, start)); - buffer.append(indentationBuffer); - this.edits[this.editsIndex-1] = new OptimizedReplaceEdit(offset, length, buffer.toString()); + this.tempBuffer.setLength(0); + this.tempBuffer.append(replacement.substring(0, start)); + if (indentationString != Util.EMPTY_STRING) { + this.tempBuffer.append(indentationString); + } + this.edits[this.editsIndex-1] = new OptimizedReplaceEdit(offset, length, this.tempBuffer.toString()); } } } @@ -4818,6 +4897,26 @@ System.arraycopy(this.edits, 0, (this.edits = new OptimizedReplaceEdit[this.editsIndex * 2]), 0, this.editsIndex); } + private void setCommentIndentation(int commentIndentationLevel) { + if (commentIndentationLevel == 0) { + this.commentIndentation = null; + } else { + int length = COMMENT_INDENTATIONS.length; + if (commentIndentationLevel > length) { + System.arraycopy(COMMENT_INDENTATIONS, 0, COMMENT_INDENTATIONS = new String[commentIndentationLevel+10], 0, length); + } + this.commentIndentation = COMMENT_INDENTATIONS[commentIndentationLevel-1]; + if (this.commentIndentation == null) { + this.tempBuffer.setLength(0); + for (int i=0; i=ALLOCATION && kind <=TYPE_MEMBERS); + Assert.isTrue(kind >=ALLOCATION && kind <=STRING_CONCATENATION); this.kind = kind; this.name = NAMES[kind]; this.location = new Location(scribe, sourceRestart);