Update jdt.core to I20191101-0300 for 4.14M2
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java
index 4b39c6b..f9e3b52 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java
@@ -498,6 +498,8 @@
 		expectedProblemAttributes.put("ExplicitThisParameterNotInLambda", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
 		expectedProblemAttributes.put("ExplicitThisParameterNotBelow18", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
 		expectedProblemAttributes.put("ExplicitlyClosedAutoCloseable", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
+		expectedProblemAttributes.put("ExportingForeignPackage", new ProblemAttributes(CategorizedProblem.CAT_MODULE));
+		expectedProblemAttributes.put("ExportedPackageDoesNotExistOrIsEmpty", new ProblemAttributes(CategorizedProblem.CAT_MODULE));
 		expectedProblemAttributes.put("ExpressionShouldBeAVariable", new ProblemAttributes(CategorizedProblem.CAT_SYNTAX));
 		expectedProblemAttributes.put("ExternalProblemFixable", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
 		expectedProblemAttributes.put("ExternalProblemNotFixable", new ProblemAttributes(CategorizedProblem.CAT_INTERNAL));
@@ -1553,6 +1555,7 @@
 		expectedProblemAttributes.put("ExplicitThisParameterNotInLambda", SKIP);
 		expectedProblemAttributes.put("ExplicitThisParameterNotBelow18", SKIP);
 		expectedProblemAttributes.put("ExplicitlyClosedAutoCloseable", new ProblemAttributes(JavaCore.COMPILER_PB_EXPLICITLY_CLOSED_AUTOCLOSEABLE));
+		expectedProblemAttributes.put("ExportingForeignPackage", SKIP);
 		expectedProblemAttributes.put("ExportedPackageDoesNotExistOrIsEmpty", SKIP);
 		expectedProblemAttributes.put("ExpressionShouldBeAVariable", SKIP);
 		expectedProblemAttributes.put("ExternalProblemFixable", SKIP);
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java
index b14ef55..2ca01b8 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java
@@ -27,8 +27,16 @@
  *******************************************************************************/
 package org.eclipse.jdt.core.tests.compiler.regression;
 
+import static java.lang.Math.abs;
+import static java.util.stream.Collectors.toList;
+
 import java.io.File;
+import java.util.List;
 import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
+import java.util.function.IntFunction;
+import java.util.stream.IntStream;
 
 import junit.framework.Test;
 
@@ -52603,7 +52611,7 @@
  */
 public void testBug543480BasedOnTest2FromComment4ToSameSameOptimization() {
 	if (this.complianceLevel >= ClassFileConstants.JDK1_8) {
-		final long durationFor2TypeParameters = compileTimesAfterWarmup(() -> runConformTest(
+		final List<Duration> durationsFor2TypeParameters = compileTimesAfterWarmup(() -> runConformTest(
 			new String[] {
 				"Test2_2.java",
 				"public class Test2_2 {\n" + 
@@ -52624,7 +52632,7 @@
 				"interface R1<T1> {}\n" + 
 				"interface R2<T1, T2> {}\n"
 			}));
-		final long durationFor11TypeParameters = compileTimesAfterWarmup(() -> runConformTest(
+		final List<Duration> durationsFor11TypeParameters = compileTimesAfterWarmup(() -> runConformTest(
 				new String[] {
 					"Test2_11.java",
 					"public class Test2_11 {\n" + 
@@ -52674,7 +52682,7 @@
 				}));
 		// Time complexity should grow roughly linearly, not O(2^n)
 		// To make the test robust, it tests for the same order of magnitude only, i.e. factor 10.
-		assertCompileTimes(durationFor2TypeParameters, 10, durationFor11TypeParameters);
+		assertCompileTimes(durationsFor2TypeParameters, 10, durationsFor11TypeParameters);
 	}
 }
 /**
@@ -52682,7 +52690,7 @@
  */
 public void testBug543480WithSameSubSuperOptimization() {
 	if (this.complianceLevel >= ClassFileConstants.JDK1_8) {
-		final long durationFor2TypeParameters = compileTimesAfterWarmup(() -> runConformTest(
+		final List<Duration> durationsFor2TypeParameters = compileTimesAfterWarmup(() -> runConformTest(
 			new String[] {
 					"WithParameterizedDependencies_2.java",
 					"abstract class WithParameterizedDependencies_2 {\n" + 
@@ -52698,7 +52706,7 @@
 					"    Type1(final Type1<T1, T2> l) {}" +
 					"}\n"
 			}));
-		final long durationFor12TypeParameters = compileTimesAfterWarmup(() -> runConformTest(
+		final List<Duration> durationsFor12TypeParameters = compileTimesAfterWarmup(() -> runConformTest(
 				new String[] {
 					"WithParameterizedDependencies_12.java",
 					"abstract class WithParameterizedDependencies_12 {\n" + 
@@ -52716,7 +52724,7 @@
 				}));
 		// Time complexity should grow roughly linearly, not O(2^n).
 		// To make the test robust, it tests for the same order of magnitude only, i.e. factor 10.
-		assertCompileTimes(durationFor2TypeParameters, 10, durationFor12TypeParameters);
+		assertCompileTimes(durationsFor2TypeParameters, 10, durationsFor12TypeParameters);
 	}
 }
 /**
@@ -52746,26 +52754,83 @@
 	}
 }
 
-protected void assertCompileTimes(final long shortTime, final double factor, final long longTime) {
-	assertTrue(longTime + " should be less than " + factor + "x the compile time of " + shortTime,
-			longTime < factor*shortTime);
+protected void assertCompileTimes(final List<Duration> shortTimes, final double factor, final List<Duration> longTimes) {
+	final double shortTimesAverage = averageExcludingBoundaries(shortTimes);
+	final double longTimesAverage = averageExcludingBoundaries(longTimes);
+	final String message = "Potential fluctuation of a performance test: average long compile time "
+			+ longTimesAverage + "ms should be less than " + factor + "x the average short compile time " + shortTimesAverage +"ms\n"
+			+ "long compile times: "+longTimes+"\n"
+			+ "short compile times: "+shortTimes;
+	assertTrue(message,longTimesAverage < factor*shortTimesAverage);
+	System.out.println(message);
 }
 
-protected long compileTimesAfterWarmup(final Runnable compileTask) {
+protected double averageExcludingBoundaries(final List<Duration> durations) {
+	return durations.stream()
+			.filter(duration -> !duration.isExcluded)
+			.mapToLong(duration -> duration.durationMs)
+			.average().orElse(-1);
+}
+
+protected List<Duration> compileTimesAfterWarmup(final Runnable compileTask) {
 	// warm up
 	duration(compileTask);
-	// average 
-	return (duration(compileTask) + duration(compileTask) +
-			  duration(compileTask) + duration(compileTask) +
-			  duration(compileTask) + duration(compileTask)) / 6;
+	runGarbageCollection();
+	// draw samples, exclude boundaries i.e. exclude potential outliers
+	final int numberOfSamples = 10;
+	final int boundarySize = 2;
+	return IntStream.rangeClosed(1, numberOfSamples)
+			.mapToObj(duration(compileTask))
+			.sorted()
+			.peek(markExcludedBoundaries(boundarySize, numberOfSamples))
+			.collect(toList());
 }
 
-protected long duration(final Runnable runnable) {
-	final long startMs = System.currentTimeMillis();
-	runnable.run();
-	final long endMs = System.currentTimeMillis();
-	final long duration = endMs-startMs;
-	return duration;
+protected static IntFunction<Duration> duration(final Runnable runnable) {
+	return index -> {
+		final long startMs = System.currentTimeMillis();
+		runnable.run();
+		final long endMs = System.currentTimeMillis();
+		final long duration = endMs-startMs;
+		return new Duration(index, duration);
+	};
+}
+
+protected static Consumer<Duration> markExcludedBoundaries(final int boundarySize, final int numberOfSamples) {
+	final AtomicInteger seenSamples = new AtomicInteger(0);
+	return duration -> {
+		final int indexFromBottom = seenSamples.get();
+		final int indexFromTop = abs(seenSamples.get() - numberOfSamples);
+		if(indexFromBottom < boundarySize) {
+			// a sample within the lower boundary
+			duration.isExcluded = true;
+		} else if(indexFromTop <= boundarySize) {
+			// a sample within the upper boundary
+			duration.isExcluded = true;
+		}
+		seenSamples.incrementAndGet();
+	};
+}
+
+protected static class Duration implements Comparable<Duration> {
+	protected final int index;
+	protected final long durationMs;
+	protected boolean isExcluded = false;
+	
+	public Duration(final int index, final long durationMs) {
+		this.index = index;
+		this.durationMs = durationMs;
+	}
+
+	@Override
+	public int compareTo(Duration other) {
+		return (int)(this.durationMs - other.durationMs);
+	}
+
+	@Override
+	public String toString() {
+		return "#"+index + " " + durationMs + "ms" + (isExcluded?" (excluded)":"");
+	}
 }
 
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest.java
index ca24f35..021bc65 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericsRegressionTest.java
@@ -6507,5 +6507,111 @@
 	};
 	runner.runConformTest();
 }
+public void testBug552388() {
+	runNegativeTest(
+		new String[] {
+			"A.java",
+			"import java.util.ArrayList;\n" + 
+			"import java.util.List;\n" + 
+			"\n" + 
+			"public class A<T extends B> {\n" + 
+			"    protected List<C> list = new ArrayList<C>();\n" + 
+			"\n" + 
+			"    class C {}\n" + 
+			"\n" + 
+			"    public void createIO() {\n" + 
+			"        A<? extends B> x = null;\n" + 
+			"        List<A<? extends B>.C> y = x.list;\n" + 
+			"    }\n" + 
+			"}\n" + 
+			"\n" + 
+			"class B {\n" + 
+			"}\n"
+		},
+		"----------\n" + 
+		"1. ERROR in A.java (at line 11)\n" + 
+		"	List<A<? extends B>.C> y = x.list;\n" + 
+		"	                           ^^^^^^\n" + 
+		"Type mismatch: cannot convert from List<A<capture#1-of ? extends B>.C> to List<A<? extends B>.C>\n" + 
+		"----------\n");
+}
+public void testBug552388b() {
+	String output = this.complianceLevel > ClassFileConstants.JDK1_6 ?
+			"----------\n" + 
+			"1. ERROR in A.java (at line 17)\n" + 
+			"	foo(l);\n" + 
+			"	^^^\n" + 
+			"The method foo(List<A<?>.C>) in the type A<T> is not applicable for the arguments (List<A<T>.C>)\n" + 
+			"----------\n" + 
+			"2. ERROR in A.java (at line 33)\n" + 
+			"	foo2(l); \n" + 
+			"	^^^^\n" + 
+			"The method foo2(List<A<?>>) in the type A<T> is not applicable for the arguments (List<A<T>>)\n" + 
+			"----------\n"
+			:
+			"----------\n" + 
+			"1. ERROR in A.java (at line 16)\n" + 
+			"	List<C> l = new ArrayList<>();\n" + 
+			"	                ^^^^^^^^^\n" + 
+			"\'<>\' operator is not allowed for source level below 1.7\n" + 
+			"----------\n" + 
+			"2. ERROR in A.java (at line 17)\n" + 
+			"	foo(l);\n" + 
+			"	^^^\n" + 
+			"The method foo(List<A<?>.C>) in the type A<T> is not applicable for the arguments (List<A<T>.C>)\n" + 
+			"----------\n" + 
+			"3. ERROR in A.java (at line 32)\n" + 
+			"	List<A<T>> l = new ArrayList<>();\n" + 
+			"	                   ^^^^^^^^^\n" + 
+			"\'<>\' operator is not allowed for source level below 1.7\n" + 
+			"----------\n" + 
+			"4. ERROR in A.java (at line 33)\n" + 
+			"	foo2(l); \n" + 
+			"	^^^^\n" + 
+			"The method foo2(List<A<?>>) in the type A<T> is not applicable for the arguments (List<A<T>>)\n" + 
+			"----------\n";
+	runNegativeTest(
+		new String[] {
+			"A.java",
+			"import java.util.*;\n" + 
+			"class A<T> {\n" + 
+			"    class C {\n" + 
+			"        T f;\n" + 
+			"    }\n" + 
+			"    C c = new C();\n" + 
+			"    A(T t) {\n" + 
+			"        c = new C();\n" + 
+			"        c.f = t;\n" + 
+			"    }\n" + 
+			"    void foo(List<A<?>.C> list) {\n" + 
+			"        list.add(new A<String>(\"\").c);\n" + 
+			"        list.add(new A<Number>(3).c);\n" + 
+			"    }\n" + 
+			"    T test() {\n" + 
+			"        List<C> l = new ArrayList<>();\n" + 
+			"        foo(l);\n" + 
+			"        return l.get(0).f;\n" + 
+			"    }\n" + 
+			"    public static void main(String... args) {\n" + 
+			"//         Number n = new A<Number>(1).test();\n" + 
+			"//         System.out.print(n.intValue());\n" + 
+			"        Number n = new A<Number>(1).test2();\n" + 
+			"        System.out.print(n.intValue());\n" + 
+			"    }\n" + 
+			"     \n" + 
+			"    void foo2(List<A<?>> list) {\n" + 
+			"        list.add(new A<String>(\"\"));\n" + 
+			"        list.add(new A<Number>(3));\n" + 
+			"    }\n" + 
+			"    T test2() {\n" + 
+			"        List<A<T>> l = new ArrayList<>();\n" + 
+			"        foo2(l); \n" + 
+			"        return l.get(0).c.f;\n" + 
+			"    }\n" + 
+			" \n" + 
+			"}\n"
+		},
+		output);
+}
 }
 
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ResourceLeakTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ResourceLeakTests.java
index 1df8aa8..8e078ef 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ResourceLeakTests.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/ResourceLeakTests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2011, 2019 GK Software AG and others.
+ * Copyright (c) 2011, 2019 GK Software SE and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -5667,4 +5667,39 @@
 		"----------\n",
 		options);
 }
+public void testBug486506() {
+	if (this.complianceLevel < ClassFileConstants.JDK1_8) return; // uses switch expression
+	Map options = getCompilerOptions();
+	options.put(JavaCore.COMPILER_PB_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+	options.put(JavaCore.COMPILER_PB_POTENTIALLY_UNCLOSED_CLOSEABLE, CompilerOptions.ERROR);
+	runLeakTest(
+		new String[] {
+			"LogMessage.java",
+			"import java.util.stream.*;\n" +
+			"import java.io.*;\n" +
+			"import java.nio.file.*;\n" +
+			"import java.nio.charset.*;\n" +
+			"class LogMessage {\n" +
+			"  LogMessage(Path path, String message) {}\n" +
+			"  public static Stream<LogMessage> streamSingleLineLogMessages(Path path) {\n" +
+			"    try {\n" +
+			"        Stream<String> lineStream = Files.lines(path, StandardCharsets.ISO_8859_1);\n" +
+			"        Stream<LogMessage> logMessageStream =\n" +
+			"                lineStream.map(message -> new LogMessage(path, message));\n" +
+			"        logMessageStream.onClose(lineStream::close);\n" +
+			"        return logMessageStream;\n" +
+			"    } catch (IOException e) {\n" +
+			"        throw new RuntimeException(e);\n" +
+			"    }\n" +
+			"  }\n" +
+			"}\n"
+		},
+		"----------\n" +
+		"1. ERROR in LogMessage.java (at line 13)\n" +
+		"	return logMessageStream;\n" +
+		"	^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+		"Potential resource leak: \'lineStream\' may not be closed at this location\n" +
+		"----------\n",
+		options);
+}
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/junit/extension/TestCase.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/junit/extension/TestCase.java
index d0510a2..46cdca4 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/junit/extension/TestCase.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/junit/extension/TestCase.java
@@ -778,14 +778,7 @@
 	super.assertPerformance();
 }
 
-
-/**
- * Clean test before run it.
- * Currently, clean only performs a gc.
- */
-protected void clean() {
-	//System.out.println("Clean test "+getName());
-	// Run gc
+protected void runGarbageCollection() {
 	int iterations = 0;
 	long delta=0, free=0;
 	for (int i=0; i<MAX_GC; i++) {
@@ -830,7 +823,7 @@
 	this.first = false;
 	boolean isFirstTestRun = CURRENT_CLASS == null;
 	if (isFirstTestRun || CURRENT_CLASS != getClass()) {
-		if (CURRENT_CLASS != null && RUN_GC) clean();
+		if (CURRENT_CLASS != null && RUN_GC) runGarbageCollection();
 		CURRENT_CLASS = getClass();
 		this.first = true;
 		CURRENT_CLASS_NAME = getClass().getName();
@@ -839,7 +832,7 @@
 
 	// Memory storage if specified
 	if (STORE_MEMORY != null && MEM_LOG_FILE != null) {
-		if (isFirstTestRun) clean();
+		if (isFirstTestRun) runGarbageCollection();
 		if (ALL_TESTS_LOG && MEM_LOG_FILE.exists()) {
 			PrintStream stream = new PrintStream(new FileOutputStream(MEM_LOG_FILE, true));
 			stream.print(CURRENT_CLASS_NAME);
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter13Test.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter13Test.java
index 21d4e4b..efec12d 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter13Test.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/dom/ASTConverter13Test.java
@@ -526,6 +526,16 @@
 
 			assertTrue("String should not be empty", escapedValue.length() != 0);
 			assertTrue("String should start with \"\"\"", escapedValue.startsWith("\"\"\""));
+			
+			String literal = ((TextBlock) initializer).getLiteralValue();
+			assertEquals("literal value not correct", 
+					"      	<html>\n" + 
+					"        <body>\n" + 
+					"            <p>Hello, world</p>\n" + 
+					"        </body>\n" + 
+					"    	</html>\n" + 
+					"    	",
+					literal);
 
 		} finally {
 			javaProject.setOption(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES, old);
@@ -607,6 +617,30 @@
 			ITypeBinding binding = initializer.resolveTypeBinding();
 			assertNotNull("No binding", binding);
 			assertEquals("Wrong qualified name", "java.lang.String", binding.getQualifiedName());
+			
+			String escapedValue = ((TextBlock) initializer).getEscapedValue();
+
+			assertTrue("String should not be empty", escapedValue.length() != 0);
+			assertTrue("String should start with \"\"\"", escapedValue.startsWith("\"\"\""));
+			assertEquals("escaped value not correct", 
+					"\"\"\"\n" + 
+					"      	<html>\n" + 
+					"        <body>\n" + 
+					"            <p>Hello, world</p>\n" + 
+					"        </body>\n" + 
+					"    	</html>\n" + 
+					"    	\"\"\"", 
+					escapedValue);
+			
+			String literal = ((TextBlock) initializer).getLiteralValue();
+			assertEquals("literal value not correct", 
+					"      	<html>\n" + 
+					"        <body>\n" + 
+					"            <p>Hello, world</p>\n" + 
+					"        </body>\n" + 
+					"    	</html>\n" + 
+					"    	", 
+					literal);
 		} finally {
 			javaProject.setOption(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES, old);
 		}
@@ -648,4 +682,51 @@
 			javaProject.setOption(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES, old);
 		}
 	}
+	
+		public void test0011() throws CoreException {
+			// saw NPE in SwitchExpression.resolveType(SwitchExpression.java:423)
+			if (!isJRE13) {
+				System.err.println("Test "+getName()+" requires a JRE 13");
+				return;
+			}
+			String source =
+				"public class Switch {\n" + 
+				"	public static void main(String[] args) {\n" + 
+				"		foo(Day.TUESDAY);\n" + 
+				"	}\n" + 
+				"\n" + 
+				"	@SuppressWarnings(\"preview\")\n" + 
+				"	private static void foo(Day day) {\n" + 
+				"		switch (day) {\n" + 
+				"		case SUNDAY, MONDAY, FRIDAY -> System.out.println(6);\n" + 
+				"		case TUESDAY -> System.out.println(7);\n" + 
+				"		case THURSDAY, SATURDAY -> System.out.println(8);\n" + 
+				"		}\n" + 
+				"	}\n" + 
+				"}\n" + 
+				"\n" + 
+				"enum Day {\n" + 
+				"	MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;\n" + 
+				"}\n";
+			this.workingCopy = getWorkingCopy("/Converter13/src/Switch.java", true/*resolve*/);
+			IJavaProject javaProject = this.workingCopy.getJavaProject();
+			String old = javaProject.getOption(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES, true);
+			try {
+				javaProject.setOption(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES, JavaCore.DISABLED);
+				javaProject.setOption(JavaCore.COMPILER_PB_REPORT_PREVIEW_FEATURES, JavaCore.IGNORE);
+				try {
+				buildAST(
+						source,
+						this.workingCopy);
+				} catch(UnsupportedOperationException e) {
+					fail("Should not throw UnsupportedOperationException");
+				} catch(AssertionFailedError e) {
+					e.printStackTrace();
+					return;
+				}
+
+				} finally {
+					javaProject.setOption(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES, old);
+				}
+		}
 }
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java
index 3ed24c8..4c83d91 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModuleBuilderTests.java
@@ -1456,6 +1456,45 @@
 			deleteProject("com.greetings");
 		}
 	}
+	public void test_Exports_foreign_package1() throws CoreException {
+		try {
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	exports java.util;\n" +
+				"}"
+			};
+			IJavaProject p2 = setupModuleProject("com.greetings", src);
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			assertMarkers("Unexpected markers",	
+					"Cannot export the package java.util which belongs to module java.base",  markers);
+		} finally {
+			deleteProject("com.greetings");
+		}
+	}
+	public void test_Exports_foreign_package2() throws CoreException {
+		try {
+			String[] src = new String[] {
+				"src/module-info.java",
+				"module com.greetings {\n" +
+				"	exports java.util;\n" +
+				"}",
+				"src/java/util/Wrong.java",
+				"package java.util;\n" +
+				"public class Wrong {}\n"
+			};
+			IJavaProject p2 = setupModuleProject("com.greetings", src);
+			p2.getProject().getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
+			IMarker[] markers = p2.getProject().findMarkers(null, true, IResource.DEPTH_INFINITE);
+			sortMarkers(markers);
+			assertMarkers("Unexpected markers",	
+					"The package java.util conflicts with a package accessible from another module: java.base",
+					markers);
+		} finally {
+			deleteProject("com.greetings");
+		}
+	}
 	public void test_DuplicateExports() throws CoreException {
 		try {
 			String[] sources = new String[] {
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
index a08a75c..ea6f94a 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/Main.java
@@ -2888,7 +2888,7 @@
 				mode = DEFAULT;
 				continue;
 			case INSIDE_RELEASE:
-				// If release is < 9, the following are diasllowed:
+				// If release is < 9, the following are disallowed:
 				// bootclasspath, -Xbootclasspath, -Xbootclasspath/a:, -Xbootclasspath/p:, 
 				// -endorseddirs, -Djava.endorsed.dirs, -extdirs, -Djava.ext.dirs
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
index 8e0bd49..0ca57f9 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
@@ -1970,6 +1970,9 @@
 	int IllegalModifierForModule = ModuleRelated + 1318;
 	/** @since 3.18 */
 	int UndefinedModuleAddReads = ModuleRelated + 1319;
+	/** @since 3.20 */
+	int ExportingForeignPackage = ModuleRelated + 1320;
+
 
 	/** @since 3.14 */
 	int DuplicateResource = Internal + 1251;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleDeclaration.java
index 9f9b676..6fa9fab 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ModuleDeclaration.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2015, 2018 IBM Corporation and others.
+ * Copyright (c) 2015, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -314,6 +314,14 @@
 				continue;
 			if (pb.hasCompilationUnit(true))
 				continue;
+			for (ModuleBinding req : this.binding.getAllRequiredModules()) {
+				for (PlainPackageBinding exported : req.getExports()) {
+					if (CharOperation.equals(pb.compoundName, exported.compoundName)) {
+						skope.problemReporter().exportingForeignPackage(stat, req);
+						return;
+					}
+				}
+			}
 			skope.problemReporter().invalidPackageReference(IProblem.PackageDoesNotExistOrIsEmpty, stat);
 		}
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java
index d6d044c..cfa3925 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ReferenceExpression.java
@@ -533,6 +533,14 @@
 			}
 		}
 		
+		if (currentScope.compilerOptions().analyseResourceLeaks) {
+			if (this.haveReceiver && CharOperation.equals(this.selector, TypeConstants.CLOSE)) {
+				FakedTrackingVariable trackingVariable = FakedTrackingVariable.getCloseTrackingVariable(this.lhs, flowInfo, flowContext);
+				if (trackingVariable != null) { // null happens if target is not a local variable or not an AutoCloseable
+					trackingVariable.markClosedInNestedMethod(); // there is a close()-call, but we don't know if it will be invoked
+				}
+			}
+		}
 		manageSyntheticAccessIfNecessary(currentScope, flowInfo);
 		return flowInfo;
 	}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
index 21dfd41..1c63824 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeBinding.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2018 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -1423,7 +1423,7 @@
 						if (TypeBinding.notEquals(enclosing, otherEnclosing))
 							return false;
 					} else {
-						if (!enclosing.isEquivalentTo(otherParamType.enclosingType()))
+						if (!enclosing.isTypeArgumentContainedBy(otherParamType.enclosingType()))
 							return false;
 					}
 				}
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 83f1800..4ea33b4 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
@@ -432,7 +432,7 @@
 	public static final int HIGH_SURROGATE_MAX_VALUE = 0xDBFF;
 	public static final int LOW_SURROGATE_MAX_VALUE = 0xDFFF;
 
-	// raw string support - 11
+	// text block support - 13
 	/* package */ int rawStart = -1;
 
 public Scanner() {
@@ -834,6 +834,10 @@
 	List<char[]> list = new ArrayList<>(lines.length);
 	for(int i = 0; i < lines.length; i++) {
 		char[] line = lines[i];
+		if (i + 1 == size && line.length == 0) {
+			list.add(line);
+			break;
+		}
 		char[][] sub = CharOperation.splitOn('\r', line);
 		for (char[] cs : sub) {
 			if (cs.length > 0) {
@@ -860,7 +864,7 @@
 				}
 			}
 		}
-		if (!blank) {
+		if (!blank || (i+1 == size)) {
 			if (prefix < 0 || whitespaces < prefix) {
  				prefix = whitespaces;
 			}
@@ -1936,7 +1940,9 @@
 								lastQuotePos = this.currentPosition;
 								// look for text block delimiter
 								if (scanForTextBlockClose()) {
-									if (this.source[this.currentPosition + 2] == '"') {
+									// Account for just the snippet being passed around
+									// If already at the EOF, bail out.
+									if (this.currentPosition + 2 < this.source.length && this.source[this.currentPosition + 2] == '"') {
 										terminators++;
 										if (terminators > 2)
 											throw new InvalidInputException(UNTERMINATED_TEXT_BLOCK);
@@ -2005,6 +2011,9 @@
 								}
 							}
 							// consume next character
+							if (this.currentPosition >= this.eofPosition) {
+								break;
+							}
 							this.unicodeAsBackSlash = false;
 							if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
 								&& (this.source[this.currentPosition] == 'u')) {
@@ -2505,7 +2514,10 @@
 									case '\n' :
 										pushLineSeparator();
 										//$FALL-THROUGH$
-									default: 
+									default:
+										if (this.currentCharacter == '\\' && this.source[this.currentPosition++] == '"') {
+											this.currentPosition++;
+										}
 										this.currentCharacter = this.source[this.currentPosition++];
 										continue Inner;
 								}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
index 4368620..8bb2c12 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
@@ -15439,6 +15439,14 @@
 			ref.pkgRef.sourceStart,
 			ref.pkgRef.sourceEnd);
 }
+public void exportingForeignPackage(PackageVisibilityStatement ref, ModuleBinding enclosingModule) {
+	String[] arguments = new String[] { CharOperation.charToString(ref.pkgName), CharOperation.charToString(enclosingModule.moduleName) };
+	this.handle(IProblem.ExportingForeignPackage,
+			arguments,
+			arguments,
+			ref.pkgRef.sourceStart,
+			ref.pkgRef.sourceEnd);
+}
 public void duplicateModuleReference(int problem, ModuleReference ref) {
 	this.handle(problem, 
 		NoArgument, new String[] { CharOperation.charToString(ref.moduleName) },
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
index b1fb8d0..ebfd8e9 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
@@ -918,6 +918,7 @@
 1317 = Invalid service implementation {0}, must be a public class or interface type
 1318 = Illegal modifier for module {0}; only open is permitted
 1319 = {0} cannot be resolved to a module, it is referenced from an add-reads directive
+1320 = Cannot export the package {0} which belongs to module {1}
 
 #### Java 9
 1351 = Variable resource not allowed here for source level below 9
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java
index 9168fb6..8600971 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/ASTConverter.java
@@ -3572,7 +3572,7 @@
 	}
 
 	public Statement convert(org.eclipse.jdt.internal.compiler.ast.YieldStatement statement) {
-		if (this.ast.apiLevel != AST.JLS13_INTERNAL) {
+		if (!this.ast.isPreviewEnabled()) {
 			return createFakeEmptyStatement(statement);		
 		}
 		YieldStatement yieldStatement = new YieldStatement(this.ast);
diff --git a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TextBlock.java b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TextBlock.java
index a74ed83..38ab6c9 100644
--- a/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TextBlock.java
+++ b/org.eclipse.jdt.core/dom/org/eclipse/jdt/core/dom/TextBlock.java
@@ -17,6 +17,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.compiler.InvalidInputException;
 import org.eclipse.jdt.internal.compiler.parser.Scanner;
 import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
@@ -240,45 +241,34 @@
 	 * @exception IllegalArgumentException if the literal value cannot be converted
 	 */
 	public String getLiteralValue() {
-		String s = getEscapedValue();
-		int len = s.length();
-		if (len < 2 || s.indexOf("\"\"\"") != 0 || !s.substring(len-3, len).equals("\"\"\"") ) { //$NON-NLS-1$ //$NON-NLS-2$
+		char[] escaped = getEscapedValue().toCharArray();
+		int len = escaped.length;
+		if (len < 7) {
 			throw new IllegalArgumentException();
 		}
 		
-		boolean newLineFound = false;
-		for (int i = 3; i < s.length(); i++) {
-			char c = s.charAt(i);
-			while (ScannerHelper.isWhitespace(c)) {
+		int start = -1;
+		loop: for (int i = 3; i < len; i++) {
+			char c = escaped[i];
+			if (ScannerHelper.isWhitespace(c)) {
 				switch (c) {
 					case 10 : /* \ u000a: LINE FEED               */
 					case 13 : /* \ u000d: CARRIAGE RETURN         */
-						newLineFound =  true;
-						break;
+						start =  i + 1;
+						break loop;
 					default:
 						break;
 				}
+			} else {
+				break loop;
 			}
 		}
-		if (!newLineFound) {
+		if (start == -1) {
 			throw new IllegalArgumentException();
 		}
-		
-		Scanner scanner = this.ast.scanner;
-		char[] source = s.toCharArray();
-		scanner.setSource(source);
-		scanner.resetTo(0, source.length);
-		try {
-			int tokenType = scanner.getNextToken();
-			switch(tokenType) {
-				case TerminalTokens.TokenNameTextBlock:
-					return scanner.getCurrentStringLiteral();
-				default:
-					throw new IllegalArgumentException();
-			}
-		} catch(InvalidInputException e) {
-			throw new IllegalArgumentException();
-		}
+		return new String(
+				CharOperation.subarray(escaped, start, len - 3)
+				);
 	}
 
 
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaProject.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaProject.java
index f095b8f..0938c2f 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaProject.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaProject.java
@@ -610,7 +610,7 @@
 	IProject getProject();
 
 	/**
-	 * Returns the <code>IModuleDescription</code> this project represents or 
+	 * Returns the {@link IModuleDescription} this project represents or 
 	 * null if the Java project doesn't represent any named module. A Java 
 	 * project is said to represent a module if any of its source package 
 	 * fragment roots (see {@link IPackageFragmentRoot#K_SOURCE}) contains a 
@@ -620,7 +620,7 @@
 	 * In the latter case the corresponding module description of the
 	 * location referenced by that classpath entry is returned.
 	 * 
-	 * @return the <code>IModule</code> this project represents.
+	 * @return the {@link IModuleDescription} this project represents.
 	 * @exception JavaModelException if this element does not exist or if an
 	 *		exception occurs while accessing its corresponding resource
 	 * @since 3.14
@@ -628,6 +628,22 @@
 	IModuleDescription getModuleDescription() throws JavaModelException;
 
 	/**
+	 * Returns the <code>IModuleDescription</code> owned by this project or 
+	 * null if the Java project doesn't own a valid Java module descriptor. 
+	 * This method considers only module descriptions contained in any of the
+	 * project's source package fragment roots (see {@link IPackageFragmentRoot#K_SOURCE}).
+	 * In particular any {@link IClasspathAttribute#PATCH_MODULE} attribute
+	 * is not considered.
+	 * 
+	 * @return the {@link IModuleDescription} this project owns.
+	 * @exception JavaModelException if this element does not exist or if an
+	 *		exception occurs while accessing its corresponding resource
+	 * @throws JavaModelException
+	 * @since 3.20
+	 */
+	IModuleDescription getOwnModuleDescription() throws JavaModelException;
+
+	/**
 	 * Returns the raw classpath for the project, as a list of classpath
 	 * entries. This corresponds to the exact set of entries which were assigned
 	 * using <code>setRawClasspath</code>, in particular such a classpath may
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ToolFactory.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ToolFactory.java
index 2b73170..9479cd8 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ToolFactory.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ToolFactory.java
@@ -547,12 +547,51 @@
 	 */
 	@SuppressWarnings("javadoc") // references deprecated TokenNameIdentifier
 	public static IScanner createScanner(boolean tokenizeComments, boolean tokenizeWhiteSpace, boolean recordLineSeparator, String sourceLevel, String complianceLevel) {
+		return createScanner(tokenizeComments, tokenizeWhiteSpace, recordLineSeparator, sourceLevel, complianceLevel, true);
+	}
+	/**
+	 * Create a scanner, indicating the level of detail requested for tokenizing. The scanner can then be
+	 * used to tokenize some source in a Java aware way.
+	 * Here is a typical scanning loop:
+	 *
+	 * <pre>
+	 * <code>
+	 *   IScanner scanner = ToolFactory.createScanner(false, false, false, false);
+	 *   scanner.setSource("int i = 0;".toCharArray());
+	 *   while (true) {
+	 *     int token = scanner.getNextToken();
+	 *     if (token == ITerminalSymbols.TokenNameEOF) break;
+	 *     System.out.println(token + " : " + new String(scanner.getCurrentTokenSource()));
+	 *   }
+	 * </code>
+	 * </pre>
+	 *
+	 * @param tokenizeComments if set to <code>false</code>, comments will be silently consumed
+	 * @param tokenizeWhiteSpace if set to <code>false</code>, white spaces will be silently consumed,
+	 * @param recordLineSeparator if set to <code>true</code>, the scanner will record positions of encountered line
+	 * separator ends. In case of multi-character line separators, the last character position is considered. These positions
+	 * can then be extracted using {@link IScanner#getLineEnds()}. Only non-unicode escape sequences are
+	 * considered as valid line separators.
+	 * @param sourceLevel if set to <code>&quot;1.3&quot;</code> or <code>null</code>, occurrences of 'assert' will be reported as identifiers
+	 * ({@link ITerminalSymbols#TokenNameIdentifier}), whereas if set to <code>&quot;1.4&quot;</code>, it
+	 * would report assert keywords ({@link ITerminalSymbols#TokenNameassert}). Java 1.4 has introduced
+	 * a new 'assert' keyword.
+	 * @param complianceLevel This is used to support the Unicode 4.0 character sets. if set to 1.5 or above,
+	 * the Unicode 4.0 is supported, otherwise Unicode 3.0 is supported.
+	 * @param enablePreview specify whether the scanner should look for preview language features for the specified compliance level
+	 * @return a scanner
+	 * @see org.eclipse.jdt.core.compiler.IScanner
+	 *
+	 * @since 3.14
+	 */
+	@SuppressWarnings("javadoc") // references deprecated TokenNameIdentifier
+	public static IScanner createScanner(boolean tokenizeComments, boolean tokenizeWhiteSpace, boolean recordLineSeparator, String sourceLevel, String complianceLevel, boolean enablePreview) {
 		PublicScanner scanner = null;
 		long sourceLevelValue = CompilerOptions.versionToJdkLevel(sourceLevel);
 		if (sourceLevelValue == 0) sourceLevelValue = ClassFileConstants.JDK1_3; // fault-tolerance
 		long complianceLevelValue = CompilerOptions.versionToJdkLevel(complianceLevel);
 		if (complianceLevelValue == 0) complianceLevelValue = ClassFileConstants.JDK1_4; // fault-tolerance
-		scanner = new PublicScanner(tokenizeComments, tokenizeWhiteSpace, false/*nls*/,sourceLevelValue /*sourceLevel*/, complianceLevelValue, null/*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/);
+		scanner = new PublicScanner(tokenizeComments, tokenizeWhiteSpace, false/*nls*/,sourceLevelValue /*sourceLevel*/, complianceLevelValue, null/*taskTags*/, null/*taskPriorities*/, true/*taskCaseSensitive*/, enablePreview);
 		scanner.recordLineSeparator = recordLineSeparator;
 		return scanner;
 	}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/ITerminalSymbols.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/ITerminalSymbols.java
index b3a9fea..1fe00e1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/ITerminalSymbols.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/compiler/ITerminalSymbols.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2018 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -101,6 +101,11 @@
 	int TokenNameDoubleLiteral = 43;
 	int TokenNameCharacterLiteral = 44;
 	int TokenNameStringLiteral = 45;
+	/**
+	 * @since 3.20
+	 * @noreference This class is not intended to be referenced by clients as it is a part of Java preview feature.
+	 */
+	int TokenNameTextBlock = 46;
 	int TokenNamePLUS_PLUS = 1;
 	int TokenNameMINUS_MINUS = 2;
 	int TokenNameEQUAL_EQUAL = 35;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
index 6e692e0..0eb1339 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java
@@ -3890,6 +3890,12 @@
 		return null;
 	}
 
+	@Override
+	public IModuleDescription getOwnModuleDescription() throws JavaModelException {
+		JavaProjectElementInfo info = (JavaProjectElementInfo) getElementInfo();
+		return info.getModule();
+	}
+
 	public List<String> getPatchedModules(IClasspathEntry cpEntry) {
 		String patchModules = ClasspathEntry.getExtraAttribute(cpEntry, IClasspathAttribute.PATCH_MODULE);
 		if (patchModules != null) {
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 1b53bad..e708256 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
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2018 IBM Corporation and others.
+ * Copyright (c) 2000, 2019 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -43,6 +43,7 @@
 	*/
 	public long sourceLevel;
 	public long complianceLevel;
+	public boolean previewEnabled;
 
 	// 1.4 feature
 	public boolean useAssertAsAnIndentifier = false;
@@ -201,6 +202,7 @@
 
 	public static final String NULL_SOURCE_STRING = "Null_Source_String"; //$NON-NLS-1$
 	public static final String UNTERMINATED_STRING = "Unterminated_String"; //$NON-NLS-1$
+	public static final String UNTERMINATED_TEXT_BLOCK = "Unterminated_Text_Block"; //$NON-NLS-1$
 	public static final String UNTERMINATED_COMMENT = "Unterminated_Comment"; //$NON-NLS-1$
 	public static final String INVALID_CHAR_IN_STRING = "Invalid_Char_In_String"; //$NON-NLS-1$
 	public static final String INVALID_DIGIT = "Invalid_Digit"; //$NON-NLS-1$
@@ -300,6 +302,9 @@
 	public static final int HIGH_SURROGATE_MAX_VALUE = 0xDBFF;
 	public static final int LOW_SURROGATE_MAX_VALUE = 0xDFFF;
 
+	// text block support - 13
+	/* package */ int rawStart = -1;
+
 public PublicScanner() {
 	this(false /*comment*/, false /*whitespace*/, false /*nls*/, ClassFileConstants.JDK1_3 /*sourceLevel*/, null/*taskTag*/, null/*taskPriorities*/, true /*taskCaseSensitive*/);
 }
@@ -313,12 +318,33 @@
 		char[][] taskTags,
 		char[][] taskPriorities,
 		boolean isTaskCaseSensitive) {
+			this(tokenizeComments,
+				tokenizeWhiteSpace,
+				checkNonExternalizedStringLiterals,
+				sourceLevel,
+				complianceLevel,
+				taskTags,
+				taskPriorities,
+				isTaskCaseSensitive,
+				true);
+}
+public PublicScanner(
+		boolean tokenizeComments,
+		boolean tokenizeWhiteSpace,
+		boolean checkNonExternalizedStringLiterals,
+		long sourceLevel,
+		long complianceLevel,
+		char[][] taskTags,
+		char[][] taskPriorities,
+		boolean isTaskCaseSensitive,
+		boolean previewEnabled) {
 
 	this.eofPosition = Integer.MAX_VALUE;
 	this.tokenizeComments = tokenizeComments;
 	this.tokenizeWhiteSpace = tokenizeWhiteSpace;
 	this.sourceLevel = sourceLevel;
 	this.complianceLevel = complianceLevel;
+	this.previewEnabled = previewEnabled;
 	this.checkNonExternalizedStringLiterals = checkNonExternalizedStringLiterals;
 	if (taskTags != null) {
 		int taskTagsLength = taskTags.length;
@@ -611,6 +637,46 @@
 	}
 	return result;
 }
+protected final boolean scanForTextBlockBeginning() {
+	if (this.complianceLevel < ClassFileConstants.JDK13 || !this.previewEnabled) {
+		return false;
+	}
+	try {
+		// Don't change the position and current character unless we are certain
+		// to be dealing with a text block. For producing all errors like before
+		// in case of a valid """ but missing \r or \n, just return false and not
+		// throw any error.
+		int temp = this.currentPosition;
+		if ((this.source[temp++] == '\"' && this.source[temp++] == '\"')) {
+			char c = this.source[temp++];
+			while (ScannerHelper.isWhitespace(c)) {
+				switch (c) {
+					case 10 : /* \ u000a: LINE FEED               */
+					case 13 : /* \ u000d: CARRIAGE RETURN         */
+						this.currentCharacter = c;
+						this.currentPosition = temp;
+						return true;
+					default:
+						break;
+				}
+				c = this.source[temp++];
+			}
+		}
+	} catch(IndexOutOfBoundsException e) {
+		//let it return false;
+	}
+	return false;
+}
+protected final boolean scanForTextBlockClose() throws InvalidInputException {
+	try {
+		if (this.source[this.currentPosition] == '\"' && this.source[this.currentPosition + 1] == '\"') {
+			return true;
+		}
+	} catch(IndexOutOfBoundsException e) {
+		//let it return false;
+	}
+	return false;
+}
 public final String getCurrentStringLiteral() {
 	//return the token REAL source (aka unicodes are precomputed).
 	//REMOVE the two " that are at the beginning and the end.
@@ -1563,26 +1629,53 @@
 					}
 					throw new InvalidInputException(INVALID_CHARACTER_CONSTANT);
 				case '"' :
+					boolean isTextBlock = false;
+					int lastQuotePos = 0;
 					try {
 						// consume next character
 						this.unicodeAsBackSlash = false;
 						boolean isUnicode = false;
-						if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
-							&& (this.source[this.currentPosition] == 'u')) {
-							getNextUnicodeChar();
-							isUnicode = true;
-						} else {
-							if (this.withoutUnicodePtr != 0) {
-								unicodeStore();
+						isTextBlock = scanForTextBlockBeginning();
+						if (!isTextBlock) {
+							if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
+									&& (this.source[this.currentPosition] == 'u')) {
+								getNextUnicodeChar();
+								isUnicode = true;
+							} else {
+								if (this.withoutUnicodePtr != 0) {
+									unicodeStore();
+								}
 							}
 						}
-
-						while (this.currentCharacter != '"') {
-							if (this.currentPosition >= this.eofPosition) {
-								throw new InvalidInputException(UNTERMINATED_STRING);
+						this.rawStart = this.currentPosition - this.startPosition;
+						int terminators = 0;
+						while (this.currentPosition <= this.eofPosition) {
+							if (this.currentCharacter == '"') {
+								if (!isTextBlock) {
+									return ITerminalSymbols.TokenNameStringLiteral;
+								}
+								lastQuotePos = this.currentPosition;
+								// look for text block delimiter
+								if (scanForTextBlockClose()) {
+									// Account for just the snippet being passed around
+									// If already at the EOF, bail out.
+									if (this.currentPosition + 2 < this.source.length && this.source[this.currentPosition + 2] == '"') {
+										terminators++;
+										if (terminators > 2)
+											throw new InvalidInputException(UNTERMINATED_TEXT_BLOCK);
+									} else {
+										this.currentPosition += 2;
+										return ITerminalSymbols.TokenNameTextBlock;
+									}
+								}
+								if (this.withoutUnicodePtr != 0) {
+									unicodeStore();
+								}
+							} else {
+								terminators = 0;
 							}
 							/**** \r and \n are not valid in string literals ****/
-							if ((this.currentCharacter == '\n') || (this.currentCharacter == '\r')) {
+							if (!isTextBlock &&  (this.currentCharacter == '\n') || (this.currentCharacter == '\r')) {
 								// relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
 								if (isUnicode) {
 									int start = this.currentPosition;
@@ -1636,22 +1729,39 @@
 								}
 							}
 							// consume next character
+							if (this.currentPosition >= this.eofPosition) {
+								break;
+							}
 							this.unicodeAsBackSlash = false;
 							if (((this.currentCharacter = this.source[this.currentPosition++]) == '\\')
-								&& (this.source[this.currentPosition] == 'u')) {
+									&& (this.source[this.currentPosition] == 'u')) {
 								getNextUnicodeChar();
 								isUnicode = true;
 							} else {
 								isUnicode = false;
+								if (isTextBlock && this.currentCharacter == '"')
+									continue;
 								if (this.withoutUnicodePtr != 0) {
 									unicodeStore();
 								}
 							}
-
+						}
+						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) {
-						this.currentPosition--;
-						throw new InvalidInputException(UNTERMINATED_STRING);
+						if (isTextBlock) {
+							this.currentPosition = (lastQuotePos > 0) ? lastQuotePos : this.startPosition + this.rawStart;
+							throw new InvalidInputException(UNTERMINATED_TEXT_BLOCK);
+						} else {
+							this.currentPosition--;
+							throw new InvalidInputException(UNTERMINATED_STRING);
+						}
 					} catch (InvalidInputException e) {
 						if (e.getMessage().equals(INVALID_ESCAPE)) {
 							// relocate if finding another quote fairly close: thus unicode '/u000D' will be fully consumed
@@ -1669,7 +1779,6 @@
 						}
 						throw e; // rethrow
 					}
-					return TokenNameStringLiteral;
 				case '/' :
 					if (!this.skipComments) {
 						int test = getNextChar('/', '*');
@@ -2069,23 +2178,57 @@
 						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:
+										if (this.currentCharacter == '\\' && this.source[this.currentPosition++] == '"') {
+											this.currentPosition++;
+										}
+										this.currentCharacter = this.source[this.currentPosition++];
+										continue Inner;
+								}
+							} else if (this.currentCharacter == '"') {
+								break Inner;
 							}
 							if (this.currentCharacter == '\r'){
 								if (this.source[this.currentPosition] == '\n') this.currentPosition++;
@@ -2129,7 +2272,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 '/' :
@@ -4513,6 +4662,7 @@
 		case TerminalTokens.TokenNameFloatingPointLiteral:
 		case TerminalTokens.TokenNameDoubleLiteral:
 		case TerminalTokens.TokenNameStringLiteral:
+		case TerminalTokens.TokenNameTextBlock:
 		case TerminalTokens.TokenNameCharacterLiteral:
 			return true;
 		default: