Bug 416320 - [Editor] Autocomplete multi-line block comments. Fixed regex matching that should've been checking the line text before the caret.
diff --git a/bundles/org.eclipse.orion.client.editor/web/orion/editor/actions.js b/bundles/org.eclipse.orion.client.editor/web/orion/editor/actions.js
index a3fe898..e0c9cb8 100644
--- a/bundles/org.eclipse.orion.client.editor/web/orion/editor/actions.js
+++ b/bundles/org.eclipse.orion.client.editor/web/orion/editor/actions.js
@@ -609,76 +609,104 @@
 			if (selection.start === selection.end) {

 				var model = editor.getModel();

 				var lineIndex = model.getLineAtOffset(selection.start);

-				var lineText = model.getLine(lineIndex, true);

+				var lineText = model.getLine(lineIndex, false);

 				var lineStart = model.getLineStart(lineIndex);

 				var index = 0;

-				var end = selection.start - lineStart;

+				var lineOffset = selection.start - lineStart;

 				var c;

-				while (index < end && ((c = lineText.charCodeAt(index)) === 32 || c === 9)) { index++; }

+				while (index < lineOffset && ((c = lineText.charCodeAt(index)) === 32 || c === 9)) { index++; }

 				var prefix = lineText.substring(0, index);

 				var options = textView.getOptions("tabSize", "expandTab"); //$NON-NLS-1$ //$NON-NLS-0$

 				var tab = options.expandTab ? new Array(options.tabSize + 1).join(" ") : "\t"; //$NON-NLS-1$ //$NON-NLS-0$

 				var lineDelimiter = model.getLineDelimiter();

-				var matchStartDoc = /^\/\*/;

-				var matchDocComment = /^\*/;

-				var matchEndDoc = /\*\//;

-				var lineTextBeforeCaret = lineText.substring(0, end).trimLeft();

-				if (this.smartIndentation && lineText.charCodeAt(end - 1) === 123) {

-					// If the character before the caret is an opening brace, smart indent the next line.

-					var text = lineText.charCodeAt(end) === 125 ?

-							   lineDelimiter + prefix + tab + lineDelimiter + prefix :

-							   lineDelimiter + prefix + tab;

+				var matchCommentStart = /^[\s]*\/\*[\*]*[\s]*$/;

+				var matchCommentDelimiter = /^[\s]*\*/;

+				var matchCommentEnd = /\*\/[\s]*$/;

+				var lineTextBeforeCaret = lineText.substring(0, lineOffset);

+				var lineTextAfterCaret = lineText.substring(lineOffset);

+				var text;

+				// If the character before the caret is an opening brace, smart indent the next line.

+				if (this.smartIndentation && lineText.charCodeAt(lineOffset - 1) === 123) {

+					text = lineText.charCodeAt(lineOffset) === 125 ?

+						   lineDelimiter + prefix + tab + lineDelimiter + prefix :

+						   lineDelimiter + prefix + tab;

 					editor.setText(text, selection.start, selection.end);

 					editor.setCaretOffset(selection.start + lineDelimiter.length + prefix.length + tab.length);

 					return true;

-				} else if ((!matchEndDoc.test(lineText)) && (matchStartDoc.test(lineTextBeforeCaret) || matchDocComment.test(lineTextBeforeCaret))) {

+				// Proceed with autocompleting multi-line comment if the text before the caret matches

+				// the start or comment delimiter (*) of a multi-line comment

+				} else if ((!matchCommentEnd.test(lineTextBeforeCaret)) &&

+							(matchCommentStart.test(lineTextBeforeCaret) || matchCommentDelimiter.test(lineTextBeforeCaret))) {

+					var caretOffset;

+

 					/**

-					 * Documentation block comment

+					 * Matches the start of a multi-line comment. Autocomplete the multi-line block comment,

+					 * moving any text after the caret into the block comment and setting the caret to be

+					 * after the comment delimiter.

 					 */

-

-					var text;

-

-					// Matches the start of a block comment (/**)

-					var match = matchStartDoc.exec(lineTextBeforeCaret);

+					var match = matchCommentStart.exec(lineTextBeforeCaret);

 					if (match) {

-						// Continue multi-line block comment in the next line

-						text = lineText.substring(selection.start) + lineDelimiter + prefix + " * "; //$NON-NLS-0$

-						editor.setText(text, selection.start, selection.end);

-						editor.setCaretOffset(selection.start + text.length);

+						text = lineDelimiter + prefix + " * "; //$NON-NLS-0$

+						// Text added into the comment block are trimmed of all preceding and trailing whitespaces.

+						// If the text after the caret contains the ending of a block comment, exclude the ending.

+						if (matchCommentEnd.test(lineTextAfterCaret)) {

+							text += lineTextAfterCaret.substring(0, lineTextAfterCaret.length - 2).trim();

+						} else {

+							text += lineTextAfterCaret.trim();

+						}

+						// Add the closing to the multi-line block comment if the next line is not a

+						// comment delimiter.

+						if ((model.getLineCount() === lineIndex + 1) ||

+							!matchCommentDelimiter.test(model.getLine(lineIndex + 1))) {

+							text += lineDelimiter + prefix + " */"; //$NON-NLS-0$

+						}

+						editor.setText(text, selection.start, selection.end + lineTextAfterCaret.length);

+						editor.setCaretOffset(selection.start + lineDelimiter.length + prefix.length + 3);

 						return true;

 					}

 

 					/**

-					 * Matches a star (*) as the start of the trimmed line, and traverse up the lines to confirm if

-					 * it is a multi-line block comment by matching the start of a block comment. If so,

-					 * continue multi-line block comment in the next line.

+					 * Matches a comment delimiter (*) as the start of the line, and traverses up the lines to confirm if

+					 * it is a multi-line comment by matching the start of a block comment. If so, continue the

+					 * multi-line comment in the next line. Any text that follows after the caret is moved to the newly

+					 * added comment delimiter.

 					 */

-					match = matchDocComment.exec(lineTextBeforeCaret);

+					match = matchCommentDelimiter.exec(lineTextBeforeCaret);

 					if (match) {

-						for (var i = lineIndex - 1; i > 0; i--) {

-							var newLine = model.getLine(i, true).trimLeft();

-							if (matchStartDoc.test(newLine)) {

-								text = lineText.substring(selection.start) + lineDelimiter + prefix + "* "; //$NON-NLS-0$

-								editor.setText(text, selection.start, selection.end);

-								editor.setCaretOffset(selection.start + text.length);

+						for (var i = lineIndex - 1; i >= 0; i--) {

+							var prevLine = model.getLine(i, false);

+							if (matchCommentStart.test(prevLine)) {

+								/**

+								 * If the text after the caret matches the end of a comment block or the character in front of the

+								 * caret is a forward slash, continue the block comment with the caret and text after the caret on

+								 * the next line directly in front of the star (*).

+								 */

+								if (matchCommentEnd.test(lineTextAfterCaret) || lineText.charCodeAt(lineOffset) === 47) {

+									text = lineDelimiter + prefix + "*" + lineTextAfterCaret; //$NON-NLS-0$

+									caretOffset = selection.start + lineDelimiter.length + prefix.length + 1;

+								} else {

+									text = lineDelimiter + prefix + "* " + lineTextAfterCaret; //$NON-NLS-0$

+									caretOffset = selection.start + lineDelimiter.length + prefix.length + 2;

+								}

+								editor.setText(text, selection.start, selection.end + lineTextAfterCaret.length);

+								editor.setCaretOffset(caretOffset);

 								return true;

-							} else if (!matchDocComment.test(newLine)) {

+							} else if (!matchCommentDelimiter.test(prevLine)) {

 								return false;

 							}

 						}

-

 					}

 

 					return false;

-				} else if (matchEndDoc.test(lineText)) {

+				} else if (matchCommentEnd.test(lineTextBeforeCaret)) {

 					// Matches the end of a block comment. Fix the indentation for the following line.

-					var text = lineText.substring(selection.start) + lineDelimiter + prefix.substring(0, prefix.length -1);

+					var text = lineText.substring(selection.start) + lineDelimiter + prefix.substring(0, prefix.length - 1);

 					editor.setText(text, selection.start, selection.end);

 					editor.setCaretOffset(selection.start + text.length);

 					return true;

 				} else if (index > 0) {

 					//TODO still wrong when typing inside folding

-					index = end;

+					index = lineOffset;

 					while (index < lineText.length && ((c = lineText.charCodeAt(index++)) === 32 || c === 9)) { selection.end++; }

 					editor.setText(model.getLineDelimiter() + prefix, selection.start, selection.end);

 					return true;