49686 [formatting] Javadoc Formatter mishandles spaces in comments
- added attribute COMMENT_STARTS_WITH_RANGE_DELIMITER
- modified wrapping for multi-line comments
- changed range-delimiter computation to respect the attribute
- added debug toString to CommentRange
diff --git a/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/formatter/comment/JavaDocTestCase.java b/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/formatter/comment/JavaDocTestCase.java
index 77d545a..b474fe5 100644
--- a/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/formatter/comment/JavaDocTestCase.java
+++ b/org.eclipse.jdt.text.tests/src/org/eclipse/jdt/text/tests/formatter/comment/JavaDocTestCase.java
@@ -82,7 +82,7 @@
 	}
 	
 	public void testMultiLineCommentBreak1() {
-		String input= PREFIX + " test<br>test" + POSTFIX; //$NON-NLS-1$
+		String input= PREFIX + " test <br>test" + POSTFIX; //$NON-NLS-1$
 		String expected= PREFIX + DELIMITER + INFIX + "test <br>" + DELIMITER + INFIX + "test" + DELIMITER + POSTFIX; //$NON-NLS-1$ //$NON-NLS-2$
 		assertEquals(expected, testFormat(input));
 	}
@@ -320,4 +320,104 @@
 		String content= PREFIX + DELIMITER + INFIX + "test" + DELIMITER + INFIX + "test" + DELIMITER + POSTFIX;
 		assertEquals(content, testFormat(content));
 	}
+	
+	/**
+	 * [formatting] Javadoc Formatter mishandles spaces in comments
+	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=49686
+	 */
+	public void testInlineTag1() {
+		String input= PREFIX + DELIMITER + INFIX + "{@link Object} has many methods." + DELIMITER + POSTFIX;  //$NON-NLS-1$
+		String expected= input;
+		String result= testFormat(input);
+		assertEquals(expected, result);
+	}
+	
+	/**
+	 * [formatting] Javadoc Formatter mishandles spaces in comments
+	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=49686
+	 */
+	public void testInlineTag2() {
+		String input= PREFIX + DELIMITER + INFIX + "{@link Object}s are cool." + DELIMITER + POSTFIX;  //$NON-NLS-1$
+		String expected= input;
+		String result= testFormat(input);
+		assertEquals(expected, result);
+	}
+	
+	/**
+	 * [formatting] Javadoc Formatter mishandles spaces in comments
+	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=49686
+	 */
+	public void testMultilineInlineTag1() {
+		setUserOption(CommentFormatterPreferenceConstants.FORMATTER_COMMENT_LINELENGTH, "20"); //$NON-NLS-1$
+		final String prefix= PREFIX + DELIMITER + INFIX + "{@link Object}";
+		final String postfix= "has many methods." + DELIMITER + POSTFIX;
+		String input= prefix + " " + postfix;  //$NON-NLS-1$
+		String expected= prefix + DELIMITER + INFIX + postfix;
+		String result= testFormat(input);
+		assertEquals(expected, result);
+	}
+	
+	/**
+	 * [formatting] Javadoc Formatter mishandles spaces in comments
+	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=49686
+	 */
+	public void testMultilineInlineTag2() {
+		setUserOption(CommentFormatterPreferenceConstants.FORMATTER_COMMENT_LINELENGTH, "20"); //$NON-NLS-1$
+		final String prefix= PREFIX + DELIMITER + INFIX + "{@link Objecterr}s";
+		final String postfix= "are cool." + DELIMITER + POSTFIX;
+		String input= prefix + " " + postfix;  //$NON-NLS-1$
+		String expected= prefix + DELIMITER + INFIX + postfix;
+		String result= testFormat(input);
+		assertEquals(expected, result);
+	}
+	
+	/**
+	 * [formatting] Javadoc Formatter mishandles spaces in comments
+	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=49686
+	 */
+	public void testTagWordbreaks1() {
+		String input= PREFIX + DELIMITER + INFIX + "<code>Object</code> rocks." + DELIMITER + POSTFIX;  //$NON-NLS-1$
+		String expected= input;
+		String result= testFormat(input);
+		assertEquals(expected, result);
+	}
+
+	/**
+	 * [formatting] Javadoc Formatter mishandles spaces in comments
+	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=49686
+	 */
+	public void testTagWordbreaks2() {
+		String input= PREFIX + DELIMITER + INFIX + "<code>Object</code>s are cool." + DELIMITER + POSTFIX;  //$NON-NLS-1$
+		String expected= input;
+		String result= testFormat(input);
+		assertEquals(expected, result);
+	}
+
+	/**
+	 * [formatting] Javadoc Formatter mishandles spaces in comments
+	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=49686
+	 */
+	public void testMultilineTagWordbreaks1() {
+		setUserOption(CommentFormatterPreferenceConstants.FORMATTER_COMMENT_LINELENGTH, "20"); //$NON-NLS-1$
+		String prefix= PREFIX + DELIMITER + INFIX + "<code>Object</code>";
+		String postfix=  "rocks." + DELIMITER + POSTFIX;  //$NON-NLS-1$
+		String input= prefix + " " + postfix;
+		String expected= prefix + DELIMITER + INFIX + postfix; 
+		String result= testFormat(input);
+		assertEquals(expected, result);
+	}
+
+	/**
+	 * [formatting] Javadoc Formatter mishandles spaces in comments
+	 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=49686
+	 */
+	public void testMultilineTagWordbreaks2() {
+		setUserOption(CommentFormatterPreferenceConstants.FORMATTER_COMMENT_LINELENGTH, "20"); //$NON-NLS-1$
+		final String prefix= PREFIX + DELIMITER + INFIX + "Foo";
+		final String postfix= "<code>Obj</code>s" + DELIMITER + POSTFIX;
+		String input= prefix + " " + postfix;
+		String expected= prefix + DELIMITER + INFIX + postfix;
+		String result= testFormat(input);
+		assertEquals(expected, result);
+	}
 }
