View | Details | Raw Unified | Return to bug 310811
Collapse All | Expand All

(-)formatter/org/eclipse/jdt/internal/formatter/CodeFormatterVisitor.java (-1 / +1 lines)
Lines 4966-4972 Link Here
4966
		ASTNode[] fragments = stringLiteral.literals;
4966
		ASTNode[] fragments = stringLiteral.literals;
4967
		int fragmentsSize = stringLiteral.counter;
4967
		int fragmentsSize = stringLiteral.counter;
4968
		Alignment binaryExpressionAlignment = this.scribe.createAlignment(
4968
		Alignment binaryExpressionAlignment = this.scribe.createAlignment(
4969
				Alignment.BINARY_EXPRESSION,
4969
				Alignment.STRING_CONCATENATION,
4970
				this.preferences.alignment_for_binary_expression,
4970
				this.preferences.alignment_for_binary_expression,
4971
				Alignment.R_OUTERMOST,
4971
				Alignment.R_OUTERMOST,
4972
				fragmentsSize,
4972
				fragmentsSize,
(-)formatter/org/eclipse/jdt/internal/formatter/Scribe.java (-237 / +336 lines)
Lines 83-88 Link Here
83
83
84
	// Line separator infos
84
	// Line separator infos
85
	final private String lineSeparator;
85
	final private String lineSeparator;
86
	final private String lineSeparatorAndSpace;
86
	final private char firstLS;
87
	final private char firstLS;
87
	final private int lsLength;
88
	final private int lsLength;
88
89
Lines 138-143 Link Here
138
	OptimizedReplaceEdit previousDisabledEdit;
139
	OptimizedReplaceEdit previousDisabledEdit;
139
	private char[] disablingTag, enablingTag;
140
	private char[] disablingTag, enablingTag;
140
141
142
	// Well know strings
143
	private String[] newEmptyLines = new String[10];
144
	private static String[] COMMENT_INDENTATIONS = new String[20];
145
146
	// final string buffers
147
	private final StringBuffer tempBuffer= new StringBuffer();
148
	private final StringBuffer blockCommentBuffer = new StringBuffer();
149
	private final StringBuffer blockCommentTokensBuffer = new StringBuffer();
150
	private final StringBuffer codeSnippetBuffer = new StringBuffer();
151
	private final StringBuffer javadocBlockRefBuffer= new StringBuffer();
152
	private final StringBuffer javadocGapLinesBuffer = new StringBuffer();
153
	private StringBuffer[] javadocHtmlTagBuffers = new StringBuffer[5];
154
	private final StringBuffer javadocTextBuffer = new StringBuffer();
155
	private final StringBuffer javadocTokensBuffer = new StringBuffer();
156
141
	Scribe(CodeFormatterVisitor formatter, long sourceLevel, IRegion[] regions, CodeSnippetParsingUtil codeSnippetParsingUtil, boolean includeComments) {
157
	Scribe(CodeFormatterVisitor formatter, long sourceLevel, IRegion[] regions, CodeSnippetParsingUtil codeSnippetParsingUtil, boolean includeComments) {
142
		initializeScanner(sourceLevel, formatter.preferences);
158
		initializeScanner(sourceLevel, formatter.preferences);
143
		this.formatter = formatter;
159
		this.formatter = formatter;
Lines 154-159 Link Here
154
			this.indentationSize = this.tabLength;
170
			this.indentationSize = this.tabLength;
155
		}
171
		}
156
		this.lineSeparator = formatter.preferences.line_separator;
172
		this.lineSeparator = formatter.preferences.line_separator;
173
		this.lineSeparatorAndSpace = this.lineSeparator+' ';
157
		this.firstLS = this.lineSeparator.charAt(0);
174
		this.firstLS = this.lineSeparator.charAt(0);
158
		this.lsLength = this.lineSeparator.length();
175
		this.lsLength = this.lineSeparator.length();
159
		this.indentationLevel = formatter.preferences.initial_indentation_level * this.indentationSize;
176
		this.indentationLevel = formatter.preferences.initial_indentation_level * this.indentationSize;
Lines 427-437 Link Here
427
							if (linesCount == 0) {
444
							if (linesCount == 0) {
428
				    			edit.replacement = ""; //$NON-NLS-1$
445
				    			edit.replacement = ""; //$NON-NLS-1$
429
							} else {
446
							} else {
430
								StringBuffer buffer = new StringBuffer();
447
								edit.replacement = getNewLineString(linesCount);
431
								for (int j=0; j<linesCount; j++) {
432
									buffer.append(this.lineSeparator);
433
								}
434
								edit.replacement = buffer.toString();
435
							}
448
							}
436
						}
449
						}
437
					}
450
					}
Lines 930-941 Link Here
930
		if (this.nlsTagCounter > 0) {
943
		if (this.nlsTagCounter > 0) {
931
			return Util.EMPTY_STRING;
944
			return Util.EMPTY_STRING;
932
		}
945
		}
933
		StringBuffer buffer = new StringBuffer();
946
		String emptyLines;
934
		if (this.lastNumberOfNewLines == 0) {
947
		if (this.lastNumberOfNewLines == 0) {
935
			linesNumber++; // add an extra line breaks
948
			linesNumber++; // add an extra line breaks
936
			for (int i = 0; i < linesNumber; i++) {
949
			if (this.indentEmptyLines) {
937
				if (this.indentEmptyLines) printIndentationIfNecessary(buffer);
950
				this.tempBuffer.setLength(0);
938
				buffer.append(this.lineSeparator);
951
				for (int i = 0; i < linesNumber; i++) {
952
					printIndentationIfNecessary(this.tempBuffer);
953
					this.tempBuffer.append(this.lineSeparator);
954
				}
955
				emptyLines = this.tempBuffer.toString();
956
			} else {
957
				emptyLines = getNewLineString(linesNumber);
939
			}
958
			}
940
			this.lastNumberOfNewLines += linesNumber;
959
			this.lastNumberOfNewLines += linesNumber;
941
			this.line += linesNumber;
960
			this.line += linesNumber;
Lines 943-951 Link Here
943
			this.needSpace = false;
962
			this.needSpace = false;
944
			this.pendingSpace = false;
963
			this.pendingSpace = false;
945
		} else if (this.lastNumberOfNewLines == 1) {
964
		} else if (this.lastNumberOfNewLines == 1) {
946
			for (int i = 0; i < linesNumber; i++) {
965
			if (this.indentEmptyLines) {
947
				if (this.indentEmptyLines) printIndentationIfNecessary(buffer);
966
				this.tempBuffer.setLength(0);
948
				buffer.append(this.lineSeparator);
967
				for (int i = 0; i < linesNumber; i++) {
968
					printIndentationIfNecessary(this.tempBuffer);
969
					this.tempBuffer.append(this.lineSeparator);
970
				}
971
				emptyLines = this.tempBuffer.toString();
972
			} else {
973
				emptyLines = getNewLineString(linesNumber);
949
			}
974
			}
950
			this.lastNumberOfNewLines += linesNumber;
975
			this.lastNumberOfNewLines += linesNumber;
951
			this.line += linesNumber;
976
			this.line += linesNumber;
Lines 958-966 Link Here
958
				return Util.EMPTY_STRING;
983
				return Util.EMPTY_STRING;
959
			}
984
			}
960
			final int realNewLineNumber = linesNumber - this.lastNumberOfNewLines + 1;
985
			final int realNewLineNumber = linesNumber - this.lastNumberOfNewLines + 1;
961
			for (int i = 0; i < realNewLineNumber; i++) {
986
			if (this.indentEmptyLines) {
962
				if (this.indentEmptyLines) printIndentationIfNecessary(buffer);
987
				this.tempBuffer.setLength(0);
963
				buffer.append(this.lineSeparator);
988
				for (int i = 0; i < realNewLineNumber; i++) {
989
					printIndentationIfNecessary(this.tempBuffer);
990
					this.tempBuffer.append(this.lineSeparator);
991
				}
992
				emptyLines = this.tempBuffer.toString();
993
			} else {
994
				emptyLines = getNewLineString(realNewLineNumber);
964
			}
995
			}
965
			this.lastNumberOfNewLines += realNewLineNumber;
996
			this.lastNumberOfNewLines += realNewLineNumber;
966
			this.line += realNewLineNumber;
997
			this.line += realNewLineNumber;
Lines 968-974 Link Here
968
			this.needSpace = false;
999
			this.needSpace = false;
969
			this.pendingSpace = false;
1000
			this.pendingSpace = false;
970
		}
1001
		}
971
		return String.valueOf(buffer);
1002
		return emptyLines;
972
	}
1003
	}
973
1004
974
	private int getIndexOfAdaptedRegionAt(int offset) {
1005
	private int getIndexOfAdaptedRegionAt(int offset) {
Lines 1026-1031 Link Here
1026
		return this.lineSeparator;
1057
		return this.lineSeparator;
1027
	}
1058
	}
1028
1059
1060
	private String getNewLineString(int linesCount) {
1061
		int length = this.newEmptyLines.length;
1062
		if (linesCount > length) {
1063
			System.arraycopy(this.newEmptyLines, 0, this.newEmptyLines = new String[linesCount+10], 0, length);
1064
		}
1065
		String newLineString = this.newEmptyLines[linesCount-1];
1066
		if (newLineString == null) {
1067
			this.tempBuffer.setLength(0);
1068
			for (int j=0; j<linesCount; j++) {
1069
				this.tempBuffer.append(this.lineSeparator);
1070
			}
1071
			newLineString = this.tempBuffer.toString();
1072
			this.newEmptyLines[linesCount-1] = newLineString;
1073
		}
1074
		return newLineString;
1075
	}
