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
*/