diff --git a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/text/comment/CommentRange.java b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/text/comment/CommentRange.java
index 252775a..f340d7c 100644
--- a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/text/comment/CommentRange.java
+++ b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/text/comment/CommentRange.java
@@ -11,6 +11,10 @@
 
 package org.eclipse.jdt.internal.corext.text.comment;
 
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
 import org.eclipse.jface.text.Position;
 
 /**
@@ -205,4 +209,49 @@
 	public final void trimEnd(final int delta) {
 		length += delta;
 	}
+	
+	/*
+	 * @see java.lang.Object#toString()
+	 */
+	public String toString() {
+		List attributes= new ArrayList();
+		if (hasAttribute(COMMENT_BLANKLINE))
+			attributes.add("COMMENT_BLANKLINE"); //$NON-NLS-1$
+		if (hasAttribute(COMMENT_BREAK))
+			attributes.add("COMMENT_BREAK"); //$NON-NLS-1$
+		if (hasAttribute(COMMENT_CLOSE))
+			attributes.add("COMMENT_CLOSE"); //$NON-NLS-1$
+		if (hasAttribute(COMMENT_CODE))
+			attributes.add("COMMENT_CODE"); //$NON-NLS-1$
+		if (hasAttribute(COMMENT_HTML))
+			attributes.add("COMMENT_HTML"); //$NON-NLS-1$
+		if (hasAttribute(COMMENT_IMMUTABLE))
+			attributes.add("COMMENT_IMMUTABLE"); //$NON-NLS-1$
+		if (hasAttribute(COMMENT_NEWLINE))
+			attributes.add("COMMENT_NEWLINE"); //$NON-NLS-1$
+		if (hasAttribute(COMMENT_OPEN))
+			attributes.add("COMMENT_OPEN"); //$NON-NLS-1$
+		if (hasAttribute(COMMENT_PARAGRAPH))
+			attributes.add("COMMENT_PARAGRAPH"); //$NON-NLS-1$
+		if (hasAttribute(COMMENT_PARAMETER))
+			attributes.add("COMMENT_PARAMETER"); //$NON-NLS-1$
+		if (hasAttribute(COMMENT_ROOT))
+			attributes.add("COMMENT_ROOT"); //$NON-NLS-1$
+		if (hasAttribute(COMMENT_SEPARATOR))
+			attributes.add("COMMENT_SEPARATOR"); //$NON-NLS-1$
+		if (hasAttribute(COMMENT_FIRST_TOKEN))
+			attributes.add("COMMENT_FIRST_TOKEN"); //$NON-NLS-1$
+		if (hasAttribute(COMMENT_STARTS_WITH_RANGE_DELIMITER))
+			attributes.add("COMMENT_STARTS_WITH_RANGE_DELIMITER"); //$NON-NLS-1$
+		
+		StringBuffer buf= new StringBuffer("CommentRange [" + offset + "+" + length + "] {"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+		for (Iterator it= attributes.iterator(); it.hasNext();) {
+			String string= (String) it.next();
+			buf.append(string);
+			if (it.hasNext())
+				buf.append(", "); //$NON-NLS-1$
+		}
+		
+		return buf.toString() + "}"; //$NON-NLS-1$
+	}
 }