1076
1029
	/**
1077
	/**
1030
	 * Answer next indentation level based on column estimated position
1078
	 * Answer next indentation level based on column estimated position
1031
	 * (if column is not indented, then use indentationLevel)
1079
	 * (if column is not indented, then use indentationLevel)
Lines 1078-1084 Link Here
1078
					this.indentationLevel = this.currentAlignment.location.outputIndentationLevel;
1126
					this.indentationLevel = this.currentAlignment.location.outputIndentationLevel;
1079
1127
1080
					// Create new line
1128
					// Create new line
1081
					StringBuffer buffer = new StringBuffer(getNewLine());
1129
					this.tempBuffer.setLength(0);
1130
					this.tempBuffer.append(getNewLine());
1082
					
1131
					
1083
					// Look for current indentation
1132
					// Look for current indentation
1084
					int currentIndentation = getCurrentIndentation(this.scanner.currentPosition);
1133
					int currentIndentation = getCurrentIndentation(this.scanner.currentPosition);
Lines 1135-1142 Link Here
1135
					this.preserveLineBreakIndentation = true;
1184
					this.preserveLineBreakIndentation = true;
1136
					
1185
					
1137
					// Print the computed indentation in the buffer
1186
					// Print the computed indentation in the buffer
1138
					printIndentationIfNecessary(buffer);
1187
					printIndentationIfNecessary(this.tempBuffer);
1139
					return buffer.toString();
1188
					return this.tempBuffer.toString();
1140
				}
1189
				}
1141
			}
1190
			}
1142
			return Util.EMPTY_STRING;
1191
			return Util.EMPTY_STRING;
Lines 1213-1233 Link Here
1213
		int relativeDepth = 0, outerMostDepth = -1;
1262
		int relativeDepth = 0, outerMostDepth = -1;
1214
		Alignment targetAlignment = this.currentAlignment;
1263
		Alignment targetAlignment = this.currentAlignment;
1215
		int previousKind = -1;
1264
		int previousKind = -1;
1216
		boolean insideMessageArguments = false;
1265
		int insideMessage = 0;
1217
		boolean insideMessageSend = false;
1266
		boolean insideStringConcat = false;
1218
		while (targetAlignment != null){
1267
		while (targetAlignment != null){
1219
			boolean couldBreak = targetAlignment.tieBreakRule == Alignment.R_OUTERMOST ||
1268
			boolean couldBreak = targetAlignment.tieBreakRule == Alignment.R_OUTERMOST ||
1220
				((insideMessageArguments || insideMessageSend) && targetAlignment.kind == Alignment.MESSAGE_ARGUMENTS
1269
				(!insideStringConcat &&
1221
						&& (!targetAlignment.wasReset() || previousKind != Alignment.MESSAGE_SEND));
1270
						insideMessage > 0 && targetAlignment.kind == Alignment.MESSAGE_ARGUMENTS &&
1271
						(!targetAlignment.wasReset() || previousKind != Alignment.MESSAGE_SEND));
1222
			if (couldBreak && targetAlignment.couldBreak()){
1272
			if (couldBreak && targetAlignment.couldBreak()){
1223
				outerMostDepth = relativeDepth;
1273
				outerMostDepth = relativeDepth;
1224
			}
1274
			}
1225
			switch (targetAlignment.kind) {
1275
			switch (targetAlignment.kind) {
1226
				case Alignment.MESSAGE_ARGUMENTS:
1276
				case Alignment.MESSAGE_ARGUMENTS:
1227
					insideMessageArguments = true;
1228
					break;
1229
				case Alignment.MESSAGE_SEND:
1277
				case Alignment.MESSAGE_SEND:
1230
					insideMessageSend = true;
1278
					insideMessage++;
1279
					break;
1280
				case Alignment.STRING_CONCATENATION:
1281
					insideStringConcat = true;
1231
					break;
1282
					break;
1232
			}
1283
			}
1233
			previousKind = targetAlignment.kind;
1284
			previousKind = targetAlignment.kind;
Lines 1251-1256 Link Here
1251
					// do not throw the exception immediately to have a chance to reset
1302
					// do not throw the exception immediately to have a chance to reset
1252
					// previously broken alignments (see bug 203588)
1303
					// previously broken alignments (see bug 203588)
1253
					alignmentException = new AlignmentException(AlignmentException.LINE_TOO_LONG, relativeDepth);
1304
					alignmentException = new AlignmentException(AlignmentException.LINE_TOO_LONG, relativeDepth);
1305
					if (insideStringConcat) throw alignmentException;
1254
				}
1306
				}
1255
			} else if (targetAlignment.wasSplit) {
1307
			} else if (targetAlignment.wasSplit) {
1256
				// reset the nearest already broken outermost alignment.
1308
				// reset the nearest already broken outermost alignment.
Lines 1532-1544 Link Here
1532
							this.line++;
1584
							this.line++;
1533
							isNewLine = false;
1585
							isNewLine = false;
1534
1586
1535
							StringBuffer buffer = new StringBuffer();
1587
							boolean addSpace = false;
1536
							if (onFirstColumn) {
1588
							if (onFirstColumn) {
1537
								// simply insert indentation if necessary
1538
								buffer.append(this.lineSeparator);
1539
								if (indentComment) {
1540
									printIndentationIfNecessary(buffer);
1541
								}
1542
								if (formatComment) {
1589
								if (formatComment) {
1543
									if (ScannerHelper.isWhitespace((char) currentCharacter)) {
1590
									if (ScannerHelper.isWhitespace((char) currentCharacter)) {
1544
										int previousStartPosition = this.scanner.currentPosition;
1591
										int previousStartPosition = this.scanner.currentPosition;
Lines 1553-1559 Link Here
1553
										}
1600
										}
1554
									}
1601
									}
1555
									if (currentCharacter != '\r' && currentCharacter != '\n') {
1602
									if (currentCharacter != '\r' && currentCharacter != '\n') {
1556
										buffer.append(' ');
1603
										addSpace = true;
1557
									}
1604
									}
1558
								}
1605
								}
1559
							} else {
1606
							} else {
Lines 1587-1596 Link Here
1587
										nextCharacterStart = previousStartPosition;
1634
										nextCharacterStart = previousStartPosition;
1588
									}
1635
									}
1589
								}
1636
								}
1590
								buffer.append(this.lineSeparator);
1591
								if (indentComment) {
1592
									printIndentationIfNecessary(buffer);
1593
								}
1594
								if (formatComment) {
1637
								if (formatComment) {
1595
									int previousStartTemp = previousStart;
1638
									int previousStartTemp = previousStart;
1596
									int nextCharacterStartTemp = nextCharacterStart;
1639
									int nextCharacterStartTemp = nextCharacterStart;
Lines 1600-1606 Link Here
1600
										nextCharacterStart = this.scanner.currentPosition;
1643
										nextCharacterStart = this.scanner.currentPosition;
1601
									}
1644
									}
1602
									if (currentCharacter == '*') {
1645
									if (currentCharacter == '*') {
1603
										buffer.append(' ');
1646
										addSpace = true;
1604
									} else {
1647
									} else {
1605
										previousStart = previousStartTemp;
1648
										previousStart = previousStartTemp;
1606
										nextCharacterStart = nextCharacterStartTemp;
1649
										nextCharacterStart = nextCharacterStartTemp;
Lines 1608-1614 Link Here
1608
									this.scanner.currentPosition = nextCharacterStart;
1651
									this.scanner.currentPosition = nextCharacterStart;
1609
								}
1652
								}
1610
							}
1653
							}
1611
							addReplaceEdit(start, previousStart - 1, String.valueOf(buffer));
1654
							String replacement;
1655
							if (indentComment) {
1656
								this.tempBuffer.setLength(0);
1657
								this.tempBuffer.append(this.lineSeparator);
1658
								if (this.indentationLevel > 0) {
1659
									printIndentationIfNecessary(this.tempBuffer);
1660
								}
1661
								if (addSpace) {
1662
									this.tempBuffer.append(' ');
1663
								}
1664
								replacement = this.tempBuffer.toString();
1665
							} else {
1666
								replacement = addSpace ? this.lineSeparatorAndSpace : this.lineSeparator;
1667
							}
1668
							addReplaceEdit(start, previousStart - 1, replacement);
1612
						} else {
1669
						} else {
1613
							this.column += (nextCharacterStart - previousStart);
1670
							this.column += (nextCharacterStart - previousStart);
1614
						}
1671
						}
Lines 1670-1681 Link Here
1670
		}
1727
		}
1671
1728
1672
		// Consume the comment prefix
1729
		// Consume the comment prefix
1673
		StringBuffer buffer = new StringBuffer();
1730
		this.blockCommentBuffer.setLength(0);
1674
		this.scanner.getNextChar();
1731
		this.scanner.getNextChar();
1675
		this.scanner.getNextChar();
1732
		this.scanner.getNextChar();
1676
		this.column += 2;
1733
		this.column += 2;
1677
		this.scanner.skipComments = true;
1734
		this.scanner.skipComments = true;
1678
		StringBuffer tokensBuffer = new StringBuffer();
1735
		this.blockCommentTokensBuffer.setLength(0);
1679
		int editStart = this.scanner.currentPosition;
1736
		int editStart = this.scanner.currentPosition;
1680
		int editEnd = -1;
1737
		int editEnd = -1;
1681
1738
Lines 1713-1726 Link Here
1713
    		boolean isTokenStar = false;
1770
    		boolean isTokenStar = false;
1714
			switch (token) {
1771
			switch (token) {
1715
				case TerminalTokens.TokenNameWHITESPACE:
1772
				case TerminalTokens.TokenNameWHITESPACE:
1716
					if (tokensBuffer.length() > 0) {
1773
					if (this.blockCommentTokensBuffer.length() > 0) {
1717
						if (hasTextOnFirstLine == 1 && multiLines) {
1774
						if (hasTextOnFirstLine == 1 && multiLines) {
1718
							printBlockCommentHeaderLine(buffer);
1775
							printBlockCommentHeaderLine(this.blockCommentBuffer);
1719
							hasTextOnFirstLine = -1;
1776
							hasTextOnFirstLine = -1;
1720
						}
1777
						}
1721
						buffer.append(tokensBuffer);
1778
						this.blockCommentBuffer.append(this.blockCommentTokensBuffer);
1722
						this.column += tokensBuffer.length();
1779
						this.column += this.blockCommentTokensBuffer.length();
1723
						tokensBuffer.setLength(0);
1780
						this.blockCommentTokensBuffer.setLength(0);
1724
						bufferHasTokens = true;
1781
						bufferHasTokens = true;
1725
						bufferHasNewLine = false;
1782
						bufferHasNewLine = false;
1726
					}
1783
					}
Lines 1741-1765 Link Here
1741
					isTokenStar = true;
1798
					isTokenStar = true;
1742
					lineNumber = Util.getLineNumber(this.scanner.currentPosition, this.lineEnds, scannerLine>1 ? scannerLine-2 : 0, this.maxLines);
1799
					lineNumber = Util.getLineNumber(this.scanner.currentPosition, this.lineEnds, scannerLine>1 ? scannerLine-2 : 0, this.maxLines);
1743
					if (lineNumber == firstLine && previousToken == SKIP_FIRST_WHITESPACE_TOKEN) {
1800
					if (lineNumber == firstLine && previousToken == SKIP_FIRST_WHITESPACE_TOKEN) {
1744
						buffer.append(' ');
1801
						this.blockCommentBuffer.append(' ');
1745
					}
1802
					}
1746
					previousToken = token;
1803
					previousToken = token;
1747
					if (this.scanner.currentCharacter == '/') {
1804
					if (this.scanner.currentCharacter == '/') {
1748
						editEnd = this.scanner.startPosition - 1;
1805
						editEnd = this.scanner.startPosition - 1;
1749
						// Add remaining buffered tokens
1806
						// Add remaining buffered tokens
1750
						if (tokensBuffer.length() > 0) {
1807
						if (this.blockCommentTokensBuffer.length() > 0) {
1751
							buffer.append(tokensBuffer);
1808
							this.blockCommentBuffer.append(this.blockCommentTokensBuffer);
1752
							this.column += tokensBuffer.length();
1809
							this.column += this.blockCommentTokensBuffer.length();
1753
						}
1810
						}
1754
						// end of comment
1811
						// end of comment
1755
						if (newLinesAtBoundaries) {
1812
						if (newLinesAtBoundaries) {
1756
							if (multiLines || hasMultiLines) {
1813
							if (multiLines || hasMultiLines) {
1757
						    	buffer.append(this.lineSeparator);
1814
						    	this.blockCommentBuffer.append(this.lineSeparator);
1758
						    	this.column = 1;
1815
						    	this.column = 1;
1759
						    	printIndentationIfNecessary(buffer);
1816
						    	printIndentationIfNecessary(this.blockCommentBuffer);
1760
							}
1817
							}
1761
						}
1818
						}
1762
						buffer.append(' ');
1819
						this.blockCommentBuffer.append(' ');
1763
						this.column += BLOCK_FOOTER_LENGTH + 1;
1820
						this.column += BLOCK_FOOTER_LENGTH + 1;
1764
				    	this.scanner.getNextChar(); // reach the end of scanner
1821
				    	this.scanner.getNextChar(); // reach the end of scanner
1765
				    	continue;
1822
				    	continue;
Lines 1824-1842 Link Here
1824
				}
1881
				}
1825
				for (int i=0; i<linesGap; i++) {
1882
				for (int i=0; i<linesGap; i++) {
1826
					// Add remaining buffered tokens
1883
					// Add remaining buffered tokens
1827
					if (tokensBuffer.length() > 0) {
1884
					if (this.blockCommentTokensBuffer.length() > 0) {
1828
						if (hasTextOnFirstLine == 1) {
1885
						if (hasTextOnFirstLine == 1) {
1829
							printBlockCommentHeaderLine(buffer);
1886
							printBlockCommentHeaderLine(this.blockCommentBuffer);
1830
							hasTextOnFirstLine = -1;
1887
							hasTextOnFirstLine = -1;
1831
						}
1888
						}
1832
						buffer.append(tokensBuffer);
1889
						this.blockCommentBuffer.append(this.blockCommentTokensBuffer);
1833
						tokensBuffer.setLength(0);
1890
						this.blockCommentTokensBuffer.setLength(0);
1834
						bufferHasTokens = true;
1891
						bufferHasTokens = true;
1835
					}
1892
					}
1836
			    	buffer.append(this.lineSeparator);
1893
			    	this.blockCommentBuffer.append(this.lineSeparator);
1837
			    	this.column = 1;
1894
			    	this.column = 1;
1838
			    	printIndentationIfNecessary(buffer);
1895
			    	printIndentationIfNecessary(this.blockCommentBuffer);
1839
		    		buffer.append(BLOCK_LINE_PREFIX);
1896
		    		this.blockCommentBuffer.append(BLOCK_LINE_PREFIX);
1840
		    		this.column += BLOCK_LINE_PREFIX_LENGTH;
1897
		    		this.column += BLOCK_LINE_PREFIX_LENGTH;
1841
		    		firstWord = true;
1898
		    		firstWord = true;
1842
					multiLines = true;
1899
					multiLines = true;
Lines 1859-1897 Link Here
1859
	    			hasTextOnFirstLine = -1;
1916
	    			hasTextOnFirstLine = -1;
1860
	    		}
1917
	    		}
1861
    		}
1918
    		}
1862
    		int lastColumn = this.column + tokensBuffer.length() + tokenLength;
1919
    		int lastColumn = this.column + this.blockCommentTokensBuffer.length() + tokenLength;
1863
    		if (insertSpace) lastColumn++;
1920
    		if (insertSpace) lastColumn++;
1864
1921
1865
    		// Append next token inserting a new line if max line is reached
1922
    		// Append next token inserting a new line if max line is reached
1866
			if (lineHasTokens && !firstWord && lastColumn > maxColumn) {
1923
			if (lineHasTokens && !firstWord && lastColumn > maxColumn) {
1867
		    	String tokensString = tokensBuffer.toString().trim();
1924
		    	String tokensString = this.blockCommentTokensBuffer.toString().trim();
1868
		    	int tokensStringLength = tokensString.length();
1925
		    	int tokensStringLength = tokensString.length();
1869
				// not enough space on the line
1926
				// not enough space on the line
1870
				if (hasTextOnFirstLine == 1) {
1927
				if (hasTextOnFirstLine == 1) {
1871
					printBlockCommentHeaderLine(buffer);
1928
					printBlockCommentHeaderLine(this.blockCommentBuffer);
1872
				}
1929
				}
1873
				if ((this.indentationLevel+tokensStringLength+tokenLength) > maxColumn) {
1930
				if ((this.indentationLevel+tokensStringLength+tokenLength) > maxColumn) {
1874
					// there won't be enough room even if we break the line before the buffered tokens
1931
					// there won't be enough room even if we break the line before the buffered tokens
1875
					// So add the buffered tokens now
1932
					// So add the buffered tokens now
1876
					buffer.append(tokensBuffer);
1933
					this.blockCommentBuffer.append(this.blockCommentTokensBuffer);
1877
					this.column += tokensBuffer.length();
1934
					this.column += this.blockCommentTokensBuffer.length();
1878
					tokensBuffer.setLength(0);
1935
					this.blockCommentTokensBuffer.setLength(0);
1879
					bufferHasNewLine = false;
1936
					bufferHasNewLine = false;
1880
					bufferHasTokens = true;
1937
					bufferHasTokens = true;
1881
				}
1938
				}
1882
				if (bufferHasTokens && !bufferHasNewLine) {
1939
				if (bufferHasTokens && !bufferHasNewLine) {
1883
			    	buffer.append(this.lineSeparator);
1940
			    	this.blockCommentBuffer.append(this.lineSeparator);
1884
			    	this.column = 1;
1941
			    	this.column = 1;
1885
			    	printIndentationIfNecessary(buffer);
1942
			    	printIndentationIfNecessary(this.blockCommentBuffer);
1886
		    		buffer.append(BLOCK_LINE_PREFIX);
1943
		    		this.blockCommentBuffer.append(BLOCK_LINE_PREFIX);
1887
			    	this.column += BLOCK_LINE_PREFIX_LENGTH;
1944
			    	this.column += BLOCK_LINE_PREFIX_LENGTH;
1888
				}
1945
				}
1889
		    	if (tokensBuffer.length() > 0) {
1946
		    	if (this.blockCommentTokensBuffer.length() > 0) {
1890
					buffer.append(tokensString);
1947
					this.blockCommentBuffer.append(tokensString);
1891
					this.column += tokensStringLength;
1948
					this.column += tokensStringLength;
1892
					tokensBuffer.setLength(0);
1949
					this.blockCommentTokensBuffer.setLength(0);
1893
		    	}
1950
		    	}
1894
				buffer.append(this.scanner.source, tokenStart, tokenLength);
1951
				this.blockCommentBuffer.append(this.scanner.source, tokenStart, tokenLength);
1895
				bufferHasTokens = true;
1952
				bufferHasTokens = true;
1896
				bufferHasNewLine = false;
1953
				bufferHasNewLine = false;
1897
				this.column += tokenLength;
1954
				this.column += tokenLength;
Lines 1900-1908 Link Here
1900
			} else {
1957
			} else {
1901
				// append token to the line
1958
				// append token to the line
1902
				if (insertSpace)  {
1959
				if (insertSpace)  {
1903
					tokensBuffer.append(' ');
1960
					this.blockCommentTokensBuffer.append(' ');
1904
				}
1961
				}
1905
				tokensBuffer.append(this.scanner.source, tokenStart, tokenLength);
1962
				this.blockCommentTokensBuffer.append(this.scanner.source, tokenStart, tokenLength);
1906
			}
1963
			}
1907
			previousToken = token;
1964
			previousToken = token;
1908
			newLine = false;
1965
			newLine = false;
Lines 1914-1921 Link Here
1914
		// Replace block comment text
1971
		// Replace block comment text
1915
		if (this.nlsTagCounter == 0 || !multiLines) {
1972
		if (this.nlsTagCounter == 0 || !multiLines) {
1916
			if (hasTokens || multiLines) {
1973
			if (hasTokens || multiLines) {
1917
				StringBuffer replacement = new StringBuffer();
1974
				StringBuffer replacement;
1918
				if (hasTextOnFirstLine == 1) {
1975
				if (hasTextOnFirstLine == 1) {
1976
					this.blockCommentTokensBuffer.setLength(0);
1977
					replacement = this.blockCommentTokensBuffer;
1919
					if ((hasMultiLines || multiLines)) {
1978
					if ((hasMultiLines || multiLines)) {
1920
						int col = this.column;
1979
						int col = this.column;
1921
						replacement.append(this.lineSeparator);
1980
						replacement.append(this.lineSeparator);
Lines 1923-1933 Link Here
1923
						printIndentationIfNecessary(replacement);
1982
						printIndentationIfNecessary(replacement);
1924
						replacement.append(BLOCK_LINE_PREFIX);
1983
						replacement.append(BLOCK_LINE_PREFIX);
1925
				    	this.column = col;
1984
				    	this.column = col;
1926
					} else if (buffer.length()==0 || buffer.charAt(0)!=' ') {
1985
					} else if (this.blockCommentBuffer.length()==0 || this.blockCommentBuffer.charAt(0)!=' ') {
1927
						replacement.append(' ');
1986
						replacement.append(' ');
1928
					}
1987
					}
1988
					replacement.append(this.blockCommentBuffer);
1989
				} else {
1990
					replacement = this.blockCommentBuffer;
1929
				}
1991
				}
1930
				replacement.append(buffer);
1931
				addReplaceEdit(editStart, editEnd, replacement.toString());
1992
				addReplaceEdit(editStart, editEnd, replacement.toString());
1932
			}
1993
			}
1933
		}
1994
		}
Lines 1954-1966 Link Here
1954
	    	buffer.append(BLOCK_LINE_PREFIX);
2015
	    	buffer.append(BLOCK_LINE_PREFIX);
1955
	    	this.column += BLOCK_LINE_PREFIX_LENGTH;
2016
	    	this.column += BLOCK_LINE_PREFIX_LENGTH;
1956
	    } else {
2017
	    } else {
1957
	    	StringBuffer insert = new StringBuffer();
2018
	    	this.tempBuffer.setLength(0);
1958
	    	insert.append(this.lineSeparator);
2019
	    	this.tempBuffer.append(this.lineSeparator);
1959
	    	this.column = 1;
2020
	    	this.column = 1;
1960
	    	printIndentationIfNecessary(insert);
2021
			printIndentationIfNecessary(this.tempBuffer);
1961
	    	insert.append(BLOCK_LINE_PREFIX);
2022
	    	this.tempBuffer.append(BLOCK_LINE_PREFIX);
1962
	    	this.column += BLOCK_LINE_PREFIX_LENGTH;
2023
	    	this.column += BLOCK_LINE_PREFIX_LENGTH;
1963
	    	buffer.insert(0, insert.toString());
2024
	    	buffer.insert(0, this.tempBuffer.toString());
1964
	    }
2025
	    }
1965
    }
2026
    }
1966
2027
Lines 2093-2108 Link Here
2093
		// 1 - strip content prefix (@see JavaDocRegion#preprocessCodeSnippet)
2154
		// 1 - strip content prefix (@see JavaDocRegion#preprocessCodeSnippet)
2094
		int firstLine = Util.getLineNumber(startPosition, this.lineEnds, 0, this.maxLines) - 1;
2155
		int firstLine = Util.getLineNumber(startPosition, this.lineEnds, 0, this.maxLines) - 1;
2095
		int lastLine = Util.getLineNumber(endPosition, this.lineEnds, firstLine>1 ? firstLine-2 : 0, this.maxLines) - 1;
2156
		int lastLine = Util.getLineNumber(endPosition, this.lineEnds, firstLine>1 ? firstLine-2 : 0, this.maxLines) - 1;
2096
		StringBuffer inputBuffer= new StringBuffer();
2157
		this.codeSnippetBuffer.setLength(0);
2097
		if (firstLine == lastLine && linesGap == 0) {
2158
		if (firstLine == lastLine && linesGap == 0) {
2098
			inputBuffer.append(snippet);
2159
			this.codeSnippetBuffer.append(snippet);
2099
		} else {
2160
		} else {
2100
			boolean hasCharsAfterStar = false;
2161
			boolean hasCharsAfterStar = false;
2101
			if (linesGap == 0) {
2162
			if (linesGap == 0) {
2102
				inputBuffer.append(this.scanner.source, startPosition, this.lineEnds[firstLine]+1-startPosition);
2163
				this.codeSnippetBuffer.append(this.scanner.source, startPosition, this.lineEnds[firstLine]+1-startPosition);
2103
				firstLine++;
2164
				firstLine++;
2104
			}
2165
			}
2105
			int initialLength = inputBuffer.length();
2166
			int initialLength = this.codeSnippetBuffer.length();
2106
			for (int currentLine=firstLine; currentLine<=lastLine; currentLine++) {
2167
			for (int currentLine=firstLine; currentLine<=lastLine; currentLine++) {
2107
				this.scanner.resetTo(this.lineEnds[currentLine-1]+1, this.lineEnds[currentLine]);
2168
				this.scanner.resetTo(this.lineEnds[currentLine-1]+1, this.lineEnds[currentLine]);
2108
				int lineStart = this.scanner.currentPosition;
2169
				int lineStart = this.scanner.currentPosition;
Lines 2149-2155 Link Here
2149
										// consuming the space after the star
2210
										// consuming the space after the star
2150
										hasCharsAfterStar = true;
2211
										hasCharsAfterStar = true;
2151
										currentLine = firstLine-1;
2212
										currentLine = firstLine-1;
2152
										inputBuffer.setLength(initialLength);
2213
										this.codeSnippetBuffer.setLength(initialLength);
2153
										continue;
2214
										continue;
2154
									}
2215
									}
2155
								}
2216
								}
Lines 2164-2176 Link Here
2164
					}
2225
					}
2165
				}
2226
				}
2166
				int end = currentLine == lastLine ? endPosition : this.lineEnds[currentLine];
2227
				int end = currentLine == lastLine ? endPosition : this.lineEnds[currentLine];
2167
				inputBuffer.append(this.scanner.source, lineStart, end+1-lineStart);
2228
				this.codeSnippetBuffer.append(this.scanner.source, lineStart, end+1-lineStart);
2168
			}
2229
			}
2169
		}
2230
		}
2170
	
2231
	
2171
		// 2 - convert HTML to Java (@see JavaDocRegion#convertHtml2Java)
2232
		// 2 - convert HTML to Java (@see JavaDocRegion#convertHtml2Java)
2172
		HTMLEntity2JavaReader reader= new HTMLEntity2JavaReader(new StringReader(inputBuffer.toString()));
2233
		HTMLEntity2JavaReader reader= new HTMLEntity2JavaReader(new StringReader(this.codeSnippetBuffer.toString()));
2173
		char[] buf= new char[inputBuffer.length()]; // html2text never gets longer, only shorter!
2234
		char[] buf= new char[this.codeSnippetBuffer.length()]; // html2text never gets longer, only shorter!
2174
		String convertedSnippet;
2235
		String convertedSnippet;
2175
		try {
2236
		try {
2176
			int read= reader.read(buf);
2237
			int read= reader.read(buf);
Lines 2191-2197 Link Here
2191
		TextEdit edit= CommentFormatterUtil.format2(CodeFormatter.K_UNKNOWN | CodeFormatter.F_INCLUDE_COMMENTS, convertedSnippet, 0, this.lineSeparator, options);
2252
		TextEdit edit= CommentFormatterUtil.format2(CodeFormatter.K_UNKNOWN | CodeFormatter.F_INCLUDE_COMMENTS, convertedSnippet, 0, this.lineSeparator, options);
2192
		if (edit == null) {
2253
		if (edit == null) {
2193
			// 3.a - not a valid code to format, keep initial buffer
2254
			// 3.a - not a valid code to format, keep initial buffer
2194
			formattedSnippet = inputBuffer.toString();
2255
			formattedSnippet = this.codeSnippetBuffer.toString();
2195
		} else {
2256
		} else {
2196
			// 3.b - valid code formatted
2257
			// 3.b - valid code formatted
2197
			// 3.b.i - get the result
2258
			// 3.b.i - get the result
Lines 2200-2214 Link Here
2200
			// 3.b.ii- convert back to HTML (@see JavaDocRegion#convertJava2Html)
2261
			// 3.b.ii- convert back to HTML (@see JavaDocRegion#convertJava2Html)
2201
			Java2HTMLEntityReader javaReader= new Java2HTMLEntityReader(new StringReader(formattedSnippet));
2262
			Java2HTMLEntityReader javaReader= new Java2HTMLEntityReader(new StringReader(formattedSnippet));
2202
			buf= new char[256];
2263
			buf= new char[256];
2203
			StringBuffer conversionBuffer= new StringBuffer();
2264
			this.codeSnippetBuffer.setLength(0);
2204
			int l;
2265
			int l;
2205
			try {
2266
			try {
2206
				do {
2267
				do {
2207
					l= javaReader.read(buf);
2268
					l= javaReader.read(buf);
2208
					if (l != -1)
2269
					if (l != -1)
2209
						conversionBuffer.append(buf, 0, l);
2270
						this.codeSnippetBuffer.append(buf, 0, l);
2210
				} while (l > 0);
2271
				} while (l > 0);
2211
				formattedSnippet = conversionBuffer.toString();
2272
				formattedSnippet = this.codeSnippetBuffer.toString();
2212
			} catch (IOException e) {
2273
			} catch (IOException e) {
2213
				// should not happen
2274
				// should not happen
2214
				CommentFormatterUtil.log(e);
2275
				CommentFormatterUtil.log(e);
Lines 2217-2248 Link Here
2217
		}
2278
		}
2218
	
2279
	
2219
		// 4 - add the content prefix (@see JavaDocRegion#postprocessCodeSnippet)
2280
		// 4 - add the content prefix (@see JavaDocRegion#postprocessCodeSnippet)
2220
		StringBuffer outputBuffer = new StringBuffer();
2281
		this.codeSnippetBuffer.setLength(0);
2221
		ILineTracker tracker = new DefaultLineTracker();
2282
		ILineTracker tracker = new DefaultLineTracker();
2222
		this.column = 1;
2283
		this.column = 1;
2223
		printIndentationIfNecessary(outputBuffer); // append indentation
2284
		printIndentationIfNecessary(this.codeSnippetBuffer); // append indentation
2224
		outputBuffer.append(BLOCK_LINE_PREFIX);
2285
		this.codeSnippetBuffer.append(BLOCK_LINE_PREFIX);
2225
		String linePrefix = outputBuffer.toString();
2286
		String linePrefix = this.codeSnippetBuffer.toString();
2226
		outputBuffer.setLength(0);
2287
		this.codeSnippetBuffer.setLength(0);
2227
		String replacement = formattedSnippet;
2288
		String replacement = formattedSnippet;
2228
		tracker.set(formattedSnippet);
2289
		tracker.set(formattedSnippet);
2229
		int numberOfLines = tracker.getNumberOfLines();
2290
		int numberOfLines = tracker.getNumberOfLines();
2230
		if (numberOfLines > 1) {
2291
		if (numberOfLines > 1) {
2231
			int lastLineOffset = -1;
2292
			int lastLineOffset = -1;
2232
			for (int i=0; i<numberOfLines-1; i++) {
2293
			for (int i=0; i<numberOfLines-1; i++) {
2233
				if (i>0) outputBuffer.append(linePrefix);
2294
				if (i>0) this.codeSnippetBuffer.append(linePrefix);
2234
				try {
2295
				try {
2235
					lastLineOffset = tracker.getLineOffset(i+1);
2296
					lastLineOffset = tracker.getLineOffset(i+1);
2236
					outputBuffer.append(formattedSnippet.substring(tracker.getLineOffset(i), lastLineOffset));
2297
					this.codeSnippetBuffer.append(formattedSnippet.substring(tracker.getLineOffset(i), lastLineOffset));
2237
				} catch (BadLocationException e) {
2298
				} catch (BadLocationException e) {
2238
					// should not happen
2299
					// should not happen
2239
					CommentFormatterUtil.log(e);
2300
					CommentFormatterUtil.log(e);
2240
					return;
2301
					return;
2241
				}
2302
				}
2242
			}
2303
			}
2243
			outputBuffer.append(linePrefix);
2304
			this.codeSnippetBuffer.append(linePrefix);
2244
			outputBuffer.append(formattedSnippet.substring(lastLineOffset));
2305
			this.codeSnippetBuffer.append(formattedSnippet.substring(lastLineOffset));
2245
			replacement = outputBuffer.toString();
2306
			replacement = this.codeSnippetBuffer.toString();
2246
		}
2307
		}
2247
	
2308
	
2248
		// 5 - replace old text with the formatted snippet
2309
		// 5 - replace old text with the formatted snippet
Lines 2778-2791 Link Here
2778
					this.lastNumberOfNewLines++;
2839
					this.lastNumberOfNewLines++;
2779
					this.line++;
2840
					this.line++;
2780
					if (newLineString == null) {
2841
					if (newLineString == null) {
2781
						StringBuffer newLineBuffer = new StringBuffer(this.lineSeparator);
2842
						this.tempBuffer.setLength(0);
2843
						this.tempBuffer.append(this.lineSeparator);
2782
						this.column = 1;
2844
						this.column = 1;
2783
						if (!this.formatter.preferences.never_indent_line_comments_on_first_column) {
2845
						if (!this.formatter.preferences.never_indent_line_comments_on_first_column) {
2784
							printIndentationIfNecessary(newLineBuffer);
2846
							printIndentationIfNecessary(this.tempBuffer);
2785
						}
2847
						}
2786
					    newLineBuffer.append(LINE_COMMENT_PREFIX);
2848
					    this.tempBuffer.append(LINE_COMMENT_PREFIX);
2787
						this.column += LINE_COMMENT_PREFIX_LENGTH;
2849
						this.column += LINE_COMMENT_PREFIX_LENGTH;
2788
						newLineString = newLineBuffer.toString();
2850
						newLineString = this.tempBuffer.toString();
2789
				    	firstColumn = this.column;
2851
				    	firstColumn = this.column;
2790
					} else {
2852
					} else {
2791
						this.column = firstColumn;
2853
						this.column = firstColumn;
Lines 2850-2859 Link Here
2850
	}
2912
	}
2851
2913
2852
	void printIndentationIfNecessary() {
2914
	void printIndentationIfNecessary() {
2853
		StringBuffer buffer = new StringBuffer();
2915
		this.tempBuffer.setLength(0);
2854
		printIndentationIfNecessary(buffer);
2916
		printIndentationIfNecessary(this.tempBuffer);
2855
		if (buffer.length() > 0) {
2917
		if (this.tempBuffer.length() > 0) {
2856
			addInsertEdit(this.scanner.getCurrentTokenStartPosition(), buffer.toString());
2918
			addInsertEdit(this.scanner.getCurrentTokenStartPosition(), this.tempBuffer.toString());
2857
			this.pendingSpace = false;
2919
			this.pendingSpace = false;
2858
		}
2920
		}
2859
	}
2921
	}
Lines 2981-2995 Link Here
2981
						commentIndentationLevel += this.indentationSize;
3043
						commentIndentationLevel += this.indentationSize;
2982
					}
3044
					}
2983
				}
3045
				}
2984
				if (commentIndentationLevel == 0) {
3046
				setCommentIndentation(commentIndentationLevel);
2985
				    this.commentIndentation = null;
2986
				} else {
2987
		    		StringBuffer indentationBuffer = new StringBuffer();
2988
		        	for (int i=0; i<commentIndentationLevel; i++) {
2989
		    			indentationBuffer.append(' ');
2990
		        	}
2991
	        		this.commentIndentation = indentationBuffer.toString();
2992
		    	}
2993
			}
3047
			}
2994
			FormatJavadocReference reference= block.reference;
3048
			FormatJavadocReference reference= block.reference;
2995
			if (reference != null) {
3049
			if (reference != null) {
Lines 3041-3052 Link Here
3041
						printJavadocGapLines(previousEnd+1, nodeStart-1, newLines, clearBlankLines, false, null);
3095
						printJavadocGapLines(previousEnd+1, nodeStart-1, newLines, clearBlankLines, false, null);
3042
					}
3096
					}
3043
				} else {
3097
				} else {
3044
					StringBuffer buffer = new StringBuffer();
3098
					this.tempBuffer.setLength(0);
3045
					if (newLines > 0) {
3099
					if (newLines > 0) {
3046
						for (int j=0; j<newLines; j++) {
3100
						for (int j=0; j<newLines; j++) {
3047
							printJavadocNewLine(buffer);
3101
							printJavadocNewLine(this.tempBuffer);
3048
						}
3102
						}
3049
						addInsertEdit(nodeStart, buffer.toString());
3103
						addInsertEdit(nodeStart, this.tempBuffer.toString());
3050
					}
3104
					}
3051
				}
3105
				}
3052
			} else {
3106
			} else {
Lines 3248-3254 Link Here
3248
3302
3249
		// First we need to know what is the indentation
3303
		// First we need to know what is the indentation
3250
		this.scanner.resetTo(block.tagEnd+1, reference.sourceEnd);
3304
		this.scanner.resetTo(block.tagEnd+1, reference.sourceEnd);
3251
		StringBuffer buffer = new StringBuffer();
3305
		this.javadocBlockRefBuffer.setLength(0);
3252
		boolean needFormat = false;
3306
		boolean needFormat = false;
3253
		int previousToken = -1;
3307
		int previousToken = -1;
3254
		int spacePosition = -1;
3308
		int spacePosition = -1;
Lines 3267-3276 Link Here
3267
							case TerminalTokens.TokenNameLPAREN:
3321
							case TerminalTokens.TokenNameLPAREN:
3268
								break;
3322
								break;
3269
							default:	// space between method arguments
3323
							default:	// space between method arguments
3270
								spacePosition = buffer.length();
3324
								spacePosition = this.javadocBlockRefBuffer.length();
3271
								// $FALL-THROUGH$ - fall through next case
3325
								// $FALL-THROUGH$ - fall through next case
3272
							case -1:
3326
							case -1:
3273
								buffer.append(' ');
3327
								this.javadocBlockRefBuffer.append(' ');
3274
								this.column++;
3328
								this.column++;
3275
								break;
3329
								break;
3276
						}
3330
						}
Lines 3283-3311 Link Here
3283
							this.lastNumberOfNewLines++;
3337
							this.lastNumberOfNewLines++;
3284
							this.line++;
3338
							this.line++;
3285
							if (newLineString == null) {
3339
							if (newLineString == null) {
3286
								StringBuffer newLineBuffer = new StringBuffer(this.lineSeparator);
3340
								this.tempBuffer.setLength(0);
3341
								this.tempBuffer.append(this.lineSeparator);
3287
						    	this.column = 1;
3342
						    	this.column = 1;
3288
						    	printIndentationIfNecessary(newLineBuffer);
3343
						    	printIndentationIfNecessary(this.tempBuffer);
3289
					    		newLineBuffer.append(BLOCK_LINE_PREFIX);
3344
					    		this.tempBuffer.append(BLOCK_LINE_PREFIX);
3290
					    		this.column += BLOCK_LINE_PREFIX_LENGTH;
3345
					    		this.column += BLOCK_LINE_PREFIX_LENGTH;
3291
								if (this.commentIndentation != null) {
3346
								if (this.commentIndentation != null) {
3292
							    	newLineBuffer.append(this.commentIndentation);
3347
							    	this.tempBuffer.append(this.commentIndentation);
3293
							    	this.column += this.commentIndentation.length();
3348
							    	this.column += this.commentIndentation.length();
3294
						    	}
3349
						    	}
3295
						    	newLineString = newLineBuffer.substring(0, newLineBuffer.length()-1); // remove last space as buffer will be inserted before a space
3350
						    	newLineString = this.tempBuffer.substring(0, this.tempBuffer.length()-1); // remove last space as buffer will be inserted before a space
3296
						    	firstColumn = this.column;
3351
						    	firstColumn = this.column;
3297
							} else {
3352
							} else {
3298
								this.column = firstColumn;
3353
								this.column = firstColumn;
3299
							}
3354
							}
3300
							this.column = firstColumn + buffer.length() - spacePosition - 1;
3355
							this.column = firstColumn + this.javadocBlockRefBuffer.length() - spacePosition - 1;
3301
							buffer.insert(spacePosition, newLineString);
3356
							this.javadocBlockRefBuffer.insert(spacePosition, newLineString);
3302
							if (headerLine) {
3357
							if (headerLine) {
3303
								headerLine = false;
3358
								headerLine = false;
3304
								maxColumn--;
3359
								maxColumn--;
3305
							}
3360
							}
3306
							spacePosition = -1;
3361
							spacePosition = -1;
3307
						}
3362
						}
3308
						buffer.append(this.scanner.source, this.scanner.startPosition, tokenLength);
3363
						this.javadocBlockRefBuffer.append(this.scanner.source, this.scanner.startPosition, tokenLength);
3309
			    		this.column += tokenLength;
3364
			    		this.column += tokenLength;
3310
			    		break;
3365
			    		break;
3311
				}
3366
				}
Lines 3315-3321 Link Here
3315
			}
3370
			}
3316
		}
3371
		}
3317
		if (needFormat) {
3372
		if (needFormat) {
3318
		    addReplaceEdit(block.tagEnd+1, reference.sourceEnd, buffer.toString());
3373
		    addReplaceEdit(block.tagEnd+1, reference.sourceEnd, this.javadocBlockRefBuffer.toString());
3319
		}
3374
		}
3320
    }
3375
    }
3321
3376
Lines 3475-3497 Link Here
3475
			// if there's no enough room to replace text, then insert the gap
3530
			// if there's no enough room to replace text, then insert the gap
3476
			if (textStartPosition > textEndPosition) {
3531
			if (textStartPosition > textEndPosition) {
3477
				if (newLines > 0) {
3532
				if (newLines > 0) {
3478
					StringBuffer buffer = new StringBuffer();
3533
					this.javadocGapLinesBuffer.setLength(0);
3479
					for (int i=0; i<newLines; i++) {
3534
					for (int i=0; i<newLines; i++) {
3480
						buffer.append(this.lineSeparator);
3535
						this.javadocGapLinesBuffer.append(this.lineSeparator);
3481
						this.column = 1;
3536
						this.column = 1;
3482
						printIndentationIfNecessary(buffer);
3537
						printIndentationIfNecessary(this.javadocGapLinesBuffer);
3483
						if (footer) {
3538
						if (footer) {
3484
							buffer.append(' ');
3539
							this.javadocGapLinesBuffer.append(' ');
3485
							this.column++;
3540
							this.column++;
3486
						} else {
3541
						} else {
3487
							buffer.append(BLOCK_LINE_PREFIX);
3542
							this.javadocGapLinesBuffer.append(BLOCK_LINE_PREFIX);
3488
							this.column += BLOCK_LINE_PREFIX_LENGTH;
3543
							this.column += BLOCK_LINE_PREFIX_LENGTH;
3489
						}
3544
						}
3490
					}
3545
					}
3491
					if (output == null) {
3546
					if (output == null) {
3492
						addInsertEdit(textStartPosition, buffer.toString());
3547
						addInsertEdit(textStartPosition, this.javadocGapLinesBuffer.toString());
3493
					} else {
3548
					} else {
3494
						output.append(buffer);
3549
						output.append(this.javadocGapLinesBuffer);
3495
					}
3550
					}
3496
				}
3551
				}
3497
				return;
3552
				return;
Lines 3512-3521 Link Here
3512
						// we just need to replace each lines between '*' with the javadoc formatted ones
3567
						// we just need to replace each lines between '*' with the javadoc formatted ones
3513
						int linesGap = this.scanner.linePtr - linePtr;
3568
						int linesGap = this.scanner.linePtr - linePtr;
3514
						if (linesGap > 0) {
3569
						if (linesGap > 0) {
3515
							StringBuffer buffer = new StringBuffer();
3570
							this.javadocGapLinesBuffer.setLength(0);
3516
							if (lineCount > 0) {
3571
							if (lineCount > 0) {
3517
								// TODO https://bugs.eclipse.org/bugs/show_bug.cgi?id=49619
3572
								// TODO https://bugs.eclipse.org/bugs/show_bug.cgi?id=49619
3518
								buffer.append( ' ');
3573
								this.javadocGapLinesBuffer.append( ' ');
3519
							}
3574
							}
3520
							for (int i = 0; i < linesGap ; i++) {
3575
							for (int i = 0; i < linesGap ; i++) {
3521
								if (clearBlankLines && lineCount >= newLines) {
3576
								if (clearBlankLines && lineCount >= newLines) {
Lines 3523-3543 Link Here
3523
									// so remove any remaining blanks and leave
3578
									// so remove any remaining blanks and leave
3524
									if (textEndPosition >= start) {
3579
									if (textEndPosition >= start) {
3525
										if (output == null) {
3580
										if (output == null) {
3526
											addReplaceEdit(start, textEndPosition, buffer.toString());
3581
											addReplaceEdit(start, textEndPosition, this.javadocGapLinesBuffer.toString());
3527
										} else {
3582
										} else {
3528
											output.append(buffer);
3583
											output.append(this.javadocGapLinesBuffer);
3529
										}
3584
										}
3530
									}
3585
									}
3531
									return;
3586
									return;
3532
								}
3587
								}
3533
								buffer.append(this.lineSeparator);
3588
								this.javadocGapLinesBuffer.append(this.lineSeparator);
3534
								this.column = 1;
3589
								this.column = 1;
3535
								printIndentationIfNecessary(buffer);
3590
								printIndentationIfNecessary(this.javadocGapLinesBuffer);
3536
								if (i == (linesGap-1)) {
3591
								if (i == (linesGap-1)) {
3537
									buffer.append(' ');
3592
									this.javadocGapLinesBuffer.append(' ');
3538
									this.column++;
3593
									this.column++;
3539
								} else {
3594
								} else {
3540
									buffer.append(BLOCK_LINE_PREFIX);
3595
									this.javadocGapLinesBuffer.append(BLOCK_LINE_PREFIX);
3541
									this.column += BLOCK_LINE_PREFIX_LENGTH;
3596
									this.column += BLOCK_LINE_PREFIX_LENGTH;
3542
								}
3597
								}
3543
								lineCount++;
3598
								lineCount++;
Lines 3545-3553 Link Here
3545
							int currentTokenStartPosition = this.scanner.getCurrentTokenStartPosition();
3600
							int currentTokenStartPosition = this.scanner.getCurrentTokenStartPosition();
3546
							int tokenLength = this.scanner.currentPosition - currentTokenStartPosition;
3601
							int tokenLength = this.scanner.currentPosition - currentTokenStartPosition;
3547
							if (output == null) {
3602
							if (output == null) {
3548
								addReplaceEdit(start, currentTokenStartPosition-1, buffer.toString());
3603
								addReplaceEdit(start, currentTokenStartPosition-1, this.javadocGapLinesBuffer.toString());
3549
							} else {
3604
							} else {
3550
								output.append(buffer);
3605
								output.append(this.javadocGapLinesBuffer);
3551
								output.append(this.scanner.source, currentTokenStartPosition, tokenLength);
3606
								output.append(this.scanner.source, currentTokenStartPosition, tokenLength);
3552
							}
3607
							}
3553
							this.column += tokenLength;
3608
							this.column += tokenLength;
Lines 3574-3624 Link Here
3574
			// Format the last whitespaces
3629
			// Format the last whitespaces
3575
			if (lineCount < newLines) {
3630
			if (lineCount < newLines) {
3576
				// Insert new lines as not enough was encountered while scanning the whitespaces
3631
				// Insert new lines as not enough was encountered while scanning the whitespaces
3577
				StringBuffer buffer = new StringBuffer();
3632
				this.javadocGapLinesBuffer.setLength(0);
3578
				if (lineCount > 0) {
3633
				if (lineCount > 0) {
3579
					// TODO https://bugs.eclipse.org/bugs/show_bug.cgi?id=49619
3634
					// TODO https://bugs.eclipse.org/bugs/show_bug.cgi?id=49619
3580
					buffer.append( ' ');
3635
					this.javadocGapLinesBuffer.append( ' ');
3581
				}
3636
				}
3582
				for (int i = lineCount; i < newLines-1; i++) {
3637
				for (int i = lineCount; i < newLines-1; i++) {
3583
					printJavadocNewLine(buffer);
3638
					printJavadocNewLine(this.javadocGapLinesBuffer);
3584
				}
3639
				}
3585
				buffer.append(this.lineSeparator);
3640
				this.javadocGapLinesBuffer.append(this.lineSeparator);
3586
				this.column = 1;
3641
				this.column = 1;
3587
				printIndentationIfNecessary(buffer);
3642
				printIndentationIfNecessary(this.javadocGapLinesBuffer);
3588
				if (footer) {
3643
				if (footer) {
3589
					buffer.append(' ');
3644
					this.javadocGapLinesBuffer.append(' ');
3590
					this.column++;
3645
					this.column++;
3591
				} else {
3646
				} else {
3592
					buffer.append(BLOCK_LINE_PREFIX);
3647
					this.javadocGapLinesBuffer.append(BLOCK_LINE_PREFIX);
3593
					this.column += BLOCK_LINE_PREFIX_LENGTH;
3648
					this.column += BLOCK_LINE_PREFIX_LENGTH;
3594
				}
3649
				}
3595
				if (output == null) {
3650
				if (output == null) {
3596
					if (textEndPosition >= start) {
3651
					if (textEndPosition >= start) {
3597
						addReplaceEdit(start, textEndPosition, buffer.toString());
3652
						addReplaceEdit(start, textEndPosition, this.javadocGapLinesBuffer.toString());
3598
					} else {
3653
					} else {
3599
						addInsertEdit(textEndPosition+1, buffer.toString());
3654
						addInsertEdit(textEndPosition+1, this.javadocGapLinesBuffer.toString());
3600
					}
3655
					}
3601
				} else {
3656
				} else {
3602
					output.append(buffer);
3657
					output.append(this.javadocGapLinesBuffer);
3603
				}
3658
				}
3604
			} else {
3659
			} else {
3605
				// Replace all remaining whitespaces by a single space
3660
				// Replace all remaining whitespaces by a single space
3606
				if (textEndPosition >= start) {
3661
				if (textEndPosition >= start) {
3607
					StringBuffer buffer = new StringBuffer();
3662
					this.javadocGapLinesBuffer.setLength(0);
3608
					if (this.scanner.linePtr > linePtr) {
3663
					if (this.scanner.linePtr > linePtr) {
3609
						if (lineCount > 0) {
3664
						if (lineCount > 0) {
3610
							// TODO https://bugs.eclipse.org/bugs/show_bug.cgi?id=49619
3665
							// TODO https://bugs.eclipse.org/bugs/show_bug.cgi?id=49619
3611
							buffer.append( ' ');
3666
							this.javadocGapLinesBuffer.append(' ');
3612
						}
3667
						}
3613
						buffer.append(this.lineSeparator);
3668
						this.javadocGapLinesBuffer.append(this.lineSeparator);
3614
						this.column = 1;
3669
						this.column = 1;
3615
						printIndentationIfNecessary(buffer);
3670
						printIndentationIfNecessary(this.javadocGapLinesBuffer);
3616
					}
3671
					}
3617
					buffer.append(' ');
3672
					this.javadocGapLinesBuffer.append(' ');
3618
					if (output == null) {
3673
					if (output == null) {
3619
						addReplaceEdit(start, textEndPosition, buffer.toString());
3674
						addReplaceEdit(start, textEndPosition, this.javadocGapLinesBuffer.toString());
3620
					} else {
3675
					} else {
3621
						output.append(buffer);
3676
						output.append(this.javadocGapLinesBuffer);
3622
					}
3677
					}
3623
					this.needSpace = false;
3678
					this.needSpace = false;
3624
				} else if (endsOnMultiply) {
3679
				} else if (endsOnMultiply) {
Lines 3650-3656 Link Here
3650
			// Iterate on text line separators
3705
			// Iterate on text line separators
3651
			int textLineStart = text.lineStart;
3706
			int textLineStart = text.lineStart;
3652
			this.scanner.tokenizeWhiteSpace = false;
3707
			this.scanner.tokenizeWhiteSpace = false;
3653
			StringBuffer buffer = null;
3708
			String newLineString = null;
3654
			for (int idx=0, max=text.separatorsPtr; idx<=max ; idx++) {
3709
			for (int idx=0, max=text.separatorsPtr; idx<=max ; idx++) {
3655
				int start = (int) text.separators[idx];
3710
				int start = (int) text.separators[idx];
3656
				int lineStart = Util.getLineNumber(start, this.lineEnds, textLineStart-1, this.maxLines);
3711
				int lineStart = Util.getLineNumber(start, this.lineEnds, textLineStart-1, this.maxLines);
Lines 3668-3681 Link Here
3668
					if (this.scanner.currentCharacter == ' ') {
3723
					if (this.scanner.currentCharacter == ' ') {
3669
						this.scanner.getNextChar();
3724
						this.scanner.getNextChar();
3670
					}
3725
					}
3671
					if (buffer == null) {
3726
					if (newLineString == null) {
3672
						buffer = new StringBuffer();
3727
						this.tempBuffer.setLength(0);
3673
						this.column = 1;
3728
						this.column = 1;
3674
						printIndentationIfNecessary(buffer);
3729
						printIndentationIfNecessary(this.tempBuffer);
3675
						buffer.append(BLOCK_LINE_PREFIX);
3730
						this.tempBuffer.append(BLOCK_LINE_PREFIX);
3676
						this.column += BLOCK_LINE_PREFIX_LENGTH;
3731
						this.column += BLOCK_LINE_PREFIX_LENGTH;
3732
						newLineString = this.tempBuffer.toString();
3677
					}
3733
					}
3678
					addReplaceEdit(end+1, this.scanner.getCurrentTokenEndPosition(), buffer.toString());
3734
					addReplaceEdit(end+1, this.scanner.getCurrentTokenEndPosition(), newLineString);
3679
					textLineStart++;
3735
					textLineStart++;
3680
				}
3736
				}
3681
			}
3737
			}
Lines 3713-3719 Link Here
3713
		int lineEnd = Util.getLineNumber(block.nodes[0].sourceEnd, this.lineEnds, lineStart-1, this.maxLines);
3769
		int lineEnd = Util.getLineNumber(block.nodes[0].sourceEnd, this.lineEnds, lineStart-1, this.maxLines);
3714
		boolean multiLinesBlock = lineEnd > (lineStart+1);
3770
		boolean multiLinesBlock = lineEnd > (lineStart+1);
3715
		int previousPosition = this.scanner.currentPosition;
3771
		int previousPosition = this.scanner.currentPosition;
3716
		StringBuffer buffer = null;
3772
		String newLineString = null;
3717
		int indentationColumn = 0;
3773
		int indentationColumn = 0;
3718
		int leadingSpaces = -1;
3774
		int leadingSpaces = -1;
3719
3775
Lines 3747-3763 Link Here
3747
					}
3803
					}
3748
					// print indentation if there were spaces without any star on the line
3804
					// print indentation if there were spaces without any star on the line
3749
					if (leadingSpaces > 0 && multiLinesBlock) {
3805
					if (leadingSpaces > 0 && multiLinesBlock) {
3750
						if (buffer == null) {
3806
						if (newLineString == null) {
3751
							buffer = new StringBuffer();
3752
							this.column = 1;
3807
							this.column = 1;
3753
							printIndentationIfNecessary(buffer);
3808
							this.tempBuffer.setLength(0);
3754
							buffer.append(BLOCK_LINE_PREFIX);
3809
							printIndentationIfNecessary(this.tempBuffer);
3810
							this.tempBuffer.append(BLOCK_LINE_PREFIX);
3755
							this.column += BLOCK_LINE_PREFIX_LENGTH;
3811
							this.column += BLOCK_LINE_PREFIX_LENGTH;
3812
							newLineString = this.tempBuffer.toString();
3756
							indentationColumn = this.column;
3813
							indentationColumn = this.column;
3757
						} else {
3814
						} else {
3758
							this.column = indentationColumn;
3815
							this.column = indentationColumn;
3759
						}
3816
						}
3760
						addReplaceEdit(newLineStart, newLineStart+indentationColumn-2, buffer.toString());
3817
						addReplaceEdit(newLineStart, newLineStart+indentationColumn-2, newLineString);
3761
					}
3818
					}
3762
					// store line start and reset positions
3819
					// store line start and reset positions
3763
					newLineStart = this.scanner.currentPosition;
3820
					newLineStart = this.scanner.currentPosition;
Lines 3785-3801 Link Here
3785
						} else {
3842
						} else {
3786
							// print indentation before the following characters
3843
							// print indentation before the following characters
3787
							if (offset == 0 && multiLinesBlock) {
3844
							if (offset == 0 && multiLinesBlock) {
3788
								if (buffer == null) {
3845
								if (newLineString == null) {
3789
									buffer = new StringBuffer();
3846
									this.tempBuffer.setLength(0);
3790
									this.column = 1;
3847
									this.column = 1;
3791
									printIndentationIfNecessary(buffer);
3848
									printIndentationIfNecessary(this.tempBuffer);
3792
									buffer.append(BLOCK_LINE_PREFIX);
3849
									this.tempBuffer.append(BLOCK_LINE_PREFIX);
3793
									this.column += BLOCK_LINE_PREFIX_LENGTH;
3850
									this.column += BLOCK_LINE_PREFIX_LENGTH;
3794
									indentationColumn = this.column;
3851
									indentationColumn = this.column;
3852
									newLineString = this.tempBuffer.toString();
3795
								} else {
3853
								} else {
3796
									this.column = indentationColumn;
3854
									this.column = indentationColumn;
3797
								}
3855
								}
3798
								addReplaceEdit(newLineStart, secondLineStart-1, buffer.toString());
3856
								addReplaceEdit(newLineStart, secondLineStart-1, newLineString);
3799
							}
3857
							}
3800
							offset++;
3858
							offset++;
3801
						}
3859
						}
Lines 3824-3853 Link Here
3824
			addReplaceEdit(firstLineEnd, end, " "); //$NON-NLS-1$
3882
			addReplaceEdit(firstLineEnd, end, " "); //$NON-NLS-1$
3825
		}
3883
		}
3826
		else if (secondLineStart > 0) {
3884
		else if (secondLineStart > 0) {
3827
			if (buffer == null) {
3885
			if (newLineString == null) {
3828
				buffer = new StringBuffer();
3886
				this.tempBuffer.setLength(0);
3829
				this.column = 1;
3887
				this.column = 1;
3830
				printIndentationIfNecessary(buffer);
3888
				printIndentationIfNecessary(this.tempBuffer);
3831
				buffer.append(BLOCK_LINE_PREFIX);
3889
				this.tempBuffer.append(BLOCK_LINE_PREFIX);
3832
				this.column += BLOCK_LINE_PREFIX_LENGTH;
3890
				this.column += BLOCK_LINE_PREFIX_LENGTH;
3891
				newLineString = this.tempBuffer.toString();
3833
				indentationColumn = this.column;
3892
				indentationColumn = this.column;
3834
			} else {
3893
			} else {
3835
				this.column = indentationColumn;
3894
				this.column = indentationColumn;
3836
			}
3895
			}
3837
			addReplaceEdit(newLineStart, secondLineStart-1, buffer.toString());
3896
			addReplaceEdit(newLineStart, secondLineStart-1, newLineString);
3838
		}
3897
		}
3839
		else if (leadingSpaces > 0) {
3898
		else if (leadingSpaces > 0) {
3840
			if (buffer == null) {
3899
			if (newLineString == null) {
3841
				buffer = new StringBuffer();
3900
				this.tempBuffer.setLength(0);
3842
				this.column = 1;
3901
				this.column = 1;
3843
				printIndentationIfNecessary(buffer);
3902
				printIndentationIfNecessary(this.tempBuffer);
3844
				buffer.append(BLOCK_LINE_PREFIX);
3903
				this.tempBuffer.append(BLOCK_LINE_PREFIX);
3845
				this.column += BLOCK_LINE_PREFIX_LENGTH;
3904
				this.column += BLOCK_LINE_PREFIX_LENGTH;
3905
				newLineString = this.tempBuffer.toString();
3846
				indentationColumn = this.column;
3906
				indentationColumn = this.column;
3847
			} else {
3907
			} else {
3848
				this.column = indentationColumn;
3908
				this.column = indentationColumn;
3849
			}
3909
			}
3850
			addReplaceEdit(newLineStart, newLineStart+indentationColumn-2, buffer.toString());
3910
			addReplaceEdit(newLineStart, newLineStart+indentationColumn-2, newLineString);
3851
		}
3911
		}
3852
3912
3853
		// Reset
3913
		// Reset
Lines 3868-3874 Link Here
3868
		int nextStart = textStart;
3928
		int nextStart = textStart;
3869
		int startLine = Util.getLineNumber(textStart, this.lineEnds, 0, this.maxLines);
3929
		int startLine = Util.getLineNumber(textStart, this.lineEnds, 0, this.maxLines);
3870
	    int htmlTagID = text.getHtmlTagID();
3930
	    int htmlTagID = text.getHtmlTagID();
3871
	    StringBuffer buffer = new StringBuffer();
3931
	    if (text.depth >= this.javadocHtmlTagBuffers.length) {
3932
	    	int length = this.javadocHtmlTagBuffers.length;
3933
	    	System.arraycopy(this.javadocHtmlTagBuffers, 0, this.javadocHtmlTagBuffers = new StringBuffer[text.depth+6], 0, length);
3934
	    }
3935
	    StringBuffer buffer = this.javadocHtmlTagBuffers[text.depth];
3936
	    if (buffer == null) {
3937
	    	buffer = new StringBuffer();
3938
	    	this.javadocHtmlTagBuffers[text.depth] = buffer;
3939
	    } else {
3940
	    	buffer.setLength(0);
3941
	    }
3872
3942
3873
	    // New line will be added before next node
3943
	    // New line will be added before next node
3874
	    int max = text.separatorsPtr;
3944
	    int max = text.separatorsPtr;
Lines 3911-3917 Link Here
3911
					printJavadocGapLines(previousEnd+1, nodeStart-1, newLines, clearBlankLines, false, null);
3981
					printJavadocGapLines(previousEnd+1, nodeStart-1, newLines, clearBlankLines, false, null);
3912
				}
3982
				}
3913
				if (newLines > 0) textOnNewLine = true;
3983
				if (newLines > 0) textOnNewLine = true;
3914
				buffer = new StringBuffer();
3984
				buffer.setLength(0);
3915
				if (node.isText()) {
3985
				if (node.isText()) {
3916
					if (immutable) {
3986
					if (immutable) {
3917
						// do not change immutable tags, just increment column
3987
						// do not change immutable tags, just increment column
Lines 4077-4089 Link Here
4077
	    this.column += BLOCK_LINE_PREFIX_LENGTH;
4147
	    this.column += BLOCK_LINE_PREFIX_LENGTH;
4078
	    this.line++;
4148
	    this.line++;
4079
	    this.lastNumberOfNewLines++;
4149
	    this.lastNumberOfNewLines++;
4080
    }
4150
	}
4081
4151
4082
	private void printJavadocText(FormatJavadocText text, FormatJavadocBlock block, boolean textOnNewLine) {
4152
	private void printJavadocText(FormatJavadocText text, FormatJavadocBlock block, boolean textOnNewLine) {
4083
4153
4084
		boolean clearBlankLines = this.formatter.preferences.comment_clear_blank_lines_in_javadoc_comment;
4154
		boolean clearBlankLines = this.formatter.preferences.comment_clear_blank_lines_in_javadoc_comment;
4085
		boolean joinLines = this.formatter.preferences.join_lines_in_comments;
4155
		boolean joinLines = this.formatter.preferences.join_lines_in_comments;
4086
		StringBuffer buffer = new StringBuffer();
4156
		this.javadocTextBuffer.setLength(0);
4087
		int textStart = text.sourceStart;
4157
		int textStart = text.sourceStart;
4088
		int nextStart = textStart;
4158
		int nextStart = textStart;
4089
		int startLine = Util.getLineNumber(textStart, this.lineEnds, 0, this.maxLines);
4159
		int startLine = Util.getLineNumber(textStart, this.lineEnds, 0, this.maxLines);
Lines 4100-4106 Link Here
4100
				}
4170
				}
4101
			}
4171
			}
4102
			this.needSpace = idx > 0;
4172
			this.needSpace = idx > 0;
4103
			printJavadocTextLine(buffer, nextStart, end, block, idx==0 || (!joinLines && textOnNewLine)/*first text?*/, needIndentation, false /*not an html tag*/);
