Bug 575556 - Accept \s only on source level >= Java 15

Change-Id: I75c55081431678556db85cfa12de8870548fb869
Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
Reviewed-on: https://git.eclipse.org/r/c/jdt/eclipse.jdt.core/+/184386
Reviewed-by: Jay Arthanareeswaran <jarthana@in.ibm.com>
Tested-by: JDT Bot <jdt-bot@eclipse.org>
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ScannerTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ScannerTest.java
index 9bf1b78..4403508 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ScannerTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ScannerTest.java
@@ -1555,4 +1555,31 @@
 		}
 		assertEquals("Wrong token type", ITerminalSymbols.TokenNameIntegerLiteral, token);
 	}
+
+	public void testBug575556_at_14() {
+		char[] source= "\"Hello\\sworld\"".toCharArray();
+		Scanner scanner = new Scanner(false, false, false, ClassFileConstants.JDK14, null, null, false);
+		scanner.setSource(source);
+		scanner.resetTo(0, source.length - 1);
+		try {
+			scanner.getNextToken();
+			fail("Should have rejected \\s");
+		} catch (InvalidInputException e) {
+			assertEquals(Scanner.INVALID_ESCAPE, e.getMessage());
+		}
+	}
+
+	public void testBug575556_at_15() {
+		char[] source= "\"Hello\\sworld\"".toCharArray();
+		Scanner scanner = new Scanner(false, false, false, ClassFileConstants.JDK15, null, null, false);
+		scanner.setSource(source);
+		scanner.resetTo(0, source.length - 1);
+		try {
+			int token = scanner.getNextToken();
+			assertEquals(TerminalTokens.TokenNameStringLiteral, token);
+			assertEquals("Unexpected string literal content", "Hello world", scanner.getCurrentStringLiteral());
+		} catch (InvalidInputException e) {
+			fail("Should have accepted \\s");
+		}
+	}
 }
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 77bd47d..b51abe6 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
@@ -3328,6 +3328,9 @@
 			this.currentCharacter = '\'';
 			break;
 		case 's' :
+			if (this.sourceLevel < ClassFileConstants.JDK15) {
+				throw new InvalidInputException(INVALID_ESCAPE);
+			}
 			this.currentCharacter = ' ';
 			break;
 		case '\\' :
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PublicScanner.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PublicScanner.java
index 23fe86f..20c484e 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PublicScanner.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/PublicScanner.java
@@ -2863,6 +2863,12 @@
 		case '\'' :
 			this.currentCharacter = '\'';
 			break;
+		case 's' :
+			if (this.sourceLevel < ClassFileConstants.JDK15) {
+				throw new InvalidInputException(INVALID_ESCAPE);
+			}
+			this.currentCharacter = ' ';
+			break;
 		case '\\' :
 			this.currentCharacter = '\\';
 			break;