Merge remote-tracking branch 'origin/master' into BETA_JAVA15
diff --git a/org.eclipse.jdt.compiler.apt.tests/lib/.cvsignore b/org.eclipse.jdt.compiler.apt.tests/lib/.cvsignore
deleted file mode 100644
index 476f129..0000000
--- a/org.eclipse.jdt.compiler.apt.tests/lib/.cvsignore
+++ /dev/null
@@ -1 +0,0 @@
-apttestprocessors.jar
\ No newline at end of file
diff --git a/org.eclipse.jdt.compiler.apt.tests/lib/apttestprocessors8.jar b/org.eclipse.jdt.compiler.apt.tests/lib/apttestprocessors8.jar
index 78d56c4..05cd7f6 100644
--- a/org.eclipse.jdt.compiler.apt.tests/lib/apttestprocessors8.jar
+++ b/org.eclipse.jdt.compiler.apt.tests/lib/apttestprocessors8.jar
Binary files differ
diff --git a/org.eclipse.jdt.compiler.apt.tests/lib/java14api.jar b/org.eclipse.jdt.compiler.apt.tests/lib/java14api.jar
index fcf9985..e24da08 100644
--- a/org.eclipse.jdt.compiler.apt.tests/lib/java14api.jar
+++ b/org.eclipse.jdt.compiler.apt.tests/lib/java14api.jar
Binary files differ
diff --git a/org.eclipse.jdt.compiler.apt.tests/processors8/org/eclipse/jdt/compiler/apt/tests/processors/elements/Java14ElementProcessor.java b/org.eclipse.jdt.compiler.apt.tests/processors8/org/eclipse/jdt/compiler/apt/tests/processors/elements/Java14ElementProcessor.java
index b8042e3..435ed7f 100644
--- a/org.eclipse.jdt.compiler.apt.tests/processors8/org/eclipse/jdt/compiler/apt/tests/processors/elements/Java14ElementProcessor.java
+++ b/org.eclipse.jdt.compiler.apt.tests/processors8/org/eclipse/jdt/compiler/apt/tests/processors/elements/Java14ElementProcessor.java
@@ -19,6 +19,7 @@
 import java.io.IOException;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -43,10 +44,13 @@
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.RecordComponentElement;
 import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.TypeParameterElement;
 import javax.lang.model.element.VariableElement;
 import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.ExecutableType;
 import javax.lang.model.type.TypeKind;
 import javax.lang.model.util.ElementFilter;
+import javax.lang.model.util.ElementScanner14;
 
 import org.eclipse.jdt.internal.compiler.apt.dispatch.BaseProcessingEnvImpl;
 import org.eclipse.jdt.compiler.apt.tests.processors.base.BaseProcessor;
@@ -157,7 +161,7 @@
 		List<? extends RecordComponentElement> recordComponents = record.getRecordComponents();
 		// Test that in the first round, we don't get an NPE
 		assertNotNull("recordComponents Should not be null", recordComponents);
-		assertEquals("recordComponents Should not be null", 1, recordComponents.size());
+		assertEquals("recordComponents Should not be null", 5, recordComponents.size());
 	}
 	/*
 	 * Test for presence of record component in a record element
@@ -175,7 +179,7 @@
 		assertNotNull("enclosedElements for record should not be null", enclosedElements);
 		List<RecordComponentElement> recordComponentsIn = ElementFilter.recordComponentsIn(enclosedElements);
 		int size = recordComponentsIn.size();
-		assertEquals("incorrect no of record components", 1, size);
+		assertEquals("incorrect no of record components", 5, size);
 		Element element = recordComponentsIn.get(0);
 		assertEquals("Incorrect kind of element", ElementKind.RECORD_COMPONENT, element.getKind());
 		RecordComponentElement recordComponent = (RecordComponentElement) element;
@@ -281,12 +285,48 @@
 		assertNotNull("enclosedElements for record should not be null", enclosedElements);
 		List<RecordComponentElement> recordComponentsIn = ElementFilter.recordComponentsIn(enclosedElements);
 		int size = recordComponentsIn.size();
-		assertEquals("incorrect no of record components", 1, size);
+		assertEquals("incorrect no of record components", 5, size);
 		Element element = recordComponentsIn.get(0);
 		assertEquals("Incorrect kind of element", ElementKind.RECORD_COMPONENT, element.getKind());
 		RecordComponentElement recordComponent = (RecordComponentElement) element;
-
 		verifyAnnotations(recordComponent, new String[]{"@MyAnnot()"});
+
+		element = recordComponentsIn.get(1);
+		assertEquals("Incorrect kind of element", ElementKind.RECORD_COMPONENT, element.getKind());
+		recordComponent = (RecordComponentElement) element;
+		verifyAnnotations(recordComponent, new String[]{"@MyAnnot2()"});
+	}
+	public void testRecords4a() {
+		Set<? extends Element> elements = roundEnv.getRootElements();
+		TypeElement record = null;
+		for (Element element : elements) {
+			if ("Point".equals(element.getSimpleName().toString())) {
+				record = (TypeElement) element;
+			}
+		}
+		assertNotNull("TypeElement for record should not be null", record);
+		verifyAnnotations(record, new String[]{"@Deprecated()"});
+
+		List<? extends Element> enclosedElements = record.getEnclosedElements();
+		assertNotNull("enclosedElements for record should not be null", enclosedElements);
+		List<RecordComponentElement> recordComponentsIn = ElementFilter.recordComponentsIn(enclosedElements);
+		int size = recordComponentsIn.size();
+		assertEquals("incorrect no of record components", 5, size);
+
+		Element element = recordComponentsIn.get(2);
+		assertEquals("Incorrect kind of element", ElementKind.RECORD_COMPONENT, element.getKind());
+		RecordComponentElement recordComponent = (RecordComponentElement) element;
+		verifyAnnotations(recordComponent, new String[]{});
+
+		element = recordComponentsIn.get(3);
+		assertEquals("Incorrect kind of element", ElementKind.RECORD_COMPONENT, element.getKind());
+		recordComponent = (RecordComponentElement) element;
+		verifyAnnotations(recordComponent, new String[]{});
+
+		element = recordComponentsIn.get(4);
+		assertEquals("Incorrect kind of element", ElementKind.RECORD_COMPONENT, element.getKind());
+		recordComponent = (RecordComponentElement) element;
+		verifyAnnotations(recordComponent, new String[]{});
 	}
 	public void testRecords5() {
 		Map<String, TypeKind> expRecComps = new HashMap<>();
@@ -383,6 +423,68 @@
 			assertEquals("Accessor method name incorrect", record.getSimpleName().toString(), method.getSimpleName().toString());
 		}
 	}
+	public void testRecords8() {
+		boolean result = false;
+        Object r = "DEFAULT";
+        Object param = new Object();
+        ScannerImpl<Object, Object> es = new ScannerImpl<>(r);
+
+		Element e = _elementUtils.getTypeElement("records.Record2");
+		List<? extends Element> recordElements = e.getEnclosedElements();
+		for (Element recComp : recordElements) {
+			if (recComp.getKind() == ElementKind.RECORD_COMPONENT) {
+				result = true;
+				Object r2 = recComp.accept(es, param);
+				assertSame("returned message not same", r, r2);
+				assertTrue("not visited", es.visited);
+				assertSame("Visited element not the same", recComp, es.el);
+				assertSame("Visited param not the same", param, es.param);
+			}
+		}
+        assertTrue("Test returned negative", result);
+	}
+	public void testRecords9() {
+			String[] arr1 = new String[] { "x", "bigInt", "r1", "floatValue", "c", "recordInstance" };
+			TypeKind[] arr2 = new TypeKind[] { TypeKind.INT, TypeKind.DECLARED, TypeKind.DECLARED, TypeKind.FLOAT,
+					TypeKind.DECLARED, TypeKind.DECLARED };
+			List<String> names = Arrays.asList(arr1);
+			List<TypeKind> types = Arrays.asList(arr2);
+
+	        Element record = _elementUtils.getTypeElement("records.R3");
+	        List<? extends Element> allElements = record.getEnclosedElements();
+	        List<RecordComponentElement> components = ElementFilter.recordComponentsIn(allElements);
+	        List<ExecutableElement> accessors = components.stream().map
+	                (RecordComponentElement::getAccessor).collect(Collectors.toList());
+	        assertEquals("Size mismatch", names.size(), accessors.size());
+	        for (ExecutableElement accessor : accessors) {
+	            String name = accessor.getSimpleName().toString();
+	            int indexOf = names.indexOf(name);
+	            assertSame("Type kind not same for \"" + name + "\".", types.get(indexOf), accessor.getReturnType().getKind());
+	            assertTrue("should be executable type for \"" + name + "\".", (accessor.asType() instanceof ExecutableType));
+	            assertNull("should be null", accessor.getDefaultValue());
+	            List<? extends AnnotationMirror> mirrors = accessor.getAnnotationMirrors();
+				if (name.equals("c") || name.equals("bigInt") || name.equals("r1")) {
+	            	assertEquals("annotations count mismatch for \"" + name + "\".", 1, mirrors.size());
+	            	Set<? extends ExecutableElement> accessorAnnotations = mirrors.get(0)
+	                        .getElementValues().keySet();
+	            	assertEquals("annotations type element mismatch for \"" + name + "\".", 1, accessorAnnotations.size());
+	            	int val = (int) accessorAnnotations.toArray(new ExecutableElement[0])[0].getDefaultValue()
+	                        .getValue();
+	            	assertEquals("Incorrect default value for \"" + name + "\".", 1, val);
+	            }
+	            if (name.equals("floatValue") || name.equals("x")) {
+	            	assertEquals("annotations count mismatch for \"" + name + "\".", 0, mirrors.size());
+	            }
+	            if (name.equals("recordInstance")) {
+	            	assertEquals("annotations count mismatch for \"" + name + "\".", 2, mirrors.size());
+	            }
+	            assertTrue("Parameters should be empty for \"" + name + "\".", accessor.getParameters().isEmpty());
+	            assertTrue("Thrown types should be empty for \"" + name + "\".", accessor.getThrownTypes().isEmpty());
+	            assertTrue("Type parameters should be empty for \"" + name + "\".", accessor.getTypeParameters().isEmpty());
+	            assertFalse("Should not be default for \"" + name + "\".", accessor.isDefault());
+	            assertFalse("Should not be varargs for \"" + name + "\".", accessor.isVarArgs());
+	        }
+	}
 
 	@Override
 	public void reportError(String msg) {
@@ -524,4 +626,55 @@
 			super(msg);
 		}
 	}
+
+	class ScannerImpl<R, P> extends ElementScanner14<R, P> {
+		public Object el;
+		boolean isType;
+		boolean isMethod;
+		public boolean visited;
+		public boolean scanned;
+		R result;
+		public Object param;
+
+		public List<TypeParameterElement> params = new ArrayList<>();
+
+		public ScannerImpl() {
+			super();
+		}
+
+		public ScannerImpl(R r) {
+			super(r);
+		}
+
+		@Override
+		public R visitType(TypeElement e, P p) {
+			el = e;
+			param = p;
+			isType = true;
+			return super.visitType(e, p);
+		}
+
+		@Override
+		public R visitExecutable(ExecutableElement e, P p) {
+			isMethod = true;
+			el = e;
+			param = p;
+			return super.visitExecutable(e, p);
+		}
+
+		public R visitRecordComponent(RecordComponentElement e, P p) {
+			el = e;
+			param = p;
+			visited = true;
+			return super.visitRecordComponent(e, p);
+		}
+
+		public R scan(Element e, P p) {
+			scanned = true;
+			if (e instanceof TypeParameterElement) {
+				params.add((TypeParameterElement) e);
+			}
+			return DEFAULT_VALUE;
+		}
+	}
 }
diff --git a/org.eclipse.jdt.compiler.apt.tests/resources/mod_locations/records/mod.records/records/MyAnnot.java b/org.eclipse.jdt.compiler.apt.tests/resources/mod_locations/records/mod.records/records/MyAnnot.java
index e7b47bc..5aea36c 100644
--- a/org.eclipse.jdt.compiler.apt.tests/resources/mod_locations/records/mod.records/records/MyAnnot.java
+++ b/org.eclipse.jdt.compiler.apt.tests/resources/mod_locations/records/mod.records/records/MyAnnot.java
@@ -5,6 +5,22 @@
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
-@Target({ElementType.FIELD, ElementType.TYPE})
+@Target({ElementType.RECORD_COMPONENT, ElementType.TYPE})
 @Retention(RetentionPolicy.RUNTIME)
-@interface MyAnnot {}
\ No newline at end of file
+@interface MyAnnot {}
+
+@Retention(RetentionPolicy.RUNTIME)
+@interface MyAnnot2 {}
+
+@Target({ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@interface MyAnnot3 {}
+
+@Target({ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+@interface MyAnnot4 {}
+
+
+@Target({ElementType.TYPE_USE})
+@Retention(RetentionPolicy.RUNTIME)
+@interface MyAnnot5 {}
\ No newline at end of file
diff --git a/org.eclipse.jdt.compiler.apt.tests/resources/mod_locations/records/mod.records/records/Point.java b/org.eclipse.jdt.compiler.apt.tests/resources/mod_locations/records/mod.records/records/Point.java
index 1c7e324..9b8f88c 100644
--- a/org.eclipse.jdt.compiler.apt.tests/resources/mod_locations/records/mod.records/records/Point.java
+++ b/org.eclipse.jdt.compiler.apt.tests/resources/mod_locations/records/mod.records/records/Point.java
@@ -1,8 +1,12 @@
 package records;
 @Deprecated
-public record Point(@MyAnnot int comp_) {
-	public Point  {
-	}
+public record Point(@MyAnnot int comp_, 
+		@MyAnnot2 int comp2_, 
+		@MyAnnot3 int comp3_,
+		@MyAnnot4 int comp4_,
+		@MyAnnot5 int comp5_) {
+
+	public Point  {}
 	public boolean equals(Object o) {
 		return false;
 	}
diff --git a/org.eclipse.jdt.compiler.apt.tests/resources/mod_locations/records/mod.records/records/R3.java b/org.eclipse.jdt.compiler.apt.tests/resources/mod_locations/records/mod.records/records/R3.java
new file mode 100644
index 0000000..946f960
--- /dev/null
+++ b/org.eclipse.jdt.compiler.apt.tests/resources/mod_locations/records/mod.records/records/R3.java
@@ -0,0 +1,34 @@
+package records;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.math.BigInteger;
+public record R3(	@MyAnn4(value=5) int x, 
+					@MyAnn2(value=5) BigInteger bigInt, 
+					@MyAnn2(value=5) @MyAnn3(value=5) R1 r1, 
+					@MyAnn3(value=5) float floatValue, 
+					@MyAnn(value=5) Character c, 
+					@MyAnn(value=5) @MyAnn2(value=5) @MyAnn3(value=5) R1 recordInstance){}
+
+record R1(){}
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.RECORD_COMPONENT, ElementType.METHOD})
+@interface MyAnn {
+     int value() default 1;
+}
+@Retention(RetentionPolicy.RUNTIME)
+@interface MyAnn2 {
+    int value() default 1;
+}
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.RECORD_COMPONENT})
+@interface MyAnn3 {
+    int value() default 1;
+}
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD})
+@interface MyAnn4 {
+    int value() default 1;
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/BatchDispatchTests.java b/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/BatchDispatchTests.java
index 48f87ab..24eec4f 100644
--- a/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/BatchDispatchTests.java
+++ b/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/BatchDispatchTests.java
@@ -149,6 +149,16 @@
 		internalTestWarnings(compiler, 1, "-nowarn", "-warn:+unused");
 	}
 
+	public void testNoWarningsInFolderWithEclipseCompiler() throws IOException {
+		JavaCompiler compiler = BatchTestUtils.getEclipseCompiler();
+		internalTestWarnings(compiler, 0, "-warn:+unused", "-nowarn:[" + BatchTestUtils.getGenFolderName() + ']');
+	}
+
+	public void testNoWarningsInFolderWithEclipseCompiler2() throws IOException {
+		JavaCompiler compiler = BatchTestUtils.getEclipseCompiler();
+		internalTestWarnings(compiler, 0, "-nowarn:[" + BatchTestUtils.getGenFolderName() + ']', "-warn:+unused");
+	}
+
 	private void internalTestWarnings(JavaCompiler compiler, int numberOfWarnings, String... extraOptions) throws IOException {
 		File targetFolder = TestUtils.concatPath(BatchTestUtils.getSrcFolderName(), "targets", "dispatch");
 		File inputFile = BatchTestUtils.copyResource("targets/dispatch/WarnGenClass.java", targetFolder);
diff --git a/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/Java14ElementsTests.java b/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/Java14ElementsTests.java
index 4a411b1..518544f 100644
--- a/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/Java14ElementsTests.java
+++ b/org.eclipse.jdt.compiler.apt.tests/src/org/eclipse/jdt/compiler/apt/tests/Java14ElementsTests.java
@@ -46,7 +46,7 @@
 		JavaCompiler compiler = BatchTestUtils.getEclipseCompiler();
 		internalTestWithPreview(compiler, MODULE_PROC, "14", "testRecords2", null, "records", true);
 	}
-	public void _testRecords2Javac() throws Exception {
+	public void testRecords2Javac() throws Exception {
 		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
 		internalTestWithPreview(compiler, MODULE_PROC, "14", "testRecords2", null, "records", true);
 	}
@@ -70,10 +70,18 @@
 		JavaCompiler compiler = BatchTestUtils.getEclipseCompiler();
 		internalTestWithPreview(compiler, MODULE_PROC, "14", "testRecords4", null, "records", true);
 	}
-	public void _testRecords4Javac() throws Exception {
+	public void testRecords4Javac() throws Exception {
 		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
 		internalTestWithPreview(compiler, MODULE_PROC, "14", "testRecords4", null, "records", true);
 	}
+	public void _testRecords4a() throws IOException {
+		JavaCompiler compiler = BatchTestUtils.getEclipseCompiler();
+		internalTestWithPreview(compiler, MODULE_PROC, "14", "testRecords4a", null, "records", true);
+	}
+	public void testRecords4aJavac() throws Exception {
+		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+		internalTestWithPreview(compiler, MODULE_PROC, "14", "testRecords4a", null, "records", true);
+	}
 	public void testRecords5() throws IOException {
 		JavaCompiler compiler = BatchTestUtils.getEclipseCompiler();
 		internalTestWithPreview(compiler, MODULE_PROC, "14", "testRecords5", null, "records", true);
@@ -98,6 +106,22 @@
 		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
 		internalTestWithPreview(compiler, MODULE_PROC, "14", "testRecords7", null, "records", true);
 	}
+	public void testRecords8() throws IOException {
+		JavaCompiler compiler = BatchTestUtils.getEclipseCompiler();
+		internalTestWithPreview(compiler, MODULE_PROC, "14", "testRecords8", null, "records", true);
+	}
+	public void testRecords8Javac() throws IOException {
+		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+		internalTestWithPreview(compiler, MODULE_PROC, "14", "testRecords8", null, "records", true);
+	}
+	public void testRecords9() throws IOException {
+		JavaCompiler compiler = BatchTestUtils.getEclipseCompiler();
+		internalTestWithPreview(compiler, MODULE_PROC, "14", "testRecords9", null, "records", true);
+	}
+	public void testRecords9Javac() throws IOException {
+		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+		internalTestWithPreview(compiler, MODULE_PROC, "14", "testRecords9", null, "records", true);
+	}
 
 	protected void internalTestWithPreview(JavaCompiler compiler, String processor, String compliance,
 			String testMethod, String testClass, String resourceArea, boolean preview) throws IOException {
diff --git a/org.eclipse.jdt.compiler.apt/lib/java14api.jar b/org.eclipse.jdt.compiler.apt/lib/java14api.jar
index fcf9985..e24da08 100644
--- a/org.eclipse.jdt.compiler.apt/lib/java14api.jar
+++ b/org.eclipse.jdt.compiler.apt/lib/java14api.jar
Binary files differ
diff --git a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/dispatch/BatchFilerImpl.java b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/dispatch/BatchFilerImpl.java
index d061ab6..b731cc0 100644
--- a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/dispatch/BatchFilerImpl.java
+++ b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/dispatch/BatchFilerImpl.java
@@ -42,7 +42,7 @@
 public class BatchFilerImpl implements Filer {
 
 	protected final BaseAnnotationProcessorManager _dispatchManager;
-	protected final BaseProcessingEnvImpl _env;
+	protected final BatchProcessingEnvImpl _env;
 	protected final JavaFileManager _fileManager;
 	protected final HashSet<URI> _createdFiles;
 
diff --git a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/dispatch/BatchProcessingEnvImpl.java b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/dispatch/BatchProcessingEnvImpl.java
index d13d2cb..cbf8abe 100644
--- a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/dispatch/BatchProcessingEnvImpl.java
+++ b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/dispatch/BatchProcessingEnvImpl.java
@@ -143,4 +143,7 @@
 		return _compilerOwner.compilerLocale;
 	}
 
+	public boolean shouldIgnoreOptionalProblems(char[] fileName) {
+		return Main.shouldIgnoreOptionalProblems(this._compilerOwner.ignoreOptionalProblemsFromFolders, fileName);
+	}
 }
diff --git a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/dispatch/HookedJavaFileObject.java b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/dispatch/HookedJavaFileObject.java
index b6b97e8..a5fbbcd 100644
--- a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/dispatch/HookedJavaFileObject.java
+++ b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/dispatch/HookedJavaFileObject.java
@@ -225,7 +225,7 @@
 			//TODO: support encoding
 			switch(this.getKind()) {
 				case SOURCE :
-					CompilationUnit unit = new CompilationUnit(null, _fileName, null /* encoding */);
+					CompilationUnit unit = new CompilationUnit(null, _fileName, null /* encoding */, null, this._filer._env.shouldIgnoreOptionalProblems(_fileName.toCharArray()), null);
 					_filer.addNewUnit(unit);
 					break;
 				case CLASS :