4173
			printJavadocTextLine(this.javadocTextBuffer, nextStart, end, block, idx==0 || (!joinLines && textOnNewLine)/*first text?*/, needIndentation, false /*not an html tag*/);
4104
			textOnNewLine = false;
4174
			textOnNewLine = false;
4105
4175
4106
			// Replace with current buffer if there are several empty lines between text lines
4176
			// Replace with current buffer if there are several empty lines between text lines
Lines 4111-4119 Link Here
4111
				int gapLine = endLine;
4181
				int gapLine = endLine;
4112
				if (joinLines) gapLine++; // if not preserving line break then gap must be at least of one line
4182
				if (joinLines) gapLine++; // if not preserving line break then gap must be at least of one line
4113
				if (startLine > gapLine) {
4183
				if (startLine > gapLine) {
4114
					addReplaceEdit(textStart, end, buffer.toString());
4184
					addReplaceEdit(textStart, end, this.javadocTextBuffer.toString());
4115
					textStart = nextStart;
4185
					textStart = nextStart;
4116
					buffer.setLength(0);
4186
					this.javadocTextBuffer.setLength(0);
4117
					int newLines = startLine - endLine;
4187
					int newLines = startLine - endLine;
4118
					if (clearBlankLines) newLines = 1;
4188
					if (clearBlankLines) newLines = 1;
4119
					printJavadocGapLines(end+1, nextStart-1, newLines, this.formatter.preferences.comment_clear_blank_lines_in_javadoc_comment, false, null);
4189
					printJavadocGapLines(end+1, nextStart-1, newLines, this.formatter.preferences.comment_clear_blank_lines_in_javadoc_comment, false, null);
Lines 4128-4137 Link Here
4128
		// Replace remaining line
4198
		// Replace remaining line
4129
		boolean needIndentation = textOnNewLine;
4199
		boolean needIndentation = textOnNewLine;
4130
		this.needSpace = text.separatorsPtr >= 0;
4200
		this.needSpace = text.separatorsPtr >= 0;
4131
		printJavadocTextLine(buffer, nextStart, text.sourceEnd, block, text.separatorsPtr==-1 /* first text?*/, needIndentation, false /*not an html tag*/);
4201
		printJavadocTextLine(this.javadocTextBuffer, nextStart, text.sourceEnd, block, text.separatorsPtr==-1 /* first text?*/, needIndentation, false /*not an html tag*/);
4132
		// TODO Bring back following optimization
4202
		// TODO Bring back following optimization
4133
		// if (lastNewLines != this.lastNumberOfNewLines || (this.column - currentColumn) != (text.sourceEnd - text.sourceStart + 1)) {
4203
		// if (lastNewLines != this.lastNumberOfNewLines || (this.column - currentColumn) != (text.sourceEnd - text.sourceStart + 1)) {
4134
			addReplaceEdit(textStart, text.sourceEnd, buffer.toString());
4204
			addReplaceEdit(textStart, text.sourceEnd, this.javadocTextBuffer.toString());
4135
		// }
4205
		// }
4136
4206
4137
		// Reset
4207
		// Reset
Lines 4147-4153 Link Here
4147
		boolean headerLine = block.isHeaderLine() && this.lastNumberOfNewLines == 0;
4217
		boolean headerLine = block.isHeaderLine() && this.lastNumberOfNewLines == 0;
4148
4218
4149
		// First we need to know what is the indentation
4219
		// First we need to know what is the indentation
4150
		StringBuffer tokensBuffer = new StringBuffer();
4220
		this.javadocTokensBuffer.setLength(0);
4151
		int firstColumn = 1 + this.indentationLevel + BLOCK_LINE_PREFIX_LENGTH;
4221
		int firstColumn = 1 + this.indentationLevel + BLOCK_LINE_PREFIX_LENGTH;
4152
		int maxColumn = this.formatter.preferences.comment_line_length + 1;
4222
		int maxColumn = this.formatter.preferences.comment_line_length + 1;
4153
		if (headerLine) {
4223
		if (headerLine) {
Lines 4179-4189 Link Here
4179
				} catch (InvalidInputException iie) {
4249
				} catch (InvalidInputException iie) {
4180
					token = consumeInvalidToken(textEnd);
4250
					token = consumeInvalidToken(textEnd);
4181
				}
4251
				}
4182
	    		int tokensBufferLength = tokensBuffer.length();
4252
	    		int tokensBufferLength = this.javadocTokensBuffer.length();
4183
    			int tokenStart = this.scanner.getCurrentTokenStartPosition();
4253
    			int tokenStart = this.scanner.getCurrentTokenStartPosition();
4184
	    		int tokenLength = (this.scanner.atEnd() ? this.scanner.eofPosition : this.scanner.currentPosition) - tokenStart;
4254
	    		int tokenLength = (this.scanner.atEnd() ? this.scanner.eofPosition : this.scanner.currentPosition) - tokenStart;
4185
				boolean insertSpace = (previousToken == TerminalTokens.TokenNameWHITESPACE || this.needSpace) && !textOnNewLine;
4255
				boolean insertSpace = (previousToken == TerminalTokens.TokenNameWHITESPACE || this.needSpace) && !textOnNewLine;
4186
				String tokensBufferString = tokensBuffer.toString().trim();
4256
				String tokensBufferString = this.javadocTokensBuffer.toString().trim();
4187
				switch (token) {
4257
				switch (token) {
4188
					case TerminalTokens.TokenNameWHITESPACE:
4258
					case TerminalTokens.TokenNameWHITESPACE:
4189
						if (tokensBufferLength > 0) {
4259
						if (tokensBufferLength > 0) {
Lines 4195-4211 Link Here
4195
								this.lastNumberOfNewLines++;
4265
								this.lastNumberOfNewLines++;
4196
								this.line++;
4266
								this.line++;
4197
								if (newLineString == null) {
4267
								if (newLineString == null) {
4198
									StringBuffer newLineBuffer = new StringBuffer(this.lineSeparator);
4268
									this.tempBuffer.setLength(0);
4269
									this.tempBuffer.append(this.lineSeparator);
4199
							    	this.column = 1;
4270
							    	this.column = 1;
4200
							    	printIndentationIfNecessary(newLineBuffer);
4271
							    	printIndentationIfNecessary(this.tempBuffer);
4201
						    		newLineBuffer.append(BLOCK_LINE_PREFIX);
4272
						    		this.tempBuffer.append(BLOCK_LINE_PREFIX);
4202
							    	this.column += BLOCK_LINE_PREFIX_LENGTH;
4273
							    	this.column += BLOCK_LINE_PREFIX_LENGTH;
4203
									if (this.commentIndentation != null) {
4274
									if (this.commentIndentation != null) {
4204
										newLineBuffer.append(this.commentIndentation);
4275
										this.tempBuffer.append(this.commentIndentation);
4205
								    	this.column += this.commentIndentation.length();
4276
								    	this.column += this.commentIndentation.length();
4206
									}
4277
									}
4207
						    		firstColumn = this.column;
4278
						    		firstColumn = this.column;
4208
						    		newLineString = newLineBuffer.toString();
4279
						    		newLineString = this.tempBuffer.toString();
4209
								} else {
4280
								} else {
4210
									this.column = firstColumn;
4281
									this.column = firstColumn;
4211
								}
4282
								}
Lines 4218-4227 Link Here
4218
									headerLine = false;
4289
									headerLine = false;
4219
								}
4290
								}
4220
							} else {
4291
							} else {
4221
								buffer.append(tokensBuffer);
4292
								buffer.append(this.javadocTokensBuffer);
4222
								this.column += tokensBufferLength;
4293
								this.column += tokensBufferLength;
4223
							}
4294
							}
4224
							tokensBuffer.setLength(0);
4295
							this.javadocTokensBuffer.setLength(0);
4225
						}
4296
						}