diff --git a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/text/comment/ICommentAttributes.java b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/text/comment/ICommentAttributes.java
index 6ed630a..bd0cd88 100644
--- a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/text/comment/ICommentAttributes.java
+++ b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/text/comment/ICommentAttributes.java
@@ -56,4 +56,7 @@
 
 	/** Range is the first token on the line in the original source */
 	public static final int COMMENT_FIRST_TOKEN= 1 << 13;
+	
+	/** Range was preceded by whitespace / line delimiters */
+	public static final int COMMENT_STARTS_WITH_RANGE_DELIMITER= 1 << 14;
 }
diff --git a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/text/comment/MultiCommentLine.java b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/text/comment/MultiCommentLine.java
index 5b21412..778863e 100644
--- a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/text/comment/MultiCommentLine.java
+++ b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/text/comment/MultiCommentLine.java
@@ -274,11 +274,13 @@
 			parent.append(result);
 		}
 
-		int attribute= COMMENT_FIRST_TOKEN;
+		int attribute= COMMENT_FIRST_TOKEN | COMMENT_STARTS_WITH_RANGE_DELIMITER;
 		while (offset < length) {
 
-			while (offset < length && Character.isWhitespace(content.charAt(offset)))
+			while (offset < length && Character.isWhitespace(content.charAt(offset))) {
 				offset++;
+				attribute |= COMMENT_STARTS_WITH_RANGE_DELIMITER;
+			}
 
 			index= offset;
 
@@ -286,7 +288,7 @@
 
 				if (content.charAt(index) == HTML_TAG_PREFIX) {
 
-					// in order to avoid recognizign any < in a comment, even those which are part of e.g.
+					// in order to avoid recognizing any < in a comment, even those which are part of e.g.
 					// java source code, we validate the tag content to be one of the recognized
 					// tags (structural, breaks, pre, code).
 					int tag= ++index;
diff --git a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/text/comment/MultiCommentRegion.java b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/text/comment/MultiCommentRegion.java
index 33089f5..c43db06 100644
--- a/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/text/comment/MultiCommentRegion.java
+++ b/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/text/comment/MultiCommentRegion.java
@@ -83,6 +83,11 @@
 				return true;
 		}
 
+		// always append elements that did not have any range separators
+		if (!next.hasAttribute(COMMENT_STARTS_WITH_RANGE_DELIMITER)) {
+			return true;
+		}
+
 		if (fIndentRoots && !line.hasAttribute(COMMENT_ROOT) && !line.hasAttribute(COMMENT_PARAMETER))
 			count -= stringToLength(line.getIndentationReference());
 
@@ -146,25 +151,12 @@
 	 * @see org.eclipse.jdt.internal.corext.text.comment.CommentRegion#getDelimiter(org.eclipse.jdt.internal.corext.text.comment.CommentRange, org.eclipse.jdt.internal.corext.text.comment.CommentRange)
 	 */
 	protected String getDelimiter(final CommentRange previous, final CommentRange next) {
-
-		if (previous != null) {
-
-			if (previous.hasAttribute(COMMENT_HTML) && next.hasAttribute(COMMENT_HTML))
-				return ""; //$NON-NLS-1$
-
-			else if (next.hasAttribute(COMMENT_OPEN) || previous.hasAttribute(COMMENT_HTML | COMMENT_CLOSE))
-				return ""; //$NON-NLS-1$
-
-			else if (!next.hasAttribute(COMMENT_CODE) && previous.hasAttribute(COMMENT_CODE))
-				return ""; //$NON-NLS-1$
-
-			else if (next.hasAttribute(COMMENT_CLOSE) && previous.getLength() <= 2 && !isAlphaNumeric(previous))
-				return ""; //$NON-NLS-1$
-
-			else if (previous.hasAttribute(COMMENT_OPEN) && next.getLength() <= 2 && !isAlphaNumeric(next))
-				return ""; //$NON-NLS-1$
+		// simply preserve range (~ word) breaks
+		if (previous != null && !previous.hasAttribute(COMMENT_STARTS_WITH_RANGE_DELIMITER)) {
+			return ""; //$NON-NLS-1$
+		} else {
+			return super.getDelimiter(previous, next);
 		}
-		return super.getDelimiter(previous, next);
 	}
 
 	/**