diff --git a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/RecordComponentElementImpl.java b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/RecordComponentElementImpl.java
index 2ce4c12..9be30c6 100644
--- a/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/RecordComponentElementImpl.java
+++ b/org.eclipse.jdt.compiler.apt/src/org/eclipse/jdt/internal/compiler/apt/model/RecordComponentElementImpl.java
@@ -15,6 +15,7 @@
 package org.eclipse.jdt.internal.compiler.apt.model;
 
 import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ElementVisitor;
 import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.RecordComponentElement;
 
@@ -45,4 +46,8 @@
 		}
 		return null;
 	}
+	@Override
+	public <R, P> R accept(ElementVisitor<R, P> visitor, P param) {
+		return visitor.visitRecordComponent(this, param);
+	}
 }
diff --git a/org.eclipse.jdt.compiler.tool.tests/lib/java14api.jar b/org.eclipse.jdt.compiler.tool.tests/lib/java14api.jar
index fcf9985..e24da08 100644
--- a/org.eclipse.jdt.compiler.tool.tests/lib/java14api.jar
+++ b/org.eclipse.jdt.compiler.tool.tests/lib/java14api.jar
Binary files differ
diff --git a/org.eclipse.jdt.compiler.tool/lib/java14api.jar b/org.eclipse.jdt.compiler.tool/lib/java14api.jar
index fcf9985..e24da08 100644
--- a/org.eclipse.jdt.compiler.tool/lib/java14api.jar
+++ b/org.eclipse.jdt.compiler.tool/lib/java14api.jar
Binary files differ
diff --git a/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/Bug562420Test.java b/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/Bug562420Test.java
new file mode 100644
index 0000000..90f691a
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/Bug562420Test.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Stephan Herrmann and others.
+
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Stephan Herrmann - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.tests.builder;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.tests.util.Util;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+
+import junit.framework.Test;
+
+public class Bug562420Test extends BuilderTests {
+	public Bug562420Test(String name) {
+		super(name);
+	}
+
+	public static Test suite() {
+		return buildTestSuite(Bug562420Test.class);
+	}
+	public void testBuilderRegression() throws JavaModelException, Exception {
+		IPath projectPath = env.addProject("Bug562420Test", "9");
+		env.removePackageFragmentRoot(projectPath, "");
+		IPath src = env.addPackageFragmentRoot(projectPath, "src");
+
+		env.addExternalJars(projectPath, Util.getJavaClassLibs());
+		IPath testAppPath = env.addClass(src, "org.easylibs.test", "TestApp",
+				"package org.easylibs.test;\n" +
+				"public class TestApp {\n" +
+				"	public static void main(String[] args) {\n" +
+				"		System.out.println(\"Hello World\");\n" +
+				"	}\n" +
+				"}\n");
+		env.addFile(testAppPath.removeLastSegments(1), "package-info.java",
+				"package org.easylibs.test;");
+		env.addFile(src, "module-info.java",
+				"module test {\n" +
+				"	requires java.base;\n" +
+				"	exports org.easylibs.test;\n" +
+				"}\n");
+		fullBuild();
+		if (CompilerOptions.versionToJdkLevel(System.getProperty("java.specification.version")) < ClassFileConstants.JDK9) {
+			expectingProblemsFor(projectPath,
+				"Problem : java.base cannot be resolved to a module [ resource : </Bug562420Test/src/module-info.java> range : <24,33> category : <160> severity : <2>]");
+		} else {
+			expectingNoProblems();
+		}
+
+		env.getJavaProject(projectPath).setOption(JavaCore.COMPILER_SOURCE, "1.8");
+		env.getJavaProject(projectPath).setOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, "1.8");
+		fullBuild();
+		expectingProblemsFor(projectPath,
+				"Problem : Syntax error on token \".\", , expected [ resource : </Bug562420Test/src/module-info.java> range : <28,29> category : <20> severity : <2>]\n" +
+				"Problem : Syntax error on token \".\", = expected [ resource : </Bug562420Test/src/module-info.java> range : <47,48> category : <20> severity : <2>]\n" +
+				"Problem : Syntax error on token \"module\", interface expected [ resource : </Bug562420Test/src/module-info.java> range : <0,6> category : <20> severity : <2>]");
+	}
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/BuilderTests.java b/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/BuilderTests.java
index 9cc8a59..fbb210a 100644
--- a/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/BuilderTests.java
+++ b/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/BuilderTests.java
@@ -549,6 +549,7 @@
 			Bug531382Test.class,
 			Bug549457Test.class,
 			Bug561287Test.class,
+			Bug562420Test.class,
 			LeakTestsBefore9.class,
 		};
 		List<Class<?>> list = new ArrayList<>(Arrays.asList(classes));
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/ComplianceDiagnoseTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/ComplianceDiagnoseTest.java
index 3eff433..88aa24d 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/ComplianceDiagnoseTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/parser/ComplianceDiagnoseTest.java
@@ -1938,7 +1938,7 @@
 	);
 }
 //TODO:  Enable after Bug 552769  is fixed