4226
						textOnNewLine = false;
4297
						textOnNewLine = false;
4227
						previousToken = token;
4298
						previousToken = token;
Lines 4238-4252 Link Here
4238
	    		if (insertSpace) lastColumn++;
4309
	    		if (insertSpace) lastColumn++;
4239
				boolean shouldSplit = lastColumn > maxColumn // the max length is reached
4310
				boolean shouldSplit = lastColumn > maxColumn // the max length is reached
4240
					&& (!isHtmlTag || previousToken == -1) // not an html tag or just at the beginning of it
4311
					&& (!isHtmlTag || previousToken == -1) // not an html tag or just at the beginning of it
4241
					&& token != TerminalTokens.TokenNameAT && (tokensBufferLength == 0 || tokensBuffer.charAt(tokensBufferLength-1) != '@'); // avoid to split just before a '@'
4312
					&& token != TerminalTokens.TokenNameAT && (tokensBufferLength == 0 || this.javadocTokensBuffer.charAt(tokensBufferLength-1) != '@'); // avoid to split just before a '@'
4242
				if (shouldSplit) {
4313
				if (shouldSplit) {
4243
					// not enough space on the line
4314
					// not enough space on the line
4244
					if ((tokensBufferLength > 0 || tokenLength < maxColumn) && !isHtmlTag && tokensBufferLength > 0 && (firstColumn+tokensBufferLength+tokenLength) >= maxColumn) {
4315
					if ((tokensBufferLength > 0 || tokenLength < maxColumn) && !isHtmlTag && tokensBufferLength > 0 && (firstColumn+tokensBufferLength+tokenLength) >= maxColumn) {
4245
						// there won't be enough room even if we break the line before the buffered tokens
4316
						// there won't be enough room even if we break the line before the buffered tokens
4246
						// So add the buffered tokens now
4317
						// So add the buffered tokens now
4247
						buffer.append(tokensBuffer);
4318
						buffer.append(this.javadocTokensBuffer);
4248
						this.column += tokensBufferLength;
4319
						this.column += tokensBufferLength;
4249
						tokensBuffer.setLength(0);
4320
						this.javadocTokensBuffer.setLength(0);
4250
						tokensBufferLength = 0;
4321
						tokensBufferLength = 0;
4251
						textOnNewLine = false;
4322
						textOnNewLine = false;
4252
					}
4323
					}
Lines 4254-4270 Link Here
4254
						this.lastNumberOfNewLines++;
4325
						this.lastNumberOfNewLines++;
4255
						this.line++;
4326
						this.line++;
4256
						if (newLineString == null) {
4327
						if (newLineString == null) {
4257
							StringBuffer newLineBuffer = new StringBuffer(this.lineSeparator);
4328
							this.tempBuffer.setLength(0);
4329
							this.tempBuffer.append(this.lineSeparator);
4258
					    	this.column = 1;
4330
					    	this.column = 1;
4259
					    	printIndentationIfNecessary(newLineBuffer);
4331
					    	printIndentationIfNecessary(this.tempBuffer);
4260
				    		newLineBuffer.append(BLOCK_LINE_PREFIX);
4332
				    		this.tempBuffer.append(BLOCK_LINE_PREFIX);
4261
					    	this.column += BLOCK_LINE_PREFIX_LENGTH;
4333
					    	this.column += BLOCK_LINE_PREFIX_LENGTH;
4262
							if (this.commentIndentation != null) {
4334
							if (this.commentIndentation != null) {
4263
								newLineBuffer.append(this.commentIndentation);
4335
								this.tempBuffer.append(this.commentIndentation);
4264
						    	this.column += this.commentIndentation.length();
4336
						    	this.column += this.commentIndentation.length();
4265
							}
4337
							}
4266
				    		firstColumn = this.column;
4338
				    		firstColumn = this.column;
4267
				    		newLineString = newLineBuffer.toString();
4339
				    		newLineString = this.tempBuffer.toString();
4268
						} else {
4340
						} else {
4269
							this.column = firstColumn;
4341
							this.column = firstColumn;
4270
						}
4342
						}
Lines 4274-4280 Link Here
4274
			    		String tokensString = tokensBufferString;
4346
			    		String tokensString = tokensBufferString;
4275
						buffer.append(tokensString);
4347
						buffer.append(tokensString);
4276
						this.column += tokensString.length();
4348
						this.column += tokensString.length();
4277
						tokensBuffer.setLength(0);
4349
						this.javadocTokensBuffer.setLength(0);
4278
						tokensBufferLength = 0;
4350
						tokensBufferLength = 0;
4279
		    		}
4351
		    		}
4280
					buffer.append(this.scanner.source, tokenStart, tokenLength);
4352
					buffer.append(this.scanner.source, tokenStart, tokenLength);
Lines 4288-4296 Link Here
4288
    			} else {
4360
    			} else {
4289
					// append token to the line
4361
					// append token to the line
4290
		    		if (insertSpace) {
4362
		    		if (insertSpace) {
4291
		    			tokensBuffer.append(' ');
4363
		    			this.javadocTokensBuffer.append(' ');
4292
		    		}
4364
		    		}
4293
					tokensBuffer.append(this.scanner.source, tokenStart, tokenLength);
4365
					this.javadocTokensBuffer.append(this.scanner.source, tokenStart, tokenLength);
4294
    			}
4366
    			}
4295
				previousToken = token;
4367
				previousToken = token;
4296
    			this.needSpace = false;
4368
    			this.needSpace = false;
Lines 4303-4311 Link Here
4303
		finally {
4375
		finally {
4304
			this.scanner.skipComments = false;
4376
			this.scanner.skipComments = false;
4305
			// Add remaining buffered tokens
4377
			// Add remaining buffered tokens
4306
			if (tokensBuffer.length() > 0) {
4378
			if (this.javadocTokensBuffer.length() > 0) {
4307
				buffer.append(tokensBuffer);
4379
				buffer.append(this.javadocTokensBuffer);
4308
				this.column += tokensBuffer.length();
4380
				this.column += this.javadocTokensBuffer.length();
4309
			}
4381
			}
4310
		}
4382
		}
