### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core 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.143.2.2 diff -u -r1.143.2.2 Scribe.java --- formatter/org/eclipse/jdt/internal/formatter/Scribe.java 25 Jun 2008 11:15:26 -0000 1.143.2.2 +++ formatter/org/eclipse/jdt/internal/formatter/Scribe.java 3 Jul 2008 09:10:18 -0000 @@ -2004,20 +2004,19 @@ // Consume the comment prefix this.scanner.resetTo(commentStart, commentEnd); - StringBuffer buffer = new StringBuffer(); this.scanner.getNextChar(); this.scanner.getNextChar(); this.column += 2; - int editStart = this.scanner.currentPosition; - StringBuffer tokensBuffer = new StringBuffer(); - boolean bufferHasTokens = false; // Scan the text token per token to compact it and size it the max line length int maxColumn = this.formatter.preferences.comment_line_length + 1; int previousToken = -1; - int previousPosition = commentStart; - boolean firstWord = true; + int lastTokenEndPosition = commentStart; + int spaceStartPosition = -1; + int spaceEndPosition = -1; this.scanner.skipComments = true; + String newLineString = null; + this.commentIndentation = null; // Consume text token per token while (!this.scanner.atEnd()) { @@ -2029,84 +2028,86 @@ } switch (token) { case TerminalTokens.TokenNameWHITESPACE: - previousToken = token; - if (tokensBuffer.length() > 0) { - buffer.append(tokensBuffer); - this.column += tokensBuffer.length(); - tokensBuffer.setLength(0); - bufferHasTokens = true; + if (previousToken == -1) { + // do not remember the first whitespace + previousToken = SKIP_FIRST_WHITESPACE_TOKEN; + } else { + previousToken = token; } + // Remember space position + spaceStartPosition = this.scanner.getCurrentTokenStartPosition(); + spaceEndPosition = this.scanner.getCurrentTokenEndPosition(); continue; case TerminalTokens.TokenNameEOF: continue; } int tokenStart = this.scanner.getCurrentTokenStartPosition(); int tokenLength = (this.scanner.atEnd() ? this.scanner.eofPosition : this.scanner.currentPosition) - tokenStart; - boolean insertSpace = previousToken == -1 || previousToken == TerminalTokens.TokenNameWHITESPACE; - int lastColumn = this.column + tokensBuffer.length() + tokenLength; - if (insertSpace) lastColumn++; - if (!firstWord && lastColumn > maxColumn) { - // not enough space on the line - this.line++; - if ((firstColumn+tokensBuffer.length()+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); - bufferHasTokens = true; - } - if (bufferHasTokens) { - buffer.append(this.lineSeparator); - this.column = 1; - printIndentationIfNecessary(buffer); - buffer.append(LINE_COMMENT_PREFIX); - this.column += LINE_COMMENT_PREFIX_LENGTH; - } - if (tokensBuffer.length() > 0) { - if (ScannerHelper.isWhitespace(tokensBuffer.charAt(0))) { - buffer.append(tokensBuffer.substring(1)); - this.column += tokensBuffer.length() - 1; - } else { - buffer.append(tokensBuffer); - this.column += tokensBuffer.length(); - } - tokensBuffer.setLength(0); - if (insertSpace) { - buffer.append(' '); - this.column++; - } - } - buffer.append(this.scanner.source, tokenStart, tokenLength); - bufferHasTokens = true; - this.column += tokenLength; - firstColumn = this.indentationLevel + LINE_COMMENT_PREFIX_LENGTH; + + // insert space at the beginning if not present + if (previousToken == -1 ) { + addInsertEdit(this.scanner.startPosition, " "); //$NON-NLS-1$ + this.column++; + } + // replace space at the beginning if present + else if (previousToken == SKIP_FIRST_WHITESPACE_TOKEN) { + addReplaceEdit(spaceStartPosition, this.scanner.startPosition-1, " "); //$NON-NLS-1$ + this.column++; + spaceStartPosition = -1; // do not use this position to split the comment } else { - // append token to the line - if (insertSpace) { - tokensBuffer.append(' '); + // not on the first token + boolean insertSpace = previousToken == TerminalTokens.TokenNameWHITESPACE; + if (insertSpace) { + // count inserted space if any in token length + tokenLength++; + } + // insert new line if max line width is reached and a space was previously encountered + if (spaceStartPosition > 0 && (this.column+tokenLength) > maxColumn) { + this.lastNumberOfNewLines++; + this.line++; + if (newLineString == null) { + StringBuffer newLineBuffer = new StringBuffer(this.lineSeparator); + this.column = 1; + printIndentationIfNecessary(newLineBuffer); + newLineBuffer.append(LINE_COMMENT_PREFIX); + this.column += LINE_COMMENT_PREFIX_LENGTH; + newLineString = newLineBuffer.toString(); + firstColumn = this.column; + } else { + this.column = firstColumn; + } + if (lastTokenEndPosition > spaceEndPosition) { + this.column += lastTokenEndPosition - (spaceEndPosition + 1); // add all previous tokens lengths since last space + } + if (this.edits[this.editsIndex-1].offset == spaceStartPosition) { + // previous space was already edited, so remove it + this.editsIndex--; + } + addReplaceEdit(spaceStartPosition, spaceEndPosition, newLineString); + spaceStartPosition = -1; + if (insertSpace) { + tokenLength--; // reduce token length as the space will be replaced by the new line + } + } + // replace space if needed + else if (insertSpace) { + addReplaceEdit(spaceStartPosition, this.scanner.startPosition-1, " "); //$NON-NLS-1$ } - tokensBuffer.append(this.scanner.source, tokenStart, tokenLength); } + // update column position and store info of the current token + this.column += tokenLength; previousToken = token; - previousPosition = this.scanner.currentPosition; - firstWord = false; + lastTokenEndPosition = this.scanner.currentPosition; } this.scanner.skipComments = false; - // Add remaining buffered tokens - if (tokensBuffer.length() > 0) { - buffer.append(tokensBuffer); - this.column += tokensBuffer.length(); - } - - // Append separator if the comment is not at the end of file + // Skip separator if the comment is not at the end of file this.indentationLevel = indentLevel; this.numberOfIndentations = indentations; this.lastNumberOfNewLines = 0; - this.scanner.resetTo(previousPosition, commentEnd); + this.scanner.resetTo(lastTokenEndPosition, commentEnd); while (!this.scanner.atEnd()) { - previousPosition = this.scanner.currentPosition; + spaceEndPosition = this.scanner.currentPosition; this.scanner.getNextChar(); if (this.scanner.currentCharacter == '\n' || this.scanner.currentCharacter == '\r') { // line comment is normally ended with new line @@ -2116,10 +2117,10 @@ break; } } - - // Replace the existing comment with new one - if (buffer.length() > 0) { - addReplaceEdit(editStart, previousPosition - 1, buffer.toString()); + + // Delete leading whitespaces if any + if (previousToken != -1 && lastTokenEndPosition != commentStart && spaceEndPosition > lastTokenEndPosition) { + addDeleteEdit(lastTokenEndPosition, spaceEndPosition-1); } } @@ -2507,7 +2508,6 @@ int previousToken = -1; int spacePosition = -1; String newLineString = null; - StringBuffer newLineBuffer = null; int firstColumn = -1; while (!this.scanner.atEnd()) { int token; @@ -2538,7 +2538,7 @@ this.lastNumberOfNewLines++; this.line++; if (newLineString == null) { - newLineBuffer = new StringBuffer(this.lineSeparator); + StringBuffer newLineBuffer = new StringBuffer(this.lineSeparator); this.column = 1; printIndentationIfNecessary(newLineBuffer); newLineBuffer.append(BLOCK_LINE_PREFIX); #P org.eclipse.jdt.core.tests.model Index: src/org/eclipse/jdt/core/tests/formatter/FormatterCommentsBugsTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/formatter/FormatterCommentsBugsTest.java,v retrieving revision 1.11.2.4 diff -u -r1.11.2.4 FormatterCommentsBugsTest.java --- src/org/eclipse/jdt/core/tests/formatter/FormatterCommentsBugsTest.java 25 Jun 2008 11:26:50 -0000 1.11.2.4 +++ src/org/eclipse/jdt/core/tests/formatter/FormatterCommentsBugsTest.java 3 Jul 2008 09:10:20 -0000 @@ -1522,4 +1522,100 @@ "}\n" ); } + +/** + * @bug 238210: [formatter] CodeFormatter wraps line comments without whitespaces + * @test Ensure that line without spaces are not wrapped by the comment formatter + * @see "https://bugs.eclipse.org/bugs/show_bug.cgi?id=238210" + */ +public void testBug238210() throws JavaModelException { + String source = + "/**\n" + + " * LineCommentTestCase\n" + + " * \n" + + " * Formatting this compilation unit with line comment enabled and comment line width set to 100 or\n" + + " * lower will result in both protected region comments to be wrapped although they do not contain\n" + + " * any whitespace (excluding leading whitespace which should be / is being ignored altogether)\n" + + " * \n" + + " * @author Axel Faust, PRODYNA AG\n" + + " */\n" + + "public class LineCommentTestCase {\n" + + "\n" + + " public void someGeneratedMethod() {\n" + + " //protected-region-start_[id=_14_0_1_3dd20592_1202209856234_914658_24183_someGeneratedMethod]\n" + + " // some manually written code\n" + + " // protected-region-end_[id=_14_0_1_3dd20592_1202209856234_914658_24183_someGeneratedMethod]\n" + + " }\n" + + "}\n"; + formatSource(source, + "/**\n" + + " * LineCommentTestCase\n" + + " * \n" + + " * Formatting this compilation unit with line comment enabled and comment line\n" + + " * width set to 100 or lower will result in both protected region comments to be\n" + + " * wrapped although they do not contain any whitespace (excluding leading\n" + + " * whitespace which should be / is being ignored altogether)\n" + + " * \n" + + " * @author Axel Faust, PRODYNA AG\n" + + " */\n" + + "public class LineCommentTestCase {\n" + + "\n" + + " public void someGeneratedMethod() {\n" + + " // protected-region-start_[id=_14_0_1_3dd20592_1202209856234_914658_24183_someGeneratedMethod]\n" + + " // some manually written code\n" + + " // protected-region-end_[id=_14_0_1_3dd20592_1202209856234_914658_24183_someGeneratedMethod]\n" + + " }\n" + + "}\n" + ); +} +public void _testBug238210_block() throws JavaModelException { + String source = + "public class BlockCommentTestCase {\n" + + "\n" + + " public void someGeneratedMethod() {\n" + + " /*\n" + + " * protected-region-start_[id=_14_0_1_3dd20592_1202209856234_914658_24183_someGeneratedMethod]\n" + + " * some manually written code\n" + + " * protected-region-end_[id=_14_0_1_3dd20592_1202209856234_914658_24183_someGeneratedMethod]\n" + + " */\n" + + " }\n" + + "}\n"; + formatSource(source, + "public class BlockCommentTestCase {\n" + + "\n" + + " public void someGeneratedMethod() {\n" + + " /*\n" + + " * protected-region-start_[id=_14_0_1_3dd20592_1202209856234_914658_24183_someGeneratedMethod]\n" + + " * some manually written code\n" + + " * protected-region-end_[id=_14_0_1_3dd20592_1202209856234_914658_24183_someGeneratedMethod]\n" + + " */\n" + + " }\n" + + "}\n" + ); +} +public void _testBug238210_javadoc() throws JavaModelException { + String source = + "public class JavadocCommentTestCase {\n" + + "\n" + + " public void someGeneratedMethod() {\n" + + " /**\n" + + " * protected-region-start_[id=_14_0_1_3dd20592_1202209856234_914658_24183_someGeneratedMethod]\n" + + " * some manually written code\n" + + " * protected-region-end_[id=_14_0_1_3dd20592_1202209856234_914658_24183_someGeneratedMethod]\n" + + " */\n" + + " }\n" + + "}\n"; + formatSource(source, + "public class JavadocCommentTestCase {\n" + + "\n" + + " public void someGeneratedMethod() {\n" + + " /**\n" + + " * protected-region-start_[id=_14_0_1_3dd20592_1202209856234_914658_24183_someGeneratedMethod]\n" + + " * some manually written code\n" + + " * protected-region-end_[id=_14_0_1_3dd20592_1202209856234_914658_24183_someGeneratedMethod]\n" + + " */\n" + + " }\n" + + "}\n" + ); +} } Index: workspace/FormatterJavadoc/test/comments/line/out/default/X08.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/workspace/FormatterJavadoc/test/comments/line/out/default/X08.java,v retrieving revision 1.1 diff -u -r1.1 X08.java --- workspace/FormatterJavadoc/test/comments/line/out/default/X08.java 6 May 2008 08:47:47 -0000 1.1 +++ workspace/FormatterJavadoc/test/comments/line/out/default/X08.java 3 Jul 2008 09:10:20 -0000 @@ -6,11 +6,10 @@ try { if (true) { // BUILD FAILED: - // C:\Darins\Debugger\20021213\eclipse\runtime-workspace - // \Mine\build.xml:4: Following error occured while executing - // this line - // C:\Darins\Debugger\20021213\eclipse\runtime-workspace\Mine\ - // subbuild.xml:4: srcdir attribute must be set! + // C:\Darins\Debugger\20021213\eclipse\runtime-workspace\Mine\build.xml:4: + // Following error occured while executing this line + // C:\Darins\Debugger\20021213\eclipse\runtime-workspace\Mine\subbuild.xml:4: + // srcdir attribute must be set! } } finally { }