-public void _test0042() {
+public void test0042() {
 	String[] testFiles = new String[] {
 		"X.java",
 		"void ___eval() {\n" +
@@ -2035,28 +2035,23 @@
 			"Syntax error, insert \"EnumBody\" to complete CompilationUnit\n" +
 			"----------\n";
 
-	String expected_Java14_ProblemLog =
+	String expectedJ14ProblemLog =
 			"----------\n" +
 			"1. ERROR in X.java (at line 1)\n" +
 			"	void ___eval() {\n" +
 			"	^^^^\n" +
 			"Syntax error on token \"void\", record expected\n" +
 			"----------\n" +
-			"2. ERROR in X.java (at line 1)\n" +
-			"	void ___eval() {\n" +
-			"	             ^\n" +
-			"Syntax error on token \")\", { expected after this token\n" +
-			"----------\n" +
-			"3. ERROR in X.java (at line 23)\n" +
-			"	}\n" +
-			"	^\n" +
-			"Syntax error, insert \"}\" to complete RecordBody\n" +
+			"2. ERROR in X.java (at line 2)\n" +
+			"	new Runnable() {\n" +
+			"	^^^\n" +
+			"Syntax error on token \"new\", record expected\n" +
 			"----------\n";
 	runComplianceParserTest(
 		testFiles,
-		expected_Java14_ProblemLog,
-		expected_Java14_ProblemLog,
-		expected_Java14_ProblemLog
+		expected13ProblemLog,
+		expected14ProblemLog,
+		(this.complianceLevel < ClassFileConstants.JDK14 ? expected15ProblemLog : expectedJ14ProblemLog)
 	);
 }
 /*
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 d197a29..064aa6e 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
@@ -1249,6 +1249,7 @@
 	    expectedProblemAttributes.put("RecordComponentCannotBeVoid", new ProblemAttributes(CategorizedProblem.CAT_PREVIEW_RELATED));
 	    expectedProblemAttributes.put("RecordIllegalVararg", new ProblemAttributes(CategorizedProblem.CAT_PREVIEW_RELATED));
 	    expectedProblemAttributes.put("RecordStaticReferenceToOuterLocalVariable", new ProblemAttributes(CategorizedProblem.CAT_PREVIEW_RELATED));
+	    expectedProblemAttributes.put("RecordCannotDefineRecordInLocalType", new ProblemAttributes(CategorizedProblem.CAT_PREVIEW_RELATED));
 	    StringBuffer failures = new StringBuffer();
 		StringBuffer correctResult = new StringBuffer(70000);
 		Field[] fields = (iProblemClass = IProblem.class).getFields();
@@ -2270,6 +2271,7 @@
 	    expectedProblemAttributes.put("RecordComponentCannotBeVoid", SKIP);
 	    expectedProblemAttributes.put("RecordIllegalVararg", SKIP);
 	    expectedProblemAttributes.put("RecordStaticReferenceToOuterLocalVariable",SKIP);
+	    expectedProblemAttributes.put("RecordCannotDefineRecordInLocalType",SKIP);
 	    Map constantNamesIndex = new HashMap();
 		Field[] fields = JavaCore.class.getFields();
 		for (int i = 0, length = fields.length; i < length; i++) {
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Compliance_1_4.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Compliance_1_4.java
index 654645f..3a230b5 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Compliance_1_4.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Compliance_1_4.java
@@ -2594,7 +2594,7 @@
 /*
  * https://bugs.eclipse.org/bugs/show_bug.cgi?id=47227
  */
-public void _test079() {
+public void test079() {
 	this.runNegativeTest(
 		new String[] {
 			"Hello.java",
@@ -2625,18 +2625,21 @@
 		"----------\n" +
 		"1. ERROR in Hello.java (at line 1)\n" +
 		"	void ___eval() {\n" +
-		"	^^^^\n" +
-		"Syntax error on token \"void\", record expected\n" +
+		"	^^^^^^^^^^^^^^\n" +
+		"Syntax error on tokens, delete these tokens\n" +
 		"----------\n" +
-		"2. ERROR in Hello.java (at line 1)\n" +
-		"	void ___eval() {\n" +
-		"	             ^\n" +
-		"Syntax error on token \")\", { expected after this token\n" +
-		"----------\n" +
-		"3. ERROR in Hello.java (at line 23)\n" +
-		"	}\n" +
-		"	^\n" +
-		"Syntax error, insert \"}\" to complete RecordBody\n" +
+		"2. ERROR in Hello.java (at line 2)\n" +
+		"	new Runnable() {\n" +
+		"		int ___run() throws Throwable {\n" +
+		"			return blah;\n" +
+		"		}\n" +
+		"		private String blarg;\n" +
+		"		public void run() {\n" +
+		"		}\n" +
+		"	};\n" +
+		"}\n" +
+		"	^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+		"Syntax error on tokens, delete these tokens\n" +
 		"----------\n"
 	);
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Compliance_1_5.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Compliance_1_5.java
index 1626778..6192c7a 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Compliance_1_5.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/Compliance_1_5.java
@@ -2722,7 +2722,62 @@
  * https://bugs.eclipse.org/bugs/show_bug.cgi?id=47227
  */
 // TODO: Enable after Bug 552769 is fixed
-public void _test079() {
+public void test079() {
+
+	String expectedErrorLog = 		"----------\n" +
+			"1. ERROR in Hello.java (at line 1)\n" +
+			"	void ___eval() {\n" +
+			"	^^^^\n" +
+			"Syntax error on token \"void\", @ expected\n" +
+			"----------\n" +
+			"2. ERROR in Hello.java (at line 1)\n" +
+			"	void ___eval() {\n" +
+			"	             ^\n" +
+			"Syntax error on token \")\", delete this token\n" +
+			"----------\n" +
+			"3. ERROR in Hello.java (at line 9)\n" +
+			"	};\n" +
+			"}\n" +
+			"	^^^^\n" +
+			"Syntax error on tokens, delete these tokens\n" +
+			"----------\n" +
+			"4. ERROR in Hello.java (at line 23)\n" +
+			"	}\n" +
+			"	^\n" +
+			"Syntax error, insert \"}\" to complete ClassBody\n" +
+			"----------\n" +
+			"5. ERROR in Hello.java (at line 23)\n" +
+			"	}\n" +
+			"	^\n" +
+			"Syntax error, insert \"}\" to complete MemberValue\n" +
+			"----------\n" +
+			"6. ERROR in Hello.java (at line 23)\n" +
+			"	}\n" +
+			"	^\n" +
+			"Syntax error, insert \")\" to complete Modifiers\n" +
+			"----------\n" +
+			"7. ERROR in Hello.java (at line 23)\n" +
+			"	}\n" +
+			"	^\n" +
+			"Syntax error, insert \"enum Identifier\" to complete EnumHeader\n" +
+			"----------\n" +
+			"8. ERROR in Hello.java (at line 23)\n" +
+			"	}\n" +
+			"	^\n" +
+			"Syntax error, insert \"EnumBody\" to complete CompilationUnit\n" +
+			"----------\n";
+	String expectedErrorLog_J14 = "----------\n" +
+			"1. ERROR in Hello.java (at line 1)\n" +
+			"	void ___eval() {\n" +
+			"	^^^^\n" +
+			"Syntax error on token \"void\", record expected\n" +
+			"----------\n" +
+			"2. ERROR in Hello.java (at line 2)\n" +
+			"	new Runnable() {\n" +
+			"	^^^\n" +
+			"Syntax error on token \"new\", record expected\n" +
+			"----------\n";
+
 	this.runNegativeTest(
 		new String[] {
 			"Hello.java",
@@ -2750,22 +2805,8 @@
 			"	}\n" +
 			"}\n"
 		},
-		"----------\n" +
-		"1. ERROR in Hello.java (at line 1)\n" +
-		"	void ___eval() {\n" +
-		"	^^^^\n" +
-		"Syntax error on token \"void\", record expected\n" +
-		"----------\n" +
-		"2. ERROR in Hello.java (at line 1)\n" +
-		"	void ___eval() {\n" +
-		"	             ^\n" +
-		"Syntax error on token \")\", { expected after this token\n" +
-		"----------\n" +
-		"3. ERROR in Hello.java (at line 23)\n" +
-		"	}\n" +
-		"	^\n" +
-		"Syntax error, insert \"}\" to complete RecordBody\n" +
-		"----------\n"
+		this.complianceLevel < ClassFileConstants.JDK14 ?
+		expectedErrorLog :expectedErrorLog_J14
 	);
 }
 /*
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 94add4c..9e73da1 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
@@ -5400,6 +5400,47 @@
 			true,
 			customOptions);
 	}
+	public void _test0178a() {
+		if (this.complianceLevel < ClassFileConstants.JDK14)
+			return;
+		Map customOptions = getCompilerOptions();
+		this.runNegativeTest(
+			new String[] {
+				"X.java",
+				"public class X <T> {\n" +
+				"	\n" +
+				"	T foo(T t) {\n" +
+				"		boolean b = false;\n" +
+				"		if (t instanceof X<T>) {\n" +
+				"			return t;\n" +
+				"		} else if (t instanceof X<String>) {\n" +
+				"			return t;\n" +
+				"		} else if (t instanceof X<?>) {\n" +  // ok
+				"			return t;\n" +
+				"		} else 	if (t instanceof T) {\n" +
+				"			return t;\n" +
+				"		} else if (t instanceof X) {\n" +
+				"			return t;\n" +
+				"		}\n" +
+				"		return null;\n" +
+				"	}\n" +
+				"}\n",
+			},
+			"----------\n" +
+			"1. ERROR in X.java (at line 5)\n" +
+			"	if (t instanceof X<T>) {\n" +
+			"	    ^^^^^^^^^^^^^^\n" +
+			"Type mismatch: cannot convert from T to X<T>\n" +
+			"----------\n" +
+			"2. ERROR in X.java (at line 7)\n" +
+			"	} else if (t instanceof X<String>) {\n" +
+			"	           ^^^^^^^^^^^^^^\n" +
+			"Type mismatch: cannot convert from T to X<String>\n" +
+			"----------\n",
+			null,
+			true,
+			customOptions);
+	}
 	// 61507
 	public void test0179() {
 		this.runConformTest(
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocTest.java
index d566b97..20dffa7 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocTest.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2016 IBM Corporation and others.
+ * Copyright (c) 2000, 2020 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -47,6 +47,7 @@
 		ALL_CLASSES.add(JavadocTestMixed.class);
 		ALL_CLASSES.add(JavadocTestForClass.class);
 		ALL_CLASSES.add(JavadocTestForRecord.class);
+		ALL_CLASSES.add(JavadocTestForModule.class);
 		ALL_CLASSES.add(JavadocTestForConstructor.class);
 		ALL_CLASSES.add(JavadocTestForField.class);
 		ALL_CLASSES.add(JavadocTestForInterface.class);
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocTestForModule.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocTestForModule.java
index 00ecdbc..466ac72 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocTestForModule.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/JavadocTestForModule.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2019 IBM Corporation and others.
+ * Copyright (c) 2019, 2020 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -479,27 +479,17 @@
 				buffer.toString(),
 				"",
 				"----------\n" +
-				"1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.one/module-info.java (at line 2)\n" +
-				"	@provides p.I\n" +
-				"	          ^^^\n" +
-				"Javadoc: Invalid provides class\n" +
-				"----------\n" +
-				"2. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.one/module-info.java (at line 3)\n" +
-				"	@uses java.util.Currenc\n" +
-				"	      ^^^^^^^^^^^^^^^^^\n" +
-				"Javadoc: Invalid uses class\n" +
-				"----------\n" +
-				"3. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.one/module-info.java (at line 7)\n" +
+				"1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.one/module-info.java (at line 7)\n" +
 				"	provides p.I1 with p.P1;\n" +
 				"	^^^^^^^^^^^^^^^^^^^^^^^\n" +
 				"Javadoc: Missing provides tag\n" +
 				"----------\n" +
-				"4. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.one/module-info.java (at line 8)\n" +
+				"2. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.one/module-info.java (at line 8)\n" +
 				"	uses java.util.Currency;\n" +
 				"	^^^^^^^^^^^^^^^^^^^^^^^\n" +
 				"Javadoc: Missing uses tag\n" +
 				"----------\n" +
-				"4 problems (4 errors)\n",
+				"2 problems (2 errors)\n",
 				false,
 				"missing and invalid tags");
 	}
@@ -895,27 +885,17 @@
 				buffer.toString(),
 				"",
 				"----------\n" +
-				"1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.one/module-info.java (at line 2)\n" +
-				"	* @provides p.I\n" +
-				"	            ^^^\n" +
-				"Javadoc: Invalid provides class\n" +
-				"----------\n" +
-				"2. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.one/module-info.java (at line 3)\n" +
-				"	* @uses java.util.Currenc\n" +
-				"	        ^^^^^^^^^^^^^^^^^\n" +
-				"Javadoc: Invalid uses class\n" +
-				"----------\n" +
-				"3. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.one/module-info.java (at line 7)\n" +
+				"1. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.one/module-info.java (at line 7)\n" +
 				"	provides p.I1 with p.P1;\n" +
 				"	^^^^^^^^^^^^^^^^^^^^^^^\n" +
 				"Javadoc: Missing provides tag\n" +
 				"----------\n" +
-				"4. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.one/module-info.java (at line 8)\n" +
+				"2. ERROR in ---OUTPUT_DIR_PLACEHOLDER---/src/mod.one/module-info.java (at line 8)\n" +
 				"	uses java.util.Currency;\n" +
 				"	^^^^^^^^^^^^^^^^^^^^^^^\n" +
 				"Javadoc: Missing uses tag\n" +
 				"----------\n" +
-				"4 problems (4 errors)\n",
+				"2 problems (2 errors)\n",
 				false,
 				"invalid tags");
 	}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java
index 98943bd..4683011 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java
@@ -18142,4 +18142,108 @@
 		"----------\n";
 	runner.runWarningTest();
 }
+public void testBug562347_561280c9() {
+	runNegativeTestWithLibs(
+		new String[] {
+			"Example.java",
+			"import java.util.HashMap;\n" +
+			"import java.util.Map;\n" +
+			"\n" +
+			"import org.eclipse.jdt.annotation.NonNullByDefault;\n" +
+			"\n" +
+			"@NonNullByDefault\n" +
+			"public class Example {\n" +
+			"    static <X> X f(X x) {\n" +
+			"        return x;\n" +
+			"    }\n" +
+			"\n" +
+			"    public void g() {\n" +
+			"        Object x0, x1, x2, x3, x4, x5, x6, x7, x8, x9;\n" +
+			"        Object x10, x11, x12, x13, x14, x15, x16, x17, x18, x19;\n" +
+			"        Object x20, x21, x22, x23, x24, x25, x26, x27, x28, x29;\n" +
+			"        Object x30, x31, x32, x33, x34, x35, x36, x37, x38, x39;\n" +
+			"        Object x40, x41, x42, x43, x44, x45, x46, x47, x48, x49;\n" +
+			"        Object x50, x51, x52, x53, x54, x55, x56, x57, x58, x59;\n" +
+			"        Object x60;\n" +
+			"        Object x61;\n" +
+			"        for (Map.Entry<String, String> entry : new HashMap<String, String>().entrySet()) {\n" +
+			"            if (f(entry.getKey()) != null) {\n" +
+			"                continue;\n" +
+			"            }\n" +
+			"            String x = \"asdf\";\n" +
+			"            x.hashCode();\n" +
+			"        }\n" +
+			"    }\n" +
+			"}\n" +
+			"\n"
+		},
+		getCompilerOptions(),
+		"----------\n" +
+		"1. ERROR in Example.java (at line 22)\n" +
+		"	if (f(entry.getKey()) != null) {\n" +
+		"	    ^^^^^^^^^^^^^^^^^\n" +
+		"Redundant null check: comparing \'@NonNull String\' against null\n" +
+		"----------\n" +
+		"2. WARNING in Example.java (at line 25)\n" +
+		"	String x = \"asdf\";\n" +
+		"	^^^^^^^^^^^^^^^^^^\n" +
+		"Dead code\n" +
+		"----------\n");
+}
+public void testBug562347() {
+	Runner runner = new Runner();
+	runner.testFiles =
+		new String[] {
+			"NotificationListingHolder.java",
+			"@SuppressWarnings(\"unused\")\n" +
+			"public final class NotificationListingHolder {\n" +
+			"    private String f1,f2,f3,f4;\n" +
+			"\n" +
+			"    private void setupActionButtons() {\n" +
+			"        Test listItemNotificationsBinding2;\n" +
+			"        boolean z;\n" +
+			"        String a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20,a21,a22,a23,a24,a25,a26,a27,a28,a29,a30,a31,a32,a33,a34,a35,a36,a37,a38,a39,a40,a41,a42,a43,a44,a45,a46,a47,a48,a49,a50,a51,a52,a53,a54,a55,a56,a57,a58;\n" +
+			"        if (z) {\n" +
+			"            String button4 = listItemNotificationsBinding2.field;\n" +
+			"            if (listItemNotificationsBinding2 != null) {\n" +
+			"                return;\n" +
+			"            }\n" +
+			"        }\n" +
+			"    }\n" +
+			"}\n" +
+			"\n" +
+			"class Test {\n" +
+			"    public final String field;\n" +
+			"}"
+		};
+	runner.expectedCompilerLog =
+		"----------\n" +
+		"1. ERROR in NotificationListingHolder.java (at line 9)\n" +
+		"	if (z) {\n" +
+		"	    ^\n" +
+		"The local variable z may not have been initialized\n" +
+		"----------\n" +
+		"2. ERROR in NotificationListingHolder.java (at line 10)\n" +
+		"	String button4 = listItemNotificationsBinding2.field;\n" +
+		"	                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+		"The local variable listItemNotificationsBinding2 may not have been initialized\n" +
+		"----------\n" +
+		"3. ERROR in NotificationListingHolder.java (at line 11)\n" +
+		"	if (listItemNotificationsBinding2 != null) {\n" +
+		"	    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+		"The local variable listItemNotificationsBinding2 may not have been initialized\n" +
+		"----------\n" +
+		"4. ERROR in NotificationListingHolder.java (at line 11)\n" +
+		"	if (listItemNotificationsBinding2 != null) {\n" +
+		"	    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+		"Redundant null check: The variable listItemNotificationsBinding2 cannot be null at this location\n" +
+		"----------\n" +
+		"5. ERROR in NotificationListingHolder.java (at line 19)\n" +
+		"	public final String field;\n" +
+		"	                    ^^^^^\n" +
+		"The blank final field field may not have been initialized\n" +
+		"----------\n";
+	runner.classLibraries = this.LIBS;
+	runner.runNegativeTest();
+}
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PatternMatching15Test.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PatternMatching15Test.java
index 3972400..2f0676c 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PatternMatching15Test.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PatternMatching15Test.java
@@ -1674,7 +1674,7 @@
 						"		foo(new String[] {\"abcd\"});\n" +
 						"	}\n" +
 						"  public static void foo(Object[] obj) {\n" +
-						"		for(int i = 0; (obj[i] instanceof String s) && s.length() > 0 ; i++) {\n" +
+						"		for(int i = 0; (obj[i] instanceof String s) && s.length() > 0 ;) {\n" +
 						"			throw new IllegalArgumentException();\n" +
 						"		}\n" +
 						"		System.out.println(s);\n" +
@@ -1685,7 +1685,7 @@
 				"1. ERROR in X38.java (at line 10)\n" +
 				"	System.out.println(s);\n" +
 				"	                   ^\n" +
-				"s cannot be resolved to a variable\n" +
+				"The pattern variable s is not in scope in this location\n" +
 				"----------\n",
 				"",
 				null,
@@ -2011,4 +2011,138 @@
 				compilerOptions);
 		compilerOptions.put(CompilerOptions.OPTION_PreserveUnusedLocal, old);
 	}
-}
\ No newline at end of file
+	public void test052() {
+		Map<String, String> compilerOptions = getCompilerOptions(true);
+		String old = compilerOptions.get(CompilerOptions.OPTION_PreserveUnusedLocal);
+		compilerOptions.put(CompilerOptions.OPTION_PreserveUnusedLocal, CompilerOptions.OPTIMIZE_OUT);
+		runConformTest(
+				new String[] {
+						"X.java",
+						"public class X {\n" +
+						"	@SuppressWarnings(\"preview\")\n" +
+						"	public static void main(String args[]) {\n" +
+						"		String result = null;\n" +
+						"		Object obj = \"abc\";\n" +
+						"		int i = switch (0) {\n" +
+						"			case 1 -> {\n" +
+						"				yield 1;\n" +
+						"			}\n" +
+						"			default -> {\n" +
+						"				for (int j = 0; !(obj instanceof String s);) {\n" +
+						"					obj = null;\n" +
+						"				}\n" +
+						"				result = s;\n" +
+						"				System.out.println(result);\n" +
+						"				yield 2;\n" +
+						"			}\n" +
+						"		};\n" +
+						"		System.out.println(i);\n" +
+						"	}\n" +
+						"}\n",
+				},
+				"abc\n" +
+				"2",
+				compilerOptions);
+		compilerOptions.put(CompilerOptions.OPTION_PreserveUnusedLocal, old);
+	}
+	public void _testBug562392a() {
+		Map<String, String> compilerOptions = getCompilerOptions(true);
+		runConformTest(
+				new String[] {
+						"X.java",
+						"public class X<T> {\n" +
+						"	public boolean foo(T obj) {\n" +
+						"		if (obj instanceof T s) {\n" +
+						"			System.out.println(s);\n" +
+						"		}\n" +
+						"		return true;\n" +
+						"	}\n" +
+						"	public static void main(String argv[]) {\n" +
+						"		String s = \"x\";\n" +
+						"		System.out.println(new X<String>().foo(s));\n" +
+						"	}\n" +
+						"}\n",
+				},
+				"x\n" +
+				"true",
+				compilerOptions);
+		}
+	public void _testBug562392b() {
+		Map<String, String> compilerOptions = getCompilerOptions(true);
+		runNegativeTest(
+				new String[] {
+						"X.java",
+						"public class X<T> {\n" +
+						"	public boolean foo(Object obj) {\n" +
+						"        if (obj instanceof T) {\n" +
+						"            return false;\n" +
+						"        }\n" +
+						"        return true;\n" +
+						"    }\n" +
+						"	public static void main(String argv[]) {\n" +
+						"		System.out.println(\"\");\n" +
+						"	}\n" +
+						"}\n",
+				},
+				"----------\n" +
+				"1. ERROR in X.java (at line 3)\n" +
+				"	if (obj instanceof T) {\n" +
+				"	    ^^^^^^^^^^^^^^^^\n" +
+				"Type mismatch: cannot convert from Object to T\n" +
+				"----------\n",
+				"",
+				null,
+				true,
+				compilerOptions);
+		}
+	public void _testBug562392c() {
+		Map<String, String> compilerOptions = getCompilerOptions(true);
+		runNegativeTest(
+				new String[] {
+						"X.java",
+						"@SuppressWarnings(\"preview\")\n" +
+						"public class X<T> {\n" +
+						"	public boolean foo(Object obj) {\n" +
+						"        if (obj instanceof T t) {\n" +
+						"            return false;\n" +
+						"        }\n" +
+						"        return true;\n" +
+						"    }\n" +
+						"	public static void main(String argv[]) {\n" +
+						"		System.out.println(\"\");\n" +
+						"	}\n" +
+						"}\n",
+				},
+				"----------\n" +
+				"1. ERROR in X.java (at line 4)\n" +
+				"	if (obj instanceof T t) {\n" +
+				"	    ^^^^^^^^^^^^^^^^^^\n" +
+				"Type mismatch: cannot convert from Object to T\n" +
+				"----------\n",
+				"",
+				null,
+				true,
+				compilerOptions);
+		}
+	public void _testBug562392d() {
+		Map<String, String> compilerOptions = getCompilerOptions(true);
+		runConformTest(
+				new String[] {
+						"X.java",
+						"@SuppressWarnings(\"preview\")\n" +
+						"public class X<T> {\n" +
+						"	public boolean foo(Object obj) {\n" +
+						"        if (null instanceof T t) {\n" +
+						"            return false;\n" +
+						"        }\n" +
+						"        return true;\n" +
+						"    }\n" +
+						"	public static void main(String argv[]) {\n" +
+						"		System.out.println(\"\");\n" +
+						"	}\n" +
+						"}\n",
+				},
+				"",
+				compilerOptions);
+		}
+}
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordsRestrictedClassTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordsRestrictedClassTest.java
index 2d148f7..8a272a0 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordsRestrictedClassTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordsRestrictedClassTest.java
@@ -50,6 +50,7 @@
 		defaultOptions.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_15);
 		defaultOptions.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
 		defaultOptions.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
+		defaultOptions.put(CompilerOptions.OPTION_Store_Annotations, CompilerOptions.ENABLED);
 		return defaultOptions;
 	}
 
@@ -2507,4 +2508,230 @@
 		true
 	);
 }
+public void testBug561778_001() throws IOException, ClassFormatException {
+	runConformTest(
+			new String[] {
+					"XTest.java",
+					"public class XTest{\n" +
+					"	static <T> T test(X<T> box) {\n" +
+					"		return box.value(); /* */\n" +
+					"	}\n" +
+					"   public static void main(String[] args) {\n" +
+					"       System.out.println(0);\n" +
+					"   }\n" +
+					"}\n",
+					"X.java",
+					"public record X<T>(T value) {\n" +
+					"}"
+			},
+		"0");
+	String expectedOutput =
+			"  // Method descriptor #24 ()Ljava/lang/Object;\n" +
+			"  // Signature: ()TT;\n" +
+			"  // Stack: 1, Locals: 1\n" +
+			"  public java.lang.Object value();\n";
+	RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "X.class", ClassFileBytesDisassembler.SYSTEM);
+}
+public void testBug561778_002() throws IOException, ClassFormatException {
+	runConformTest(
+			new String[] {
+					"XTest.java",
+					"public class XTest{\n" +
+					"	static <T> Y<T> test(X<T> box) {\n" +
+					"		return box.value(); /* */\n" +
+					"	}\n" +
+					"   public static void main(String[] args) {\n" +
+					"       System.out.println(0);\n" +
+					"   }\n" +
+					"}\n",
+					"X.java",
+					"public record X<T>(Y<T> value) {\n" +
+					"}\n" +
+					"class Y<T> {\n" +
+					"}"
+			},
+		"0");
+	String expectedOutput =
+			"  // Method descriptor #24 ()LY;\n" +
+			"  // Signature: ()LY<TT;>;\n" +
+			"  // Stack: 1, Locals: 1\n" +
+			"  public Y value();\n";
+	RecordsRestrictedClassTest.verifyClassFile(expectedOutput, "X.class", ClassFileBytesDisassembler.SYSTEM);
+}
+public void testBug562219_001() {
+	this.runNegativeTest(
+			new String[] {
+				"X.java",
+				"public class X {\n"+
+				"       public void foo() {\n"+
+				"               @SuppressWarnings(\"unused\")\n"+
+				"               class Y {\n"+
+				"                       @SuppressWarnings(\"preview\")\n"+
+				"                       class Z {\n"+
+				"                               record R() {\n"+
+				"                                       \n"+
+				"                               }\n"+
+				"                       }\n"+
+				"               }\n"+
+				"       }\n"+
+				"}\n"
+			},
+		"----------\n" +
+		"1. ERROR in X.java (at line 7)\n" +
+		"	record R() {\n" +
+		"	       ^\n" +
+		"A record declaration R is not allowed in a local inner class\n" +
+		"----------\n",
+		null,
+		true
+	);
+}
+public void testBug562219_002() {
+	this.runNegativeTest(
+			new String[] {
+				"X.java",
+				"public class X {\n"+
+				"    public void foo() {\n"+
+				"        @SuppressWarnings(\"unused\")\n"+
+				"        class Y {\n"+
+				"           @SuppressWarnings(\"preview\")\n"+
+				"           record R() {}\n"+
+				"        }\n"+
+				"    }\n"+
+				"}\n"
+			},
+		"----------\n" +
+		"1. ERROR in X.java (at line 6)\n" +
+		"	record R() {}\n" +
+		"	       ^\n" +
+		"A record declaration R is not allowed in a local inner class\n" +
+		"----------\n",
+		null,
+		true
+	);
+}
+/*
+ * Test that annotation with implicit target as METHOD are included in the
+ * generated bytecode on the record component and its accessor method
+ */
+public void _test562250a() throws IOException, ClassFormatException {
+	runConformTest(
+			new String[] {
+					"X.java",
+					"import java.lang.annotation.*;\n" +
+					"import java.lang.reflect.*;\n" +
+					"\n" +
+					"record Point(@Annot int a) {\n" +
+					"}\n" +
+					"@Retention(RetentionPolicy.RUNTIME)\n" +
+					"@interface Annot {\n" +
+					"}\n" +
+					"public class X {\n" +
+					"	public static void main(String[] args) throws Exception {\n" +
+					"			Class<?> cls = Class.forName(\"Point\");\n" +
+					"			RecordComponent[] recordComponents = cls.getRecordComponents();\n" +
+					"			for (RecordComponent recordComponent : recordComponents) {\n" +
+					"				Annotation[] annotations = recordComponent.getAnnotations();\n" +
+					"				System.out.println(\"RecordComponents:\");\n" +
+					"				for (Annotation annot : annotations) {\n" +
+					"					System.out.println(annot);\n" +
+					"				}\n" +
+					"				Method accessor = recordComponent.getAccessor();\n" +
+					"				System.out.println(\"Accessors:\");\n" +
+					"				annotations =accessor.getAnnotations();\n" +
+					"				for (Annotation annot : annotations) {\n" +
+					"					System.out.println(annot);\n" +
+					"				}\n" +
+					"			}\n" +
+					"	}\n" +
+					"}"
+			},
+		"RecordComponents:\n" +
+		"@Annot()\n" +
+		"Accessors:\n" +
+		"@Annot()");
+}
+/*
+ * Test that annotation with explicit target as METHOD are included in the
+ * generated bytecode on the record component and its accessor method
+ */
+public void _test562250b() throws IOException, ClassFormatException {
+	runConformTest(
+			new String[] {
+					"X.java",
+					"import java.lang.annotation.*;\n" +
+					"import java.lang.reflect.*;\n" +
+					"\n" +
+					"record Point(@Annot int a) {\n" +
+					"}\n" +
+					"@Target({ElementType.METHOD})\n"+
+					"@Retention(RetentionPolicy.RUNTIME)\n" +
+					"@interface Annot {\n" +
+					"}\n" +
+					"public class X {\n" +
+					"	public static void main(String[] args) throws Exception {\n" +
+					"			Class<?> cls = Class.forName(\"Point\");\n" +
+					"			RecordComponent[] recordComponents = cls.getRecordComponents();\n" +
+					"			for (RecordComponent recordComponent : recordComponents) {\n" +
+					"				Annotation[] annotations = recordComponent.getAnnotations();\n" +
+					"				System.out.println(\"RecordComponents:\");\n" +
+					"				for (Annotation annot : annotations) {\n" +
+					"					System.out.println(annot);\n" +
+					"				}\n" +
+					"				Method accessor = recordComponent.getAccessor();\n" +
+					"				System.out.println(\"Accessors:\");\n" +
+					"				annotations =accessor.getAnnotations();\n" +
+					"				for (Annotation annot : annotations) {\n" +
+					"					System.out.println(annot);\n" +
+					"				}\n" +
+					"			}\n" +
+					"	}\n" +
+					"}"
+			},
+		"RecordComponents:\n" +
+		"@Annot()\n" +
+		"Accessors:\n" +
+		"@Annot()");
+}
+/*
+ * Test that even though annotations with FIELD as a target are permitted by the
+ * compiler on a record component, the generated bytecode doesn't contain these annotations
+ * on the record component.
+ */
+public void _test562250c() throws IOException, ClassFormatException {
+	runConformTest(
+			new String[] {
+					"X.java",
+					"import java.lang.annotation.*;\n" +
+					"import java.lang.reflect.*;\n" +
+					"\n" +
+					"record Point(@Annot int a) {\n" +
+					"}\n" +
+					"@Target({ElementType.FIELD})\n"+
+					"@Retention(RetentionPolicy.RUNTIME)\n" +
+					"@interface Annot {\n" +
+					"}\n" +
+					"public class X {\n" +
+					"	public static void main(String[] args) throws Exception {\n" +
+					"			Class<?> cls = Class.forName(\"Point\");\n" +
+					"			RecordComponent[] recordComponents = cls.getRecordComponents();\n" +
+					"			for (RecordComponent recordComponent : recordComponents) {\n" +
+					"				Annotation[] annotations = recordComponent.getAnnotations();\n" +
+					"				System.out.println(\"RecordComponents:\");\n" +
+					"				for (Annotation annot : annotations) {\n" +
+					"					System.out.println(annot);\n" +
+					"				}\n" +
+					"				Method accessor = recordComponent.getAccessor();\n" +
+					"				System.out.println(\"Accessors:\");\n" +
+					"				annotations =accessor.getAnnotations();\n" +
+					"				for (Annotation annot : annotations) {\n" +
+					"					System.out.println(annot);\n" +
+					"				}\n" +
+					"			}\n" +
+					"	}\n" +
+					"}"
+			},
+		"RecordComponents:\n" +
+		"Accessors:");
+}
 }
\ No newline at end of file
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionsYieldTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionsYieldTest.java
index 35979da..6c8ae9e 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionsYieldTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/SwitchExpressionsYieldTest.java
@@ -4611,4 +4611,63 @@
 				"----------\n");
 
 	}
+
+	public void testBug562129() {
+		if (this.complianceLevel < ClassFileConstants.JDK14) return;
+		runNegativeTest(
+			new String[] {
+				"SwitchExpressionError.java",
+				"class SwitchExpressionError {\n" +
+				"\n" +
+				"    static boolean howMany(int k) {\n" +
+				"        return false || switch (k) {\n" +
+				"            case 1 -> true;\n" +
+				"            case 2 -> Boolean.FALSE;\n" +
+				"            case 3 -> r;\n" +
+				"        };\n" +
+				"    }\n" +
+				"\n" +
+				"}\n"
+			},
+			"----------\n" +
+			"1. ERROR in SwitchExpressionError.java (at line 4)\n" +
+			"	return false || switch (k) {\n" +
+			"	                        ^\n" +
+			"A switch expression should have a default case\n" +
+			"----------\n" +
+			"2. ERROR in SwitchExpressionError.java (at line 7)\n" +
+			"	case 3 -> r;\n" +
+			"	          ^\n" +
+			"r cannot be resolved to a variable\n" +
+			"----------\n");
+	}
+	public void testBug562198_001() {
+		runConformTest(
+			new String[] {
+				"X.java",
+				"public class X {\n"+
+				"    int a[] = {1, 2, 3};\n"+
+				"    public int foo() {\n"+
+				"        return switch (0) {\n"+
+				"               case 0 -> {\n"+
+				"                       yield a[0];\n"+
+				"               }\n"+
+				"            default -> {\n"+
+				"                try {\n"+
+				"                    // do nothing\n"+
+				"                } finally {\n"+
+				"                    // do nothing\n"+
+				"                }\n"+
+				"                yield 0;\n"+
+				"            }\n"+
+				"        };\n"+
+				"    }\n"+
+				"    public static void main(String[] args) {\n"+
+				"               System.out.println(new X().foo());\n"+
+				"       }\n"+
+				"}\n"
+			},
+			"1");
+	}
+
 }
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TextBlockTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TextBlockTest.java
index e8006e6..79f4631 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TextBlockTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/TextBlockTest.java
@@ -1337,4 +1337,20 @@
 				true,
 				copy);
 	}
+	public void testBug562460() {
+		runConformTest(
+				new String[] {
+						"X.java",
+						"public class X {\n" +
+						"	public static String textb = \"\"\"\n" +
+						"a\\sb\\sc\"\"\";\n" +
+						"	public static void main(String[] args) {\n" +
+						"		System.out.println(textb.equals(\"a b c\"));\n" +
+						"	}\n" +
+						"}\n"
+				},
+				"true",
+				getCompilerOptions(),
+				new String[] {"--enable-preview"});
+	}
 }
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelCompletionTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelCompletionTests.java
index 989100b..d0215db 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelCompletionTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelCompletionTests.java
@@ -23,6 +23,7 @@
 import org.eclipse.core.runtime.Path;
 import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.internal.codeassist.RelevanceConstants;
+import org.eclipse.jdt.internal.codeassist.impl.AssistOptions;
 
 import junit.framework.*;
 
@@ -165,9 +166,9 @@
 	super.setUpSuite();
 	this.oldOptions = JavaCore.getOptions();
 	Hashtable<String, String> options = new Hashtable<>(this.oldOptions);
-	options.put(JavaCore.CODEASSIST_SUBSTRING_MATCH, JavaCore.DISABLED);
 	options.put(JavaCore.CODEASSIST_SUBWORD_MATCH, JavaCore.DISABLED);
 	JavaCore.setOptions(options);
+	System.setProperty(AssistOptions.PROPERTY_SubstringMatch, "false");
 	waitUntilIndexesReady();
 }
 @Override
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests9.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests9.java
index 77b6350..6a9596b 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests9.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/CompletionTests9.java
@@ -13,8 +13,6 @@
  *******************************************************************************/
 package org.eclipse.jdt.core.tests.model;
 
-import java.util.Hashtable;
-
 import org.eclipse.core.resources.IncrementalProjectBuilder;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.Path;
@@ -25,6 +23,7 @@
 import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.tests.util.AbstractCompilerTest;
+import org.eclipse.jdt.internal.codeassist.impl.AssistOptions;
 
 import junit.framework.Test;
 
@@ -147,14 +146,12 @@
 	String str = this.workingCopies[0].getSource();
 	String completeBehind = "p";
 	int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
-	Hashtable<String, String> tmpOld = JavaCore.getOptions();
-	Hashtable<String, String> options = new Hashtable<>(tmpOld);
-	options.put(JavaCore.CODEASSIST_SUBSTRING_MATCH, JavaCore.DISABLED);
-	JavaCore.setOptions(options);
+	String oldValue = System.getProperty(AssistOptions.PROPERTY_SubstringMatch);
+	System.setProperty(AssistOptions.PROPERTY_SubstringMatch, "false");
 
 	this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
 
-	JavaCore.setOptions(tmpOld);
+	System.setProperty(AssistOptions.PROPERTY_SubstringMatch, oldValue);
 	String expected = "provides[KEYWORD]{provides, null, null, provides, null, 49}";
 	assertResults(expected,	requestor.getResults());
 }
@@ -171,14 +168,12 @@
 	String str = this.workingCopies[0].getSource();
 	String completeBehind = "p";
 	int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
-	Hashtable<String, String> tmpOld = JavaCore.getOptions();
-	Hashtable<String, String> options = new Hashtable<>(tmpOld);
-	options.put(JavaCore.CODEASSIST_SUBSTRING_MATCH, JavaCore.ENABLED);
-	JavaCore.setOptions(options);
+	String oldValue = System.getProperty(AssistOptions.PROPERTY_SubstringMatch);
+	System.setProperty(AssistOptions.PROPERTY_SubstringMatch, "true");
 
 	this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
 
-	JavaCore.setOptions(tmpOld);
+	System.setProperty(AssistOptions.PROPERTY_SubstringMatch, oldValue);
 	String expected = "exports[KEYWORD]{exports, null, null, exports, null, 19}\n"
 			+ "provides[KEYWORD]{provides, null, null, provides, null, 49}";
 	assertResults(expected,	requestor.getResults());
@@ -196,14 +191,12 @@
 	String completeBehind = "u";
 	int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
 
-	Hashtable<String, String> tmpOld = JavaCore.getOptions();
-	Hashtable<String, String> options = new Hashtable<>(tmpOld);
-	options.put(JavaCore.CODEASSIST_SUBSTRING_MATCH, JavaCore.ENABLED);
-	JavaCore.setOptions(options);
+	String oldValue = System.getProperty(AssistOptions.PROPERTY_SubstringMatch);
+	System.setProperty(AssistOptions.PROPERTY_SubstringMatch, "true");
 
 	this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
 
-	JavaCore.setOptions(tmpOld);
+	System.setProperty(AssistOptions.PROPERTY_SubstringMatch, oldValue);
 
 	String expected = "requires[KEYWORD]{requires, null, null, requires, null, 19}\n"
 			+ "uses[KEYWORD]{uses, null, null, uses, null, 49}";
@@ -243,17 +236,15 @@
 	String completeBehind = "mypa";
 	int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
 
-	Hashtable<String, String> tmpOld = JavaCore.getOptions();
-	Hashtable<String, String> options = new Hashtable<>(tmpOld);
-	options.put(JavaCore.CODEASSIST_SUBSTRING_MATCH, JavaCore.DISABLED);
-	JavaCore.setOptions(options);
+	String oldValue = System.getProperty(AssistOptions.PROPERTY_SubstringMatch);
+	System.setProperty(AssistOptions.PROPERTY_SubstringMatch, "false");
 
 	this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
 	String expected = "mypack1[PACKAGE_REF]{mypack1, mypack1, null, null, null, 49}\n"
 			+ "mypack2[PACKAGE_REF]{mypack2, mypack2, null, null, null, 49}\n"
 			+ "mypackage[PACKAGE_REF]{mypackage, mypackage, null, null, null, 49}";
 	assertResults(expected, requestor.getResults());
-	JavaCore.setOptions(tmpOld);
+	System.setProperty(AssistOptions.PROPERTY_SubstringMatch, oldValue);
 }
 
 public void test486988_0008() throws JavaModelException {
@@ -289,15 +280,13 @@
 	String completeBehind = "mypack1 t";
 	int cursorLocation = str.lastIndexOf(completeBehind) + completeBehind.length();
 
-	Hashtable<String, String> tmpOld = JavaCore.getOptions();
-	Hashtable<String, String> options = new Hashtable<>(tmpOld);
-	options.put(JavaCore.CODEASSIST_SUBSTRING_MATCH, JavaCore.DISABLED);
-	JavaCore.setOptions(options);
+	String oldValue = System.getProperty(AssistOptions.PROPERTY_SubstringMatch);
+	System.setProperty(AssistOptions.PROPERTY_SubstringMatch, "false");
 
 	this.workingCopies[0].codeComplete(cursorLocation, requestor, this.wcOwner);
 	String expected = "to[KEYWORD]{to, null, null, to, null, 49}";
 	assertResults(expected, requestor.getResults());
-	JavaCore.setOptions(tmpOld);
+	System.setProperty(AssistOptions.PROPERTY_SubstringMatch, oldValue);
 
 }
 public void test486988_0009() throws Exception {
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests10.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests10.java
index c086841..863d50d 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests10.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ResolveTests10.java
@@ -127,4 +127,31 @@
 				Signature.getUnionTypeBounds(typeSignature) // method name is wrong, it actually means: getIntersectionTypeBounds
 			);
 	}
+	public void testBug562382() throws CoreException {
+		this.wc = getWorkingCopy("/Resolve/src/X.java",
+				"class X {\n" +
+				"	class Number {};\n" +
+				"	class Integer extends Number {};\n" +
+				"	interface Function<T, R> {\n" +
+				"	    R apply(T t);\n" +
+				"	}\n" +
+				"	Function<Number, Integer> fail() {\n" +
+				"		return new Function<>() {\n" +
+				"			@Override\n" +
+				"			public Integer apply(Number t) {\n" +
+				"				return null;\n" +
+				"			}\n" +
+				"		};\n" +
+				"	}\n" +
+				"}"
+				);
+		String str = this.wc.getSource();
+		String selection = "Number";
+		int start = str.lastIndexOf(selection);
+		int length = selection.length();
+
+		IJavaElement[] selected = this.wc.codeSelect(start, length);
+		assertEquals(1, selected.length);
+		assertEquals("Number", selected[0].getElementName());
+	}
 }
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/SubstringCompletionTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/SubstringCompletionTests.java
index d46c6db..f6707a2 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/SubstringCompletionTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/SubstringCompletionTests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2015, 2019 Gábor Kövesdán and others.
+ * Copyright (c) 2015, 2020 Gábor Kövesdán and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -13,11 +13,9 @@
  *******************************************************************************/
 package org.eclipse.jdt.core.tests.model;
 
-import java.util.Hashtable;
-
 import org.eclipse.jdt.core.ICompilationUnit;
-import org.eclipse.jdt.core.JavaCore;
 import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.internal.codeassist.impl.AssistOptions;
 
 import junit.framework.Test;
 
@@ -37,9 +35,7 @@
 		setUpProjectCompliance(COMPLETION_PROJECT, "1.8", true);
 	}
 	super.setUpSuite();
-	Hashtable<String, String> options = new Hashtable<>(this.oldOptions);
-	options.put(JavaCore.CODEASSIST_SUBSTRING_MATCH, JavaCore.ENABLED);
-	JavaCore.setOptions(options);
+	System.setProperty(AssistOptions.PROPERTY_SubstringMatch, "true");
 }
 @Override
 public void tearDownSuite() throws Exception {
diff --git a/org.eclipse.jdt.core.tests.performance/.cvsignore b/org.eclipse.jdt.core.tests.performance/.cvsignore
deleted file mode 100644
index c5e82d7..0000000
--- a/org.eclipse.jdt.core.tests.performance/.cvsignore
+++ /dev/null
@@ -1 +0,0 @@
-bin
\ No newline at end of file
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 f351e5c..43157d0 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
@@ -3320,25 +3320,34 @@
 
 private static char[][] decodeIgnoreOptionalProblemsFromFolders(String folders) {
 	StringTokenizer tokenizer = new StringTokenizer(folders, File.pathSeparator);
-	char[][] result = new char[tokenizer.countTokens()][];
+	char[][] result = new char[2 * tokenizer.countTokens()][];
 	int count = 0;
 	while (tokenizer.hasMoreTokens()) {
 		String fileName = tokenizer.nextToken();
 		// relative folder names are created relative to the current user dir
 		File file = new File(fileName);
 		if (file.exists()) {
+			String absolutePath = file.getAbsolutePath();
+			result[count++] = absolutePath.toCharArray();
 			// if the file exists, we should try to use its canonical path
 			try {
-				result[count++] = file.getCanonicalPath().toCharArray();
+				String canonicalPath = file.getCanonicalPath();
+				if (!absolutePath.equals(canonicalPath)) {
+					result[count++] = canonicalPath.toCharArray();
+				}
 			} catch (IOException e) {
-				// if we got exception during canonicalization, fall back to the name that was specified
-				result[count++] = fileName.toCharArray();
+				// ignore
 			}
 		} else {
 			// if the file does not exist, use the name that was specified
 			result[count++] = fileName.toCharArray();
 		}
 	}
+	if (count < result.length) {
+		char[][] shortened = new char[count][];
+		System.arraycopy(result, 0, shortened, 0, count);
+		result = shortened;
+	}
 	return result;
 }
 
@@ -5358,7 +5367,7 @@
 		}
 	}
 }