4311
    }
4383
    }
Lines 4518-4544 Link Here
4518
			// Split the existing edit to keep the change before the beginning of the last line
4590
			// Split the existing edit to keep the change before the beginning of the last line
4519
			// but change the indentation after. Note that at this stage, the add*Edit methods
4591
			// but change the indentation after. Note that at this stage, the add*Edit methods
4520
			// cannot be longer used as the edits are disabled
4592
			// cannot be longer used as the edits are disabled
4521
			StringBuffer indentationBuffer = new StringBuffer();
4593
			String indentationString;
4522
			int currentIndentation = getCurrentIndentation(this.scanner.currentPosition);
4594
			int currentIndentation = getCurrentIndentation(this.scanner.currentPosition);
4523
			if (currentIndentation > 0 && this.indentationLevel > 0) {
4595
			if (currentIndentation > 0 && this.indentationLevel > 0) {
4524
				int col = this.column;
4596
				int col = this.column;
4525
				printIndentationIfNecessary(indentationBuffer);
4597
				this.tempBuffer.setLength(0);
4598
				printIndentationIfNecessary(this.tempBuffer);
4599
				indentationString = this.tempBuffer.toString();
4526
				this.column = col;
4600
				this.column = col;
4601
			} else {
4602
				indentationString = Util.EMPTY_STRING;
4527
			}
4603
			}
4528
			String replacement = currentEdit.replacement;
4604
			String replacement = currentEdit.replacement;
4529
			if (replacement.length() == 0) {
4605
			if (replacement.length() == 0) {
4530
				// previous edit was a delete, as we're sure to have a new line before
4606
				// previous edit was a delete, as we're sure to have a new line before
4531
				// the comment, then the edit needs to be either replaced entirely with
4607
				// the comment, then the edit needs to be either replaced entirely with
4532
				// the expected indentation
4608
				// the expected indentation
4533
				this.edits[this.editsIndex-1] = new OptimizedReplaceEdit(beginningOfLine, offset+length-beginningOfLine, indentationBuffer.toString());
4609
				this.edits[this.editsIndex-1] = new OptimizedReplaceEdit(beginningOfLine, offset+length-beginningOfLine, indentationString);
4534
			} else {
4610
			} else {
4535
				int idx = replacement.lastIndexOf(this.lineSeparator);
4611
				int idx = replacement.lastIndexOf(this.lineSeparator);
4536
				if (idx >= 0) {
4612
				if (idx >= 0) {
4537
					// replace current edit if it contains a line separator
4613
					// replace current edit if it contains a line separator
4538
					int start = idx + this.lsLength;
4614
					int start = idx + this.lsLength;
4539
					StringBuffer buffer = new StringBuffer(replacement.substring(0, start));
4615
					this.tempBuffer.setLength(0);
4540
					buffer.append(indentationBuffer);
4616
					this.tempBuffer.append(replacement.substring(0, start));
4541
					this.edits[this.editsIndex-1] = new OptimizedReplaceEdit(offset, length, buffer.toString());
4617
					if (indentationString != Util.EMPTY_STRING) {
4618
						this.tempBuffer.append(indentationString);
4619
					}
4620
					this.edits[this.editsIndex-1] = new OptimizedReplaceEdit(offset, length, this.tempBuffer.toString());
4542
				}
4621
				}
4543
			}
4622
			}
