Bug 551351 - [13][compiler] Double slash in text block recognized as
line comment

Change-Id: Ie75a99e9f7d49139d71314c6b7099b086aa95486
Signed-off-by: Jay Arthanareeswaran <jarthana@in.ibm.com>
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/ParserTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/ParserTest.java
index e9c12eb..407758e 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/ParserTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/ParserTest.java
@@ -759,7 +759,7 @@
 			"1. ERROR in X.java (at line 4)\n" + 
 			"	Srtring bar = \"\"\"\n" + 
 			"    }\n" + 
-			"	              ^^^^^^^^^\n" + 
+			"	              ^^^^\n" + 
 			"Text block is not properly closed with the delimiter\n" + 
 			"----------\n" :
 			"----------\n" + 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java
index 3963baa..73f3526 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Scanner.java
@@ -1766,14 +1766,14 @@
 						if (isTextBlock) {
 							if (lastQuotePos > 0)
 								this.currentPosition = lastQuotePos;
+							this.currentPosition = (lastQuotePos > 0) ? lastQuotePos : this.startPosition + this.rawStart;
 							throw new InvalidInputException(UNTERMINATED_TEXT_BLOCK);
 						} else {
 							throw new InvalidInputException(UNTERMINATED_STRING);
 						}
 					} catch (IndexOutOfBoundsException e) {
 						if (isTextBlock) {
-							if (lastQuotePos > 0)
-								this.currentPosition = lastQuotePos;
+							this.currentPosition = (lastQuotePos > 0) ? lastQuotePos : this.startPosition + this.rawStart;
 							throw new InvalidInputException(UNTERMINATED_TEXT_BLOCK);
 						} else {
 							this.currentPosition--;
@@ -2199,32 +2199,61 @@
 						break NextToken;
 					}
 				case '"' :
+					boolean isTextBlock = false;
+					int firstClosingBrace = 0;
 					try {
 						try { // consume next character
-							this.unicodeAsBackSlash = false;
-							if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
-									&& (this.source[this.currentPosition] == 'u')) {
-								getNextUnicodeChar();
-							} else {
-								if (this.withoutUnicodePtr != 0) {
-									unicodeStore();
+							isTextBlock = scanForTextBlockBeginning();
+							if (!isTextBlock) {
+								this.unicodeAsBackSlash = false;
+								if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+										&& (this.source[this.currentPosition] == 'u')) {
+									getNextUnicodeChar();
+								} else {
+									if (this.withoutUnicodePtr != 0) {
+										unicodeStore();
+									}
 								}
 							}
 						} catch (InvalidInputException ex) {
 								// ignore
 						}
-						while (this.currentCharacter != '"') {
-							if (this.currentPosition >= this.eofPosition) {
-								return;
+						
+						Inner: while (this.currentPosition <= this.eofPosition) {
+							if (isTextBlock) {
+								switch (this.currentCharacter) {
+									case '"':
+										// look for text block delimiter
+										if (scanForTextBlockClose()) {
+											this.currentPosition += 2;
+											this.currentCharacter = this.source[this.currentPosition];
+											isTextBlock = false;
+											break Inner;
+										}
+										break;
+									case '}':
+										if (firstClosingBrace == 0)
+											firstClosingBrace = this.currentPosition;
+										break;
+									case '\r' :
+										if (this.source[this.currentPosition] == '\n') 
+											this.currentPosition++;
+										//$FALL-THROUGH$
+									case '\n' :
+										pushLineSeparator();
+										//$FALL-THROUGH$
+									default: 
+										this.currentCharacter = this.source[this.currentPosition++];
+										continue Inner;
+								}
+							} else if (this.currentCharacter == '"') {
+								break Inner;
 							}
 							if (this.currentCharacter == '\r'){
-								// For text block, we don't want to overlook \n. Hence, don't advance past \n
-								//if (this.source[this.currentPosition] == '\n') this.currentPosition++;
+								if (this.source[this.currentPosition] == '\n') this.currentPosition++;
 								break NextToken; // the string cannot go further that the line
 							}
 							if (this.currentCharacter == '\n'){
-								// For text block, we don't want to overlook \n. Hence, go back one char
-								this.currentPosition--;
 								break; // the string cannot go further that the line
 							}
 							if (this.currentCharacter == '\\') {
@@ -2262,7 +2291,13 @@
 							}
 						}
 					} catch (IndexOutOfBoundsException e) {
-						return;
+						if(isTextBlock) {
+							// Pull it back to the first closing brace after the beginning
+							// of the unclosed text block and let recovery take over.
+							if (firstClosingBrace > 0) {
+								this.currentPosition = firstClosingBrace - 1;
+							}
+						}
 					}
 					break NextToken;
 				case '/' :
diff --git a/org.eclipse.jdt.tests.latestBREE/src/org/eclipse/jdt/core/tests/compiler/regression/latest/TextBlockTest.java b/org.eclipse.jdt.tests.latestBREE/src/org/eclipse/jdt/core/tests/compiler/regression/latest/TextBlockTest.java
index d4f5032..7b5c1d1 100644
--- a/org.eclipse.jdt.tests.latestBREE/src/org/eclipse/jdt/core/tests/compiler/regression/latest/TextBlockTest.java
+++ b/org.eclipse.jdt.tests.latestBREE/src/org/eclipse/jdt/core/tests/compiler/regression/latest/TextBlockTest.java
@@ -115,6 +115,26 @@
 				"Text block is not properly closed with the delimiter\n" + 
 				"----------\n");
 	}
+	public void test003a() {
+		runNegativeTest(
+				new String[] {
+						"X.java",
+						"public class X {\n" +
+						"	public static String textb = \"\"\"\n" + 
+						"\n" +
+						"	public static void main(String[] args) {\n" +
+						"		System.out.println(textb);\n" +
+						"	}\n" +
+						"}\n"
+				},
+				"----------\n" + 
+				"1. ERROR in X.java (at line 2)\n" + 
+				"	public static String textb = \"\"\"\n" + 
+				"\n" + 
+				"	                             ^^^^\n" + 
+				"Text block is not properly closed with the delimiter\n" + 
+				"----------\n");
+	}
 	/*
 	 * negative - unescaped '\' in a text block
 	 */