-protected final static boolean shouldIgnoreOptionalProblems(char[][] folderNames, char[] fileName) {
+public final static boolean shouldIgnoreOptionalProblems(char[][] folderNames, char[] fileName) {
 	if (folderNames == null || fileName == null) {
 		return false;
 	}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnJavadocTag.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnJavadocTag.java
index 7b1f581..0faab36 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnJavadocTag.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/complete/CompletionOnJavadocTag.java
@@ -16,7 +16,7 @@
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.JavadocSingleNameReference;
-import org.eclipse.jdt.internal.compiler.ast.RecordDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
 import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
@@ -132,11 +132,8 @@
 							switch (scope.kind) {
 								case Scope.CLASS_SCOPE:
 									if (scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_5) {
-										boolean isRecordWithComponent = false;
-										if( ((ClassScope)scope).referenceContext instanceof RecordDeclaration) {
-											RecordDeclaration rd = (RecordDeclaration)((ClassScope)scope).referenceContext;
-											isRecordWithComponent = rd.nRecordComponents >0 ;
-										}
+										TypeDeclaration typeDecl = ((ClassScope)scope).referenceContext;
+										boolean isRecordWithComponent = typeDecl.isRecord() && typeDecl.nRecordComponents >0 ;
 										if (((ClassScope)scope).referenceContext.binding.isGenericType() || isRecordWithComponent) {
 											filteredTags[size++] = possibleTag;
 										}
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistOptions.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistOptions.java
index 92a40a3..cc7f502 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistOptions.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/impl/AssistOptions.java
@@ -55,13 +55,13 @@
 		"org.eclipse.jdt.core.codeComplete.discouragedReferenceCheck"; 	//$NON-NLS-1$
 	public static final String OPTION_CamelCaseMatch =
 		"org.eclipse.jdt.core.codeComplete.camelCaseMatch"; 	//$NON-NLS-1$
-	public static final String OPTION_SubstringMatch =
-			"org.eclipse.jdt.core.codeComplete.substringMatch"; 	//$NON-NLS-1$
 	public static final String OPTION_SubwordMatch =
 			"org.eclipse.jdt.core.codeComplete.subwordMatch"; 	//$NON-NLS-1$
 	public static final String OPTION_SuggestStaticImports =
 		"org.eclipse.jdt.core.codeComplete.suggestStaticImports"; 	//$NON-NLS-1$
 
+	public static final String PROPERTY_SubstringMatch = "jdt.codeCompleteSubstringMatch"; //$NON-NLS-1$
+
 	public static final String ENABLED = "enabled"; //$NON-NLS-1$
 	public static final String DISABLED = "disabled"; //$NON-NLS-1$
 
@@ -239,12 +239,8 @@
 				this.camelCaseMatch = false;
 			}
 		}
-		if ((optionValue = optionsMap.get(OPTION_SubstringMatch)) != null) {
-			if (ENABLED.equals(optionValue)) {
-				this.substringMatch = true;
-			} else if (DISABLED.equals(optionValue)) {
-				this.substringMatch = false;
-			}
+		if ("false".equals(System.getProperty(PROPERTY_SubstringMatch))) {  //$NON-NLS-1$
+			this.substringMatch = false;
 		}
 		if ((optionValue = optionsMap.get(OPTION_SubwordMatch)) != null) {
 			if (ENABLED.equals(optionValue)) {
diff --git a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java
index fea7d23..2a8bb8b 100644
--- a/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java
+++ b/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/select/SelectionParser.java
@@ -678,14 +678,6 @@
 protected void consumeFormalParameter(boolean isVarArgs) {
 	if (this.indexOfAssistIdentifier() < 0) {
 		super.consumeFormalParameter(isVarArgs);
-		if((!this.diet || this.dietInt != 0) && this.astPtr > -1) {
-			Argument argument = (Argument) this.astStack[this.astPtr];
-			if(argument.type == this.assistNode) {
-				this.isOrphanCompletionNode = true;
-				this.restartRecovery	= true;	// force to restart in recovery mode
-				this.lastIgnoredToken = -1;
-			}
-		}
 	} else {
 		boolean isReceiver = this.intStack[this.intPtr--] == 0;
 	    if (isReceiver) {
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 56a31e2..6eb0595 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
@@ -2316,6 +2316,9 @@
 	/** @since 3.22
 	 * @noreference preview feature error */
 	int RecordStaticReferenceToOuterLocalVariable= PreviewRelated + 1755;
+	/** @since 3.22
+	 * @noreference preview feature error */
+	int RecordCannotDefineRecordInLocalType= PreviewRelated + 1756;
 	/* records - end */
 	/* instanceof pattern: */
 	/** @since 3.22
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompactConstructorDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompactConstructorDeclaration.java
index e9a2150..88fa4f5 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompactConstructorDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CompactConstructorDeclaration.java
@@ -20,7 +20,7 @@
 
 public class CompactConstructorDeclaration extends ConstructorDeclaration {
 
-	public RecordDeclaration recordDeclaration;
+	public TypeDeclaration recordDeclaration;
 
 	public CompactConstructorDeclaration(CompilationResult compilationResult) {
 		super(compilationResult);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java
index d57623a..c38ba90 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java
@@ -180,6 +180,12 @@
 		return this.binding.isFinal();
 	return (this.modifiers & ClassFileConstants.AccFinal) != 0;
 }
+@Override
+public StringBuffer print(int indent, StringBuffer output) {
+	if (this.isARecordComponent)
+		output.append("/* Implicit */"); //$NON-NLS-1$
+	return super.print(indent, output);
+}
 
 @Override
 public StringBuffer printStatement(int indent, StringBuffer output) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java
index d600dfb..db8a662 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ForStatement.java
@@ -403,6 +403,17 @@
 
 	@Override
 	public void resolve(BlockScope upperScope) {
+		if (this.condition != null && this.condition.containsPatternVariable()) {
+			this.condition.traverse(new ASTVisitor() {
+				@Override
+				public boolean visit(
+						InstanceOfExpression instanceOfExpression,
+						BlockScope sc) {
+					instanceOfExpression.resolvePatternVariable(upperScope);
+					return true; // We want to resolve all pattern variables if any inside the condition
+				}
+			}, upperScope);
+		}
 		// use the scope that will hold the init declarations
 		this.scope = (this.bits & ASTNode.NeededScope) != 0 ? new BlockScope(upperScope) : upperScope;
 		if (this.initializations != null)
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java
index 63939ca..3ce4c1a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Javadoc.java
@@ -213,10 +213,8 @@
 		// @param tags
 		int paramTagsSize = this.paramReferences == null ? 0 : this.paramReferences.length;
 		for (int i = 0; i < paramTagsSize; i++) {
-			if(scope.referenceContext instanceof RecordDeclaration) {
-				RecordDeclaration rd = (RecordDeclaration)scope.referenceContext;
-				if(  rd.nRecordComponents > 0)
-					break;
+			if(scope.referenceContext.nRecordComponents > 0) {
+				break;
 			}
 			JavadocSingleNameReference param = this.paramReferences[i];
 			scope.problemReporter().javadocUnexpectedTag(param.tagSourceStart, param.tagSourceEnd);
@@ -762,10 +760,7 @@
 				parameters = typeDeclaration.typeParameters;
 				typeVariables = typeDeclaration.binding.typeVariables;
 				modifiers = typeDeclaration.binding.modifiers;
-				if (typeDeclaration instanceof RecordDeclaration) {
-					RecordDeclaration recordDecl = (RecordDeclaration)typeDeclaration;
-					recordParameters = recordDecl.getArgs();
-				}
+				recordParameters = typeDeclaration.args;
 				break;
 		}
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
index a811880..598ff74 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/MethodDeclaration.java
@@ -201,13 +201,15 @@
 		if (this.arguments != null && this.arguments.length != 0)
 			return null;
 		ClassScope skope = this.scope.classScope();
-		if (!(skope.referenceContext instanceof RecordDeclaration))
+		TypeDeclaration typeDecl = skope.referenceContext;
+		if (!typeDecl.isRecord())
 			return null;
-		RecordDeclaration rd = (RecordDeclaration) skope.referenceContext;
-		Argument[] args = rd.getArgs();
+		if (!(skope.referenceContext.isRecord()))
+			return null;
+		Argument[] args = typeDecl.args;
 		if (args == null || args.length == 0)
 			return null;
-		for (Argument arg : rd.getArgs()) {
+		for (Argument arg : args) {
 			if (arg == null || arg.name == null)
 				continue;
 			if (CharOperation.equals(this.selector, arg.name)) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/RecordDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/RecordDeclaration.java
deleted file mode 100644
index 37470c2..0000000
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/RecordDeclaration.java
+++ /dev/null
@@ -1,296 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2019, 2020 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * https://www.eclipse.org/legal/epl-2.0/
- *
- * SPDX-License-Identifier: EPL-2.0
- *
- * Contributors:
- *     IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.internal.compiler.ast;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.ClassFile;
-import org.eclipse.jdt.internal.compiler.CompilationResult;
-import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
-import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
-import org.eclipse.jdt.internal.compiler.lookup.Scope;
-import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
-import org.eclipse.jdt.internal.compiler.parser.Parser;
-
-public class RecordDeclaration extends TypeDeclaration {
-
-	private Argument[] args;
-	public int nRecordComponents;
-	public boolean isLocalRecord;
-	public static Set<String> disallowedComponentNames;
-	static {
-		disallowedComponentNames = new HashSet<>(6);
-		disallowedComponentNames.add("clone"); //$NON-NLS-1$
-		disallowedComponentNames.add("finalize"); //$NON-NLS-1$
-		disallowedComponentNames.add("getClass"); //$NON-NLS-1$
-		disallowedComponentNames.add("hashCode"); //$NON-NLS-1$
-		disallowedComponentNames.add("notify");   //$NON-NLS-1$
-		disallowedComponentNames.add("notifyAll");//$NON-NLS-1$
-		disallowedComponentNames.add("toString"); //$NON-NLS-1$
-		disallowedComponentNames.add("wait"); //$NON-NLS-1$
-	}
-	public RecordDeclaration(CompilationResult compilationResult) {
-		super(compilationResult);
-		this.modifiers |= ExtraCompilerModifiers.AccRecord;
-	}
-	public RecordDeclaration(TypeDeclaration t) {
-		super(t.compilationResult);
-		this.modifiers = t.modifiers | ExtraCompilerModifiers.AccRecord;
-		this.modifiersSourceStart = t.modifiersSourceStart;
-		this.annotations = t.annotations;
-		this.name = t.name;
-		this.superInterfaces = t.superInterfaces;
-		this.fields = t.fields;
-		this.methods = t.methods;
-		this.memberTypes = t.memberTypes;
-		this.binding = t.binding;
-		this.scope = t.scope;
-		this.initializerScope = t.initializerScope;
-		this.staticInitializerScope = t.staticInitializerScope;
-		this.ignoreFurtherInvestigation = t.ignoreFurtherInvestigation;
-		this.maxFieldCount = t.maxFieldCount;
-		this.declarationSourceStart = t.declarationSourceStart;
-		this.declarationSourceEnd = t.declarationSourceEnd;
-		this.bodyStart = t.bodyStart;
-		this.bodyEnd = t.bodyEnd;
-		this.missingAbstractMethods = t.missingAbstractMethods; // TODO: Investigate whether this is relevant.
-		this.javadoc = t.javadoc;
-		this.allocation = t.allocation;
-		this.enclosingType = t.enclosingType;
-		this.typeParameters = t.typeParameters;
-		this.sourceStart = t.sourceStart;
-		this.sourceEnd = t.sourceEnd;
-		this.restrictedIdentifierStart = t.restrictedIdentifierStart;
-	}
-	public ConstructorDeclaration getConstructor(Parser parser) {
-		if (this.methods != null) {
-			for (int i = this.methods.length; --i >= 0;) {
-				AbstractMethodDeclaration am;
-				if ((am = this.methods[i]).isConstructor()) {
-					if (!CharOperation.equals(am.selector, this.name)) {
-						// the constructor was in fact a method with no return type
-						// unless an explicit constructor call was supplied
-						ConstructorDeclaration c = (ConstructorDeclaration) am;
-						if (c.constructorCall == null || c.constructorCall.isImplicitSuper()) { //changed to a method
-							MethodDeclaration m = parser.convertToMethodDeclaration(c, this.compilationResult);
-							this.methods[i] = m;
-						}
-					} else {
-						if (am instanceof CompactConstructorDeclaration) {
-							CompactConstructorDeclaration ccd = (CompactConstructorDeclaration) am;
-							ccd.recordDeclaration = this;
-							if (ccd.arguments == null)
-								ccd.arguments = this.args;
-							return ccd;
-						}
-						// now we are looking at a "normal" constructor
-						if (this.args == null && am.arguments == null)
-							return (ConstructorDeclaration) am;
-					}
-				}
-			}
-		}
-		/* At this point we can only say that there is high possibility that there is a constructor
-		 * If it is a CCD, then definitely it is there (except for empty one); else we need to check
-		 * the bindings to say that there is a canonical constructor. To take care at binding resolution time.
-		 */
-		return null;
-	}
-
-	/** Returns an implicit canonical constructor, if any.
-	 */
-	public static ConstructorDeclaration getImplicitCanonicalConstructor(AbstractMethodDeclaration[] methods) {
-		if (methods == null)
-			return null;
-		for (AbstractMethodDeclaration am : methods) {
-			if (am instanceof ConstructorDeclaration && (am.bits & (ASTNode.IsCanonicalConstructor | ASTNode.IsImplicit)) != 0)
-				return (ConstructorDeclaration) am;
-		}
-		return null;
-	}
-	@Override
-	public ConstructorDeclaration createDefaultConstructor(boolean needExplicitConstructorCall, boolean needToInsert) {
-		//Add to method'set, the default constuctor that just recall the
-		//super constructor with no arguments
-		//The arguments' type will be positionned by the TC so just use
-		//the default int instead of just null (consistency purpose)
-
-		ConstructorDeclaration constructor = new ConstructorDeclaration(this.compilationResult);
-		constructor.bits |= ASTNode.IsCanonicalConstructor | ASTNode.IsImplicit;
-		constructor.selector = this.name;
-//		constructor.modifiers = this.modifiers & ExtraCompilerModifiers.AccVisibilityMASK;
-		constructor.modifiers = this.modifiers & ClassFileConstants.AccPublic;
-		constructor.modifiers |= ClassFileConstants.AccPublic; // JLS 14 8.10.5
-		constructor.arguments = this.args;
-
-		constructor.declarationSourceStart = constructor.sourceStart =
-				constructor.bodyStart = this.sourceStart;
-		constructor.declarationSourceEnd =
-			constructor.sourceEnd = constructor.bodyEnd =  this.sourceStart - 1;
-
-		//the super call inside the constructor
-		if (needExplicitConstructorCall) {
-			constructor.constructorCall = SuperReference.implicitSuperConstructorCall();
-			constructor.constructorCall.sourceStart = this.sourceStart;
-			constructor.constructorCall.sourceEnd = this.sourceEnd;
-		}
-	/* The body of the implicitly declared canonical constructor initializes each field corresponding
-		 * to a record component with the corresponding formal parameter in the order that they appear
-		 * in the record component list.*/
-		List<Statement> statements = new ArrayList<>();
-		int l = this.args != null ? this.args.length : 0;
-		if (l > 0 && this.fields != null) {
-			List<String> fNames = Arrays.stream(this.fields)
-					.filter(f -> f.isARecordComponent)
-					.map(f ->new String(f.name))
-					.collect(Collectors.toList());
-			for (int i = 0; i < l; ++i) {
-				Argument arg = this.args[i];
-				if (!fNames.contains(new String(arg.name)))
-					continue;
-				FieldReference lhs = new FieldReference(arg.name, 0);
-				lhs.receiver = ThisReference.implicitThis();
-				statements.add(new Assignment(lhs, new SingleNameReference(arg.name, 0), 0));
-			}
-		}
-		constructor.statements = statements.toArray(new Statement[0]);
-
-		//adding the constructor in the methods list: rank is not critical since bindings will be sorted
-		if (needToInsert) {
-			if (this.methods == null) {
-				this.methods = new AbstractMethodDeclaration[] { constructor };
-			} else {
-				AbstractMethodDeclaration[] newMethods;
-				System.arraycopy(
-					this.methods,
-					0,
-					newMethods = new AbstractMethodDeclaration[this.methods.length + 1],
-					1,
-					this.methods.length);
-				newMethods[0] = constructor;
-				this.methods = newMethods;
-			}
-		}
-		return constructor;
-	}
-
-	@Override
-	public void generateCode(ClassFile enclosingClassFile) {
-		super.generateCode(enclosingClassFile);
-	}
-	@Override
-	public boolean isRecord() {
-		return true;
-	}
-	@Override
-	public StringBuffer printHeader(int indent, StringBuffer output) {
-		printModifiers(this.modifiers, output);
-		if (this.annotations != null) {
-			printAnnotations(this.annotations, output);
-			output.append(' ');
-		}
-
-		output.append("record "); //$NON-NLS-1$
-		output.append(this.name);
-		output.append('(');
-		if (this.nRecordComponents > 0 && this.fields != null) {
-			for (int i = 0; i < this.nRecordComponents; i++) {
-				if (i > 0) output.append(", "); //$NON-NLS-1$
-				output.append(this.fields[i].type.getTypeName()[0]);
-				output.append(' ');
-				output.append(this.fields[i].name);
-			}
-		}
-		output.append(')');
-		if (this.typeParameters != null) {
-			output.append("<");//$NON-NLS-1$
-			for (int i = 0; i < this.typeParameters.length; i++) {
-				if (i > 0) output.append( ", "); //$NON-NLS-1$
-				this.typeParameters[i].print(0, output);
-			}
-			output.append(">");//$NON-NLS-1$
-		}
-		if (this.superInterfaces != null && this.superInterfaces.length > 0) {
-			output.append(" implements "); //$NON-NLS-1$
-			for (int i = 0; i < this.superInterfaces.length; i++) {
-				if (i > 0) output.append( ", "); //$NON-NLS-1$
-				this.superInterfaces[i].print(0, output);
-			}
-		}
-		return output;
-	}
-	@Override
-	public StringBuffer printBody(int indent, StringBuffer output) {
-		output.append(" {"); //$NON-NLS-1$
-		if (this.memberTypes != null) {
-			for (int i = 0; i < this.memberTypes.length; i++) {
-				if (this.memberTypes[i] != null) {
-					output.append('\n');
-					this.memberTypes[i].print(indent + 1, output);
-				}
-			}
-		}
-		if (this.fields != null) {
-			for (int fieldI = 0; fieldI < this.fields.length; fieldI++) {
-				if (this.fields[fieldI] != null) {
-					output.append('\n');
-					if (fieldI < this.nRecordComponents)
-						output.append("/* Implicit */"); //$NON-NLS-1$ //TODO BETA_JAVA14: Move this to FD?
-					this.fields[fieldI].print(indent + 1, output);
-				}
-			}
-		}
-		if (this.methods != null) {
-			for (int i = 0; i < this.methods.length; i++) {
-				if (this.methods[i] != null) {
-					output.append('\n');
-					AbstractMethodDeclaration amd = this.methods[i];
-					if (amd instanceof MethodDeclaration && (amd.bits & ASTNode.IsImplicit) != 0)
-						output.append("/* Implicit */\n"); //$NON-NLS-1$// TODO BETA_JAVA14: Move this to MD?
-					amd.print(indent + 1, output);
-				}
-			}
-		}
-		output.append('\n');
-		return printIndent(indent, output).append('}');
-	}
-	public Argument[] getArgs() {
-		return this.args;
-	}
-	public void setArgs(Argument[] args) {
-		this.args = args;
-	}
-	public static void checkAndFlagRecordNameErrors(char[] typeName, ASTNode node, Scope skope) {
-		if (CharOperation.equals(typeName, TypeConstants.RECORD_RESTRICTED_IDENTIFIER)) {
-			if (skope.compilerOptions().sourceLevel == ClassFileConstants.JDK14) {
-					skope.problemReporter().recordIsAReservedTypeName(node);
-			}
-		}
-	}
-	AbstractMethodDeclaration[] getMethod(char[] name1) {
-		if (name1 == null || name1.length == 0 || this.methods == null)
-			return null;
-		List<AbstractMethodDeclaration> amList = new ArrayList<>(0);
-		for (AbstractMethodDeclaration amd : this.methods) {
-			if (CharOperation.equals(name1, amd.selector))
-				amList.add(amd);
-		}
-		return amList.toArray(new AbstractMethodDeclaration[0]);
-	}
-}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchExpression.java
index bb16830..42b6e63 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/SwitchExpression.java
@@ -542,6 +542,7 @@
 			 */
 			if (typeBbolean) {
 				for (int i = 0; i < resultExpressionsCount; ++i) {
+					if (this.originalValueResultExpressionTypes[i] == null) continue;
 					if (this.originalValueResultExpressionTypes[i].id == T_boolean) continue;
 					this.finalValueResultExpressionTypes[i] = env.computeBoxingType(this.originalValueResultExpressionTypes[i]);
 					this.resultExpressions.get(i).computeConversion(this.scope, this.finalValueResultExpressionTypes[i], this.originalValueResultExpressionTypes[i]);
@@ -604,7 +605,7 @@
 				resultNumeric = resultNumeric != null ? resultNumeric : check_nonconstant_int();
 
 				resultNumeric = resultNumeric != null ? resultNumeric : // one among the first few rules applied.
-					getResultNumeric(typeSet, this.originalValueResultExpressionTypes); // check the rest
+					getResultNumeric(typeSet); // check the rest
 				typeSet = null; // hey gc!
 				for (int i = 0; i < resultExpressionsCount; ++i) {
 					this.resultExpressions.get(i).computeConversion(this.scope,
@@ -701,7 +702,7 @@
 		return areAllIntegerResultExpressionsConvertibleToTargetType(candidate) ?
 				candidate : null;
 	}
-	private TypeBinding getResultNumeric(Set<TypeBinding> typeSet, TypeBinding[] armTypes) {
+	private TypeBinding getResultNumeric(Set<TypeBinding> typeSet) {
 		// note: if an expression has a type integer, then it will be a constant
 		// since non-constant integers are already processed before reaching here.
 
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
index e17e07c..84d5c75 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java
@@ -24,6 +24,13 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.ast;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
 import org.eclipse.jdt.core.compiler.*;
 import org.eclipse.jdt.internal.compiler.*;
 import org.eclipse.jdt.internal.compiler.impl.*;
@@ -81,6 +88,23 @@
 	// 1.5 support
 	public TypeParameter[] typeParameters;
 
+	// 14 Records preview support
+	public Argument[] args;
+	public int nRecordComponents;
+	public boolean isLocalRecord;
+	public static Set<String> disallowedComponentNames;
+	static {
+		disallowedComponentNames = new HashSet<>(6);
+		disallowedComponentNames.add("clone"); //$NON-NLS-1$
+		disallowedComponentNames.add("finalize"); //$NON-NLS-1$
+		disallowedComponentNames.add("getClass"); //$NON-NLS-1$
+		disallowedComponentNames.add("hashCode"); //$NON-NLS-1$
+		disallowedComponentNames.add("notify");   //$NON-NLS-1$
+		disallowedComponentNames.add("notifyAll");//$NON-NLS-1$
+		disallowedComponentNames.add("toString"); //$NON-NLS-1$
+		disallowedComponentNames.add("wait"); //$NON-NLS-1$
+	}
+
 public TypeDeclaration(CompilationResult compilationResult){
 	this.compilationResult = compilationResult;
 }
@@ -280,6 +304,14 @@
 	}
 }
 
+public static void checkAndFlagRecordNameErrors(char[] typeName, ASTNode node, Scope skope) {
+	if (CharOperation.equals(typeName, TypeConstants.RECORD_RESTRICTED_IDENTIFIER)) {
+		if (skope.compilerOptions().sourceLevel == ClassFileConstants.JDK14) {
+				skope.problemReporter().recordIsAReservedTypeName(node);
+		}
+	}
+}
+
 /**
  * Check for constructor vs. method with no return type.
  * Answers true if at least one constructor is defined
@@ -325,7 +357,76 @@
 	return this.compilationResult;
 }
 
+
+public ConstructorDeclaration createDefaultConstructorForRecord(boolean needExplicitConstructorCall, boolean needToInsert) {
+	//Add to method'set, the default constuctor that just recall the
+	//super constructor with no arguments
+	//The arguments' type will be positionned by the TC so just use
+	//the default int instead of just null (consistency purpose)
+
+	ConstructorDeclaration constructor = new ConstructorDeclaration(this.compilationResult);
+	constructor.bits |= ASTNode.IsCanonicalConstructor | ASTNode.IsImplicit;
+	constructor.selector = this.name;
+//	constructor.modifiers = this.modifiers & ExtraCompilerModifiers.AccVisibilityMASK;
+	constructor.modifiers = this.modifiers & ClassFileConstants.AccPublic;
+	constructor.modifiers |= ClassFileConstants.AccPublic; // JLS 14 8.10.5
+	constructor.arguments = this.args;
+
+	constructor.declarationSourceStart = constructor.sourceStart =
+			constructor.bodyStart = this.sourceStart;
+	constructor.declarationSourceEnd =
+		constructor.sourceEnd = constructor.bodyEnd =  this.sourceStart - 1;
+
+	//the super call inside the constructor
+	if (needExplicitConstructorCall) {
+		constructor.constructorCall = SuperReference.implicitSuperConstructorCall();
+		constructor.constructorCall.sourceStart = this.sourceStart;
+		constructor.constructorCall.sourceEnd = this.sourceEnd;
+	}
+/* The body of the implicitly declared canonical constructor initializes each field corresponding
+	 * to a record component with the corresponding formal parameter in the order that they appear
+	 * in the record component list.*/
+	List<Statement> statements = new ArrayList<>();
+	int l = this.args != null ? this.args.length : 0;
+	if (l > 0 && this.fields != null) {
+		List<String> fNames = Arrays.stream(this.fields)
+				.filter(f -> f.isARecordComponent)
+				.map(f ->new String(f.name))
+				.collect(Collectors.toList());
+		for (int i = 0; i < l; ++i) {
+			Argument arg = this.args[i];
+			if (!fNames.contains(new String(arg.name)))
+				continue;
+			FieldReference lhs = new FieldReference(arg.name, 0);
+			lhs.receiver = ThisReference.implicitThis();
+			statements.add(new Assignment(lhs, new SingleNameReference(arg.name, 0), 0));
+		}
+	}
+	constructor.statements = statements.toArray(new Statement[0]);
+
+	//adding the constructor in the methods list: rank is not critical since bindings will be sorted
+	if (needToInsert) {
+		if (this.methods == null) {
+			this.methods = new AbstractMethodDeclaration[] { constructor };
+		} else {
+			AbstractMethodDeclaration[] newMethods;
+			System.arraycopy(
+				this.methods,
+				0,
+				newMethods = new AbstractMethodDeclaration[this.methods.length + 1],
+				1,
+				this.methods.length);
+			newMethods[0] = constructor;
+			this.methods = newMethods;
+		}
+	}
+	return constructor;
+}
+
+
 public ConstructorDeclaration createDefaultConstructor(	boolean needExplicitConstructorCall, boolean needToInsert) {
+	if (this.isRecord())
+		return createDefaultConstructorForRecord(needExplicitConstructorCall, needToInsert);
 	//Add to method'set, the default constuctor that just recall the
 	//super constructor with no arguments
 	//The arguments' type will be positionned by the TC so just use
@@ -400,10 +501,10 @@
 	constructor.constructorCall.sourceEnd = this.sourceEnd;
 
 	if (argumentsLength > 0) {
-		Expression[] args;
-		args = constructor.constructorCall.arguments = new Expression[argumentsLength];
+		Expression[] args1;
+		args1 = constructor.constructorCall.arguments = new Expression[argumentsLength];
 		for (int i = argumentsLength; --i >= 0;) {
-			args[i] = new SingleNameReference((baseName + i).toCharArray(), 0L);
+			args1[i] = new SingleNameReference((baseName + i).toCharArray(), 0L);
 		}
 	}
 
@@ -534,6 +635,42 @@
 	return null;
 }
 
+/* only for records */
+public ConstructorDeclaration getConstructor(Parser parser) {
+	if (this.methods != null) {
+		for (int i = this.methods.length; --i >= 0;) {
+			AbstractMethodDeclaration am;
+			if ((am = this.methods[i]).isConstructor()) {
+				if (!CharOperation.equals(am.selector, this.name)) {
+					// the constructor was in fact a method with no return type
+					// unless an explicit constructor call was supplied
+					ConstructorDeclaration c = (ConstructorDeclaration) am;
+					if (c.constructorCall == null || c.constructorCall.isImplicitSuper()) { //changed to a method
+						MethodDeclaration m = parser.convertToMethodDeclaration(c, this.compilationResult);
+						this.methods[i] = m;
+					}
+				} else {
+					if (am instanceof CompactConstructorDeclaration) {
+						CompactConstructorDeclaration ccd = (CompactConstructorDeclaration) am;
+						ccd.recordDeclaration = this;
+						if (ccd.arguments == null)
+							ccd.arguments = this.args;
+						return ccd;
+					}
+					// now we are looking at a "normal" constructor
+					if (this.args == null && am.arguments == null)
+						return (ConstructorDeclaration) am;
+				}
+			}
+		}
+	}
+	/* At this point we can only say that there is high possibility that there is a constructor
+	 * If it is a CCD, then definitely it is there (except for empty one); else we need to check
+	 * the bindings to say that there is a canonical constructor. To take care at binding resolution time.
+	 */
+	return null;
+}
+
 /**
  * Generic bytecode generation for type
  */
@@ -856,7 +993,7 @@
 }
 
 public boolean isRecord() {
-	return false;
+	return (this.modifiers & ExtraCompilerModifiers.AccRecord) != 0;
 }
 
 /*
@@ -1059,6 +1196,18 @@
 			break;
 	}
 	output.append(this.name);
+	if (this.isRecord()) {
+		output.append('(');
+		if (this.nRecordComponents > 0 && this.fields != null) {
+			for (int i = 0; i < this.nRecordComponents; i++) {
+				if (i > 0) output.append(", "); //$NON-NLS-1$
+				output.append(this.fields[i].type.getTypeName()[0]);
+				output.append(' ');
+				output.append(this.fields[i].name);
+			}
+		}
+		output.append(')');
+	}
 	if (this.typeParameters != null) {
 		output.append("<");//$NON-NLS-1$
 		for (int i = 0; i < this.typeParameters.length; i++) {
@@ -1067,7 +1216,8 @@
 		}
 		output.append(">");//$NON-NLS-1$
 	}
-	if (this.superclass != null) {
+
+	if (!this.isRecord() && this.superclass != null) {
 		output.append(" extends ");  //$NON-NLS-1$
 		this.superclass.print(0, output);
 	}
@@ -1118,7 +1268,7 @@
 				this.scope.problemReporter().varIsReservedTypeName(this);
 			}
 		}
-		RecordDeclaration.checkAndFlagRecordNameErrors(this.name, this, this.scope);
+		TypeDeclaration.checkAndFlagRecordNameErrors(this.name, this, this.scope);
 		// resolve annotations and check @Deprecated annotation
 		long annotationTagBits = sourceType.getAnnotationTagBits();
 		if ((annotationTagBits & TagBits.AnnotationDeprecated) == 0
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeParameter.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeParameter.java
index 185dda1..d15b4c0 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeParameter.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeParameter.java
@@ -120,7 +120,7 @@
 				scope.problemReporter().varIsNotAllowedHere(this);
 			}
 		}
-		RecordDeclaration.checkAndFlagRecordNameErrors(this.name, this, scope);
+		TypeDeclaration.checkAndFlagRecordNameErrors(this.name, this, scope);
 	}
 
 	@Override
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
index db75e3a..96e2bf0 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeReference.java
@@ -387,7 +387,7 @@
 	final int totalDimensions = dimensions + additionalDimensions;
 	Annotation [][] mergedAnnotations = new Annotation[totalDimensions][];
 	if (annotationsOnDimensions != null) {
-		System.arraycopy(annotationsOnDimensions, 0, mergedAnnotations, 0, dimensions); 
+		System.arraycopy(annotationsOnDimensions, 0, mergedAnnotations, 0, dimensions);
 	}
 	if (additionalAnnotations != null) {
 		for (int i = dimensions, j = 0; i < totalDimensions; i++, j++) {
@@ -532,7 +532,7 @@
 		} else {
 			reportInvalidType(scope);
 		}
-		RecordDeclaration.checkAndFlagRecordNameErrors(getTypeName(0), this, scope);
+		TypeDeclaration.checkAndFlagRecordNameErrors(getTypeName(0), this, scope);
 		switch (type.problemId()) {
 			case ProblemReasons.NotFound :
 			case ProblemReasons.NotVisible :
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java
index 2c9904b..c43e55c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java
@@ -316,6 +316,10 @@
 		}
 		return this.resolvedType;
 	}
+	@Override
+	public boolean containsPatternVariable() {
+		return this.expression.containsPatternVariable();
+	}
 
 	@Override
 	public void traverse(
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java
index a26218b..393398a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java
@@ -1471,8 +1471,8 @@
 		case Opcodes.OPC_getfield :
 			if (returnTypeSize == 2) {
 				this.stackDepth++;
-				pushTypeBinding(1, typeBinding);
 			}
+			pushTypeBinding(1, typeBinding);
 			break;
 		case Opcodes.OPC_getstatic :
 			if (returnTypeSize == 2) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
index 2c2bc23..bcb5ad2 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
@@ -1815,8 +1815,7 @@
 
 	// treating extra storage
 	if (this.extra != null || otherInits.extra != null) {
-		// four areas, but not all combinations are possible: only one of copyLimit/resetLimit will be > 0, takeLimit is exclusive to all others
-		int takeLimit = 0;  // [..takeLimit]			: this is unreachable, take null info from other as-is
+		// three areas, but not all combinations are possible: only one of copyLimit/resetLimit will be > 0
 		int mergeLimit = 0; // [0..mergeLimit]			: both flows have extra bits. Merge'em
 		int copyLimit = 0;  // (mergeLimit..copyLimit] 	: only other has extra bits. Copy'em, sheding some doubt
 		int resetLimit = 0; // (copyLimit..resetLimit]  : only this has extra bits. Shed doubt on them.
@@ -1899,87 +1898,95 @@
 			copyLimit = 0; // no need to carry inexisting nulls
 			mergeLimit = 0;
 		}
+		i = 0;
 		if (thisWasUnreachable) {
-			// completely ignore unreachable info (don't shed any doubts on other)
-			takeLimit = Math.max(resetLimit, mergeLimit);
-			mergeLimit = 0;
-			resetLimit = 0;
-		}
-		// compose nulls
-		for (i = 0; i < takeLimit; i++) {
-    		this.extra[1 + 1][i] = otherInits.extra[1+1][i];
-    		this.extra[2 + 1][i] = otherInits.extra[2+1][i];
-    		this.extra[3 + 1][i] = otherInits.extra[3+1][i];
-    		this.extra[4 + 1][i] = otherInits.extra[4+1][i];
-		}
-		for (; i < mergeLimit; i++) {
-    		this.extra[1 + 1][i] = (a1=this.extra[1+1][i]) & (b1=otherInits.extra[1+1][i]) & (
-    				((a2=this.extra[2+1][i]) & (((b2=otherInits.extra[2+1][i]) &
-    												~(((a3=this.extra[3+1][i]) & (a4=this.extra[4+1][i])) ^ ((b3=otherInits.extra[3+1][i]) & (b4=otherInits.extra[4+1][i]))))
-    											|(a3 & a4 & (nb2=~b2))))
-    				|((na2=~a2) & ((b2 & b3 & b4)
-    						|(nb2 & ((na3=~a3) ^ b3)))));
-    		this.extra[2 + 1][i] = b2 & ((nb3=~b3) | (nb1 = ~b1) | a3 & (a4 | (na1 = ~a1)) & (nb4=~b4))
-        			| a2 & (b2 | (na4=~a4) & b3 & (b4 | nb1) | na3 | na1);
-    		this.extra[3 + 1][i] =   a3 & (na1 | a1 & na2 | b3 & (na4 ^ b4))
-								   | b3 & (nb1 | b1 & nb2);
-    		this.extra[4 + 1][i] = na3 & (nb1 & nb3 & b4
-              			| b1 & (nb2 & nb3 | a4 & b2 & nb4)
-              			| na1 & a4 & (nb3 | b1 & b2))
-        			| a3 & a4 & (b3 & b4 | b1 & nb2 | na1 & a2)
-        			| na2 & (nb1 & b4 | b1 & nb3 | na1 & a4) & nb2
-        			| a1 & (na3 & (nb3 & b4
-                        			| b1 & b2 & b3 & nb4
-                        			| na2 & (nb3 | nb2))
-                			| na2 & b3 & b4
-                			| a2 & (nb1 & b4 | a3 & na4 & b1) & nb3)
-                	|nb1 & b2 & b3 & b4;
-    		this.extra[IN][i] |= otherInits.extra[IN][i];
-    		this.extra[INN][i] |= otherInits.extra[INN][i];
-			thisHasNulls = thisHasNulls ||
-				this.extra[3][i] != 0 ||
-				this.extra[4][i] != 0 ||
-				this.extra[5][i] != 0 ;
-			if (COVERAGE_TEST_FLAG) {
-				if(CoverageTestId == 37) {
-					this.extra[5][i] = ~0;
+			if (otherInits.extra != null) {
+				// take null info only from other, as much as available and without shedding doubt:
+				for (; i < mergeLimit; i++) {
+					this.extra[1 + 1][i] = otherInits.extra[1+1][i];
+					this.extra[2 + 1][i] = otherInits.extra[2+1][i];
+					this.extra[3 + 1][i] = otherInits.extra[3+1][i];
+					this.extra[4 + 1][i] = otherInits.extra[4+1][i];
 				}
 			}
-		}
-		for (; i < copyLimit; i++) {
-    		this.extra[1 + 1][i] = 0;
-    		this.extra[2 + 1][i] = (b2 = otherInits.extra[2 + 1][i]) & (nb3 = ~(b3 = otherInits.extra[3 + 1][i]) | (nb1 = ~(b1 = otherInits.extra[1 + 1][i])));
-    		this.extra[3 + 1][i] = b3 & ((nb2 = ~b2) & (b4 = otherInits.extra[4 + 1][i]) | nb1) | b1 & nb2 & ~b4;
-    		this.extra[4 + 1][i] = (nb3 | nb2) & nb1 & b4	| b1 & nb3 & nb2;
-    		this.extra[IN][i] |= otherInits.extra[IN][i];
-    		this.extra[INN][i] |= otherInits.extra[INN][i];
-			thisHasNulls = thisHasNulls ||
-				this.extra[3][i] != 0 ||
-				this.extra[4][i] != 0 ||
-				this.extra[5][i] != 0;
-			if (COVERAGE_TEST_FLAG) {
-				if(CoverageTestId == 38) {
-					this.extra[5][i] = ~0;
-				}
+			// clear the remaining length of this.extra
+			for (; i < resetLimit; i++) {
+				this.extra[1 + 1][i] = 0;
+				this.extra[2 + 1][i] = 0;
+				this.extra[3 + 1][i] = 0;
+				this.extra[4 + 1][i] = 0;
 			}
-		}
-		for (; i < resetLimit; i++) {
-    		a1 = this.extra[1 + 1][i];
-      		this.extra[1 + 1][i] = 0;
-      		this.extra[2 + 1][i] = (a2 = this.extra[2 + 1][i]) & (na3 = ~(a3 = this.extra[3 + 1][i]) | (na1 = ~a1));
-      		this.extra[3 + 1][i] = a3 & ((na2 = ~a2) & (a4 = this.extra[4 + 1][i]) | na1) | a1 & na2 & ~a4;
-      		this.extra[4 + 1][i] = (na3 | na2) & na1 & a4	| a1 & na3 & na2;
-      		if (otherInits.extra != null && otherInits.extra[0].length > i) {
+		} else {
+			// compose nulls
+			for (; i < mergeLimit; i++) {
+	    		this.extra[1 + 1][i] = (a1=this.extra[1+1][i]) & (b1=otherInits.extra[1+1][i]) & (
+	    				((a2=this.extra[2+1][i]) & (((b2=otherInits.extra[2+1][i]) &
+	    												~(((a3=this.extra[3+1][i]) & (a4=this.extra[4+1][i])) ^ ((b3=otherInits.extra[3+1][i]) & (b4=otherInits.extra[4+1][i]))))
+	    											|(a3 & a4 & (nb2=~b2))))
+	    				|((na2=~a2) & ((b2 & b3 & b4)
+	    						|(nb2 & ((na3=~a3) ^ b3)))));
+	    		this.extra[2 + 1][i] = b2 & ((nb3=~b3) | (nb1 = ~b1) | a3 & (a4 | (na1 = ~a1)) & (nb4=~b4))
+	        			| a2 & (b2 | (na4=~a4) & b3 & (b4 | nb1) | na3 | na1);
+	    		this.extra[3 + 1][i] =   a3 & (na1 | a1 & na2 | b3 & (na4 ^ b4))
+									   | b3 & (nb1 | b1 & nb2);
+	    		this.extra[4 + 1][i] = na3 & (nb1 & nb3 & b4
+	              			| b1 & (nb2 & nb3 | a4 & b2 & nb4)
+	              			| na1 & a4 & (nb3 | b1 & b2))
+	        			| a3 & a4 & (b3 & b4 | b1 & nb2 | na1 & a2)
+	        			| na2 & (nb1 & b4 | b1 & nb3 | na1 & a4) & nb2
+	        			| a1 & (na3 & (nb3 & b4
+	                        			| b1 & b2 & b3 & nb4
+	                        			| na2 & (nb3 | nb2))
+	                			| na2 & b3 & b4
+	                			| a2 & (nb1 & b4 | a3 & na4 & b1) & nb3)
+	                	|nb1 & b2 & b3 & b4;
 	    		this.extra[IN][i] |= otherInits.extra[IN][i];
 	    		this.extra[INN][i] |= otherInits.extra[INN][i];
-      		}
-			thisHasNulls = thisHasNulls ||
-				this.extra[3][i] != 0 ||
-				this.extra[4][i] != 0 ||
-				this.extra[5][i] != 0;
-			if (COVERAGE_TEST_FLAG) {
-				if(CoverageTestId == 39) {
-					this.extra[5][i] = ~0;
+				thisHasNulls = thisHasNulls ||
+					this.extra[3][i] != 0 ||
+					this.extra[4][i] != 0 ||
+					this.extra[5][i] != 0 ;
+				if (COVERAGE_TEST_FLAG) {
+					if(CoverageTestId == 37) {
+						this.extra[5][i] = ~0;
+					}
+				}
+			}
+			for (; i < copyLimit; i++) {
+	    		this.extra[1 + 1][i] = 0;
+	    		this.extra[2 + 1][i] = (b2 = otherInits.extra[2 + 1][i]) & (nb3 = ~(b3 = otherInits.extra[3 + 1][i]) | (nb1 = ~(b1 = otherInits.extra[1 + 1][i])));
+	    		this.extra[3 + 1][i] = b3 & ((nb2 = ~b2) & (b4 = otherInits.extra[4 + 1][i]) | nb1) | b1 & nb2 & ~b4;
+	    		this.extra[4 + 1][i] = (nb3 | nb2) & nb1 & b4	| b1 & nb3 & nb2;
+	    		this.extra[IN][i] |= otherInits.extra[IN][i];
+	    		this.extra[INN][i] |= otherInits.extra[INN][i];
+				thisHasNulls = thisHasNulls ||
+					this.extra[3][i] != 0 ||
+					this.extra[4][i] != 0 ||
+					this.extra[5][i] != 0;
+				if (COVERAGE_TEST_FLAG) {
+					if(CoverageTestId == 38) {
+						this.extra[5][i] = ~0;
+					}
+				}
+			}
+			for (; i < resetLimit; i++) {
+	    		a1 = this.extra[1 + 1][i];
+	      		this.extra[1 + 1][i] = 0;
+	      		this.extra[2 + 1][i] = (a2 = this.extra[2 + 1][i]) & (na3 = ~(a3 = this.extra[3 + 1][i]) | (na1 = ~a1));
+	      		this.extra[3 + 1][i] = a3 & ((na2 = ~a2) & (a4 = this.extra[4 + 1][i]) | na1) | a1 & na2 & ~a4;
+	      		this.extra[4 + 1][i] = (na3 | na2) & na1 & a4	| a1 & na3 & na2;
+	      		if (otherInits.extra != null && otherInits.extra[0].length > i) {
+		    		this.extra[IN][i] |= otherInits.extra[IN][i];
+		    		this.extra[INN][i] |= otherInits.extra[INN][i];
+	      		}
+				thisHasNulls = thisHasNulls ||
+					this.extra[3][i] != 0 ||
+					this.extra[4][i] != 0 ||
+					this.extra[5][i] != 0;
+				if (COVERAGE_TEST_FLAG) {
+					if(CoverageTestId == 39) {
+						this.extra[5][i] = ~0;
+					}
 				}
 			}
 		}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
index 591075f..1d47311 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/ClassScope.java
@@ -42,7 +42,7 @@
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression;import org.eclipse.jdt.internal.compiler.ast.RecordDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.QualifiedAllocationExpression;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
 import org.eclipse.jdt.internal.compiler.ast.TypeReference;
@@ -105,7 +105,7 @@
 					anonymousType.tagBits |= TagBits.HierarchyHasProblems;
 					anonymousType.setSuperClass(getJavaLangObject());
 				} else if (supertype.erasure().id == TypeIds.T_JavaLangRecord) {
-					if (!(this.referenceContext instanceof RecordDeclaration)) {
+					if (!(this.referenceContext.isRecord())) {
 						problemReporter().recordCannotExtendRecord(anonymousType, typeReference, supertype);
 						anonymousType.tagBits |= TagBits.HierarchyHasProblems;
 						anonymousType.setSuperClass(getJavaLangObject());
@@ -381,7 +381,7 @@
 				problemReporter().abstractMethodInConcreteClass(sourceType);
 		}
 		if (sourceType.isRecord()) {
-			assert this.referenceContext instanceof RecordDeclaration;
+			assert this.referenceContext.isRecord();
 			methodBindings = sourceType.checkAndAddSyntheticRecordMethods(methodBindings, count);
 			count = methodBindings.length;
 		}
@@ -500,6 +500,11 @@
 				problemReporter().illegalLocalTypeDeclaration(this.referenceContext);
 				sourceType.modifiers = 0;
 				return;
+			} else if (sourceType.isRecord()) {
+				if (enclosingType != null && enclosingType.isLocalType()) {
+					problemReporter().illegalLocalTypeDeclaration(this.referenceContext);
+					return;
+				}
 			}
 			if (sourceType.isAnonymousType()) {
 				if (compilerOptions().complianceLevel < ClassFileConstants.JDK9)
@@ -1016,7 +1021,7 @@
 			} else if (superclass.erasure().id == TypeIds.T_JavaLangEnum) {
 				problemReporter().cannotExtendEnum(sourceType, superclassRef, superclass);
 			} else if (superclass.erasure().id == TypeIds.T_JavaLangRecord) {
-				if (!(this.referenceContext instanceof RecordDeclaration)) {
+				if (!(this.referenceContext.isRecord())) {
 					problemReporter().recordCannotExtendRecord(sourceType, superclassRef, superclass);
 				} else {
 					return connectRecordSuperclass();
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
index ff75ef8..564f75d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/LookupEnvironment.java
@@ -467,7 +467,9 @@
 		scope = new CompilationUnitScope(unit, this.globalOptions);
 		unitModule = unit.moduleDeclaration.setBinding(new SourceModuleBinding(moduleName, scope, this.root));
 	} else {
-		unitModule = unit.module(this);
+		if (this.globalOptions.sourceLevel >= ClassFileConstants.JDK9) {
+			unitModule = unit.module(this);
+		}
 		scope = new CompilationUnitScope(unit, unitModule != null ? unitModule.environment : this);
 	}
 	scope.buildTypeBindings(accessRestriction);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
index 490ee18..4eb5754 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
@@ -76,7 +76,6 @@
 import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.LambdaExpression;
 import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
-import org.eclipse.jdt.internal.compiler.ast.RecordDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.ReferenceExpression;
 import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
 import org.eclipse.jdt.internal.compiler.ast.SwitchStatement;
@@ -147,7 +146,7 @@
 	this.fields = Binding.UNINITIALIZED_FIELDS;
 	this.methods = Binding.UNINITIALIZED_METHODS;
 	this.prototype = this;
-	this.isRecordDeclaration = scope.referenceContext instanceof RecordDeclaration;
+	this.isRecordDeclaration = scope.referenceContext.isRecord();
 	computeId();
 }
 
@@ -923,7 +922,24 @@
 
 	SyntheticMethodBinding accessMethod = null;
 	SyntheticMethodBinding[] accessors = (SyntheticMethodBinding[]) this.synthetics[SourceTypeBinding.METHOD_EMUL].get(selector);
-	accessMethod = new SyntheticMethodBinding(this, getField(selector, true), index);
+	FieldBinding field = getField(selector, true);
+	accessMethod = new SyntheticMethodBinding(this, field, index);
+	AnnotationBinding[] annotations = field.getAnnotations();
+	if (annotations.length > 0) {
+		List<AnnotationBinding> list = new ArrayList<>();
+		for (AnnotationBinding binding : annotations) {
+			long bits = binding.getAnnotationType().getAnnotationTagBits();
+			if ((bits & TagBits.AnnotationForMethod) != 0
+					|| (bits & TagBits.AnnotationTargetMASK) == 0) {
+				list.add(binding);
+			}
+		}
+		if (list.size() > 0) {
+			AnnotationBinding[] annots = new AnnotationBinding[list.size()];
+			annotations = list.toArray(annots);
+			accessMethod.setAnnotations(annotations, true);
+		}
+	}
 	if (accessors == null) {
 		this.synthetics[SourceTypeBinding.METHOD_EMUL].put(selector, accessors = new SyntheticMethodBinding[2]);
 		accessors[0] = accessMethod;
@@ -2990,7 +3006,7 @@
 public void computeRecordComponents() {
 	if (!this.isRecordDeclaration || this.recordComponents != null)
 		return;
-	Argument[] recComps = ((RecordDeclaration) this.scope.referenceContext).getArgs();
+	Argument[] recComps = this.scope.referenceContext.args;
 	List<FieldBinding> list = new ArrayList<>();
 	if (recComps != null && recComps.length > 0 && this.fields != null) {
 		List<String> recordComponentNames = new ArrayList<>(0);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java
index 4e6df4f..bd24898 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java
@@ -446,6 +446,9 @@
 		assert declaringSourceType.isRecord();
 		this.declaringClass = declaringSourceType;
 		this.modifiers = ClassFileConstants.AccPublic;
+		if (targetField.type instanceof TypeVariableBinding ||
+				targetField.type instanceof ParameterizedTypeBinding)
+			this.modifiers |= ExtraCompilerModifiers.AccGenericSignature;
 		if (this.declaringClass.isStrictfp())
 			this.modifiers |= ClassFileConstants.AccStrictfp;
 		this.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved);
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java
index 1429127..68563bc 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/TagBits.java
@@ -128,8 +128,6 @@
 	long SE7AnnotationTargetMASK = AnnotationForType | AnnotationForField | AnnotationForMethod
 				| AnnotationForParameter | AnnotationForConstructor | AnnotationForLocalVariable
 				| AnnotationForAnnotationType | AnnotationForPackage;
-	long AnnotationTargetMASK = SE7AnnotationTargetMASK | AnnotationTarget
-				| AnnotationForTypeUse | AnnotationForTypeParameter | AnnotationForModule;
 	// 2-bits for retention (should check (tagBits & RetentionMask) == RuntimeRetention
 	long AnnotationSourceRetention = ASTNode.Bit45L;
 	long AnnotationClassRetention = ASTNode.Bit46L;
@@ -165,6 +163,9 @@
 	/** From Java 14 */
 	long AnnotationForRecordComponent = ASTNode.Bit31;
 
+	long AnnotationTargetMASK = SE7AnnotationTargetMASK | AnnotationTarget
+			| AnnotationForTypeUse | AnnotationForTypeParameter | AnnotationForModule | AnnotationForRecordComponent;
+
 	long AllStandardAnnotationsMask =
 				  AnnotationTargetMASK
 				| AnnotationRetentionMASK
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
index a00a7eb..653e39d 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java
@@ -973,7 +973,7 @@
 private boolean expectTypeAnnotation = false;
 private boolean reparsingLambdaExpression = false;
 
-private Map<RecordDeclaration, Integer[]> recordNestedMethodLevels;
+private Map<TypeDeclaration, Integer[]> recordNestedMethodLevels;
 
 public Parser () {
 	// Caveat Emptor: For inheritance purposes and then only in very special needs. Only minimal state is initialized !
@@ -2706,7 +2706,7 @@
 	}
 	typeDecl.bodyStart = typeDecl.sourceEnd + 1;
 	if (isRecord) {
-		typeDecl = new RecordDeclaration(typeDecl);
+		typeDecl.modifiers |= ExtraCompilerModifiers.AccRecord;
 	}
 	pushOnAstStack(typeDecl);
 
@@ -3556,8 +3556,10 @@
 	int recordIndex = -1;
 	Integer[] nestingTypeAndMethod = null;
 	for (int i = this.astPtr; i >= 0; --i) {
-		if (this.astStack[i] instanceof RecordDeclaration) {
-			RecordDeclaration node = (RecordDeclaration) this.astStack[i];
+		if (this.astStack[i] instanceof TypeDeclaration) {
+			TypeDeclaration node = (TypeDeclaration) this.astStack[i];
+			if (!node.isRecord())
+				continue;
 			nestingTypeAndMethod = this.recordNestedMethodLevels.get(node);
 			if (nestingTypeAndMethod != null) { // record declaration is done yet
 				recordIndex = i;
@@ -6603,6 +6605,7 @@
 	// TypeAnnotationsopt ::= $empty
 	pushOnTypeAnnotationLengthStack(0); // signal absence of @308 annotations.
 }
+// BEGIN_AUTOGENERATED_REGION_CONSUME_RULE
 // This method is part of an automatic generation : do NOT edit-modify
 protected void consumeRule(int act) {
   switch ( act ) {
@@ -8807,6 +8810,7 @@
 
 	}
 }
+// END_AUTOGENERATED_REGION_CONSUME_RULE
 protected void consumeVariableDeclaratorIdParameter () {
 	pushOnIntStack(1);  // signal "normal" variable declarator id parameter.
 }
@@ -10817,41 +10821,41 @@
 		dispatchDeclarationIntoRecordDeclaration(length);
 	}
 
-	RecordDeclaration rd = (RecordDeclaration) this.astStack[this.astPtr];
-	this.recordNestedMethodLevels.remove(rd);
+	TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr];
+	this.recordNestedMethodLevels.remove(typeDecl);
 	if (!this.options.enablePreviewFeatures){
-		problemReporter().previewFeatureNotEnabled(rd.sourceStart, rd.sourceEnd, "Records"); //$NON-NLS-1$
+		problemReporter().previewFeatureNotEnabled(typeDecl.sourceStart, typeDecl.sourceEnd, "Records"); //$NON-NLS-1$
 	} else {
 		if (this.options.isAnyEnabled(IrritantSet.PREVIEW)) {
-			problemReporter().previewFeatureUsed(rd.sourceStart, rd.sourceEnd);
+			problemReporter().previewFeatureUsed(typeDecl.sourceStart, typeDecl.sourceEnd);
 		}
 	}
 	//convert constructor that do not have the type's name into methods
-	ConstructorDeclaration cd = rd.getConstructor(this);
+	ConstructorDeclaration cd = typeDecl.getConstructor(this);
 	if (cd == null) {
 		/* create canonical constructor - check for the clash later at binding time */
-		cd = rd.createDefaultConstructor(!(this.diet && this.dietInt == 0), true);
+		cd = typeDecl.createDefaultConstructor(!(this.diet && this.dietInt == 0), true);
 	} else {
 		cd.bits |= ASTNode.IsCanonicalConstructor;
 	}
 
 	if (this.scanner.containsAssertKeyword) {
-		rd.bits |= ASTNode.ContainsAssertion;
+		typeDecl.bits |= ASTNode.ContainsAssertion;
 	}
-	rd.addClinit();
-	rd.bodyEnd = this.endStatementPosition;
-	if (length == 0 && !containsComment(rd.bodyStart, rd.bodyEnd)) {
-		rd.bits |= ASTNode.UndocumentedEmptyBlock;
+	typeDecl.addClinit();
+	typeDecl.bodyEnd = this.endStatementPosition;
+	if (length == 0 && !containsComment(typeDecl.bodyStart, typeDecl.bodyEnd)) {
+		typeDecl.bits |= ASTNode.UndocumentedEmptyBlock;
 	}
 	TypeReference superClass = new QualifiedTypeReference(TypeConstants.JAVA_LANG_RECORD, new long[] {0});
 	superClass.bits |= ASTNode.IsSuperType;
-	rd.superclass = superClass;
-	rd.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition);
+	typeDecl.superclass = superClass;
+	typeDecl.declarationSourceEnd = flushCommentsDefinedPriorTo(this.endStatementPosition);
 }
 protected void consumeRecordHeaderPart() {
 	// RecordHeaderPart ::= RecordHeaderName RecordHeader ClassHeaderImplementsopt
 	TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr];
-	assert typeDecl instanceof RecordDeclaration;
+	assert typeDecl.isRecord();
 	// do nothing
 }
 protected void consumeRecordHeaderNameWithTypeParameters() {
@@ -10866,13 +10870,13 @@
 	// RecordComponentHeaderRightParen ::= ')'
 	int length = this.astLengthStack[this.astLengthPtr--];
 	this.astPtr -= length;
-	RecordDeclaration rd = (RecordDeclaration) this.astStack[this.astPtr];
+	TypeDeclaration typeDecl = (TypeDeclaration) this.astStack[this.astPtr];
 	int nestedMethodLevel = this.nestedMethod[this.nestedType];
-	rd.isLocalRecord = nestedMethodLevel > 0;
-	if (rd.isLocalRecord)
-		rd.modifiers |= ClassFileConstants.AccStatic; // JLS 14 Sec 14.3
-	this.recordNestedMethodLevels.put(rd, new Integer[] {this.nestedType, nestedMethodLevel});
-	this.astStack[this.astPtr] = rd;
+	typeDecl.isLocalRecord = nestedMethodLevel > 0;
+	if (typeDecl.isLocalRecord)
+		typeDecl.modifiers |= ClassFileConstants.AccStatic; // JLS 14 Sec 14.3
+	this.recordNestedMethodLevels.put(typeDecl, new Integer[] {this.nestedType, nestedMethodLevel});
+	this.astStack[this.astPtr] = typeDecl;
 //	rd.sourceEnd = 	this.rParenPos;
 	if (length != 0) {
 		Argument[] args = new Argument[length];
@@ -10882,18 +10886,18 @@
 				args,
 				0,
 				length);
-		rd.setArgs(args);
-		convertToFields(rd, args);
+		typeDecl.args = args;
+		convertToFields(typeDecl, args);
 	}
-	rd.bodyStart = this.rParenPos+1;
+	typeDecl.bodyStart = this.rParenPos+1;
 	this.listLength = 0; // reset this.listLength after having read all parameters
 	// recovery
 	if (this.currentElement != null){
-		this.lastCheckPoint = rd.bodyStart;
-		if (this.currentElement.parseTree() == rd) return;
+		this.lastCheckPoint = typeDecl.bodyStart;
+		if (this.currentElement.parseTree() == typeDecl) return;
 	}
 }
-private void convertToFields(RecordDeclaration rd, Argument[] args) {
+private void convertToFields(TypeDeclaration typeDecl, Argument[] args) {
 	int length = args.length;
 	FieldDeclaration[] fields = new FieldDeclaration[length];
 	int nFields = 0;
@@ -10902,8 +10906,8 @@
 		Argument arg = args[i];
 		arg.bits |= ASTNode.IsRecordComponent;
 		String argName = new String(arg.name);
-		if (RecordDeclaration.disallowedComponentNames.contains(argName)) {
-			problemReporter().recordIllegalComponentNameInRecord(arg, rd);
+		if (TypeDeclaration.disallowedComponentNames.contains(argName)) {
+			problemReporter().recordIllegalComponentNameInRecord(arg, typeDecl);
 			continue;
 		}
 		if (argsSet.contains(argName)) {
@@ -10911,11 +10915,11 @@
 			continue;
 		}
 		if (arg.type.getLastToken() == TypeConstants.VOID) {
-			problemReporter().recordComponentCannotBeVoid(rd, arg);
+			problemReporter().recordComponentCannotBeVoid(typeDecl, arg);
 			continue;
 		}
 		if (arg.isVarArgs() && i < max - 1)
-			problemReporter().recordIllegalVararg(arg, rd);
+			problemReporter().recordIllegalVararg(arg, typeDecl);
 
 		argsSet.add(argName);
 		FieldDeclaration f = fields[nFields++] = createFieldDeclaration(arg.name, arg.sourceStart, arg.sourceEnd);
@@ -10968,8 +10972,8 @@
 		System.arraycopy(fields	, 0, tmp, 0, nFields);
 		fields = tmp;
 	}
-	rd.fields = fields;
-	rd.nRecordComponents = fields.length;
+	typeDecl.fields = fields;
+	typeDecl.nRecordComponents = fields.length;
 }
 protected void consumeRecordHeader() {
 	//RecordHeader ::= '(' RecordComponentsopt RecordComponentHeaderRightParen
@@ -11208,7 +11212,7 @@
 	}
 
 	//arrays creation
-	RecordDeclaration recordDecl = (RecordDeclaration) this.astStack[this.astPtr];
+	TypeDeclaration recordDecl = (TypeDeclaration) this.astStack[this.astPtr];
 	int nCreatedFields = recordDecl.fields != null ? recordDecl.fields.length : 0;
 	if (nFields != 0) {
 		FieldDeclaration[] tmp = new FieldDeclaration[(recordDecl.fields != null ? recordDecl.fields.length  : 0) + nFields];
@@ -11278,11 +11282,11 @@
 		}
 	}
 }
-private void checkForRecordMemberErrors(RecordDeclaration recordDecl, int nCreatedFields) {
-	if (recordDecl.fields == null)
+private void checkForRecordMemberErrors(TypeDeclaration typeDecl, int nCreatedFields) {
+	if (typeDecl.fields == null)
 		return;
-	for (int i = nCreatedFields; i < recordDecl.fields.length; i++) {
-		FieldDeclaration f = recordDecl.fields[i];
+	for (int i = nCreatedFields; i < typeDecl.fields.length; i++) {
+		FieldDeclaration f = typeDecl.fields[i];
 		if (f != null && !f.isStatic()) {
 			if (f instanceof Initializer)
 				problemReporter().recordInstanceInitializerBlockInRecord((Initializer) f);
@@ -11290,9 +11294,9 @@
 				problemReporter().recordNonStaticFieldDeclarationInRecord(f);
 		}
 	}
-	if (recordDecl.methods != null) {
-		for (int i = 0; i < recordDecl.methods.length; i++) {
-			AbstractMethodDeclaration method = recordDecl.methods[i];
+	if (typeDecl.methods != null) {
+		for (int i = 0; i < typeDecl.methods.length; i++) {
+			AbstractMethodDeclaration method = typeDecl.methods[i];
 			if ((method.modifiers & ClassFileConstants.AccNative) != 0) {
 				problemReporter().recordIllegalNativeModifierInRecord(method);
 			}
@@ -11473,8 +11477,9 @@
 
 	if (typeDecl.memberTypes != null) {
 		for (int i = typeDecl.memberTypes.length - 1; i >= 0; i--) {
-			typeDecl.memberTypes[i].enclosingType = typeDecl;
-			markNestedRecordStatic(typeDecl.memberTypes[i]);
+			TypeDeclaration memberType = typeDecl.memberTypes[i];
+			memberType.enclosingType = typeDecl;
+			markNestedRecordStatic(memberType);
 		}
 	}
 }
@@ -11484,7 +11489,7 @@
 	 * A nested record type is implicitly static.
 	 * It is permitted for the declaration of a nested record type to redundantly specify the static modifier.
 	 */
-	if (typeDeclaration instanceof RecordDeclaration)
+	if (typeDeclaration.isRecord())
 		typeDeclaration.modifiers |= ClassFileConstants.AccStatic;
 }
 protected void dispatchDeclarationIntoEnumDeclaration(int length) {
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java
index addd30a..d68662e 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/ParserBasicInformation.java
@@ -18,8 +18,9 @@
 public interface ParserBasicInformation {
 
 	public final static int
+	// BEGIN_AUTOGENERATED_REGION
 
-	ERROR_SYMBOL = 132,
+					ERROR_SYMBOL = 132,
 					MAX_NAME_LENGTH = 41,
 					NUM_STATES = 1197,
 
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 566bc23..5ec504b 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
@@ -741,7 +741,7 @@
 		char c = line[i];
 		if (c == '\\') {
 			if (i < end) {
-				if (lastPointer + 1 == i) {
+				if (lastPointer == i) {
 					lastPointer = i+1;
 				} else {
 					result.append(CharOperation.subarray(line, lastPointer == 0 ? start : lastPointer+1, i));
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/TerminalTokens.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/TerminalTokens.java
index 9f03708..379c8c7 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/TerminalTokens.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/TerminalTokens.java
@@ -37,6 +37,7 @@
 							TokenNameCOMMENT_BLOCK = 1002,
 							TokenNameCOMMENT_JAVADOC = 1003;
 
+	// BEGIN_AUTOGENERATED_REGION
 	int TokenNameIdentifier = 21,
 							TokenNameabstract = 52,
 							TokenNameassert = 79,
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 fdaea69..d9ae777 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
@@ -149,7 +149,6 @@
 import org.eclipse.jdt.internal.compiler.ast.QualifiedSuperReference;
 import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
 import org.eclipse.jdt.internal.compiler.ast.Receiver;
-import org.eclipse.jdt.internal.compiler.ast.RecordDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.Reference;
 import org.eclipse.jdt.internal.compiler.ast.ReferenceExpression;
 import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
@@ -2859,6 +2858,8 @@
 		problemID = IProblem.CannotDefineAnnotationInLocalType;
 	} else if ((typeDeclaration.modifiers & ClassFileConstants.AccInterface) != 0) {
 		problemID = IProblem.CannotDefineInterfaceInLocalType;
+	} else if (typeDeclaration.isRecord()) {
+		problemID = IProblem.RecordCannotDefineRecordInLocalType;
 	}
 	if (problemID != 0) {
 		String[] arguments = new String[] {new String(typeDeclaration.name)};
@@ -11544,16 +11545,16 @@
 		stmt.sourceStart,
 		stmt.sourceEnd);
 }
-public void recordIllegalComponentNameInRecord(Argument arg, RecordDeclaration rd) {
+public void recordIllegalComponentNameInRecord(Argument arg, TypeDeclaration typeDecl) {
 	if (!this.options.enablePreviewFeatures)
 		return;
 	this.handle(
 		IProblem.RecordIllegalComponentNameInRecord,
 		new String[] {
-				new String(arg.name), new String(rd.name)
+				new String(arg.name), new String(typeDecl.name)
 			},
 			new String[] {
-					new String(arg.name), new String(rd.name)
+					new String(arg.name), new String(typeDecl.name)
 			},
 		arg.sourceStart,
 		arg.sourceEnd);
@@ -11733,8 +11734,8 @@
 		recordDecl.sourceStart,
 		recordDecl.sourceEnd);
 }
-public void recordIllegalVararg(Argument argType, RecordDeclaration recordDecl) {
-	String[] arguments = new String[] {CharOperation.toString(argType.type.getTypeName()), new String(recordDecl.name)};
+public void recordIllegalVararg(Argument argType, TypeDeclaration typeDecl) {
+	String[] arguments = new String[] {CharOperation.toString(argType.type.getTypeName()), new String(typeDecl.name)};
 	this.handle(
 		IProblem.RecordIllegalVararg,
 		arguments,
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 ab874bd..76ac8be 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
@@ -1048,6 +1048,7 @@
 1753 = void is an invalid type for the component {0} of a record
 1754 = The variable argument type {0} of the record {1} must be the last parameter
 1755 = Cannot make a static reference to the non-static variable {0} from a local record
+1756 = A record declaration {0} is not allowed in a local inner class
 
 1760 = The pattern variable {0} is not in scope in this location
 
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 3aedfec..61541e6 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
@@ -3503,7 +3503,7 @@
 				recordDeclaration.typeParameters().add(convert(typeParameter));
 			}
 		}
-		Argument[] args = ((org.eclipse.jdt.internal.compiler.ast.RecordDeclaration)typeDeclaration).getArgs();
+		Argument[] args = typeDeclaration.args;
 		if (args != null) {
 			for (Argument arg : args) {
 				recordDeclaration.recordComponents().add(convert(arg));
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
index 03bd8d1..f72fab4 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java
@@ -2775,11 +2775,10 @@
 	 *    be found as a substring in a case-insensitive way.</p>
 	 * <dl>
 	 * <dt>Option id:</dt><dd><code>"org.eclipse.jdt.core.codeComplete.substringMatch"</code></dd>
-	 * <dt>Possible values:</dt><dd><code>{ "enabled", "disabled" }</code></dd>
-	 * <dt>Default:</dt><dd><code>"enabled"</code></dd>
 	 * </dl>
 	 * @since 3.12
-	 * @category CodeAssistOptionID
+	 * @deprecated - this option has no effect
+	 * @category DeprecatedOptionID
 	 */
 	public static final String CODEASSIST_SUBSTRING_MATCH = PLUGIN_ID + ".codeComplete.substringMatch"; //$NON-NLS-1$
 	/**
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java
index 7feb5c0..e76f939 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/compiler/parser/SourceTypeConverter.java
@@ -480,7 +480,7 @@
 		if ((TypeDeclaration.kind(typeInfo.getModifiers()) == TypeDeclaration.RECORD_DECL)) {
 			// The first choice constructor that takes CompilationResult as arg is not setting all the fields
 			// Hence, use the one that does
-			type = new RecordDeclaration(type);
+			type.modifiers |= ExtraCompilerModifiers.AccRecord;
 		}
 		if (typeInfo.getEnclosingType() == null) {
 			if (typeHandle.isAnonymous()) {
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java
index 65cdf03..031a67c 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaCorePreferenceInitializer.java
@@ -111,7 +111,6 @@
 		defaultOptionsMap.put(JavaCore.CODEASSIST_FORBIDDEN_REFERENCE_CHECK, JavaCore.ENABLED);
 		defaultOptionsMap.put(JavaCore.CODEASSIST_DISCOURAGED_REFERENCE_CHECK, JavaCore.DISABLED);
 		defaultOptionsMap.put(JavaCore.CODEASSIST_CAMEL_CASE_MATCH, JavaCore.ENABLED);
-		defaultOptionsMap.put(JavaCore.CODEASSIST_SUBSTRING_MATCH, JavaCore.ENABLED);
 		defaultOptionsMap.put(JavaCore.CODEASSIST_SUBWORD_MATCH, JavaCore.ENABLED);
 		defaultOptionsMap.put(JavaCore.CODEASSIST_SUGGEST_STATIC_IMPORTS, JavaCore.ENABLED);
 		defaultOptionsMap.put(ChunkCache.CHUNK_CACHE_SIZE_MB, Double.toString(ChunkCache.CHUNK_CACHE_SIZE_MB_DEFAULT));
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java
index 6a3f3c9..6a6e1a2 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java
@@ -2490,7 +2490,6 @@
 		defaultOptionsMap.put(JavaCore.CODEASSIST_FORBIDDEN_REFERENCE_CHECK, JavaCore.ENABLED);
 		defaultOptionsMap.put(JavaCore.CODEASSIST_DISCOURAGED_REFERENCE_CHECK, JavaCore.DISABLED);
 		defaultOptionsMap.put(JavaCore.CODEASSIST_CAMEL_CASE_MATCH, JavaCore.ENABLED);
-		defaultOptionsMap.put(JavaCore.CODEASSIST_SUBSTRING_MATCH, JavaCore.ENABLED);
 		defaultOptionsMap.put(JavaCore.CODEASSIST_SUBWORD_MATCH, JavaCore.ENABLED);
 		defaultOptionsMap.put(JavaCore.CODEASSIST_SUGGEST_STATIC_IMPORTS, JavaCore.ENABLED);
 
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 d12f2cf..09d13a6 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
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2019 IBM Corporation and others.
+ * Copyright (c) 2000, 2020 IBM Corporation and others.
  *
  * This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License 2.0
@@ -84,12 +84,14 @@
 import org.eclipse.jdt.core.compiler.CategorizedProblem;
 import org.eclipse.jdt.core.compiler.CharOperation;
 import org.eclipse.jdt.core.eval.IEvaluationContext;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
 import org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
 import org.eclipse.jdt.internal.compiler.env.AutomaticModuleNaming;
 import org.eclipse.jdt.internal.compiler.env.IModule;
 import org.eclipse.jdt.internal.compiler.env.IModule.IModuleReference;
 import org.eclipse.jdt.internal.compiler.env.IModule.IPackageExport;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
 import org.eclipse.jdt.internal.compiler.util.JRTUtil;
 import org.eclipse.jdt.internal.compiler.util.ObjectVector;
@@ -1925,10 +1927,29 @@
 					{
 						manager.deltaState.addClasspathValidation(JavaProject.this);
 					}
+					checkExpireModule(propertyName, event.getOldValue(), event.getNewValue());
 					manager.resetProjectOptions(JavaProject.this);
 					JavaProject.this.resetCaches(); // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=233568
 				}
 			}
+
+			void checkExpireModule(String propertyName, Object oldValue, Object newValue) {
+				if (propertyName.equals(JavaCore.COMPILER_SOURCE)) {
+					if (oldValue instanceof String && newValue instanceof String
+						&& CompilerOptions.versionToJdkLevel((String) oldValue) >= ClassFileConstants.JDK9
+						&& CompilerOptions.versionToJdkLevel((String) newValue) < ClassFileConstants.JDK9)
+					{
+						try {
+							// this is a change from modular to non-modular, forget the module if any:
+							IModuleDescription module = getModuleDescription();
+							if (module != null)
+								((JavaElement)module).close();
+						} catch (JavaModelException e) {
+							// ignore
+						}
+					}
+				}
+			}
 		};
 		eclipsePreferences.addPreferenceChangeListener(this.preferencesChangeListener);
 		return eclipsePreferences;
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java
index 365a8ab..ba153df 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/ClasspathJar.java
@@ -326,6 +326,15 @@
 @Override
 public boolean hasCompilationUnit(String pkgName, String moduleName) {
 	if (scanContent()) {
+		if (!this.knownPackageNames.includes(pkgName)) {
+			// Don't waste time walking through the zip if we know that it doesn't
+			// contain a directory that matches pkgName
+			return false;
+		}
+
+		// Even if knownPackageNames contained the pkg we're looking for, we still need to verify
+		// that the package in this jar actually contains at least one .class file (since
+		// knownPackageNames includes empty packages)
 		for (Enumeration<? extends ZipEntry> e = this.zipFile.entries(); e.hasMoreElements(); ) {
 			String fileName = e.nextElement().getName();
 			if (fileName.startsWith(pkgName)
@@ -334,6 +343,7 @@
 				return true;
 		}
 	}
+
 	return false;
 }
 
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/eval/EvaluationContextWrapper.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/eval/EvaluationContextWrapper.java
index 7a8ee4c..1c14be8 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/eval/EvaluationContextWrapper.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/eval/EvaluationContextWrapper.java
@@ -230,12 +230,13 @@
 	}
 	INameEnvironment environment = null;
 	try {
+		String fullyQualifiedName = declaringType == null? null : declaringType.getFullyQualifiedName('.');
 		this.context.evaluate(
 			codeSnippet.toCharArray(),
 			varTypeNames,
 			varNames,
 			localVariableModifiers,
-			declaringType == null? null : declaringType.getFullyQualifiedName().toCharArray(),
+			fullyQualifiedName == null? null : fullyQualifiedName.toCharArray(),
 			isStatic,
 			isConstructorCall,
 			environment = getBuildNameEnvironment(),
diff --git a/org.eclipse.jdt.core/pom.xml b/org.eclipse.jdt.core/pom.xml
index f59c0f2..4acde60 100644
--- a/org.eclipse.jdt.core/pom.xml
+++ b/org.eclipse.jdt.core/pom.xml
@@ -73,7 +73,7 @@
       <plugin>
         <groupId>org.eclipse.tycho.extras</groupId>
         <artifactId>tycho-custom-bundle-plugin</artifactId>
-        <version>${tycho-extras.version}</version>
+        <version>${tycho.version}</version>
         <executions>
           <execution>
             <id>antadapter</id>
diff --git a/org.eclipse.jdt.core/scripts/GenerateParserScript.java b/org.eclipse.jdt.core/scripts/GenerateParserScript.java
new file mode 100644
index 0000000..56cb92a
--- /dev/null
+++ b/org.eclipse.jdt.core/scripts/GenerateParserScript.java
@@ -0,0 +1,143 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Bart Jacobs and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ */
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
+import org.eclipse.jdt.internal.compiler.parser.Parser;
+
+public class GenerateParserScript {
+
+	private static void assertTrue(boolean b) { if (!b) throw new AssertionError(); }
+
+	public static void main(String[] args) throws IOException, InterruptedException {
+		File grammarDir = new File("../grammar");
+		File parserDir = new File("../compiler/org/eclipse/jdt/internal/compiler/parser");
+		String jikespg = System.getProperty("JIKESPG");
+		assertTrue(jikespg != null);
+
+		if (!jikespg.equals("JIKESPG_EXTERNAL")) {
+			// Run JikesPG
+			Process process = Runtime.getRuntime().exec(new String[] {jikespg, "java.g"}, null, grammarDir);
+			boolean ok = false;
+			try (BufferedReader jikespgOutput = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
+				for (;;) {
+					String line = jikespgOutput.readLine();
+					if (line == null)
+						break;
+					System.out.println(line);
+					if (line.equals("This grammar is LALR(1)."))
+						ok = true;
+				}
+			}
+			int exitCode = process.waitFor();
+			assertTrue(exitCode == 0);
+			if (!ok)
+				System.exit(1);
+		}
+
+		// Update parserNN.rsc and readableNames.props
+		File javadclFile = new File(grammarDir, "javadcl.java");
+		File javahdrFile = new File(grammarDir, "javahdr.java");
+		Parser.buildFilesFromLPG(javadclFile.toString(), javahdrFile.toString());
+		for (int i = 1; i <= 24; i++) {
+			String filename = "parser"+i+".rsc";
+			Files.move(new File(filename).toPath(), new File(parserDir, filename).toPath(), StandardCopyOption.REPLACE_EXISTING);
+		}
+		{
+			String filename = "readableNames.props";
+			Files.move(new File(filename).toPath(), new File(parserDir, filename).toPath(), StandardCopyOption.REPLACE_EXISTING);
+		}
+
+		// Update TerminalTokens.java
+		File javasymFile = new File(grammarDir, "javasym.java");
+		File terminalTokensFile = new File(parserDir, "TerminalTokens.java");
+		String javasymText = new String(Files.readAllBytes(javasymFile.toPath())).replace("\r\n",  "\n");
+		String terminalTokensText = new String(Files.readAllBytes(terminalTokensFile.toPath()));
+		{
+			String startTag = "// BEGIN_AUTOGENERATED_REGION\n";
+			int start = terminalTokensText.indexOf(startTag);
+			assertTrue(start >= 0);
+			start += startTag.length();
+			String terminalTokensProlog = terminalTokensText.substring(0, start);
+
+			String javasymProlog =
+					"interface javasym\n" + 
+					"{\n" + 
+					"    public final static int\n" +
+					"      ";
+			assertTrue(javasymText.startsWith(javasymProlog));
+			javasymText = javasymText.substring(javasymProlog.length());
+			javasymText = javasymText.replace(",\n      ", ",\n\t\t\t\t\t\t\t");
+			javasymText = javasymText.replace("TokenName$eof", "TokenNameEOF");
+			javasymText = javasymText.replace("TokenName$error", "TokenNameERROR");
+			Files.write(terminalTokensFile.toPath(), (terminalTokensProlog + "\tint " + javasymText).getBytes());
+		}
+
+		// Update ParserBasicInformation.java
+		File javadefFile = new File(grammarDir, "javadef.java");
+		File parserBasicInformationFile = new File(parserDir, "ParserBasicInformation.java");
+		String javadefText = new String(Files.readAllBytes(javadefFile.toPath())).replace("\r\n", "\n");
+		String parserBasicInformationText = new String(Files.readAllBytes(parserBasicInformationFile.toPath()));
+		{
+			String startTag = "// BEGIN_AUTOGENERATED_REGION";
+			int start = parserBasicInformationText.indexOf(startTag);
+			assertTrue(start >= 0);
+			start += startTag.length();
+			String parserBasicInformationProlog = parserBasicInformationText.substring(0, start);
+
+			String javadefProlog =
+					"interface javadef\n" + 
+					"{\n" + 
+					"    public final static int";
+			assertTrue(javadefText.startsWith(javadefProlog));
+			javadefText = javadefText.substring(javadefProlog.length());
+			javadefText = javadefText.replace("\n      ", "\n\t\t\t\t\t");
+			javadefText = javadefText.replaceAll(" +", " ");
+			javadefText = javadefText.replace("};\n\n", "}\n");
+
+			Files.write(parserBasicInformationFile.toPath(), (parserBasicInformationProlog + javadefText).getBytes());
+		}
+
+		// Update method consumeRule in Parser.java
+		File parserFile = new File(parserDir, "Parser.java");
+		String parserText = new String(Files.readAllBytes(parserFile.toPath()));
+		File javaActionFile = new File(grammarDir, "JavaAction.java");
+		String javaActionText = new String(Files.readAllBytes(javaActionFile.toPath()))
+									.replace("\r\n",  "\n").replace(" \n", "\n").replace(" \n", "\n");
+		{
+			String startTag = "// BEGIN_AUTOGENERATED_REGION_CONSUME_RULE\n";
+			String endTag = "// END_AUTOGENERATED_REGION_CONSUME_RULE\n";
+			int start = parserText.indexOf(startTag);
+			assertTrue(start >= 0);
+			start += startTag.length();
+			int end = parserText.indexOf(endTag, start);
+			assertTrue(end >= 0);
+
+			String newParserText = parserText.substring(0, start) + javaActionText + parserText.substring(end);
+
+			Files.write(parserFile.toPath(), newParserText.getBytes());
+		}
+
+		// Clean up JikesPG output files
+		Files.delete(javadclFile.toPath());
+		Files.delete(javahdrFile.toPath());
+		Files.delete(javaActionFile.toPath());
+		Files.delete(javasymFile.toPath());
+		Files.delete(javadefFile.toPath());
+		Files.delete(new File(grammarDir, "javaprs.java").toPath());
+		Files.delete(new File(grammarDir, "java.l").toPath());
+	}
+
+}
diff --git a/org.eclipse.jdt.core/scripts/build-parser.launch b/org.eclipse.jdt.core/scripts/build-parser.launch
new file mode 100644
index 0000000..55abf6b
--- /dev/null
+++ b/org.eclipse.jdt.core/scripts/build-parser.launch
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.ant.AntLaunchConfigurationType">
+    <booleanAttribute key="org.eclipse.ant.ui.DEFAULT_VM_INSTALL" value="false"/>
+    <stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${working_set:&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;resources&gt;&#10;&lt;item path=&quot;/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser&quot; type=&quot;2&quot;/&gt;&#10;&lt;/resources&gt;}"/>
+    <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
+        <listEntry value="/eclipse.jdt.core/org.eclipse.jdt.core/scripts/build-parser.xml"/>
+    </listAttribute>
+    <listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
+        <listEntry value="1"/>
+    </listAttribute>
+    <booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_CLASSPATH_ONLY_JAR" value="false"/>
+    <stringAttribute key="org.eclipse.jdt.launching.CLASSPATH_PROVIDER" value="org.eclipse.ant.ui.AntClasspathProvider"/>
+    <stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11"/>
+    <stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.eclipse.ant.internal.launching.remote.InternalAntRunner"/>
+    <stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.jdt.core"/>
+    <stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.ant.ui.AntClasspathProvider"/>
+    <stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/org.eclipse.jdt.core/scripts/build-parser.xml}"/>
+    <stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-DJIKESPG=${JIKESPG}"/>
+    <stringAttribute key="process_factory_id" value="org.eclipse.ant.ui.remoteAntProcessFactory"/>
+</launchConfiguration>
diff --git a/org.eclipse.jdt.core/scripts/build-parser.xml b/org.eclipse.jdt.core/scripts/build-parser.xml
new file mode 100644
index 0000000..db649fc
--- /dev/null
+++ b/org.eclipse.jdt.core/scripts/build-parser.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Copyright (c) 2020 Stephan Hermmann and others.
+
+    This program and the accompanying materials
+    are made available under the terms of the Eclipse Public License 2.0
+    which accompanies this distribution, and is available at
+    https://www.eclipse.org/legal/epl-2.0/
+
+    SPDX-License-Identifier: EPL-2.0
+    
+    Contributors:
+        IBM Corporation - initial API and implementation
+ -->
+
+<project name="build-parser" default="build" basedir=".">
+
+	<!-- Usage hints:
+		1. In your workspace please create a String Substitution named JIKESPG pointing to the jikespg executable.
+		   See  Preferences > Run/Debug > String Substitutions
+		2. Invoke the script via build-parser.launch
+	 -->
+	<target name="build">
+ 		<javac srcdir="${basedir}" includes="GenerateParserScript.java" destdir="${basedir}"
+ 					classpath="${basedir}/../bin"
+					debuglevel="lines,source"
+					source="1.8"
+					target="1.8">
+			<compilerarg/>
+		</javac>
+		<java classname="GenerateParserScript" classpath=".:${basedir}/../bin">
+			<sysproperty key="JIKESPG" value="${JIKESPG}"/>
+		</java>
+	</target>
+</project>
\ No newline at end of file