4544
		}
4623
		}
Lines 4818-4823 Link Here
4818
		System.arraycopy(this.edits, 0, (this.edits = new OptimizedReplaceEdit[this.editsIndex * 2]), 0, this.editsIndex);
4897
		System.arraycopy(this.edits, 0, (this.edits = new OptimizedReplaceEdit[this.editsIndex * 2]), 0, this.editsIndex);
4819
	}
4898
	}
4820
4899
4900
	private void setCommentIndentation(int commentIndentationLevel) {
4901
		if (commentIndentationLevel == 0) {
4902
		    this.commentIndentation = null;
4903
		} else {
4904
			int length = COMMENT_INDENTATIONS.length;
4905
			if (commentIndentationLevel > length) {
4906
				System.arraycopy(COMMENT_INDENTATIONS, 0, COMMENT_INDENTATIONS = new String[commentIndentationLevel+10], 0, length);
4907
			}
4908
			this.commentIndentation = COMMENT_INDENTATIONS[commentIndentationLevel-1];
4909
			if (this.commentIndentation == null) {
4910
				this.tempBuffer.setLength(0);
4911
				for (int i=0; i<commentIndentationLevel; i++) {
4912
					this.tempBuffer.append(' ');
4913
				}
4914
				this.commentIndentation = this.tempBuffer.toString();
4915
				COMMENT_INDENTATIONS[commentIndentationLevel-1] = this.commentIndentation;
4916
			}
4917
		}
4918
	}
4919
4821
	/*
4920
	/*
4822
	 * Look for the tags identified by the scanner to see whether some of them
4921
	 * Look for the tags identified by the scanner to see whether some of them
4823
	 * may change the status of the edition for the formatter.
4922
	 * may change the status of the edition for the formatter.
(-)formatter/org/eclipse/jdt/internal/formatter/align/Alignment.java (-1 / +3 lines)
Lines 46-51 Link Here
46
	public static final int SUPER_INTERFACES = 21;
46
	public static final int SUPER_INTERFACES = 21;
47
	public static final int THROWS = 22;
47
	public static final int THROWS = 22;
48
	public static final int TYPE_MEMBERS = 23;
48
	public static final int TYPE_MEMBERS = 23;
49
	public static final int STRING_CONCATENATION = 24;
49
50
50
	// name of alignment
51
	// name of alignment
51
	public String name;
52
	public String name;
Lines 74-79 Link Here
74
		"superInterfaces", //$NON-NLS-1$
75
		"superInterfaces", //$NON-NLS-1$
75
		"throws", //$NON-NLS-1$
76
		"throws", //$NON-NLS-1$
76
		"typeMembers", //$NON-NLS-1$
77
		"typeMembers", //$NON-NLS-1$
78
		"stringConcatenation", //$NON-NLS-1$
77
	};
79
	};
78
80
79
	// link to enclosing alignment
81
	// link to enclosing alignment
Lines 193-199 Link Here
193
	// location to align and break on.
195
	// location to align and break on.
194
	public Alignment(int kind, int mode, int tieBreakRule, Scribe scribe, int fragmentCount, int sourceRestart, int continuationIndent){
196
	public Alignment(int kind, int mode, int tieBreakRule, Scribe scribe, int fragmentCount, int sourceRestart, int continuationIndent){
195
197
196
		Assert.isTrue(kind >=ALLOCATION && kind <=TYPE_MEMBERS);
198
		Assert.isTrue(kind >=ALLOCATION && kind <=STRING_CONCATENATION);
197
		this.kind = kind;
199
		this.kind = kind;
198
		this.name = NAMES[kind];
200
		this.name = NAMES[kind];
199
		this.location = new Location(scribe, sourceRestart);
201
		this.location = new Location(scribe, sourceRestart);

Return to bug 310811